Add modal to confirm workflow draft version overriding (#7758)
In this PR: - Allow the `<ConfirmationModal />` to take additional buttons to display between the cancel and the confirm buttons. - Create a modal that's displayed when the user tries wants to use a workflow version as draft while a draft version already exists. The displayed modal contains a link to the current draft version and a button to confirm the overriding of the current draft version. A demo: https://github.com/user-attachments/assets/6349f418-1b11-45b3-9f5e-061ca74c2966 Closes twentyhq/private-issues#114
This commit is contained in:
committed by
GitHub
parent
f3ec6a759f
commit
fc6748de0a
@ -25,6 +25,7 @@ export type ConfirmationModalProps = {
|
|||||||
confirmationPlaceholder?: string;
|
confirmationPlaceholder?: string;
|
||||||
confirmationValue?: string;
|
confirmationValue?: string;
|
||||||
confirmButtonAccent?: ButtonAccent;
|
confirmButtonAccent?: ButtonAccent;
|
||||||
|
AdditionalButtons?: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledConfirmationModal = styled(Modal)`
|
const StyledConfirmationModal = styled(Modal)`
|
||||||
@ -33,7 +34,8 @@ const StyledConfirmationModal = styled(Modal)`
|
|||||||
height: auto;
|
height: auto;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledCenteredButton = styled(Button)`
|
export const StyledCenteredButton = styled(Button)`
|
||||||
|
box-sizing: border-box;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: ${({ theme }) => theme.spacing(2)};
|
margin-top: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
@ -68,6 +70,7 @@ export const ConfirmationModal = ({
|
|||||||
confirmationValue,
|
confirmationValue,
|
||||||
confirmationPlaceholder,
|
confirmationPlaceholder,
|
||||||
confirmButtonAccent = 'danger',
|
confirmButtonAccent = 'danger',
|
||||||
|
AdditionalButtons,
|
||||||
}: ConfirmationModalProps) => {
|
}: ConfirmationModalProps) => {
|
||||||
const [inputConfirmationValue, setInputConfirmationValue] =
|
const [inputConfirmationValue, setInputConfirmationValue] =
|
||||||
useState<string>('');
|
useState<string>('');
|
||||||
@ -138,6 +141,9 @@ export const ConfirmationModal = ({
|
|||||||
title="Cancel"
|
title="Cancel"
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{AdditionalButtons}
|
||||||
|
|
||||||
<StyledCenteredButton
|
<StyledCenteredButton
|
||||||
onClick={handleConfirmClick}
|
onClick={handleConfirmClick}
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
|
|||||||
@ -0,0 +1,62 @@
|
|||||||
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
|
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||||
|
import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL';
|
||||||
|
import {
|
||||||
|
ConfirmationModal,
|
||||||
|
StyledCenteredButton,
|
||||||
|
} from '@/ui/layout/modal/components/ConfirmationModal';
|
||||||
|
import { openOverrideWorkflowDraftConfirmationModalState } from '@/workflow/states/openOverrideWorkflowDraftConfirmationModalState';
|
||||||
|
import { WorkflowVersion } from '@/workflow/types/Workflow';
|
||||||
|
import { useRecoilState } from 'recoil';
|
||||||
|
|
||||||
|
export const OverrideWorkflowDraftConfirmationModal = ({
|
||||||
|
draftWorkflowVersionId,
|
||||||
|
workflowVersionUpdateInput,
|
||||||
|
}: {
|
||||||
|
draftWorkflowVersionId: string;
|
||||||
|
workflowVersionUpdateInput: Pick<WorkflowVersion, 'trigger' | 'steps'>;
|
||||||
|
}) => {
|
||||||
|
const [
|
||||||
|
openOverrideWorkflowDraftConfirmationModal,
|
||||||
|
setOpenOverrideWorkflowDraftConfirmationModal,
|
||||||
|
] = useRecoilState(openOverrideWorkflowDraftConfirmationModalState);
|
||||||
|
|
||||||
|
const { updateOneRecord: updateOneWorkflowVersion } =
|
||||||
|
useUpdateOneRecord<WorkflowVersion>({
|
||||||
|
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOverrideDraft = async () => {
|
||||||
|
await updateOneWorkflowVersion({
|
||||||
|
idToUpdate: draftWorkflowVersionId,
|
||||||
|
updateOneRecordInput: workflowVersionUpdateInput,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ConfirmationModal
|
||||||
|
isOpen={openOverrideWorkflowDraftConfirmationModal}
|
||||||
|
setIsOpen={setOpenOverrideWorkflowDraftConfirmationModal}
|
||||||
|
title="A draft already exists"
|
||||||
|
subtitle="A draft already exists for this workflow. Are you sure you want to erase it?"
|
||||||
|
onConfirmClick={handleOverrideDraft}
|
||||||
|
deleteButtonText={'Override Draft'}
|
||||||
|
AdditionalButtons={
|
||||||
|
<StyledCenteredButton
|
||||||
|
to={buildShowPageURL(
|
||||||
|
CoreObjectNameSingular.WorkflowVersion,
|
||||||
|
draftWorkflowVersionId,
|
||||||
|
)}
|
||||||
|
onClick={() => {
|
||||||
|
setOpenOverrideWorkflowDraftConfirmationModal(false);
|
||||||
|
}}
|
||||||
|
variant="secondary"
|
||||||
|
title="Go to Draft"
|
||||||
|
fullWidth
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,13 +1,15 @@
|
|||||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
|
import { OverrideWorkflowDraftConfirmationModal } from '@/workflow/components/OverrideWorkflowDraftConfirmationModal';
|
||||||
import { useActivateWorkflowVersion } from '@/workflow/hooks/useActivateWorkflowVersion';
|
import { useActivateWorkflowVersion } from '@/workflow/hooks/useActivateWorkflowVersion';
|
||||||
import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion';
|
import { useCreateNewWorkflowVersion } from '@/workflow/hooks/useCreateNewWorkflowVersion';
|
||||||
import { useDeactivateWorkflowVersion } from '@/workflow/hooks/useDeactivateWorkflowVersion';
|
import { useDeactivateWorkflowVersion } from '@/workflow/hooks/useDeactivateWorkflowVersion';
|
||||||
import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion';
|
import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion';
|
||||||
|
import { openOverrideWorkflowDraftConfirmationModalState } from '@/workflow/states/openOverrideWorkflowDraftConfirmationModalState';
|
||||||
import { Workflow, WorkflowVersion } from '@/workflow/types/Workflow';
|
import { Workflow, WorkflowVersion } from '@/workflow/types/Workflow';
|
||||||
|
import { useSetRecoilState } from 'recoil';
|
||||||
import { IconPencil, IconPlayerStop, IconPower, isDefined } from 'twenty-ui';
|
import { IconPencil, IconPlayerStop, IconPower, isDefined } from 'twenty-ui';
|
||||||
|
|
||||||
export const RecordShowPageWorkflowVersionHeader = ({
|
export const RecordShowPageWorkflowVersionHeader = ({
|
||||||
@ -46,6 +48,8 @@ export const RecordShowPageWorkflowVersionHeader = ({
|
|||||||
skip: !isDefined(workflowVersion),
|
skip: !isDefined(workflowVersion),
|
||||||
limit: 1,
|
limit: 1,
|
||||||
});
|
});
|
||||||
|
const draftWorkflowVersion: WorkflowVersion | undefined =
|
||||||
|
draftWorkflowVersions[0];
|
||||||
|
|
||||||
const showUseAsDraftButton =
|
const showUseAsDraftButton =
|
||||||
!loadingDraftWorkflowVersions &&
|
!loadingDraftWorkflowVersions &&
|
||||||
@ -57,7 +61,7 @@ export const RecordShowPageWorkflowVersionHeader = ({
|
|||||||
workflowVersionRelatedWorkflowQuery.record.lastPublishedVersionId;
|
workflowVersionRelatedWorkflowQuery.record.lastPublishedVersionId;
|
||||||
|
|
||||||
const hasAlreadyDraftVersion =
|
const hasAlreadyDraftVersion =
|
||||||
!loadingDraftWorkflowVersions && draftWorkflowVersions.length > 0;
|
!loadingDraftWorkflowVersions && isDefined(draftWorkflowVersion);
|
||||||
|
|
||||||
const isWaitingForWorkflowVersion = !isDefined(workflowVersion);
|
const isWaitingForWorkflowVersion = !isDefined(workflowVersion);
|
||||||
|
|
||||||
@ -65,10 +69,9 @@ export const RecordShowPageWorkflowVersionHeader = ({
|
|||||||
const { deactivateWorkflowVersion } = useDeactivateWorkflowVersion();
|
const { deactivateWorkflowVersion } = useDeactivateWorkflowVersion();
|
||||||
const { createNewWorkflowVersion } = useCreateNewWorkflowVersion();
|
const { createNewWorkflowVersion } = useCreateNewWorkflowVersion();
|
||||||
|
|
||||||
const { updateOneRecord: updateOneWorkflowVersion } =
|
const setOpenOverrideWorkflowDraftConfirmationModal = useSetRecoilState(
|
||||||
useUpdateOneRecord<WorkflowVersion>({
|
openOverrideWorkflowDraftConfirmationModalState,
|
||||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
);
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -80,13 +83,7 @@ export const RecordShowPageWorkflowVersionHeader = ({
|
|||||||
disabled={isWaitingForWorkflowVersion}
|
disabled={isWaitingForWorkflowVersion}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (hasAlreadyDraftVersion) {
|
if (hasAlreadyDraftVersion) {
|
||||||
await updateOneWorkflowVersion({
|
setOpenOverrideWorkflowDraftConfirmationModal(true);
|
||||||
idToUpdate: draftWorkflowVersions[0].id,
|
|
||||||
updateOneRecordInput: {
|
|
||||||
trigger: workflowVersion.trigger,
|
|
||||||
steps: workflowVersion.steps,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
await createNewWorkflowVersion({
|
await createNewWorkflowVersion({
|
||||||
workflowId: workflowVersion.workflow.id,
|
workflowId: workflowVersion.workflow.id,
|
||||||
@ -125,6 +122,16 @@ export const RecordShowPageWorkflowVersionHeader = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{isDefined(workflowVersion) && isDefined(draftWorkflowVersion) ? (
|
||||||
|
<OverrideWorkflowDraftConfirmationModal
|
||||||
|
draftWorkflowVersionId={draftWorkflowVersion.id}
|
||||||
|
workflowVersionUpdateInput={{
|
||||||
|
steps: workflowVersion.steps,
|
||||||
|
trigger: workflowVersion.trigger,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
import { createState } from 'twenty-ui';
|
||||||
|
|
||||||
|
export const openOverrideWorkflowDraftConfirmationModalState =
|
||||||
|
createState<boolean>({
|
||||||
|
key: 'openOverrideWorkflowDraftConfirmationModalState',
|
||||||
|
defaultValue: false,
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user