Skip to content

Commit 36e484e

Browse files
committed
refactor(frontend): fetch flowId directly from backend, remove manual cache manipulation for createStep and duplicate step
1 parent f8949a9 commit 36e484e

File tree

12 files changed

+32
-143
lines changed

12 files changed

+32
-143
lines changed

packages/backend/src/graphql/schema.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,7 @@ type Step {
669669
executionSteps: [ExecutionStep]
670670
config: StepConfig
671671
createdAt: String
672+
flowId: String
672673
}
673674

674675
type StepConfig {

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

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,7 @@ export default function Editor(props: EditorProps): React.ReactElement {
3030
useContext(EditorContext)
3131

3232
const { handleReorderUpdate } = useReorderSteps(flow.id)
33-
const rawSteps = flow.steps
34-
const steps = useMemo(
35-
// Populate each step's flowId so that IStep isn't LYING about flowId being
36-
// non-undefined. We do it here instead of fetching in GraphQL since all
37-
// steps have same pipe, so a bit wasteful to repeat this data over the wire.
38-
() =>
39-
rawSteps.map((step) => ({
40-
...step,
41-
flow,
42-
flowId: flow.id,
43-
})),
44-
[flow, rawSteps],
45-
)
33+
const steps = flow.steps
4634

4735
const currentStep = useMemo(() => {
4836
return steps.find((step) => step.id === currentStepId)

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

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -17,59 +17,13 @@ interface DuplicateStepButtonProps {
1717
step: IStep
1818
}
1919

20-
/**
21-
* Helper function to update the flow in the cache
22-
*/
23-
function updateHandlerFactory(flowId: string, previousStepId: string) {
24-
return function createStepUpdateHandler(cache: any, mutationResult: any) {
25-
const { data } = mutationResult
26-
const { createStep: createdStep } = data
27-
const { getFlow: flow } = cache.readQuery({
28-
query: GET_FLOW,
29-
variables: { id: flowId },
30-
})
31-
32-
// getFlow requires certain attributes to be returned
33-
const completeCreatedStep = {
34-
...createdStep,
35-
iconUrl: null,
36-
webhookUrl: null,
37-
config: {
38-
stepName: createdStep?.config?.stepName || null,
39-
templateConfig: {
40-
appEventKey: null,
41-
},
42-
approval: {
43-
branch: createdStep?.config?.approval?.branch ?? null,
44-
stepId: createdStep?.config?.approval?.stepId ?? null,
45-
},
46-
},
47-
createdAt: new Date().toISOString(),
48-
}
49-
50-
const steps = flow.steps.reduce((steps: any[], currentStep: any) => {
51-
if (currentStep.id === previousStepId) {
52-
return [...steps, currentStep, completeCreatedStep]
53-
}
54-
55-
return [...steps, currentStep]
56-
}, [])
57-
58-
cache.writeQuery({
59-
query: GET_FLOW,
60-
variables: { id: flowId },
61-
data: { getFlow: { ...flow, steps } },
62-
})
63-
}
64-
}
65-
6620
export default function DuplicateStepButton(props: DuplicateStepButtonProps) {
6721
const { isNested, step } = props
6822

6923
const { flow, isMobile, onDrawerOpen, setCurrentStepId } =
7024
useContext(EditorContext)
7125

72-
const [createStep] = useMutation(CREATE_STEP)
26+
const [createStep] = useMutation(CREATE_STEP, { refetchQueries: [GET_FLOW] })
7327
const onDuplicateStep = useCallback(async () => {
7428
const duplicateConfig = {
7529
...(step.config?.approval && {
@@ -96,7 +50,6 @@ export default function DuplicateStepButton(props: DuplicateStepButtonProps) {
9650

9751
const createdStep = await createStep({
9852
variables: { input: mutationInput },
99-
update: updateHandlerFactory(flow.id, step.id),
10053
})
10154

10255
const newStep = createdStep.data.createStep

packages/frontend/src/components/FlowStepConfigurationModal/ChooseAndAddConnection/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ export default function ChooseAndAddConnection(
134134
selectedApp.key,
135135
selectedEvent.key,
136136
connectionId,
137-
{ approval: approvalConfig },
137+
approvalConfig && { approval: approvalConfig },
138138
)
139139
newStepId = createdStep.id
140140
} else if (step) {

packages/frontend/src/components/FlowStepConfigurationModal/ChooseAppAndEvent/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import { useQuery } from '@apollo/client'
55

66
import { EditorContext } from '@/contexts/Editor'
77
import { MrfContext } from '@/contexts/MrfContext'
8+
import client from '@/graphql/client'
89
import { GET_APP_CONNECTIONS } from '@/graphql/queries/get-app-connections'
10+
import { GET_FLOW } from '@/graphql/queries/get-flow'
911
import { getMrfApprovalConfig } from '@/helpers/formsg'
1012
import {
1113
TOOLBOX_ACTIONS,
@@ -118,10 +120,11 @@ export default function ChooseAppAndEvent(props: ChooseAppAndEventProps) {
118120
app.key,
119121
triggerOrAction.key,
120122
excelConnection?.id || undefined,
121-
{ approval: approvalConfig },
123+
approvalConfig && { approval: approvalConfig },
122124
)
123125
newStepId = createdStep.id
124126
} else if (step) {
127+
// This part of the code happens when updating an empty step
125128
// account for the if-then edge case
126129
if (
127130
app.key === TOOLBOX_APP_KEY &&
@@ -140,6 +143,8 @@ export default function ChooseAppAndEvent(props: ChooseAppAndEventProps) {
140143
})
141144
newStepId = updatedStep.id
142145
}
146+
// we refetch GET_FLOW after everything is completed
147+
await client.refetchQueries({ include: [GET_FLOW] })
143148
}
144149
onClose()
145150
onDrawerOpen()

packages/frontend/src/contexts/Editor.tsx

Lines changed: 5 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -117,52 +117,6 @@ type EditorProviderProps = {
117117
resetFormRef?: React.MutableRefObject<(() => void) | null>
118118
}
119119

120-
/**
121-
* Helper function to update the flow in the cache
122-
*/
123-
function updateHandlerFactory(flowId: string, previousStepId: string) {
124-
return function createStepUpdateHandler(cache: any, mutationResult: any) {
125-
const { data } = mutationResult
126-
const { createStep: createdStep } = data
127-
const { getFlow: flow } = cache.readQuery({
128-
query: GET_FLOW,
129-
variables: { id: flowId },
130-
})
131-
132-
// getFlow requires certain attributes to be returned
133-
const completeCreatedStep = {
134-
...createdStep,
135-
iconUrl: null,
136-
webhookUrl: null,
137-
config: {
138-
stepName: null,
139-
templateConfig: {
140-
appEventKey: createdStep.config?.templateConfig?.appEventKey ?? null,
141-
},
142-
approval: {
143-
branch: createdStep.config?.approval?.branch ?? null,
144-
stepId: createdStep.config?.approval?.stepId ?? null,
145-
},
146-
},
147-
createdAt: new Date().toISOString(),
148-
}
149-
150-
const steps = flow.steps.reduce((steps: any[], currentStep: any) => {
151-
if (currentStep.id === previousStepId) {
152-
return [...steps, currentStep, completeCreatedStep]
153-
}
154-
155-
return [...steps, currentStep]
156-
}, [])
157-
158-
cache.writeQuery({
159-
query: GET_FLOW,
160-
variables: { id: flowId },
161-
data: { getFlow: { ...flow, steps } },
162-
})
163-
}
164-
}
165-
166120
export const EditorProvider = ({
167121
readOnly,
168122
flow,
@@ -260,36 +214,17 @@ export const EditorProvider = ({
260214

261215
const createdStep = await createStep({
262216
variables: { input: mutationInput },
263-
update: updateHandlerFactory(flowId, previousStepId),
264217
})
265218

266-
const newStep = createdStep.data.createStep
219+
let newStep = createdStep.data.createStep
267220
setCurrentStepId(newStep.id)
268221

269222
// account for the for-each and if-then
270-
if (appKey === TOOLBOX_APP_KEY) {
271-
// Get the complete step data from the cache
272-
const { getFlow: updatedFlow } = client.readQuery({
273-
query: GET_FLOW,
274-
variables: { id: flowId },
275-
})
276-
277-
const completeStep = updatedFlow.steps.find(
278-
(s: IStep) => s.id === newStep.id,
279-
)
280-
281-
if (completeStep) {
282-
const completeStepWithFlow = {
283-
...completeStep,
284-
flowId: flowId,
285-
}
286-
if (eventKey === TOOLBOX_ACTIONS.IfThen) {
287-
return (await initializeIfThen(
288-
completeStepWithFlow,
289-
)) as unknown as IStep
290-
}
291-
}
223+
if (appKey === TOOLBOX_APP_KEY && eventKey === TOOLBOX_ACTIONS.IfThen) {
224+
newStep = await initializeIfThen(newStep)
292225
}
226+
// we refetch GET_FLOW after everything is completed
227+
await client.refetchQueries({ include: [GET_FLOW] })
293228

294229
return newStep as IStep
295230
},

packages/frontend/src/graphql/link.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { ApolloLink } from '@apollo/client'
22
import { from, HttpLink } from '@apollo/client'
33
import { onError } from '@apollo/client/link/error'
4+
import { removeTypenameFromVariables } from '@apollo/client/link/remove-typename'
45

56
import { INVALID_TILE_VIEW_KEY, NOT_AUTHORISED } from '@/config/errors'
67
import * as URLS from '@/config/urls'
@@ -62,7 +63,13 @@ const createLink = (options: CreateLinkOptions): ApolloLink => {
6263

6364
const httpOptions = { uri, token }
6465

65-
return from([createErrorLink(onError), createHttpLink(httpOptions)])
66+
return from([
67+
// this removes the __typename from variables before sending to the server,
68+
// which prevents validation errors especially when duplicating steps
69+
removeTypenameFromVariables(),
70+
createErrorLink(onError),
71+
createHttpLink(httpOptions),
72+
])
6673
}
6774

6875
export default createLink

packages/frontend/src/graphql/mutations/create-step.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ export const CREATE_STEP = gql`
1010
parameters
1111
position
1212
status
13+
flowId
14+
createdAt
1315
connection {
1416
id
1517
}

packages/frontend/src/graphql/mutations/update-step.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export const UPDATE_STEP = graphql(`
1111
parameters
1212
status
1313
position
14+
flowId
15+
createdAt
1416
connection {
1517
id
1618
}

packages/frontend/src/graphql/queries/get-flow.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export const GET_FLOW = gql`
1515
webhookUrl
1616
status
1717
position
18+
flowId
1819
createdAt
1920
connection {
2021
id

0 commit comments

Comments
 (0)