Skip to content
Open
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
30 changes: 21 additions & 9 deletions assets/js/components/Banner/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@ import LearnMoreLink from './LearnMoreLink';
import Title from './Title';
import TitleIcon from './TitleIcon';

function getSVGDataByBreakpoint( breakpoint, svg ) {
const isMobile = breakpoint === BREAKPOINT_SMALL;
const isTablet = breakpoint === BREAKPOINT_TABLET;

if ( isTablet && svg?.tablet ) {
return svg.tablet;
}

if ( ( isMobile || isTablet ) && svg?.mobile ) {
return svg.mobile;
}

if ( ! isMobile && ! isTablet && svg?.desktop ) {
return svg.desktop;
}

return null;
}

const Banner = forwardRef(
(
{
Expand All @@ -62,15 +81,7 @@ const Banner = forwardRef(
ref
) => {
const breakpoint = useBreakpoint();
const isMobileOrTablet =
breakpoint === BREAKPOINT_SMALL || breakpoint === BREAKPOINT_TABLET;

let SVGData = null;
if ( isMobileOrTablet && svg?.mobile ) {
SVGData = svg.mobile;
} else if ( ! isMobileOrTablet && svg?.desktop ) {
SVGData = svg.desktop;
}
const SVGData = getSVGDataByBreakpoint( breakpoint, svg );

const svgMode = svg?.verticalPosition ? svg.verticalPosition : 'center';

Expand Down Expand Up @@ -139,6 +150,7 @@ Banner.propTypes = {
svg: PropTypes.shape( {
desktop: PropTypes.elementType,
mobile: PropTypes.elementType,
tablet: PropTypes.elementType,
verticalPosition: PropTypes.oneOf( [ 'top', 'center', 'bottom' ] ),
} ),
footer: PropTypes.node,
Expand Down
56 changes: 56 additions & 0 deletions assets/js/components/Banner/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ import { createElement } from '@wordpress/element';
import { render } from '@tests/js/test-utils';
import Banner from './index';

let mockBreakpoint = 'desktop';

jest.mock( '@/js/hooks/useBreakpoint', () => {
const actual = jest.requireActual( '@/js/hooks/useBreakpoint' );

return {
...actual,
useBreakpoint: () => mockBreakpoint,
};
} );

describe( 'Banner', () => {
describe( 'description prop', () => {
it( 'renders string description correctly', () => {
Expand Down Expand Up @@ -211,4 +222,49 @@ describe( 'Banner', () => {
expect( container.firstChild ).toHaveClass( 'custom-class' );
} );
} );

describe( 'svg prop', () => {
beforeEach( () => {
mockBreakpoint = 'desktop';
} );

it( 'renders tablet SVG at tablet breakpoint when provided', () => {
mockBreakpoint = 'tablet';

const { container } = render(
<Banner
title="Test Banner"
description="Test description"
svg={ {
desktop: 'desktop.svg',
mobile: 'mobile.svg',
tablet: 'tablet.svg',
} }
/>
);

expect(
container.querySelector( '.googlesitekit-banner__svg-wrapper' )
).toHaveStyle( 'background-image: url(tablet.svg)' );
} );

it( 'falls back to mobile SVG at tablet breakpoint when tablet SVG is not provided', () => {
mockBreakpoint = 'tablet';

const { container } = render(
<Banner
title="Test Banner"
description="Test description"
svg={ {
desktop: 'desktop.svg',
mobile: 'mobile.svg',
} }
/>
);

expect(
container.querySelector( '.googlesitekit-banner__svg-wrapper' )
).toHaveStyle( 'background-image: url(mobile.svg)' );
} );
} );
} );
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ SetupCTA.propTypes = {
svg: PropTypes.shape( {
desktop: PropTypes.elementType,
mobile: PropTypes.elementType,
tablet: PropTypes.elementType,
verticalPosition: PropTypes.oneOf( [ 'top', 'center', 'bottom' ] ),
} ),
footer: PropTypes.node,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,42 @@ import PropTypes from 'prop-types';
/**
* WordPress dependencies
*/
import { useCallback, useEffect, useState } from '@wordpress/element';
import {
createInterpolateElement,
useCallback,
useEffect,
useState,
} from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { addQueryArgs } from '@wordpress/url';

/**
* Internal dependencies
*/
import { useDispatch, useSelect } from 'googlesitekit-data';
import { useShowTooltip } from '@/js/components/AdminScreenTooltip';
import useRetriableNotificationDismissButtonLabel from '@/js/components/notifications/useRetriableNotificationDismissButtonLabel';
import { CORE_LOCATION } from '@/js/googlesitekit/datastore/location/constants';
import { CORE_SITE } from '@/js/googlesitekit/datastore/site/constants';
import { CORE_USER } from '@/js/googlesitekit/datastore/user/constants';
import { CORE_MODULES } from '@/js/googlesitekit/modules/datastore/constants';
import SetupCTA from '@/js/googlesitekit/notifications/components/layout/SetupCTA';
import { CORE_NOTIFICATIONS } from '@/js/googlesitekit/notifications/datastore/constants';
import useActivateModuleCallback from '@/js/hooks/useActivateModuleCallback';
import { useFeature } from '@/js/hooks/useFeature';
import { MODULE_SLUG_READER_REVENUE_MANAGER } from '@/js/modules/reader-revenue-manager/constants';
import { WEEK_IN_SECONDS } from '@/js/util';
import BannerExpressSetupSVGMobile from '@/svg/graphics/banner-rrm-express-setup-cta-mobile.svg?url';
import BannerExpressSetupSVGTablet from '@/svg/graphics/banner-rrm-express-setup-cta-tablet.svg?url';
import BannerExpressSetupSVGDesktop from '@/svg/graphics/banner-rrm-express-setup-cta.svg?url';
import BannerSVGMobile from '@/svg/graphics/banner-rrm-setup-cta-mobile.svg?url';
import BannerSVGDesktop from '@/svg/graphics/banner-rrm-setup-cta.svg?url';

export default function ReaderRevenueManagerSetupCTABanner( {
id,
Notification,
} ) {
const rrmExpressSetupEnabled = useFeature( 'rrmExpressSetup' );
const [ isSaving, setIsSaving ] = useState( false );

const onSetupActivate = useActivateModuleCallback(
Expand All @@ -68,6 +82,16 @@ export default function ReaderRevenueManagerSetupCTABanner( {
const showTooltip = useShowTooltip( tooltipSettings );

const { triggerSurvey } = useDispatch( CORE_USER );
const { navigateTo } = useDispatch( CORE_LOCATION );
const { activateModule } = useDispatch( CORE_MODULES );
const { setInternalServerError } = useDispatch( CORE_SITE );

const existingSetupURL = useSelect( ( select ) =>
select( CORE_SITE ).getAdminURL( 'googlesitekit-dashboard', {
slug: MODULE_SLUG_READER_REVENUE_MANAGER,
reAuth: true,
} )
);

const isDismissalFinal = useSelect( ( select ) =>
select( CORE_NOTIFICATIONS ).isNotificationDismissalFinal( id )
Expand All @@ -80,24 +104,77 @@ export default function ReaderRevenueManagerSetupCTABanner( {
triggerSurvey( 'view_reader_revenue_manager_cta' );
}, [ triggerSurvey ] );

const onExpressSetupCallback = useCallback( () => {
async function navigateToExpressSetup() {
setIsSaving( true );

const { error, response } = await activateModule(
MODULE_SLUG_READER_REVENUE_MANAGER
);

if ( ! error ) {
navigateTo(
addQueryArgs( response.moduleReauthURL, {
expressSetup: true,
cta: 'newsletter',
} )
);
} else {
setInternalServerError( {
id: `${ MODULE_SLUG_READER_REVENUE_MANAGER }-setup-error`,
description: error.message,
} );
setIsSaving( false );
}
}

navigateToExpressSetup();
}, [ activateModule, navigateTo, setInternalServerError ] );

const title = rrmExpressSetupEnabled
? __( 'Turn casual visitors into loyal readers', 'google-site-kit' )
: __(
'Grow your revenue and deepen reader engagement',
'google-site-kit'
);

const description = rrmExpressSetupEnabled
? createInterpolateElement(
__(
'Add a simple signup form to your site to start building your email subscriber list, powered by Reader Revenue Manager. Want to do more? <link>Explore other features</link> like reader contributions, paywalls, or surveys.',
'google-site-kit'
),
{
link: (
// eslint-disable-next-line jsx-a11y/anchor-has-content
<a
href={ existingSetupURL ?? '' }
className="googlesitekit-banner__description_link"
/>
),
}
)
: __(
'Turn casual visitors into loyal readers and earn more from your content with paywalls, contributions, surveys, newsletter sign-ups and reader insight tools.',
'google-site-kit'
);

return (
<Notification>
<SetupCTA
notificationID={ id }
title={ __(
'Grow your revenue and deepen reader engagement',
'google-site-kit'
) }
description={ __(
'Turn casual visitors into loyal readers and earn more from your content with paywalls, contributions, surveys, newsletter sign-ups and reader insight tools.',
'google-site-kit'
) }
title={ title }
description={ description }
ctaButton={ {
label: __(
'Set up Reader Revenue Manager',
'google-site-kit'
),
onClick: onSetupCallback,
label: rrmExpressSetupEnabled
? __( 'Set up a sign-up form', 'google-site-kit' )
: __(
'Set up Reader Revenue Manager',
'google-site-kit'
),
onClick: rrmExpressSetupEnabled
? onExpressSetupCallback
: onSetupCallback,
inProgress: isSaving,
dismissOnClick: true,
dismissOptions: {
Expand All @@ -115,13 +192,24 @@ export default function ReaderRevenueManagerSetupCTABanner( {
disabled: isSaving,
} }
svg={ {
desktop: BannerSVGDesktop,
mobile: BannerSVGMobile,
desktop: rrmExpressSetupEnabled
? BannerExpressSetupSVGDesktop
: BannerSVGDesktop,
mobile: rrmExpressSetupEnabled
? BannerExpressSetupSVGMobile
: BannerSVGMobile,
tablet: rrmExpressSetupEnabled
? BannerExpressSetupSVGTablet
: undefined,
verticalPosition: 'center',
} }
learnMoreLink={ {
href: 'https://readerrevenue.withgoogle.com',
} }
learnMoreLink={
rrmExpressSetupEnabled
? undefined
: {
href: 'https://readerrevenue.withgoogle.com',
}
}
/>
</Notification>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export const Default = Template.bind( {} );
Default.storyName = 'Default';
Default.scenario = {};

export const ExpressSetup = Template.bind( {} );
ExpressSetup.storyName = 'Express Setup';
ExpressSetup.parameters = {
features: [ 'rrmExpressSetup' ],
};
ExpressSetup.scenario = {};

export default {
title: 'Modules/ReaderRevenueManager/Components/Dashboard/ReaderRevenueManagerSetupCTABanner',
decorators: [
Expand All @@ -62,7 +69,7 @@ export default {
.dispatch( CORE_USER )
.finishResolution( 'getDismissedPrompts', [] );

fetchMock.postOnce(
fetchMock.post(
new RegExp(
'^/google-site-kit/v1/core/user/data/dismiss-prompt'
),
Expand All @@ -74,7 +81,8 @@ export default {
},
},
status: 200,
}
},
{ overwriteRoutes: true }
);
}

Expand Down
Loading
Loading