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
42 changes: 5 additions & 37 deletions e2e-tests/specs/onboarding.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ test.describe('Onboarding', () => {
expect(await page.locator('.ss-card .ss-badge').count()).toBeGreaterThan(0);

// 'All' and 'Free' should show after you select a category.
// Match exactly: card page-shot buttons (e.g. "Gallery", "Ballet Blog",
// "All Courses") also contain "all" as a substring, so a non-exact name
// match resolves to multiple elements once the grid renders a full page.
await page.locator('.ob-cat-wrap').first().click();
await expect(page.getByRole('button', { name: 'All' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Free' })).toBeVisible();
await expect(page.getByRole('button', { name: 'All', exact: true })).toBeVisible();
await expect(page.getByRole('button', { name: 'Free', exact: true })).toBeVisible();

// Check card structure.
const firstListedSiteCard = page.locator('.ss-card-wrap').first();
Expand All @@ -62,41 +65,6 @@ test.describe('Onboarding', () => {
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
5 changes: 3 additions & 2 deletions includes/Starter_Ranking.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ private static function fetch_order( $builder, $query = null, $budget = null ) {
$deadline = time() + ( null !== $budget ? (int) $budget : self::REQUEST_BUDGET );
$start = self::base_url() . '/api/workflows/' . self::SLUG . '/start';
$body = array(
'site_url' => home_url(),
'builder' => $builder,
'site_url' => home_url(),
'site_title' => sanitize_text_field( get_bloginfo( 'name' ) ),
'builder' => $builder,
);

if ( null !== $query && '' !== $query ) {
Expand Down
96 changes: 0 additions & 96 deletions onboarding/src/Components/OnboardingPromoNotice.js

This file was deleted.

10 changes: 5 additions & 5 deletions onboarding/src/Components/Sites.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ const Sites = ( {
sortBy,
selectedColors,
} ) => {
const [ maxShown, setMaxShown ] = useState( 9 );
const [ maxShown, setMaxShown ] = useState( 12 );
const { sites = {} } = getSites;

useEffect( () => {
setMaxShown( 9 );
setMaxShown( 12 );
}, [ editor, category, searchQuery, sortBy, selectedColors ] );

const getBuilders = () => Object.keys( sites );
Expand Down Expand Up @@ -218,9 +218,9 @@ const Sites = ( {
const rest = filterByColors( filterByCategory( ranked, category ) ).filter(
( site ) => site && site.slug && ! inMatches[ site.slug ]
);
const remainder = matches.length % 3;
const remainder = matches.length % 4;
const pad =
remainder === 0 ? 0 : Math.min( 3 - remainder, rest.length );
remainder === 0 ? 0 : Math.min( 4 - remainder, rest.length );

return {
list: [ ...matches, ...rest ],
Expand Down Expand Up @@ -280,7 +280,7 @@ const Sites = ( {
return false;
}

setMaxShown( ( shown ) => shown + 9 );
setMaxShown( ( shown ) => shown + 12 );
} }
>
<span
Expand Down
40 changes: 36 additions & 4 deletions onboarding/src/Components/StarterSiteCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ const StarterSiteCard = ( {
setSite,
handleNextStep,
trackingId,
editor
editor,
selectedColors = []
} ) => {
const {
upsell,
Expand Down Expand Up @@ -93,6 +94,32 @@ const StarterSiteCard = ( {
screenshot: screenshotMap[ color ] || screenshot,
} ) );
}, [ data?.colors, data?.screenshots_by_color, screenshot ] );
// First globally-selected color this card actually has, returned as the
// canonical RAW colorOptions slug so option.slug === activeColor still hits.
// selectedColors are normalized lowercase (Filters.js) while colorOptions
// slugs / screenshots_by_color keys are raw, so match case-insensitively.
const filterColor = useMemo( () => {
if (
! Array.isArray( selectedColors ) ||
! selectedColors.length ||
! colorOptions.length
) {
return '';
}

const normalizedToSlug = new Map(
colorOptions.map( ( option ) => [
String( option.slug || '' ).trim().toLowerCase(),
option.slug,
] )
);

const matched = selectedColors.find( ( color ) =>
normalizedToSlug.has( color )
);

return matched ? normalizedToSlug.get( matched ) : '';
}, [ selectedColors, colorOptions ] );
const previewColors = colorOptions.slice( 0, 2 );
const [ activePage, setActivePage ] = useState( pageShots[0]?.key || 'home' );
const [ activeColor, setActiveColor ] = useState( colorOptions[0]?.slug || '' );
Expand All @@ -102,9 +129,12 @@ const StarterSiteCard = ( {
setActivePage( pageShots[0]?.key || 'home' );
}, [ pageShots ] );

// Seed the displayed color from the global filter when this card matches a
// selected color; otherwise fall back to the first palette. Re-runs only on
// filter/colorOptions changes, so manual swatch clicks survive until then.
useEffect( () => {
setActiveColor( colorOptions[0]?.slug || '' );
}, [ colorOptions ] );
setActiveColor( filterColor || colorOptions[0]?.slug || '' );
}, [ colorOptions, filterColor ] );

const activePageShot =
pageShots.find( ( shot ) => shot.key === activePage ) || pageShots[0] || null;
Expand Down Expand Up @@ -194,7 +224,7 @@ const StarterSiteCard = ( {
) ) }
</div>
) }
{ colorOptions.length > 0 && (
{ colorOptions.length > 1 && (
<div
className={
isColorExpanded
Expand Down Expand Up @@ -290,12 +320,14 @@ export default compose(
getCurrentEditor,
getCurrentCategory,
getSearchQuery,
getSelectedColors,
} = select( 'ti-onboarding' );
return {
trackingId: getTrackingId(),
editor: getCurrentEditor(),
category: getCurrentCategory(),
query: getSearchQuery(),
selectedColors: getSelectedColors() || [],
};
} ),
withDispatch( ( dispatch, { data } ) => {
Expand Down
Loading
Loading