From 8a2935bc097231aca3c006ea7af6a4ef6b8c52ff Mon Sep 17 00:00:00 2001 From: Donna Peplinskie Date: Tue, 10 Dec 2024 08:04:21 -0500 Subject: [PATCH] Add experimental UI for site identification step in the migration flow (#97072) * Remove obsolete translation checks * Add experimental UI for "Why should you host with us?" section * Add additional interface * Add border-radius to icons * Add feature flag check to tests This will ensure tests don't fail when the feature flag is enabled. --- .../site-migration-identify/index.tsx | 149 +++++++++++------- .../site-migration-identify/style.scss | 46 ++++++ .../site-migration-identify/test/index.tsx | 17 +- 3 files changed, 152 insertions(+), 60 deletions(-) diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/index.tsx index 95d966056d9b1..f4cbba9d1c0ec 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/index.tsx @@ -1,7 +1,8 @@ -import { useHasEnTranslation } from '@automattic/i18n-utils'; +import config from '@automattic/calypso-config'; import { StepContainer, Title, SubTitle, HOSTED_SITE_MIGRATION_FLOW } from '@automattic/onboarding'; +import { Icon, next, published, shield } from '@wordpress/icons'; import { useTranslate } from 'i18n-calypso'; -import { type FC, useEffect, useState, useCallback } from 'react'; +import { type FC, ReactElement, useEffect, useState, useCallback } from 'react'; import CaptureInput from 'calypso/blocks/import/capture/capture-input'; import ScanningStep from 'calypso/blocks/import/scanning'; import DocumentHead from 'calypso/components/data/document-head'; @@ -21,6 +22,41 @@ interface HostingDetailsProps { items: { title: string; description: string }[]; } +interface HostingDetailsWithIconsProps { + items: { + icon: ReactElement; + description: string; + }[]; +} + +const isMigrationExperimentEnabled = config.isEnabled( 'migration-flow/experiment' ); + +const HostingDetailsWithIcons: FC< HostingDetailsWithIconsProps > = ( { items } ) => { + const translate = useTranslate(); + + return ( +
+

+ { translate( 'Why should you host with us?' ) } +

+ +
+ ); +}; + const HostingDetails: FC< HostingDetailsProps > = ( { items } ) => { const translate = useTranslate(); @@ -52,27 +88,7 @@ interface Props { export const Analyzer: FC< Props > = ( { onComplete, onSkip, hideImporterListLink = false } ) => { const translate = useTranslate(); - const hasEnTranslation = useHasEnTranslation(); const [ siteURL, setSiteURL ] = useState< string >( '' ); - - // TODO: Remove extra steps for non-English locales once we have translations -- title. - const titleInUse = hasEnTranslation( 'Let’s find your site' ) - ? translate( 'Let’s find your site' ) - : translate( 'Let’s import your content' ); - - // TODO: Remove extra steps for non-English locales once we have translations -- subtitle. - const subtitleInUse = hasEnTranslation( - "Drop your current site address below to get started. In the next step, we'll measure your site's performance and confirm its eligibility for migration." - ) - ? translate( - "Drop your current site address below to get started. In the next step, we'll measure your site's performance and confirm its eligibility for migration." - ) - : translate( 'Drop your current site address below to get started.' ); - - // TODO: Remove extra steps for non-English locales once we have translations -- CTA text. - const nextLabelText = hasEnTranslation( 'Check my site' ) ? translate( 'Check my site' ) : false; - const nextLabelProp = nextLabelText ? { nextLabelText } : {}; // If we don't pass anything, the default label 'Continue' will be used. - const { data: siteInfo, isError: hasError, @@ -90,46 +106,59 @@ export const Analyzer: FC< Props > = ( { onComplete, onSkip, hideImporterListLin return ; } - // TODO: Remove extra steps and properties for non-English locales once we have translations -- hosting details. - const hostingDetailItems = { - 'unmatched-uptime': { - title: translate( 'Unmatched Reliability and Uptime' ), - titleString: 'Unmatched Reliability and Uptime', // Temporary string for non-English locales. Remove once we have translations. - description: translate( - "Our infrastructure's 99.99% uptime, combined with our automatic update system, ensures your site remains accessible and secure." - ), - descriptionString: - "Our infrastructure's 99.99% uptime, combined with our automatic update system, ensures your site remains accessible and secure.", // Temporary string for non-English locales. Remove once we have translations. - }, - 'effortless-customization': { - title: translate( 'Effortless Customization' ), - titleString: 'Effortless Customization', - description: translate( - 'Our tools and options let you easily design a website to meet your needs, whether you’re a beginner or an expert.' - ), - descriptionString: - 'Our tools and options let you easily design a website to meet your needs, whether you’re a beginner or an expert.', - }, - 'blazing-fast-speed': { - title: translate( 'Blazing Fast Page Speed' ), - titleString: 'Blazing Fast Page Speed', - description: translate( - 'Our global CDN with 28+ locations delivers lightning-fast load times for a seamless visitor experience.' - ), - descriptionString: - 'Our global CDN with 28+ locations delivers lightning-fast load times for a seamless visitor experience.', - }, - }; + let hostingDetailItems; - const hasTranslationsForAllItems = Object.values( hostingDetailItems ).every( - ( item ) => hasEnTranslation( item.titleString ) && hasEnTranslation( item.descriptionString ) - ); + if ( isMigrationExperimentEnabled ) { + hostingDetailItems = { + 'blazing-fast-speed': { + icon: next, + description: translate( + 'Blazing fast speeds with lightning-fast load times for a seamless experience.' + ), + }, + 'unmatched-uptime': { + icon: published, + description: translate( + 'Unmatched reliability with 99.999% uptime and unmetered traffic.' + ), + }, + security: { + icon: shield, + description: translate( 'Round-the-clock security monitoring and DDoS protection.' ), + }, + }; + } else { + hostingDetailItems = { + 'unmatched-uptime': { + title: translate( 'Unmatched Reliability and Uptime' ), + description: translate( + "Our infrastructure's 99.99% uptime, combined with our automatic update system, ensures your site remains accessible and secure." + ), + }, + 'effortless-customization': { + title: translate( 'Effortless Customization' ), + description: translate( + 'Our tools and options let you easily design a website to meet your needs, whether you’re a beginner or an expert.' + ), + }, + 'blazing-fast-speed': { + title: translate( 'Blazing Fast Page Speed' ), + description: translate( + 'Our global CDN with 28+ locations delivers lightning-fast load times for a seamless visitor experience.' + ), + }, + }; + } return (
- { titleInUse } - { subtitleInUse } + { translate( 'Let’s find your site' ) } + + { translate( + "Drop your current site address below to get started. In the next step, we'll measure your site's performance and confirm its eligibility for migration." + ) } +
= ( { onComplete, onSkip, hideImporterListLin 'Or ' ) } hideImporterListLink={ hideImporterListLink } - { ...nextLabelProp } + nextLabelText={ translate( 'Check my site' ) } />
- { hasTranslationsForAllItems && ( + { isMigrationExperimentEnabled ? ( + + ) : ( ) }
diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/style.scss b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/style.scss index d8adba1fd2e85..c1c9df5f98a15 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/style.scss +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/style.scss @@ -124,3 +124,49 @@ } } } + +.import__site-identify-hosting-details-experiment { + margin: 40px auto 0 auto; + max-width: 350px; + + &-title { + color: var(--studio-gray-100); + font-size: 1.25rem; + font-weight: 500; + margin-bottom: 0.5rem; + text-align: center; + } + + &-list { + background-color: #f6f7f7; + font-size: 0.75rem; + list-style: none; + margin: 0; + padding: 2rem; + + &-item { + display: flex; + gap: 0.5rem; + margin-bottom: 1rem; + + &:last-child { + margin-bottom: 0; + } + } + } + + &-icon { + background-color: #dcdcde; + border: 2px solid #dcdcde; + border-radius: 4px; + display: flex; + fill: var(--studio-gray-70); + flex: 0 0 24px; + padding: 4px; + } + + &-description { + color: var(--studio-black); + line-height: 1.66666667; + } +} diff --git a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/test/index.tsx b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/test/index.tsx index 8a84a63ce9257..b7701dcd0f0d8 100644 --- a/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/test/index.tsx +++ b/client/landing/stepper/declarative-flow/internals/steps-repository/site-migration-identify/test/index.tsx @@ -1,6 +1,7 @@ /** * @jest-environment jsdom */ +import config, { isEnabled } from '@automattic/calypso-config'; import { screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import nock from 'nock'; @@ -39,11 +40,23 @@ const API_RESPONSE_WITH_OTHER_PLATFORM: UrlData = { }; const MOCK_WORDPRESS_SITE_SLUG = 'test-example.wordpress.com'; - const getInput = () => screen.getByLabelText( /Enter your site address/ ); +const isMigrationExperimentEnabled = isEnabled( 'migration-flow/experiment' ); + +const restoreIsMigrationExperimentEnabled = () => { + if ( isMigrationExperimentEnabled ) { + config.enable( 'migration-flow/experiment' ); + } else { + config.disable( 'migration-flow/experiment' ); + } +}; + describe( 'SiteMigrationIdentify', () => { beforeAll( () => nock.disableNetConnect() ); + afterEach( () => { + restoreIsMigrationExperimentEnabled(); + } ); it( 'continues the flow and saves the migration domain when the platform is wordpress', async () => { useSiteSlug.mockReturnValue( MOCK_WORDPRESS_SITE_SLUG ); @@ -156,6 +169,8 @@ describe( 'SiteMigrationIdentify', () => { } ); it( 'shows why host with us points', async () => { + config.disable( 'migration-flow/experiment' ); + const submit = jest.fn(); render( { navigation: { submit } } );