Skip to content

Commit 8ad5881

Browse files
committed
fix: warn for unsaved changes on delete step
1 parent ba6619c commit 8ad5881

File tree

3 files changed

+42
-5
lines changed

3 files changed

+42
-5
lines changed

packages/frontend/src/components/FlowStep/components/StepDeleteButton.tsx

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,31 @@ import { useMutation } from '@apollo/client'
66
import { Flex, useDisclosure } from '@chakra-ui/react'
77
import { IconButton } from '@opengovsg/design-system-react'
88

9+
import UnsavedChangesAlert from '@/components/Editor/UnsavedChangesAlert'
910
import MenuAlertDialog from '@/components/MenuAlertDialog'
1011
import { EditorContext } from '@/contexts/Editor'
1112
import client from '@/graphql/client'
1213
import { CREATE_STEP } from '@/graphql/mutations/create-step'
1314
import { DELETE_STEP } from '@/graphql/mutations/delete-step'
1415
import { GET_FLOW } from '@/graphql/queries/get-flow'
1516
import { GET_TEST_EXECUTION_STEPS } from '@/graphql/queries/get-test-execution-steps'
17+
import { useUnsavedChanges } from '@/hooks/useUnsavedChanges'
1618

1719
import { findAdjacentSteps, shouldCreateEmptyStep } from '../utils'
1820

1921
interface StepDeleteButtonProps {
2022
isNested?: boolean
2123
isDeletingStep?: boolean
2224
step: IStep
25+
caption?: string
2326
}
2427

2528
export default function StepDeleteButton(props: StepDeleteButtonProps) {
26-
const { isNested, step } = props
29+
const { isNested, step, caption } = props
2730
const cancelRef = useRef<HTMLButtonElement>(null)
31+
const customBody = caption
32+
? `Are you sure you want to delete step ${caption}? You can't undo this action afterwards.`
33+
: undefined
2834
const {
2935
isOpen: isDialogOpen,
3036
onOpen: onDialogOpen,
@@ -40,6 +46,16 @@ export default function StepDeleteButton(props: StepDeleteButtonProps) {
4046
setShouldWarnOnLeave,
4147
} = useContext(EditorContext)
4248

49+
const {
50+
cancelRef: cancelUnsavedRef,
51+
isWarningOpen,
52+
onWarningClose,
53+
handleProceed,
54+
handleLeave,
55+
} = useUnsavedChanges({
56+
onProceed: onDialogOpen,
57+
})
58+
4359
/**
4460
* NOTE: refetch test execution steps when deleting a step so that we can
4561
* check which steps are using variables from steps that have been deleted
@@ -106,8 +122,8 @@ export default function StepDeleteButton(props: StepDeleteButtonProps) {
106122
<IconButton
107123
boxSize={isNested ? 6 : 8}
108124
onClick={(event) => {
109-
onDialogOpen()
110125
event.stopPropagation()
126+
handleProceed()
111127
}}
112128
variant="clear"
113129
aria-label="Delete Step"
@@ -128,6 +144,14 @@ export default function StepDeleteButton(props: StepDeleteButtonProps) {
128144
dialogType="delete"
129145
onClick={onDelete}
130146
isLoading={isDeletingStep || isCreatingStep}
147+
customBody={customBody}
148+
/>
149+
150+
<UnsavedChangesAlert
151+
cancelRef={cancelUnsavedRef}
152+
isOpen={isWarningOpen}
153+
onClose={onWarningClose}
154+
onLeave={handleLeave}
131155
/>
132156
</>
133157
)

packages/frontend/src/components/FlowStep/index.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,11 @@ export default function FlowStep(
239239
/>
240240
<StepCaptionAndDemo app={app} caption={caption} />
241241
{isDeletable && (
242-
<StepDeleteButton isNested={isNested} step={step} />
242+
<StepDeleteButton
243+
isNested={isNested}
244+
step={step}
245+
caption={caption}
246+
/>
243247
)}
244248
</Flex>
245249
</Flex>

packages/frontend/src/components/MenuAlertDialog/index.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,36 @@ interface MenuAlertDialogProps {
2020
dialogHeader: AlertHeaderType
2121
onClick: (() => void) | MouseEventHandler
2222
isLoading: boolean
23+
customBody?: string
2324
}
2425

2526
interface AlertDialogContent {
2627
header: string
2728
body: string
2829
buttonText: string
30+
customBody?: string
2931
}
3032

3133
function getAlertDialogContent(
3234
dialogHeader: AlertHeaderType,
3335
dialogType: AlertDialogType,
36+
customBody?: string,
3437
): AlertDialogContent {
3538
switch (dialogType) {
3639
case 'delete':
3740
return {
3841
header: `Delete ${dialogHeader}`,
39-
body: `Are you sure you want to delete this ${dialogHeader?.toLowerCase()}? You can't undo this action afterwards.`,
42+
body:
43+
customBody ??
44+
`Are you sure you want to delete this ${dialogHeader?.toLowerCase()}? You can't undo this action afterwards.`,
4045
buttonText: 'Delete',
4146
}
4247
case 'duplicate':
4348
return {
4449
header: 'Duplicate Pipe',
45-
body: `You'll need to replace the data in every step and test each step in your duplicated pipe before publishing it.`,
50+
body:
51+
customBody ??
52+
`You'll need to replace the data in every step and test each step in your duplicated pipe before publishing it.`,
4653
buttonText: 'Duplicate',
4754
}
4855
}
@@ -57,10 +64,12 @@ export default function MenuAlertDialog(props: MenuAlertDialogProps) {
5764
dialogType,
5865
onClick,
5966
isLoading,
67+
customBody,
6068
} = props
6169
const { header, body, buttonText } = getAlertDialogContent(
6270
dialogHeader,
6371
dialogType,
72+
customBody,
6473
)
6574

6675
return (

0 commit comments

Comments
 (0)