Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental UI for site identification step in the migration flow #97072

Merged
merged 5 commits into from
Dec 10, 2024
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
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
Loading