Skip to content

Commit

Permalink
Domains: Add empty state to All Domains page (Automattic#78841)
Browse files Browse the repository at this point in the history
* Extract empty state component

* Render empty state if no domains at all

* Scope empty state to All Domains

* Remove icon from CTA

* Rewrite CTA targets
  • Loading branch information
zaguiini authored Jun 30, 2023
1 parent 9519dd8 commit 52cae38
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 82 deletions.
63 changes: 46 additions & 17 deletions client/my-sites/domains/domain-management/list/all-domains.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import BulkEditContactInfo from './bulk-edit-contact-info';
import DomainOnlyUpsellCarousel from './domain-only-upsell-carousel';
import DomainsTable from './domains-table';
import DomainsTableFilterButton from './domains-table-filter-button';
import { EmptyDomainsListCardSkeleton } from './empty-domains-list-card-skeleton';
import { filterDomainsByOwner, filterDomainOnlyDomains } from './helpers';
import ListItemPlaceholder from './item-placeholder';
import {
Expand Down Expand Up @@ -245,6 +246,19 @@ class AllDomains extends Component {
} );
};

getSelectedFilter = () => {
const { context } = this.props;
return context?.query?.filter || 'all-domains';
};

getDomainsList = ( selectedFilter = this.getSelectedFilter() ) => {
const { sites } = this.props;

return selectedFilter === 'domain-only'
? filterDomainOnlyDomains( this.mergeFilteredDomainsWithDomainsDetails(), sites )
: filterDomainsByOwner( this.mergeFilteredDomainsWithDomainsDetails(), selectedFilter );
};

renderDomainsList() {
if ( this.isLoading() ) {
return Array.from( { length: 3 } ).map( ( _, n ) => (
Expand All @@ -256,7 +270,6 @@ class AllDomains extends Component {
purchases,
sites,
currentRoute,
context,
requestingSiteDomains,
hasLoadedUserPurchases,
isContactEmailEditContext,
Expand All @@ -266,12 +279,22 @@ class AllDomains extends Component {

const { isSavingContactInfo } = this.state;

const selectedFilter = context?.query?.filter || 'all-domains';
const domains = this.getDomainsList();

const domains =
selectedFilter === 'domain-only'
? filterDomainOnlyDomains( this.mergeFilteredDomainsWithDomainsDetails(), sites )
: filterDomainsByOwner( this.mergeFilteredDomainsWithDomainsDetails(), selectedFilter );
if ( domains.length === 0 && this.getSelectedFilter() === 'all-domains' ) {
return (
<EmptyDomainsListCardSkeleton
title={ translate( 'All Domains' ) }
line={ translate(
'Here you will be able to manage all the domains you own on WordPress.com. Start by adding some:'
) }
action={ translate( 'Add a domain' ) }
actionURL="/domains/add"
secondaryAction={ translate( 'Transfer a domain' ) }
secondaryActionURL="/start/domain-transfer/domains"
/>
);
}

const domainsTableColumns = [
{
Expand Down Expand Up @@ -668,17 +691,23 @@ class AllDomains extends Component {
),
};

const buttons = [
this.maybeRenderSeeAllDomainsLink(),
this.renderDomainTableFilterButton(),
<OptionsDomainButton key="breadcrumb_button_1" specificSiteActions />,
<OptionsDomainButton key="breadcrumb_button_3" ellipsisButton borderless />,
];

const mobileButtons = [
<OptionsDomainButton key="breadcrumb_button_1" specificSiteActions />,
<OptionsDomainButton key="breadcrumb_button_3" ellipsisButton borderless />,
];
const hasNoDomains = this.getDomainsList( 'all-domains' ).length === 0;

const buttons = hasNoDomains
? []
: [
this.maybeRenderSeeAllDomainsLink(),
this.renderDomainTableFilterButton(),
<OptionsDomainButton key="breadcrumb_button_1" specificSiteActions />,
<OptionsDomainButton key="breadcrumb_button_3" ellipsisButton borderless />,
];

const mobileButtons = hasNoDomains
? []
: [
<OptionsDomainButton key="breadcrumb_button_1" specificSiteActions />,
<OptionsDomainButton key="breadcrumb_button_3" ellipsisButton borderless />,
];

return <DomainHeader items={ [ item ] } buttons={ buttons } mobileButtons={ mobileButtons } />;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Card, Button } from '@automattic/components';
import classNames from 'classnames';
import customerHomeIllustrationTaskFindDomain from 'calypso/assets/images/domains/free-domain.svg';
import TrackComponentView from 'calypso/lib/analytics/track-component-view';
import { useDispatch } from 'calypso/state';
import { recordTracksEvent } from 'calypso/state/analytics/actions';

interface EmptyDomainsListCardSkeletonProps {
className?: string;
isCompact?: boolean;
title?: string;
line?: string;
actionURL: string;
contentType: string;
action: string;
secondaryActionURL: string;
secondaryAction: string;
}

export const EmptyDomainsListCardSkeleton = ( {
className,
isCompact,
title,
line,
actionURL,
contentType,
action,
secondaryActionURL,
secondaryAction,
}: EmptyDomainsListCardSkeletonProps ) => {
const dispatch = useDispatch();

const getActionClickHandler =
( type: string, buttonURL: string, sourceCardType: string ) => () => {
dispatch(
recordTracksEvent( 'calypso_empty_domain_list_card_action', {
button_type: type,
button_url: buttonURL,
source_card_type: sourceCardType,
} )
);
};

const illustration = customerHomeIllustrationTaskFindDomain && (
<img src={ customerHomeIllustrationTaskFindDomain } alt="" width={ 150 } />
);

return (
<Card className={ classNames( 'empty-domains-list-card', className ) }>
<div
className={ classNames( 'empty-domains-list-card__wrapper', {
'is-compact': isCompact,
'has-title-only': title && ! line,
} ) }
>
<div className="empty-domains-list-card__illustration">{ illustration }</div>
<div className="empty-domains-list-card__content">
<div className="empty-domains-list-card__text">
{ title ? <h2>{ title }</h2> : null }
{ line ? <h3>{ line }</h3> : null }
</div>
<div className="empty-domains-list-card__actions">
<Button
primary
onClick={ getActionClickHandler( 'primary', actionURL, contentType ) }
href={ actionURL }
>
{ action }
</Button>
<Button
onClick={ getActionClickHandler( 'secondary', secondaryActionURL, contentType ) }
href={ secondaryActionURL }
>
{ secondaryAction }
</Button>
</div>
</div>
</div>
<TrackComponentView
eventName="calypso_get_your_domain_empty_impression"
eventProperties={ { content_type: contentType } }
/>
</Card>
);
};
Original file line number Diff line number Diff line change
@@ -1,33 +1,15 @@
import { isFreePlan } from '@automattic/calypso-products';
import { Card, Button } from '@automattic/components';
import classNames from 'classnames';
import { useTranslate } from 'i18n-calypso';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import customerHomeIllustrationTaskFindDomain from 'calypso/assets/images/domains/free-domain.svg';
import TrackComponentView from 'calypso/lib/analytics/track-component-view';
import { domainAddNew, domainUseMyDomain } from 'calypso/my-sites/domains/paths';
import { recordTracksEvent } from 'calypso/state/analytics/actions';
import { EmptyDomainsListCardSkeleton } from './empty-domains-list-card-skeleton';

import './style.scss';

function EmptyDomainsListCard( {
selectedSite,
hasDomainCredit,
isCompact,
dispatchRecordTracksEvent,
hasNonWpcomDomains,
} ) {
function EmptyDomainsListCard( { selectedSite, hasDomainCredit, isCompact, hasNonWpcomDomains } ) {
const translate = useTranslate();

const getActionClickHandler = ( type, buttonURL, sourceCardType ) => () => {
dispatchRecordTracksEvent( 'calypso_empty_domain_list_card_action', {
button_type: type,
button_url: buttonURL,
source_card_type: sourceCardType,
} );
};

const siteHasPaidPlan =
selectedSite?.plan?.product_slug && ! isFreePlan( selectedSite.plan.product_slug );

Expand Down Expand Up @@ -66,50 +48,22 @@ function EmptyDomainsListCard( {
contentType = 'free_domain_credit';
}

const illustration = customerHomeIllustrationTaskFindDomain && (
<img src={ customerHomeIllustrationTaskFindDomain } alt="" width={ 150 } />
);
const className = classNames( {
'has-non-wpcom-domains': hasNonWpcomDomains,
} );

return (
<Card
className={ classNames( 'empty-domains-list-card', {
'has-non-wpcom-domains': hasNonWpcomDomains,
} ) }
>
<div
className={ classNames( 'empty-domains-list-card__wrapper', {
'is-compact': isCompact,
'has-title-only': title && ! line,
} ) }
>
<div className="empty-domains-list-card__illustration">{ illustration }</div>
<div className="empty-domains-list-card__content">
<div className="empty-domains-list-card__text">
{ title ? <h2>{ title }</h2> : null }
{ line ? <h3>{ line }</h3> : null }
</div>
<div className="empty-domains-list-card__actions">
<Button
primary
onClick={ getActionClickHandler( 'primary', actionURL, contentType ) }
href={ actionURL }
>
{ action }
</Button>
<Button
onClick={ getActionClickHandler( 'secondary', secondaryActionURL, contentType ) }
href={ secondaryActionURL }
>
{ secondaryAction }
</Button>
</div>
</div>
</div>
<TrackComponentView
eventName="calypso_get_your_domain_empty_impression"
eventProperties={ { content_type: contentType } }
/>
</Card>
<EmptyDomainsListCardSkeleton
className={ className }
isCompact={ isCompact }
title={ title }
line={ line }
contentType={ contentType }
action={ action }
actionURL={ actionURL }
secondaryAction={ secondaryAction }
secondaryActionURL={ secondaryActionURL }
/>
);
}

Expand All @@ -122,6 +76,4 @@ EmptyDomainsListCard.propTypes = {
hasNonWpcomDomains: PropTypes.bool,
};

export default connect( null, { dispatchRecordTracksEvent: recordTracksEvent } )(
EmptyDomainsListCard
);
export default EmptyDomainsListCard;

0 comments on commit 52cae38

Please sign in to comment.