Skip to content

fix confirm close dialog + add restart confirm dialog #12761

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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 (
<StyledCloseButtonContainer>
<IconButton Icon={IconX} onClick={handleClose} />
<IconButton Icon={IconX} onClick={onClose} />
</StyledCloseButtonContainer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const StyledRtlLtr = styled.div`
type SpreadSheetImportModalWrapperProps = {
children: React.ReactNode;
modalId: string;
onClose?: () => void;
onClose: () => void;
};

export const SpreadSheetImportModalWrapper = ({
Expand All @@ -44,6 +44,7 @@ export const SpreadSheetImportModalWrapper = ({
modalId={modalId}
isClosable={true}
onClose={onClose}
shouldCloseModalOnClickOutsideOrEscape={false}
>
<StyledRtlLtr dir={rtl ? 'rtl' : 'ltr'}>
<SpreadSheetImportModalCloseButton onClose={onClose} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<any>
Expand Down Expand Up @@ -31,11 +36,46 @@ export const SpreadsheetImport = <T extends string>(
...props,
} as SpreadsheetImportProps<T>;

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 (
<ReactSpreadsheetImportContextProvider values={mergedProps}>
<SpreadSheetImportModalWrapper
modalId={SPREADSHEET_IMPORT_MODAL_ID}
onClose={mergedProps.onClose}
onClose={confirmOnClose}
>
<SpreadsheetImportStepperContainer />
</SpreadSheetImportModalWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,27 @@ export const MatchColumnsStep = <T extends string>({
),
);

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 (
<>
<StyledContent>
Expand Down Expand Up @@ -282,10 +303,8 @@ export const MatchColumnsStep = <T extends string>({
onContinue={handleOnContinue}
isLoading={isLoading}
continueTitle={t`Next Step`}
onBack={() => {
onBack?.();
setColumns([]);
}}
backTitle={t`Restart Import`}
onBack={openRestartDialog}
isContinueDisabled={!hasMatchedColumns}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ export default meta;
export const Default = () => (
<DialogManagerScope dialogManagerScopeId="dialog-manager">
<ReactSpreadsheetImportContextProvider values={mockRsiValues}>
<SpreadSheetImportModalWrapper modalId="select-header-step">
<SpreadSheetImportModalWrapper
modalId="select-header-step"
onClose={() => null}
>
<SelectHeaderStep
importedRows={headerSelectionTableFields}
setCurrentStepState={() => null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand All @@ -217,6 +218,7 @@ export const Modal = ({
onClose,
modalVariant = 'primary',
dataGloballyPreventClickOutside = false,
shouldCloseModalOnClickOutsideOrEscape = true,
}: ModalProps) => {
const isMobile = useIsMobile();
const modalRef = useRef<HTMLDivElement>(null);
Expand All @@ -236,7 +238,7 @@ export const Modal = ({

const handleClose = () => {
onClose?.();
closeModal(modalId);
if (shouldCloseModalOnClickOutsideOrEscape) closeModal(modalId);
};
Comment on lines 239 to 242
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: handleClose might execute onClose even when shouldCloseModalOnClickOutsideOrEscape is false, which could be unexpected. Consider moving the onClose call inside the if condition


return (
Expand Down
Loading