0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-20 22:42:53 -05:00

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
This commit is contained in:
Sodbileg Gansukh 2023-11-16 19:26:25 +08:00 committed by GitHub
parent 17f8844134
commit 8377bd8410
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 72 additions and 3 deletions

View file

@ -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'}]
}
};

View file

@ -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<PreviewModalProps> = ({
@ -73,6 +76,7 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
previewBgColor = 'grey',
selectedURL,
previewToolbarTabs,
previewToolbarBreadcrumbs,
buttonsDisabled,
sidebarButtons,
sidebarHeader,
@ -85,7 +89,8 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
afterClose,
onSelectURL,
onSelectDesktopView,
onSelectMobileView
onSelectMobileView,
onBreadcrumbsBack
}) => {
const modal = useModal();
const {setGlobalDirtyState} = useGlobalDirtyState();
@ -145,6 +150,16 @@ export const PreviewModalContent: React.FC<PreviewModalProps> = ({
width='wide'
onTabChange={onSelectURL!}
/>;
} else if (previewToolbarBreadcrumbs) {
toolbarLeft = <Breadcrumbs
activeItemClassName='hidden md:!block md:!visible'
containerClassName='whitespace-nowrap'
itemClassName='hidden md:!block md:!visible'
items={previewToolbarBreadcrumbs}
separatorClassName='hidden md:!block md:!visible'
backIcon
onBack={onBreadcrumbsBack}
/>;
}
const selectedIconColorClass = 'text-black dark:text-green';

View file

@ -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;

View file

@ -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');
}}

View file

@ -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'
>
<div className='-mt-6 flex h-full flex-col items-center justify-center text-center'>
<div className='absolute left-6 top-5'>
<Breadcrumbs
activeItemClassName='hidden md:!block md:!visible'
containerClassName='whitespace-nowrap'
itemClassName='hidden md:!block md:!visible'
items={[{label: 'Offers', onClick: () => {
updateRoute('offers/edit');
}}, {label: offer?.name || ''}]}
separatorClassName='hidden md:!block md:!visible'
backIcon
onBack={() => {
updateRoute('offers/edit');
}}
/>
</div>
<Icon name='tags-check' size='xl' />
<h1 className='mt-6 text-4xl'>Your new offer is live!</h1>
<p className='mt-3 max-w-[510px] text-[1.6rem]'>You can share the link anywhere. In your newsletter, social media, a podcast, or in-person. It all just works.</p>