Skip to content

Commit

Permalink
Add experimental UI for site identification step in the migration flow (
Browse files Browse the repository at this point in the history
#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.
  • Loading branch information
donnapep authored Dec 10, 2024
1 parent 55ba554 commit 8a2935b
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 (
<div className="import__site-identify-hosting-details-experiment">
<p className="import__site-identify-hosting-details-experiment-title">
{ translate( 'Why should you host with us?' ) }
</p>
<ul className="import__site-identify-hosting-details-experiment-list">
{ items.map( ( item, index ) => (
<li key={ index } className="import__site-identify-hosting-details-experiment-list-item">
<Icon
className="import__site-identify-hosting-details-experiment-icon"
icon={ item.icon }
size={ 24 }
/>
<p className="import__site-identify-hosting-details-experiment-description">
{ item.description }
</p>
</li>
) ) }
</ul>
</div>
);
};

const HostingDetails: FC< HostingDetailsProps > = ( { items } ) => {
const translate = useTranslate();

Expand Down Expand Up @@ -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,
Expand All @@ -90,46 +106,59 @@ export const Analyzer: FC< Props > = ( { onComplete, onSkip, hideImporterListLin
return <ScanningStep />;
}

// 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 (
<div className="import__capture-wrapper">
<div className="import__heading import__heading-center">
<Title>{ titleInUse }</Title>
<SubTitle>{ subtitleInUse }</SubTitle>
<Title>{ translate( 'Let’s find your site' ) }</Title>
<SubTitle>
{ 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."
) }
</SubTitle>
</div>
<div className="import__capture-container">
<CaptureInput
Expand All @@ -144,10 +173,12 @@ export const Analyzer: FC< Props > = ( { onComplete, onSkip, hideImporterListLin
'Or <button>pick your current platform from a list</button>'
) }
hideImporterListLink={ hideImporterListLink }
{ ...nextLabelProp }
nextLabelText={ translate( 'Check my site' ) }
/>
</div>
{ hasTranslationsForAllItems && (
{ isMigrationExperimentEnabled ? (
<HostingDetailsWithIcons items={ Object.values( hostingDetailItems ) } />
) : (
<HostingDetails items={ Object.values( hostingDetailItems ) } />
) }
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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 } } );

Expand Down

0 comments on commit 8a2935b

Please sign in to comment.