Skip to content

Commit 6d74a0e

Browse files
committed
feat: introduce mrf action that cannot be added by user
1 parent 0cd9f54 commit 6d74a0e

File tree

11 files changed

+72
-5
lines changed

11 files changed

+72
-5
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import mrfSubmission from './mrf-submission'
2+
3+
export default [mrfSubmission]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { IGlobalVariable, IRawAction } from '@plumber/types'
2+
3+
import getDataOutMetadata from '../../triggers/new-submission/get-data-out-metadata'
4+
5+
const action: IRawAction = {
6+
name: 'New form response',
7+
key: 'mrfSubmission',
8+
hiddenFromUser: true,
9+
description:
10+
'This is a hidden action that signifies a subsequent MRF submission',
11+
getDataOutMetadata,
12+
13+
async testRun(_$: IGlobalVariable) {
14+
// TODO: this should run testRun for the trigger execution step
15+
},
16+
}
17+
18+
export default action

packages/backend/src/apps/formsg/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { IApp } from '@plumber/types'
22

33
import beforeRequest from './common/before-request'
4+
import actions from './actions'
45
import auth from './auth'
56
import triggers from './triggers'
67

@@ -16,7 +17,7 @@ const app: IApp = {
1617
beforeRequest,
1718
auth,
1819
triggers,
19-
actions: [],
20+
actions,
2021
demoVideoDetails: {
2122
url: 'https://demo.arcade.software/6cWULLTHkTH4XsSB1rs1?embed&show_copy_link=true',
2223
title: 'Setting up FormSG',

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { raw } from 'objection'
22

3+
import { BadUserInputError } from '@/errors/graphql-errors'
4+
import App from '@/models/app'
35
import FlowConnections from '@/models/flow-connections'
46
import Step from '@/models/step'
57
import { getConnection } from '@/services/connection'
@@ -13,6 +15,18 @@ const createStep: MutationResolvers['createStep'] = async (
1315
) => {
1416
const { input } = params
1517

18+
const triggerOrAction = await App.findTriggerOrActionByKey(
19+
input.appKey,
20+
input.key,
21+
)
22+
23+
if (!triggerOrAction) {
24+
throw new BadUserInputError('No such trigger or action')
25+
}
26+
if ('hiddenFromUser' in triggerOrAction && triggerOrAction.hiddenFromUser) {
27+
throw new BadUserInputError('Action can only be created by system')
28+
}
29+
1630
return await Step.transaction(async (trx) => {
1731
await trx.raw('SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;')
1832

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { IAction } from '@/../../types'
12
import { BadUserInputError } from '@/errors/graphql-errors'
23
import {
34
addFlowConnection,
@@ -16,6 +17,14 @@ const updateStep: MutationResolvers['updateStep'] = async (
1617
) => {
1718
const { input } = params
1819

20+
const triggerOrAction = await App.findTriggerOrActionByKey(
21+
input.appKey,
22+
input.key,
23+
)
24+
if (!triggerOrAction) {
25+
throw new BadUserInputError('No such trigger or action')
26+
}
27+
1928
const step = await Step.transaction(async (trx) => {
2029
const step = await context.currentUser
2130
.withAccessibleSteps({ requiredRole: 'editor', trx })
@@ -52,8 +61,10 @@ const updateStep: MutationResolvers['updateStep'] = async (
5261
// NOTE: we use this function to first validate the step parameters
5362
// to avoid misuse and saving invalid step parameters
5463
if (step.type === 'action') {
55-
const app = await App.findOneByKey(input.appKey)
56-
const action = app?.actions?.find((action) => action.key === step.key)
64+
const action = triggerOrAction as IAction
65+
if (action?.hiddenFromUser) {
66+
throw new BadUserInputError('Action can only be updated by system')
67+
}
5768
action?.validateStepParameters?.(input.parameters)
5869
}
5970

packages/backend/src/graphql/queries/get-apps.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export const ACTION_APPS_RANKING = [
5757
customApiApp.key,
5858
vaultWorkspaceApp.key,
5959
twilioApp.key,
60+
formsgApp.key,
6061
]
6162

6263
function sortApps(apps: IApp[]): IApp[] {

packages/backend/src/graphql/schema.graphql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ type Action {
174174
name: String
175175
key: String
176176
description: String
177+
hiddenFromUser: Boolean
177178
groupsLaterSteps: Boolean
178179
setupMessage: SetupMessage
179180
isNew: Boolean

packages/backend/src/models/app.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { IApp } from '@plumber/types'
1+
import { IAction, IApp, ITrigger } from '@plumber/types'
22

33
import { memoize } from 'lodash'
44

@@ -37,6 +37,17 @@ class App {
3737
return appInfoConverter(rawAppData)
3838
}
3939

40+
static async findTriggerOrActionByKey(
41+
appKey: string,
42+
key: string,
43+
): Promise<ITrigger | IAction> {
44+
const app = await this.findOneByKey(appKey)
45+
return (
46+
app.triggers?.find((trigger) => trigger.key === key) ||
47+
app.actions?.find((action) => action.key === key)
48+
)
49+
}
50+
4051
static getAllAppsWithFunctions = memoize(async () => {
4152
return await this.findAll(null, false)
4253
})

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,14 +288,18 @@ export default function ChooseApp(props: ChooseAppProps) {
288288

289289
const triggersOrActions = isTrigger
290290
? app.triggers
291-
: app.actions
291+
: app.actions?.filter((action) => !action.hiddenFromUser)
292292
const singleTriggerOrAction =
293293
triggersOrActions?.length === 1
294294
? triggersOrActions[0]
295295
: null
296296

297297
const isAppDisabled = appSelectableMap?.[app.key] === false
298298

299+
if (!triggersOrActions?.length) {
300+
return null
301+
}
302+
299303
return (
300304
<Flex
301305
key={app.key}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export const GET_APPS = gql`
178178
groupsLaterSteps
179179
isNew
180180
linkToGuide
181+
hiddenFromUser
181182
substeps {
182183
key
183184
name

0 commit comments

Comments
 (0)