diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.stories.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.stories.tsx index 62e66f6260..9dfdf05fa9 100644 --- a/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.stories.tsx +++ b/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.stories.tsx @@ -135,4 +135,16 @@ export const StickyFooter: Story = { title: 'Sticky footer', children: longContent } +}; + +export const Dirty: Story = { + args: { + size: 'md', + dirty: true, + onOk: () => { + alert('Clicked OK!'); + }, + title: 'Dirty modal', + children:

Simulates if there were unsaved changes of a form. Click on Cancel

+ } }; \ No newline at end of file diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx index 2a55ad8845..3a55e7e9af 100644 --- a/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx +++ b/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx @@ -1,10 +1,11 @@ import Button, {IButton} from '../Button'; import ButtonGroup from '../ButtonGroup'; +import ConfirmationModal from './ConfirmationModal'; import Heading from '../Heading'; +import NiceModal, {useModal} from '@ebay/nice-modal-react'; import React from 'react'; import StickyFooter from '../StickyFooter'; import clsx from 'clsx'; -import {useModal} from '@ebay/nice-modal-react'; export type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'bleed' | number; @@ -31,6 +32,9 @@ export interface ModalProps { backDropClick?: boolean; stickyFooter?: boolean; scrolling?: boolean; + dirty?: boolean; + closeConfrimationTitle?: string; + closeConfirmationPrompt?: React.ReactNode; } const Modal: React.FC = ({ @@ -50,19 +54,45 @@ const Modal: React.FC = ({ backDrop = true, backDropClick = true, stickyFooter = false, - scrolling = true + scrolling = true, + dirty = false, + closeConfrimationTitle = 'Are you sure you want to leave this page?', + closeConfirmationPrompt = ( + <> +

{`Hey there! It looks like you didn't save the changes you made.`}

+

Save before you go!

+ + ) }) => { const modal = useModal(); let buttons: IButton[] = []; + const removeModal = () => { + if (!dirty) { + modal.remove(); + } else { + NiceModal.show(ConfirmationModal, { + title: closeConfrimationTitle, + prompt: closeConfirmationPrompt, + okLabel: 'Leave', + cancelLabel: 'Stay', + okColor: 'red', + onOk: (confirmationModal) => { + modal.remove(); + confirmationModal?.remove(); + } + }); + } + }; + if (!footer) { if (cancelLabel) { buttons.push({ key: 'cancel-modal', label: cancelLabel, onClick: (onCancel ? onCancel : () => { - modal.remove(); + removeModal(); }), disabled: buttonsDisabled }); @@ -146,7 +176,7 @@ const Modal: React.FC = ({ const handleBackdropClick = (e: React.MouseEvent) => { if (e.target === e.currentTarget && backDropClick) { - modal.remove(); + removeModal(); } }; diff --git a/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx b/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx index 6e3eb1b36b..b1c5817871 100644 --- a/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx +++ b/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx @@ -67,7 +67,7 @@ async function handleThemeUpload({ prompt: ( <> {uploadedTheme.name} uploaded successfully. - Do you want to activate it now ? + Do you want to activate it now? ), okLabel: 'Activate',