From 19fe508ec38850fcdb0e6fe5c4b8b7c00df5c579 Mon Sep 17 00:00:00 2001 From: Etienne <45695613+etiennejouan@users.noreply.github.com> Date: Fri, 20 Jun 2025 15:20:17 +0200 Subject: [PATCH] fix confirm close dialog + add restart confirm dialog (#12761) Test: - On upload > No dialog at modal closing - On match > Confirm cancel dialog at closing (escape, click outside, cancel cross) - On match > Restart dialog at Restart Import - On validation > Confirm cancel dialog at closing (escape, click outside, cancel cross) - On import > Confirm cancel dialog at closing (escape, click outside, cancel cross) - On import > No confirm at import end closes : https://github.com/twentyhq/core-team-issues/issues/1071 --- .../SpreadSheetImportModalCloseButton.tsx | 43 +------------------ .../SpreadSheetImportModalWrapper.tsx | 3 +- .../provider/components/SpreadsheetImport.tsx | 42 +++++++++++++++++- .../MatchColumnsStep/MatchColumnsStep.tsx | 27 ++++++++++-- .../__stories__/SelectHeader.stories.tsx | 5 ++- .../ui/layout/modal/components/Modal.tsx | 4 +- 6 files changed, 75 insertions(+), 49 deletions(-) diff --git a/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalCloseButton.tsx b/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalCloseButton.tsx index 5fd5bd257..9ffcd272a 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalCloseButton.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalCloseButton.tsx @@ -1,10 +1,5 @@ import styled from '@emotion/styled'; -import { useSpreadsheetImportInitialStep } from '@/spreadsheet-import/hooks/useSpreadsheetImportInitialStep'; -import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal'; -import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager'; -import { useStepBar } from '@/ui/navigation/step-bar/hooks/useStepBar'; -import { useLingui } from '@lingui/react/macro'; import { IconX } from 'twenty-ui/display'; import { IconButton } from 'twenty-ui/input'; @@ -20,49 +15,15 @@ const StyledCloseButtonContainer = styled.div` `; type SpreadSheetImportModalCloseButtonProps = { - onClose?: () => void; + onClose: () => void; }; export const SpreadSheetImportModalCloseButton = ({ onClose, }: SpreadSheetImportModalCloseButtonProps) => { - const { initialStepState } = useSpreadsheetImportInternal(); - - const { initialStep } = useSpreadsheetImportInitialStep( - initialStepState?.type, - ); - - const { activeStep } = useStepBar({ - initialStep, - }); - - const { enqueueDialog } = useDialogManager(); - - const { t } = useLingui(); - - const handleClose = () => { - if (activeStep === -1) { - onClose?.(); - return; - } - enqueueDialog({ - title: t`Exit import flow`, - message: t`Are you sure? Your current information will not be saved.`, - buttons: [ - { title: t`Cancel` }, - { - title: t`Exit`, - onClick: onClose, - accent: 'danger', - role: 'confirm', - }, - ], - }); - }; - return ( - + ); }; diff --git a/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalWrapper.tsx b/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalWrapper.tsx index 067ef5bf3..e6352d538 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalWrapper.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/components/SpreadSheetImportModalWrapper.tsx @@ -28,7 +28,7 @@ const StyledRtlLtr = styled.div` type SpreadSheetImportModalWrapperProps = { children: React.ReactNode; modalId: string; - onClose?: () => void; + onClose: () => void; }; export const SpreadSheetImportModalWrapper = ({ @@ -44,6 +44,7 @@ export const SpreadSheetImportModalWrapper = ({ modalId={modalId} isClosable={true} onClose={onClose} + shouldCloseModalOnClickOutsideOrEscape={false} > diff --git a/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx b/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx index 83f0777a7..ef265a29e 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/provider/components/SpreadsheetImport.tsx @@ -2,8 +2,13 @@ import { ReactSpreadsheetImportContextProvider } from '@/spreadsheet-import/comp import { SpreadSheetImportModalWrapper } from '@/spreadsheet-import/components/SpreadSheetImportModalWrapper'; import { SPREADSHEET_IMPORT_MODAL_ID } from '@/spreadsheet-import/constants/SpreadsheetImportModalId'; import { SpreadsheetMaxRecordImportCapacity } from '@/spreadsheet-import/constants/SpreadsheetMaxRecordImportCapacity'; +import { useSpreadsheetImportInitialStep } from '@/spreadsheet-import/hooks/useSpreadsheetImportInitialStep'; +import { useSpreadsheetImportInternal } from '@/spreadsheet-import/hooks/useSpreadsheetImportInternal'; import { SpreadsheetImportStepperContainer } from '@/spreadsheet-import/steps/components/SpreadsheetImportStepperContainer'; import { SpreadsheetImportDialogOptions as SpreadsheetImportProps } from '@/spreadsheet-import/types'; +import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager'; +import { useStepBar } from '@/ui/navigation/step-bar/hooks/useStepBar'; +import { useLingui } from '@lingui/react/macro'; export const defaultSpreadsheetImportProps: Partial< SpreadsheetImportProps @@ -31,11 +36,46 @@ export const SpreadsheetImport = ( ...props, } as SpreadsheetImportProps; + const { enqueueDialog } = useDialogManager(); + + const { initialStepState } = useSpreadsheetImportInternal(); + + const { initialStep } = useSpreadsheetImportInitialStep( + initialStepState?.type, + ); + + const { activeStep } = useStepBar({ + initialStep, + }); + + const { t } = useLingui(); + + const confirmOnClose = () => { + if (activeStep < 1) { + mergedProps.onClose(); + return; + } + + enqueueDialog({ + title: t`Exit import flow`, + message: t`Are you sure? Your current information will not be saved.`, + buttons: [ + { title: t`Cancel` }, + { + title: t`Exit`, + onClick: mergedProps.onClose, + accent: 'danger', + role: 'confirm', + }, + ], + }); + }; + return ( diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx index 51d86cc32..3054a4308 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/MatchColumnsStep/MatchColumnsStep.tsx @@ -247,6 +247,27 @@ export const MatchColumnsStep = ({ ), ); + const onBackConfirmation = () => { + onBack?.(); + setColumns([]); + }; + + const openRestartDialog = () => { + enqueueDialog({ + title: t`Restart Import`, + message: t`You will lose all your mappings.`, + buttons: [ + { title: t`Cancel` }, + { + title: t`Restart`, + onClick: onBackConfirmation, + accent: 'danger', + role: 'confirm', + }, + ], + }); + }; + return ( <> @@ -282,10 +303,8 @@ export const MatchColumnsStep = ({ onContinue={handleOnContinue} isLoading={isLoading} continueTitle={t`Next Step`} - onBack={() => { - onBack?.(); - setColumns([]); - }} + backTitle={t`Restart Import`} + onBack={openRestartDialog} isContinueDisabled={!hasMatchedColumns} /> diff --git a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/__stories__/SelectHeader.stories.tsx b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/__stories__/SelectHeader.stories.tsx index 6f8eca418..b5fe67451 100644 --- a/packages/twenty-front/src/modules/spreadsheet-import/steps/components/__stories__/SelectHeader.stories.tsx +++ b/packages/twenty-front/src/modules/spreadsheet-import/steps/components/__stories__/SelectHeader.stories.tsx @@ -42,7 +42,10 @@ export default meta; export const Default = () => ( - + null} + > null} diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx index ec6df0927..d1feb0c16 100644 --- a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx +++ b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx @@ -195,6 +195,7 @@ export type ModalProps = React.PropsWithChildren & { onEnter?: () => void; modalVariant?: ModalVariants; dataGloballyPreventClickOutside?: boolean; + shouldCloseModalOnClickOutsideOrEscape?: boolean; } & ( | { isClosable: true; onClose?: () => void } | { isClosable?: false; onClose?: never } @@ -217,6 +218,7 @@ export const Modal = ({ onClose, modalVariant = 'primary', dataGloballyPreventClickOutside = false, + shouldCloseModalOnClickOutsideOrEscape = true, }: ModalProps) => { const isMobile = useIsMobile(); const modalRef = useRef(null); @@ -236,7 +238,7 @@ export const Modal = ({ const handleClose = () => { onClose?.(); - closeModal(modalId); + if (shouldCloseModalOnClickOutsideOrEscape) closeModal(modalId); }; return (