From 8377bd8410b6d05fb1a6f1e35464f61cf7ca67e0 Mon Sep 17 00:00:00 2001 From: Sodbileg Gansukh Date: Thu, 16 Nov 2023 19:26:25 +0800 Subject: [PATCH] Added Breadcrumbs toolbar option to PreviewModal in AdminX (#19016) no issues - currently there are urls and tabs as a toolbar option for the preview modal - as part of adding offers to AdminX, we needed a breadcrumbs option for navigating between list and create/edit screens - previewToolbarBreadcrumbs is used for passing an array with the type BreadcrumbItem - onBreadcrumbsBack is used for passing a function to be called when the back button of the breadcrumbs is clicked --- .../src/global/modal/PreviewModal.stories.tsx | 8 +++++ .../src/global/modal/PreviewModal.tsx | 17 ++++++++- .../settings/growth/offers/AddOfferModal.tsx | 9 ++++- .../settings/growth/offers/EditOfferModal.tsx | 6 ++++ .../settings/growth/offers/OfferSuccess.tsx | 35 ++++++++++++++++++- 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/apps/admin-x-design-system/src/global/modal/PreviewModal.stories.tsx b/apps/admin-x-design-system/src/global/modal/PreviewModal.stories.tsx index 5ba3a773a7..6f2c41718a 100644 --- a/apps/admin-x-design-system/src/global/modal/PreviewModal.stories.tsx +++ b/apps/admin-x-design-system/src/global/modal/PreviewModal.stories.tsx @@ -96,3 +96,11 @@ export const FullBleed: Story = { size: 'bleed' } }; + +export const BreadcrumbsToolbar: Story = { + args: { + ...Default.args, + previewToolbarTabs: undefined, + previewToolbarBreadcrumbs: [{label: 'Previous', onClick: () => {}}, {label: 'Current'}] + } +}; diff --git a/apps/admin-x-design-system/src/global/modal/PreviewModal.tsx b/apps/admin-x-design-system/src/global/modal/PreviewModal.tsx index ec8dd1bff0..4c68a4fa40 100644 --- a/apps/admin-x-design-system/src/global/modal/PreviewModal.tsx +++ b/apps/admin-x-design-system/src/global/modal/PreviewModal.tsx @@ -4,6 +4,7 @@ import React, {useEffect, useState} from 'react'; import useGlobalDirtyState from '../../hooks/useGlobalDirtyState'; import {confirmIfDirty} from '../../utils/modals'; import {ButtonColor, ButtonProps} from '../Button'; +import Breadcrumbs, {BreadcrumbItem} from '../Breadcrumbs'; import ButtonGroup from '../ButtonGroup'; import Heading, {HeadingLevel} from '../Heading'; import Icon from '../Icon'; @@ -33,6 +34,7 @@ export interface PreviewModalProps { deviceSelector?: boolean; siteLink?: string; previewToolbarURLs?: SelectOption[]; + previewToolbarBreadcrumbs?: BreadcrumbItem[]; previewBgColor?: 'grey' | 'white' | 'greygradient'; selectedURL?: string; previewToolbarTabs?: Tab[]; @@ -49,6 +51,7 @@ export interface PreviewModalProps { onSelectURL?: (url: string) => void; onSelectDesktopView?: () => void; onSelectMobileView?: () => void; + onBreadcrumbsBack?: () => void; } export const PreviewModalContent: React.FC = ({ @@ -73,6 +76,7 @@ export const PreviewModalContent: React.FC = ({ previewBgColor = 'grey', selectedURL, previewToolbarTabs, + previewToolbarBreadcrumbs, buttonsDisabled, sidebarButtons, sidebarHeader, @@ -85,7 +89,8 @@ export const PreviewModalContent: React.FC = ({ afterClose, onSelectURL, onSelectDesktopView, - onSelectMobileView + onSelectMobileView, + onBreadcrumbsBack }) => { const modal = useModal(); const {setGlobalDirtyState} = useGlobalDirtyState(); @@ -145,6 +150,16 @@ export const PreviewModalContent: React.FC = ({ width='wide' onTabChange={onSelectURL!} />; + } else if (previewToolbarBreadcrumbs) { + toolbarLeft = ; } const selectedIconColorClass = 'text-black dark:text-green'; diff --git a/apps/admin-x-settings/src/components/settings/growth/offers/AddOfferModal.tsx b/apps/admin-x-settings/src/components/settings/growth/offers/AddOfferModal.tsx index f97f8379a2..201298b130 100644 --- a/apps/admin-x-settings/src/components/settings/growth/offers/AddOfferModal.tsx +++ b/apps/admin-x-settings/src/components/settings/growth/offers/AddOfferModal.tsx @@ -433,9 +433,15 @@ const AddOfferModal = () => { okColor={okProps.color} okLabel='Publish' preview={iframe} + previewToolbarBreadcrumbs={[{label: 'Offers', onClick: () => { + updateRoute('offers/edit'); + }}, {label: 'New offer'}]} sidebar={sidebar} size='lg' title='Offer' + onBreadcrumbsBack={() => { + updateRoute('offers/edit'); + }} onCancel={cancelAddOffer} onOk={async () => { if (!(await handleSave({fakeWhenUnchanged: true}))) { @@ -444,7 +450,8 @@ const AddOfferModal = () => { message: 'Can\'t save offer, please double check that you\'ve filled all mandatory fields.' }); } - }} />; + }} + />; }; export default AddOfferModal; diff --git a/apps/admin-x-settings/src/components/settings/growth/offers/EditOfferModal.tsx b/apps/admin-x-settings/src/components/settings/growth/offers/EditOfferModal.tsx index aa9eabbfea..d74ae14972 100644 --- a/apps/admin-x-settings/src/components/settings/growth/offers/EditOfferModal.tsx +++ b/apps/admin-x-settings/src/components/settings/growth/offers/EditOfferModal.tsx @@ -269,10 +269,16 @@ const EditOfferModal: React.FC<{id: string}> = ({id}) => { okColor={okProps.color} okLabel={okProps.label || 'Save'} preview={iframe} + previewToolbarBreadcrumbs={[{label: 'Offers', onClick: () => { + updateRoute('offers/edit'); + }}, {label: offerById[0]?.name || ''}]} sidebar={sidebar} size='lg' testId='offer-update-modal' title='Offer' + onBreadcrumbsBack={() => { + updateRoute('offers/edit'); + }} onCancel={() => { updateRoute('offers/edit'); }} diff --git a/apps/admin-x-settings/src/components/settings/growth/offers/OfferSuccess.tsx b/apps/admin-x-settings/src/components/settings/growth/offers/OfferSuccess.tsx index 306719ec38..4a889f0cb0 100644 --- a/apps/admin-x-settings/src/components/settings/growth/offers/OfferSuccess.tsx +++ b/apps/admin-x-settings/src/components/settings/growth/offers/OfferSuccess.tsx @@ -1,8 +1,11 @@ +import {Breadcrumbs} from '@tryghost/admin-x-design-system'; import {Button} from '@tryghost/admin-x-design-system'; import {Icon} from '@tryghost/admin-x-design-system'; import {Modal} from '@tryghost/admin-x-design-system'; import {Offer, useBrowseOffersById} from '@tryghost/admin-x-framework/api/offers'; +import {currencyToDecimal} from '../../../../utils/currency'; import {getHomepageUrl} from '@tryghost/admin-x-framework/api/site'; +import {numberWithCommas} from '../../../../utils/helpers'; import {useEffect, useState} from 'react'; import {useGlobalData} from '../../../providers/GlobalDataProvider'; import {useRouting} from '@tryghost/admin-x-framework/routing'; @@ -39,7 +42,22 @@ const OfferSuccess: React.FC<{id: string}> = ({id}) => { }; const handleTwitter = () => { - window.open(`https://twitter.com/intent/tweet?url=${encodeURI(offerLink)}&text=${encodeURIComponent(offer?.name || '')}`, '_blank'); + let tweetText = ''; + + switch (offer?.type) { + case 'percent': + tweetText = offer?.amount + '% discount'; + break; + case 'fixed': + tweetText = numberWithCommas(currencyToDecimal(offer?.amount)) + ' ' + offer?.currency + ' discount'; + break; + case 'trial': + tweetText = offer?.amount + ' days free trial'; + break; + default: + break; + }; + window.open(`https://twitter.com/intent/tweet?url=${encodeURI(offerLink)}&text=${encodeURIComponent(offer?.name || '')} — Check out ${encodeURIComponent(tweetText)} on:`, '_blank'); }; const handleFacebook = () => { @@ -61,6 +79,21 @@ const OfferSuccess: React.FC<{id: string}> = ({id}) => { topRightContent='close' >
+
+ { + updateRoute('offers/edit'); + }}, {label: offer?.name || ''}]} + separatorClassName='hidden md:!block md:!visible' + backIcon + onBack={() => { + updateRoute('offers/edit'); + }} + /> +

Your new offer is live!

You can share the link anywhere. In your newsletter, social media, a podcast, or in-person. It all just works.