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:
parent
17f8844134
commit
8377bd8410
5 changed files with 72 additions and 3 deletions
|
@ -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'}]
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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');
|
||||
}}
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue