From e7c537f2178c940cdd819d55d6cedcbf8cde8e4e Mon Sep 17 00:00:00 2001 From: Ali BARIN Date: Fri, 28 Jan 2022 20:48:56 +0100 Subject: [PATCH] feat: introduce action event step in flow step --- packages/backend/src/apps/twitter/info.json | 9 --- .../src/graphql/mutations/update-step.ts | 16 +++-- packages/backend/src/graphql/types/step.ts | 2 + packages/backend/src/models/step.ts | 4 +- packages/web/src/components/Editor/index.tsx | 1 + .../web/src/components/EditorLayout/index.tsx | 9 ++- .../web/src/components/FlowStep/index.tsx | 72 +++++++++++++++---- packages/web/src/config/urls.ts | 3 +- .../web/src/graphql/mutations/update-step.ts | 1 + packages/web/src/graphql/queries/get-flow.ts | 1 + packages/web/src/types/step.ts | 1 + 11 files changed, 86 insertions(+), 33 deletions(-) diff --git a/packages/backend/src/apps/twitter/info.json b/packages/backend/src/apps/twitter/info.json index 44318274..6af211b9 100644 --- a/packages/backend/src/apps/twitter/info.json +++ b/packages/backend/src/apps/twitter/info.json @@ -229,9 +229,6 @@ "key": "myTweet", "description": "Will be triggered when you tweet something new.", "subSteps": [ - { - "name": "Choose app & event" - }, { "name": "Choose account" }, @@ -245,9 +242,6 @@ "key": "userTweet", "description": "Will be triggered when a specific user tweet something new.", "subSteps": [ - { - "name": "Choose app & event" - }, { "name": "Choose account" }, @@ -273,9 +267,6 @@ "key": "createTweet", "description": "Will create a tweet.", "subSteps": [ - { - "name": "Choose app & event" - }, { "name": "Choose account" }, diff --git a/packages/backend/src/graphql/mutations/update-step.ts b/packages/backend/src/graphql/mutations/update-step.ts index 2602776c..fc866892 100644 --- a/packages/backend/src/graphql/mutations/update-step.ts +++ b/packages/backend/src/graphql/mutations/update-step.ts @@ -7,15 +7,16 @@ import RequestWithCurrentUser from '../../types/express/request-with-current-use type Params = { input: { - id: number, - key: string, - appKey: string, + id: number; + key: string; + appKey: string; + parameters: string; flow: { - id: number, - }, + id: number; + }; connection: { - id: number - }, + id: number; + }; } } const updateStepResolver = async (params: Params, req: RequestWithCurrentUser) => { @@ -35,6 +36,7 @@ const updateStepResolver = async (params: Params, req: RequestWithCurrentUser) = key: input.key, appKey: input.appKey, connectionId: input.connection.id, + parameters: input.parameters, }); return step; diff --git a/packages/backend/src/graphql/types/step.ts b/packages/backend/src/graphql/types/step.ts index 09a2dea0..fbc41275 100644 --- a/packages/backend/src/graphql/types/step.ts +++ b/packages/backend/src/graphql/types/step.ts @@ -23,6 +23,7 @@ const stepType = new GraphQLObjectType({ }, }), }, + parameters: { type: GraphQLString }, connection: { type: ConnectionType }, position: { type: GraphQLInt }, }, @@ -51,6 +52,7 @@ export const stepInputType = new GraphQLInputObjectType({ }, }), }, + parameters: { type: GraphQLString }, previousStep: { type: new GraphQLInputObjectType({ name: 'PreviousStepInput', diff --git a/packages/backend/src/models/step.ts b/packages/backend/src/models/step.ts index c01ea944..e389b6c8 100644 --- a/packages/backend/src/models/step.ts +++ b/packages/backend/src/models/step.ts @@ -15,7 +15,7 @@ class Step extends Base { type!: StepEnumType; connectionId: number; position: number; - parameters: any; + parameters: string; static tableName = 'steps'; @@ -31,7 +31,7 @@ class Step extends Base { type: { type: 'string', enum: ['action', 'trigger'] }, connectionId: { type: ['integer', null] }, position: { type: 'integer' }, - parameters: { type: ['object', null] }, + parameters: { type: ['string', null] }, }, }; diff --git a/packages/web/src/components/Editor/index.tsx b/packages/web/src/components/Editor/index.tsx index c16878a6..5ceba84e 100644 --- a/packages/web/src/components/Editor/index.tsx +++ b/packages/web/src/components/Editor/index.tsx @@ -53,6 +53,7 @@ export default function Editor(props: EditorProps): React.ReactElement { const mutationInput: Record = { id: step.id, key: step.key, + parameters: JSON.stringify(step.parameters, null, 2), connection: { id: step.connection?.id }, diff --git a/packages/web/src/components/EditorLayout/index.tsx b/packages/web/src/components/EditorLayout/index.tsx index c5ac8071..8de8eaeb 100644 --- a/packages/web/src/components/EditorLayout/index.tsx +++ b/packages/web/src/components/EditorLayout/index.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { useParams } from 'react-router-dom'; +import { Link, useParams } from 'react-router-dom'; import { useQuery } from '@apollo/client'; import Stack from '@mui/material/Stack'; import Box from '@mui/material/Box'; @@ -14,6 +14,7 @@ import Editor from 'components/Editor'; import useFormatMessage from 'hooks/useFormatMessage'; import { GET_FLOW } from 'graphql/queries/get-flow'; import type { Flow } from 'types/flow'; +import * as URLS from 'config/urls'; export default function EditorLayout(): React.ReactElement { const { flowId } = useParams(); @@ -26,7 +27,11 @@ export default function EditorLayout(): React.ReactElement { - + diff --git a/packages/web/src/components/FlowStep/index.tsx b/packages/web/src/components/FlowStep/index.tsx index 5a5bf531..390bda65 100644 --- a/packages/web/src/components/FlowStep/index.tsx +++ b/packages/web/src/components/FlowStep/index.tsx @@ -27,21 +27,37 @@ type FlowStepProps = { onChange?: (step: Step) => void; } -const optionGenerator = (app: App): { label: string; value: string; } => ({ - label: app.name, - value: app.key, +const optionGenerator = (app: Record): { label: string; value: string; } => ({ + label: app.name as string, + value: app.key as string, }); -const getOption = (options: Record[], appKey: string) => options.find(app => app.value === appKey); +const getOption = (options: Record[], appKey: unknown) => options.find(app => app.value === appKey as string); + +const parseStep = (step: any) => { + try { + const parameters = JSON.parse(step.parameters); + return { + ...step, + parameters, + } + } catch (err) { + // highly likely that step does not have any parameters and thus, the error is thrown + return step; + } +}; export default function FlowStep(props: FlowStepProps): React.ReactElement | null { const { collapsed, index, onChange } = props; - const [step, setStep] = React.useState(props.step); + const [step, setStep] = React.useState(() => parseStep(props.step)); + const isTrigger = step.type === StepType.Trigger; + const isAction = step.type === StepType.Action; const initialRender = React.useRef(true); const formatMessage = useFormatMessage(); const [currentSubstep, setCurrentSubstep] = React.useState(0); const { data } = useQuery(GET_APPS) const apps: App[] = data?.getApps; + const app = apps?.find((currentApp: App) => currentApp.key === step.appKey); // emit the step change to the parent component React.useEffect(() => { @@ -52,21 +68,35 @@ export default function FlowStep(props: FlowStepProps): React.ReactElement | nul } }, [step, onChange]); - const appAndEventOptions = React.useMemo(() => apps?.map(optionGenerator), [apps]); + const appAndEventOptions = React.useMemo(() => apps?.map((app) => optionGenerator(app)), [apps]); + const actionOptions = React.useMemo(() => app?.triggers?.map((trigger) => optionGenerator(trigger)) ?? [], [app?.key]); - const onAppAndEventChange = React.useCallback((event: React.SyntheticEvent, selectedOption: unknown) => { + const onAppChange = React.useCallback((event: React.SyntheticEvent, selectedOption: unknown) => { if (typeof selectedOption === 'object') { const typedSelectedOption = selectedOption as { value: string; }; const option: { value: string } = typedSelectedOption; const appKey = option.value as string; - setStep((step) => ({ ...step, appKey })); + setStep((step) => ({ ...step, appKey, parameters: {} })); + } + }, []); + + const onEventChange = React.useCallback((event: React.SyntheticEvent, selectedOption: unknown) => { + if (typeof selectedOption === 'object') { + const typedSelectedOption = selectedOption as { value: string; }; + const option: { value: string } = typedSelectedOption; + const eventKey = option.value as string; + setStep((step) => ({ + ...step, + parameters: { + ...step.parameters, + eventKey, + } + })); } }, []); if (!apps) return null; - const app = apps.find((currentApp: App) => currentApp.key === step.appKey); - const onOpen = () => collapsed && props.onOpen?.(); const onClose = () => props.onClose?.(); @@ -81,7 +111,7 @@ export default function FlowStep(props: FlowStepProps): React.ReactElement | nul
{ - step.type === StepType.Trigger ? + isTrigger ? formatMessage('flowStep.triggerType') : formatMessage('flowStep.actionType') } @@ -110,7 +140,25 @@ export default function FlowStep(props: FlowStepProps): React.ReactElement | nul sx={{ width: 300 }} renderInput={(params) => } value={getOption(appAndEventOptions, step.appKey)} - onChange={onAppAndEventChange} + onChange={onAppChange} + /> + + + + + toggleSubstep(1)}> + Action event + + + + } + value={getOption(actionOptions, step?.parameters?.eventKey)} + onChange={onEventChange} /> diff --git a/packages/web/src/config/urls.ts b/packages/web/src/config/urls.ts index 1a94ec05..014bb74d 100644 --- a/packages/web/src/config/urls.ts +++ b/packages/web/src/config/urls.ts @@ -20,5 +20,6 @@ export const CREATE_FLOW = '/editor/create'; export const FLOW_EDITOR = (flowId: string): string => `/editor/${flowId}`; export const FLOWS = '/flows'; -export const FLOW = (flowId: string): string => `/flows/${flowId}`; +// TODO: revert this back to /flows/:flowId once we have a proper single flow page +export const FLOW = (flowId: string): string => `/editor/${flowId}`; export const FLOW_PATTERN = '/flows/:flowId'; diff --git a/packages/web/src/graphql/mutations/update-step.ts b/packages/web/src/graphql/mutations/update-step.ts index 966b7437..d6b53c1e 100644 --- a/packages/web/src/graphql/mutations/update-step.ts +++ b/packages/web/src/graphql/mutations/update-step.ts @@ -7,6 +7,7 @@ export const UPDATE_STEP = gql` type key appKey + parameters connection { id } diff --git a/packages/web/src/graphql/queries/get-flow.ts b/packages/web/src/graphql/queries/get-flow.ts index 946c0148..74e823d5 100644 --- a/packages/web/src/graphql/queries/get-flow.ts +++ b/packages/web/src/graphql/queries/get-flow.ts @@ -14,6 +14,7 @@ export const GET_FLOW = gql` connection { id } + parameters } } } diff --git a/packages/web/src/types/step.ts b/packages/web/src/types/step.ts index 9c85b183..73b692a0 100644 --- a/packages/web/src/types/step.ts +++ b/packages/web/src/types/step.ts @@ -10,6 +10,7 @@ export type Step = { appKey: string; type: StepType; previousStepId: number | null; + parameters: Record; connection: { id: number; };