diff --git a/packages/backend/src/graphql/mutation-resolvers.js b/packages/backend/src/graphql/mutation-resolvers.js index 7305b068..b17acdd2 100644 --- a/packages/backend/src/graphql/mutation-resolvers.js +++ b/packages/backend/src/graphql/mutation-resolvers.js @@ -7,7 +7,6 @@ import generateAuthUrl from './mutations/generate-auth-url.js'; import createConnection from './mutations/create-connection.js'; import resetConnection from './mutations/reset-connection.js'; import updateConnection from './mutations/update-connection.js'; -import updateFlowStatus from './mutations/update-flow-status.js'; const mutationResolvers = { createConnection, @@ -16,7 +15,6 @@ const mutationResolvers = { resetConnection, updateConnection, updateCurrentUser, - updateFlowStatus, updateUser, verifyConnection, }; diff --git a/packages/backend/src/graphql/mutations/update-flow-status.js b/packages/backend/src/graphql/mutations/update-flow-status.js deleted file mode 100644 index 0df919ad..00000000 --- a/packages/backend/src/graphql/mutations/update-flow-status.js +++ /dev/null @@ -1,91 +0,0 @@ -import Flow from '../../models/flow.js'; -import flowQueue from '../../queues/flow.js'; -import { - REMOVE_AFTER_30_DAYS_OR_150_JOBS, - REMOVE_AFTER_7_DAYS_OR_50_JOBS, -} from '../../helpers/remove-job-configuration.js'; -import globalVariable from '../../helpers/global-variable.js'; - -const JOB_NAME = 'flow'; -const EVERY_15_MINUTES_CRON = '*/15 * * * *'; - -const updateFlowStatus = async (_parent, params, context) => { - const conditions = context.currentUser.can('publish', 'Flow'); - const isCreator = conditions.isCreator; - const allFlows = Flow.query(); - const userFlows = context.currentUser.$relatedQuery('flows'); - const baseQuery = isCreator ? userFlows : allFlows; - - let flow = await baseQuery - .clone() - .findOne({ - id: params.input.id, - }) - .throwIfNotFound(); - - const newActiveValue = params.input.active; - - if (flow.active === newActiveValue) { - return flow; - } - - const triggerStep = await flow.getTriggerStep(); - - if (triggerStep.status === 'incomplete') { - throw flow.IncompleteStepsError; - } - - const trigger = await triggerStep.getTriggerCommand(); - const interval = trigger.getInterval?.(triggerStep.parameters); - const repeatOptions = { - pattern: interval || EVERY_15_MINUTES_CRON, - }; - - if (trigger.type === 'webhook') { - const $ = await globalVariable({ - flow, - connection: await triggerStep.$relatedQuery('connection'), - app: await triggerStep.getApp(), - step: triggerStep, - testRun: false, - }); - - if (newActiveValue && trigger.registerHook) { - await trigger.registerHook($); - } else if (!newActiveValue && trigger.unregisterHook) { - await trigger.unregisterHook($); - } - } else { - if (newActiveValue) { - flow = await flow.$query().patchAndFetch({ - publishedAt: new Date().toISOString(), - }); - - const jobName = `${JOB_NAME}-${flow.id}`; - - await flowQueue.add( - jobName, - { flowId: flow.id }, - { - repeat: repeatOptions, - jobId: flow.id, - removeOnComplete: REMOVE_AFTER_7_DAYS_OR_50_JOBS, - removeOnFail: REMOVE_AFTER_30_DAYS_OR_150_JOBS, - } - ); - } else { - const repeatableJobs = await flowQueue.getRepeatableJobs(); - const job = repeatableJobs.find((job) => job.id === flow.id); - - await flowQueue.removeRepeatableByKey(job.key); - } - } - - flow = await flow.$query().withGraphFetched('steps').patchAndFetch({ - active: newActiveValue, - }); - - return flow; -}; - -export default updateFlowStatus; diff --git a/packages/backend/src/graphql/schema.graphql b/packages/backend/src/graphql/schema.graphql index 680cd798..a0e394c8 100644 --- a/packages/backend/src/graphql/schema.graphql +++ b/packages/backend/src/graphql/schema.graphql @@ -8,7 +8,6 @@ type Mutation { resetConnection(input: ResetConnectionInput): Connection updateConnection(input: UpdateConnectionInput): Connection updateCurrentUser(input: UpdateCurrentUserInput): User - updateFlowStatus(input: UpdateFlowStatusInput): Flow updateUser(input: UpdateUserInput): User verifyConnection(input: VerifyConnectionInput): Connection } @@ -234,11 +233,6 @@ input VerifyConnectionInput { id: String! } -input UpdateFlowStatusInput { - id: String! - active: Boolean! -} - input ExecuteFlowInput { stepId: String! } diff --git a/packages/backend/src/models/flow.js b/packages/backend/src/models/flow.js index 2b2d4d10..163e32c9 100644 --- a/packages/backend/src/models/flow.js +++ b/packages/backend/src/models/flow.js @@ -125,7 +125,13 @@ class Flow extends Base { get IncompleteStepsError() { return new ValidationError({ - message: 'All steps should be completed before updating flow status!', + data: { + flow: [ + { + message: 'All steps should be completed before updating flow status!' + } + ], + }, type: 'incompleteStepsError', }); } @@ -366,8 +372,13 @@ class Flow extends Base { if (allSteps.length < 2) { throw new ValidationError({ - message: - 'There should be at least one trigger and one action steps in the flow!', + data: { + flow: [ + { + message: 'There should be at least one trigger and one action steps in the flow!' + } + ], + }, type: 'insufficientStepsError', }); } diff --git a/packages/web/src/components/EditorLayout/index.jsx b/packages/web/src/components/EditorLayout/index.jsx index 63981930..c8878b5c 100644 --- a/packages/web/src/components/EditorLayout/index.jsx +++ b/packages/web/src/components/EditorLayout/index.jsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { Link, useParams } from 'react-router-dom'; -import { useMutation } from '@apollo/client'; import Stack from '@mui/material/Stack'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; @@ -16,12 +15,11 @@ import Container from 'components/Container'; import Editor from 'components/Editor'; import Can from 'components/Can'; import useFormatMessage from 'hooks/useFormatMessage'; -import { UPDATE_FLOW_STATUS } from 'graphql/mutations/update-flow-status'; import * as URLS from 'config/urls'; import { TopBar } from './style'; import useFlow from 'hooks/useFlow'; import useUpdateFlow from 'hooks/useUpdateFlow'; -import { useQueryClient } from '@tanstack/react-query'; +import useUpdateFlowStatus from 'hooks/useUpdateFlowStatus'; import EditorNew from 'components/EditorNew/EditorNew'; const useNewFlowEditor = process.env.REACT_APP_USE_NEW_FLOW_EDITOR === 'true'; @@ -30,10 +28,9 @@ export default function EditorLayout() { const { flowId } = useParams(); const formatMessage = useFormatMessage(); const { mutateAsync: updateFlow } = useUpdateFlow(flowId); - const [updateFlowStatus] = useMutation(UPDATE_FLOW_STATUS); + const { mutateAsync: updateFlowStatus } = useUpdateFlowStatus(flowId); const { data, isLoading: isFlowLoading } = useFlow(flowId); const flow = data?.data; - const queryClient = useQueryClient(); const onFlowNameUpdate = async (name) => { await updateFlow({ @@ -41,24 +38,6 @@ export default function EditorLayout() { }); }; - const onFlowStatusUpdate = React.useCallback( - async (active) => { - try { - await updateFlowStatus({ - variables: { - input: { - id: flowId, - active, - }, - }, - }); - - await queryClient.invalidateQueries({ queryKey: ['flows', flowId] }); - } catch (err) {} - }, - [flowId, queryClient], - ); - return ( <> onFlowStatusUpdate(!flow.active)} + onClick={() => updateFlowStatus(!flow.active)} data-test={ flow?.active ? 'unpublish-flow-button' : 'publish-flow-button' } @@ -153,7 +132,7 @@ export default function EditorLayout() {