Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 0 additions & 35 deletions e2e-tests/specs/onboarding.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@

// 'All' and 'Free' should show after you select a category.
await page.locator('.ob-cat-wrap').first().click();
await expect(page.getByRole('button', { name: 'All' })).toBeVisible();

Check failure on line 52 in e2e-tests/specs/onboarding.spec.js

View workflow job for this annotation

GitHub Actions / E2E Test

[chromium] › specs/onboarding.spec.js:37:9 › Onboarding › Site Listing Page Rendering

1) [chromium] › specs/onboarding.spec.js:37:9 › Onboarding › Site Listing Page Rendering ───────── Retry #2 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toBeVisible() failed Locator: getByRole('button', { name: 'All' }) Expected: visible Error: strict mode violation: getByRole('button', { name: 'All' }) resolved to 3 elements: 1) <button class="cat all">All</button> aka getByRole('button', { name: 'All', exact: true }) 2) <div tabindex="0" role="button" class="ss-card">…</div> aka getByRole('button', { name: 'Home About Us Gallery Contact +' }) 3) <button type="button" class="ss-page-shot">Gallery</button> aka getByRole('button', { name: 'Gallery', exact: true }) Call log: - Expect "toBeVisible" with timeout 5000ms - waiting for getByRole('button', { name: 'All' }) 50 | // 'All' and 'Free' should show after you select a category. 51 | await page.locator('.ob-cat-wrap').first().click(); > 52 | await expect(page.getByRole('button', { name: 'All' })).toBeVisible(); | ^ 53 | await expect(page.getByRole('button', { name: 'Free' })).toBeVisible(); 54 | 55 | // Check card structure. at /home/runner/work/templates-patterns-collection/templates-patterns-collection/e2e-tests/specs/onboarding.spec.js:52:65

Check failure on line 52 in e2e-tests/specs/onboarding.spec.js

View workflow job for this annotation

GitHub Actions / E2E Test

[chromium] › specs/onboarding.spec.js:37:9 › Onboarding › Site Listing Page Rendering

1) [chromium] › specs/onboarding.spec.js:37:9 › Onboarding › Site Listing Page Rendering ───────── Retry #1 ─────────────────────────────────────────────────────────────────────────────────────── Error: expect(locator).toBeVisible() failed Locator: getByRole('button', { name: 'All' }) Expected: visible Error: strict mode violation: getByRole('button', { name: 'All' }) resolved to 3 elements: 1) <button class="cat all">All</button> aka getByRole('button', { name: 'All', exact: true }) 2) <div tabindex="0" role="button" class="ss-card">…</div> aka getByRole('button', { name: 'Home About Us Gallery Contact +' }) 3) <button type="button" class="ss-page-shot">Gallery</button> aka getByRole('button', { name: 'Gallery', exact: true }) Call log: - Expect "toBeVisible" with timeout 5000ms - waiting for getByRole('button', { name: 'All' }) 50 | // 'All' and 'Free' should show after you select a category. 51 | await page.locator('.ob-cat-wrap').first().click(); > 52 | await expect(page.getByRole('button', { name: 'All' })).toBeVisible(); | ^ 53 | await expect(page.getByRole('button', { name: 'Free' })).toBeVisible(); 54 | 55 | // Check card structure. at /home/runner/work/templates-patterns-collection/templates-patterns-collection/e2e-tests/specs/onboarding.spec.js:52:65
await expect(page.getByRole('button', { name: 'Free' })).toBeVisible();

// Check card structure.
Expand All @@ -62,41 +62,6 @@
await expect(firstListedSiteCard.locator('.ss-title')).not.toBeEmpty();
});

test('Onboarding promo notice can be dismissed and stays hidden after reload', async ({ page, admin }) => {
await admin.visitAdminPage(ONBOARDING_URL);

const promoNotice = page.locator('.ob-onboarding-promo');
await expect(promoNotice).toBeVisible();

// The client sends the dismiss action via FormData, which fetch encodes as
// multipart/form-data. Inspect the raw body bytes so the predicate works
// regardless of whether the encoding is multipart or url-encoded.
const isDismissCall = (request) =>
request.url().includes('admin-ajax.php') &&
request.method() === 'POST' &&
(request.postDataBuffer()?.toString('utf8') ?? '').includes(
'dismiss_onboarding_promo_notice'
);

const dismissRequest = page.waitForRequest(isDismissCall);
const dismissResponse = page.waitForResponse((response) =>
isDismissCall(response.request())
);

await promoNotice.getByRole('button', { name: 'Dismiss notice' }).click();

const request = await dismissRequest;
const response = await dismissResponse;
expect(request.postDataBuffer()?.toString('utf8')).toContain(
'dismiss_onboarding_promo_notice'
);
expect(response.ok()).toBeTruthy();

await expect(promoNotice).toBeHidden();
await page.reload();
await expect(promoNotice).toBeHidden();
});

test('Site Import Customization Rendering', async ({ page, admin }) => {
await admin.visitAdminPage(ONBOARDING_URL);
await openFirstSiteAndWaitForData( page );
Expand Down
59 changes: 3 additions & 56 deletions includes/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,9 @@ class Admin {
const IMPORTED_TEMPLATES_COUNT_OPT = 'tiob_premade_imported';
const FEEDBACK_DISMISSED_OPT = 'tiob_feedback_dismiss';

const TC_REMOVED_KEY = 'tiob_tc_removed';
const TC_NEW_NOTICE_DISMISSED = 'tiob_new_tc_notice_dismissed';
const ONBOARDING_PROMO_NOTICE_DISMISSED = 'tiob_onboarding_promo_notice_dismissed';
const VISITED_LIBRARY_OPT = 'tiob_library_visited';
const TC_REMOVED_KEY = 'tiob_tc_removed';
const TC_NEW_NOTICE_DISMISSED = 'tiob_new_tc_notice_dismissed';
const VISITED_LIBRARY_OPT = 'tiob_library_visited';

/**
* Admin page slug
Expand Down Expand Up @@ -89,7 +88,6 @@ public function init() {
add_action( 'wp_ajax_tpc_get_logs', array( $this, 'external_get_logs' ) );

add_action( 'wp_ajax_dismiss_new_tc_notice', array( $this, 'dismiss_new_tc_notice' ) );
add_action( 'wp_ajax_dismiss_onboarding_promo_notice', array( $this, 'dismiss_onboarding_promo_notice' ) );

$this->register_feedback_settings();

Expand Down Expand Up @@ -163,52 +161,6 @@ public function dismiss_new_tc_notice() {
$this->ensure_ajax_response( $response );
}

/**
* Dismiss onboarding promo notice.
*
* @return void
*/
public function dismiss_onboarding_promo_notice() {
$response = array(
'success' => false,
'code' => 'ti__ob_not_allowed',
'message' => 'Not allowed!',
);

if ( ! isset( $_REQUEST['nonce'] ) ) {
$this->ensure_ajax_response( $response );
return;
}

$nonce = sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) );

if ( ! wp_verify_nonce( $nonce, 'dismiss_onboarding_promo_notice' ) ) {
$this->ensure_ajax_response( $response );
return;
}

if ( ! current_user_can( 'install_plugins' ) ) {
$this->ensure_ajax_response( $response );
return;
}

$response['success'] = true;
unset( $response['code'] );
unset( $response['message'] );

update_option( self::ONBOARDING_PROMO_NOTICE_DISMISSED, 'yes' );
$this->ensure_ajax_response( $response );
}

/**
* Decide if the onboarding promo notice should be shown.
*
* @return bool
*/
private function should_show_onboarding_promo_notice() {
return get_option( self::ONBOARDING_PROMO_NOTICE_DISMISSED, 'no' ) !== 'yes';
}

/**
* Decide if the business/agency variant of the onboarding promo text should be shown.
*
Expand Down Expand Up @@ -937,11 +889,6 @@ private function get_localization() {
'ajaxURL' => esc_url( admin_url( 'admin-ajax.php' ) ),
'nonce' => wp_create_nonce( 'dismiss_new_tc_notice' ),
),
'onboardingPromoNotice' => array(
'show' => $this->should_show_onboarding_promo_notice(),
'ajaxURL' => esc_url( admin_url( 'admin-ajax.php' ) ),
'nonce' => wp_create_nonce( 'dismiss_onboarding_promo_notice' ),
),
'onboardingPluginCompatibility' => array(
'hyve-lite' => is_php_version_compatible( '8.1' ),
),
Expand Down
96 changes: 0 additions & 96 deletions onboarding/src/Components/OnboardingPromoNotice.js

This file was deleted.

38 changes: 28 additions & 10 deletions onboarding/src/Components/Steps/SiteList.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Toast from '../Toast';
import Filters from '../Filters';
import Sites from '../Sites';
import EditorSelector from '../EditorSelector';
import OnboardingPromoNotice from '../OnboardingPromoNotice';
import SVG from '../../utils/svg';
import { get, track } from '../../utils/rest';

Expand Down Expand Up @@ -41,18 +40,16 @@ const SiteList = ( {

const toastMessage = createInterpolateElement(
__(
'Unlock Access to all premium templates with Neve Business plan. <a></a>.',
'Included with Neve Business. <a>See plans</a>',
'templates-patterns-collection'
),
{
a: (
<a
href={ tiobDash.onboardingUpsell.upgradeToast }
target="_blank"
rel="external noreferrer noopener"
>
{ __( 'Get Started', 'templates-patterns-collection' ) }
</a>
rel="noopener noreferrer"
/>
),
}
);
Expand Down Expand Up @@ -211,13 +208,30 @@ const SiteList = ( {
<div className="ob-container">
<div className="ob-container-inner">
<div className="ob-title-wrap">
<h1>
{ __( 'Choose a design', 'templates-patterns-collection' ) }
</h1>
<div className="ob-title-text">
<h1>
{ __(
'Choose a design',
'templates-patterns-collection'
) }
</h1>
<p className="ob-subtitle">
{ createInterpolateElement(
__(
'<count>Nearly 200 starter sites</count> across every niche, with dozens added recently.',
'templates-patterns-collection'
),
{
count: (
<span className="ob-subtitle__count" />
),
}
) }
</p>
</div>
<EditorSelector />
</div>
<Filters />
<OnboardingPromoNotice />
{ ( personalizing || searching ) && (
<div
className="ob-ranking-loader"
Expand Down Expand Up @@ -248,6 +262,10 @@ const SiteList = ( {
setShowToast={ setShowToast }
svgIcon={ SVG.logo }
className={ showToast === true ? 'show' : '' }
heading={ __(
'Unlock every premium template',
'templates-patterns-collection'
) }
message={ toastMessage }
/>
) }
Expand Down
27 changes: 21 additions & 6 deletions onboarding/src/Components/Toast.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
import classnames from 'classnames';
import { __ } from '@wordpress/i18n';

const Toast = ( { svgIcon, message, className, setShowToast } ) => {
const Toast = ( { svgIcon, heading, message, className, setShowToast } ) => {
const handleClose = () => {
setShowToast( 'dismissed' );
};

return (
<div className={ classnames( 'ob-toast', className ) }>
<div
className={ classnames( 'ob-toast', className ) }
role="status"
aria-live="polite"
>
{ svgIcon && (
<span className="ob-toast-icon" aria-hidden="true">
{ svgIcon }
</span>
) }
<div className="ob-toast-content">
{ svgIcon && <div className="ob-toast-icon">{ svgIcon }</div> }
{ message && <p>{ message }</p> }
{ heading && <p className="ob-toast-heading">{ heading }</p> }
{ message && <p className="ob-toast-message">{ message }</p> }
</div>
<button className="ob-toast-close" onClick={ handleClose }>
&times;
<button
type="button"
className="ob-toast-close"
onClick={ handleClose }
aria-label={ __( 'Dismiss', 'templates-patterns-collection' ) }
>
<span aria-hidden="true">&times;</span>
</button>
</div>
);
Expand Down
35 changes: 35 additions & 0 deletions onboarding/src/scss/_general.scss
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,41 @@ iframe {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}

.ob-title-text {
display: flex;
flex-direction: column;
gap: 4px;

h1 {
margin: 0;
}
}

.ob-subtitle {
margin: 6px 0 0;
max-width: 56ch;
// ~#6E6D6D on white ≈ 4.6:1 → passes WCAG AA while staying clearly secondary to the near-black h1.
color: mix($main-text, $inverted-text, 56%);
font-size: 14px;
line-height: 20px;
font-weight: 400;
letter-spacing: 0.1px;

// Subtle emphasis on the catalog claim — weight only, no brand color (would read promotional).
.ob-subtitle__count {
font-weight: 600;
color: $main-text;
}
}

@media (max-width: #{$tablet}) {
.ob-subtitle {
font-size: 13px;
line-height: 19px;
}
}

/**
Expand Down
Loading
Loading