From ddeba39a2ca8e26817eda4b43a6aee6eaeccfebd Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Tue, 11 Mar 2025 17:38:47 +0100 Subject: [PATCH] Reset step output schema when step is removed (#10762) When a step is deleted in a draft version, its variable are still available in the following steps. This is because step output schema was not reset. We needed either to refresh or to change version so output schema gets updated. This PR: - migrates to a family state global + context not linked to a component - add a reset step output schema function - reset when a step is removed --- .../CommandMenuWorkflowEditStep.tsx | 8 +- .../CommandMenuWorkflowRunViewStep.tsx | 8 +- .../CommandMenuWorkflowViewStep.tsx | 8 +- .../form-types/components/VariableChip.tsx | 17 ++- .../hooks/usePopulateStepsOutputSchema.ts | 76 ------------ .../workflow/hooks/useStepsOutputSchema.ts | 117 +++++++++++++----- .../states/context/WorkflowStepContext.ts | 8 ++ ...WorkflowVersionComponentInstanceContext.ts | 4 - .../stepsOutputSchemaFamilySelector.ts | 26 ++++ .../states/stepsOutputSchemaFamilyState.ts | 16 +-- .../getStepOutputSchemaFamilyStateKey.ts | 4 + .../components/WorkflowDiagramEffect.tsx | 14 ++- .../components/WorkflowRunVisualizer.tsx | 6 +- .../WorkflowRunVisualizerEffect.tsx | 12 ++ .../WorkflowVersionOutputSchemaEffect.tsx | 19 --- .../components/WorkflowVersionVisualizer.tsx | 14 +-- .../WorkflowVersionVisualizerEffect.tsx | 11 +- .../components/WorkflowVisualizer.tsx | 18 ++- .../RightDrawerWorkflowEditStep.tsx | 8 +- .../RightDrawerWorkflowRunViewStep.tsx | 8 +- .../RightDrawerWorkflowViewStep.tsx | 8 +- .../workflow-steps/hooks/useDeleteStep.ts | 12 +- .../useAvailableVariablesInWorkflowStep.ts | 21 ++-- .../decorators/WorkflowStepDecorator.tsx | 14 +-- 24 files changed, 242 insertions(+), 215 deletions(-) delete mode 100644 packages/twenty-front/src/modules/workflow/hooks/usePopulateStepsOutputSchema.ts create mode 100644 packages/twenty-front/src/modules/workflow/states/context/WorkflowStepContext.ts delete mode 100644 packages/twenty-front/src/modules/workflow/states/context/WorkflowVersionComponentInstanceContext.ts create mode 100644 packages/twenty-front/src/modules/workflow/states/selectors/stepsOutputSchemaFamilySelector.ts create mode 100644 packages/twenty-front/src/modules/workflow/utils/getStepOutputSchemaFamilyStateKey.ts delete mode 100644 packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionOutputSchemaEffect.tsx diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx index 3022c0a5c..4aeb0a9cd 100644 --- a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx @@ -2,7 +2,7 @@ import { workflowIdComponentState } from '@/command-menu/pages/workflow/states/w import { CommandMenuWorkflowEditStepContent } from '@/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepContent'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { WorkflowStepContextProvider } from '@/workflow/states/context/WorkflowStepContext'; import { isDefined } from 'twenty-shared'; export const CommandMenuWorkflowEditStep = () => { @@ -14,10 +14,10 @@ export const CommandMenuWorkflowEditStep = () => { } return ( - - + ); }; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx index 1adff9df2..1ff2c7c74 100644 --- a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx @@ -4,7 +4,7 @@ import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { WorkflowStepContextProvider } from '@/workflow/states/context/WorkflowStepContext'; import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; import { WorkflowRunStepInputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepInputDetail'; import { WorkflowRunStepOutputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepOutputDetail'; @@ -66,8 +66,8 @@ export const CommandMenuWorkflowRunViewStep = () => { } return ( - { {activeTabId === 'output' ? ( ) : null} - + ); }; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx index 554579f96..97825c9c1 100644 --- a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx @@ -1,5 +1,5 @@ import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { WorkflowStepContextProvider } from '@/workflow/states/context/WorkflowStepContext'; import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail'; @@ -7,8 +7,8 @@ export const CommandMenuWorkflowViewStep = () => { const flow = useFlowOrThrow(); const workflowSelectedNode = useWorkflowSelectedNodeOrThrow(); return ( - { steps={flow.steps} readonly /> - + ); }; diff --git a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/VariableChip.tsx b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/VariableChip.tsx index e286ff6f2..1fc18c8b4 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/form-types/components/VariableChip.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/form-types/components/VariableChip.tsx @@ -1,9 +1,11 @@ -import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema'; +import { useWorkflowStepContextOrThrow } from '@/workflow/states/context/WorkflowStepContext'; +import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector'; import { extractRawVariableNamePart } from '@/workflow/workflow-variables/utils/extractRawVariableNamePart'; import { searchVariableThroughOutputSchema } from '@/workflow/workflow-variables/utils/searchVariableThroughOutputSchema'; import { css, useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useLingui } from '@lingui/react/macro'; +import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; import { IconAlertTriangle, IconX } from 'twenty-ui'; @@ -76,21 +78,26 @@ export const VariableChip = ({ }: VariableChipProps) => { const theme = useTheme(); const { t } = useLingui(); - const { getStepsOutputSchema } = useStepsOutputSchema({}); + const { workflowVersionId } = useWorkflowStepContextOrThrow(); + const stepId = extractRawVariableNamePart({ rawVariableName, part: 'stepId', }); + const stepsOutputSchema = useRecoilValue( + stepsOutputSchemaFamilySelector({ + workflowVersionId, + stepIds: [stepId], + }), + ); if (!isDefined(stepId)) { return null; } - const stepOutputSchema = getStepsOutputSchema([stepId])?.[0]; - const { variableLabel, variablePathLabel } = searchVariableThroughOutputSchema({ - stepOutputSchema, + stepOutputSchema: stepsOutputSchema?.[0], rawVariableName, isFullRecord, }); diff --git a/packages/twenty-front/src/modules/workflow/hooks/usePopulateStepsOutputSchema.ts b/packages/twenty-front/src/modules/workflow/hooks/usePopulateStepsOutputSchema.ts deleted file mode 100644 index 590735ebb..000000000 --- a/packages/twenty-front/src/modules/workflow/hooks/usePopulateStepsOutputSchema.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; -import { stepsOutputSchemaComponentFamilyState } from '@/workflow/states/stepsOutputSchemaFamilyState'; -import { WorkflowVersion } from '@/workflow/types/Workflow'; -import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName'; -import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon'; -import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; -import { getTriggerIcon } from '@/workflow/workflow-trigger/utils/getTriggerIcon'; -import { - OutputSchema, - StepOutputSchema, -} from '@/workflow/workflow-variables/types/StepOutputSchema'; -import { getTriggerStepName } from '@/workflow/workflow-variables/utils/getTriggerStepName'; -import { useRecoilCallback } from 'recoil'; -import { isDefined } from 'twenty-shared'; - -export const usePopulateStepsOutputSchema = ({ - workflowVersionId, -}: { - workflowVersionId: string; -}) => { - const stepsOutputSchemaFamilyState = useRecoilComponentCallbackStateV2( - stepsOutputSchemaComponentFamilyState, - workflowVersionId, - ); - - const populateStepsOutputSchema = useRecoilCallback( - ({ set }) => - (workflowVersion: WorkflowVersion) => { - workflowVersion?.steps?.forEach((step) => { - const stepOutputSchema: StepOutputSchema = { - id: step.id, - name: step.name, - icon: getActionIcon(step.type), - outputSchema: step.settings.outputSchema as OutputSchema, - }; - - set(stepsOutputSchemaFamilyState(step.id), stepOutputSchema); - }); - - const trigger = workflowVersion.trigger; - - if (isDefined(trigger)) { - const triggerIconKey = - trigger.type === 'DATABASE_EVENT' - ? getTriggerIcon({ - type: trigger.type, - eventName: splitWorkflowTriggerEventName( - trigger.settings?.eventName, - ).event, - }) - : getTriggerIcon({ - type: trigger.type, - }); - - const triggerOutputSchema: StepOutputSchema = { - id: TRIGGER_STEP_ID, - name: isDefined(trigger.name) - ? trigger.name - : getTriggerStepName(trigger), - icon: triggerIconKey, - outputSchema: trigger.settings.outputSchema as OutputSchema, - }; - - set( - stepsOutputSchemaFamilyState(TRIGGER_STEP_ID), - triggerOutputSchema, - ); - } - }, - [stepsOutputSchemaFamilyState], - ); - - return { - populateStepsOutputSchema, - }; -}; diff --git a/packages/twenty-front/src/modules/workflow/hooks/useStepsOutputSchema.ts b/packages/twenty-front/src/modules/workflow/hooks/useStepsOutputSchema.ts index f7a7e0dd4..063ab1433 100644 --- a/packages/twenty-front/src/modules/workflow/hooks/useStepsOutputSchema.ts +++ b/packages/twenty-front/src/modules/workflow/hooks/useStepsOutputSchema.ts @@ -1,40 +1,97 @@ -import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow'; -import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; -import { stepsOutputSchemaComponentFamilyState } from '@/workflow/states/stepsOutputSchemaFamilyState'; +import { stepsOutputSchemaFamilyState } from '@/workflow/states/stepsOutputSchemaFamilyState'; +import { WorkflowVersion } from '@/workflow/types/Workflow'; +import { getStepOutputSchemaFamilyStateKey } from '@/workflow/utils/getStepOutputSchemaFamilyStateKey'; +import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName'; +import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon'; +import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; +import { getTriggerIcon } from '@/workflow/workflow-trigger/utils/getTriggerIcon'; +import { + OutputSchema, + StepOutputSchema, +} from '@/workflow/workflow-variables/types/StepOutputSchema'; +import { getTriggerStepName } from '@/workflow/workflow-variables/utils/getTriggerStepName'; import { useRecoilCallback } from 'recoil'; import { isDefined } from 'twenty-shared'; -export const useStepsOutputSchema = ({ - instanceIdFromProps, -}: { - instanceIdFromProps?: string; -}) => { - const instanceId = useAvailableComponentInstanceIdOrThrow( - WorkflowVersionComponentInstanceContext, - instanceIdFromProps, - ); +export const useStepsOutputSchema = () => { + const populateStepsOutputSchema = useRecoilCallback( + ({ set }) => + (workflowVersion: WorkflowVersion) => { + workflowVersion.steps?.forEach((step) => { + const stepOutputSchema: StepOutputSchema = { + id: step.id, + name: step.name, + icon: getActionIcon(step.type), + outputSchema: step.settings?.outputSchema as OutputSchema, + }; - const stepsOutputSchemaFamilyState = useRecoilComponentCallbackStateV2( - stepsOutputSchemaComponentFamilyState, - instanceId, - ); + set( + stepsOutputSchemaFamilyState( + getStepOutputSchemaFamilyStateKey(workflowVersion.id, step.id), + ), + stepOutputSchema, + ); + }); - const getStepsOutputSchema = useRecoilCallback( - ({ snapshot }) => - (stepIds: string[]) => { - const stepsOutputSchema = stepIds - .map((stepId) => - snapshot - .getLoadable(stepsOutputSchemaFamilyState(stepId)) - .getValue(), - ) - .filter(isDefined); + const trigger = workflowVersion.trigger; - return stepsOutputSchema; + if (isDefined(trigger)) { + const triggerIconKey = + trigger.type === 'DATABASE_EVENT' + ? getTriggerIcon({ + type: trigger.type, + eventName: splitWorkflowTriggerEventName( + trigger.settings?.eventName, + ).event, + }) + : getTriggerIcon({ + type: trigger.type, + }); + + const triggerOutputSchema: StepOutputSchema = { + id: TRIGGER_STEP_ID, + name: isDefined(trigger.name) + ? trigger.name + : getTriggerStepName(trigger), + icon: triggerIconKey, + outputSchema: trigger.settings?.outputSchema as OutputSchema, + }; + + set( + stepsOutputSchemaFamilyState( + getStepOutputSchemaFamilyStateKey( + workflowVersion.id, + TRIGGER_STEP_ID, + ), + ), + triggerOutputSchema, + ); + } }, - [stepsOutputSchemaFamilyState], + [], ); - return { getStepsOutputSchema }; + const deleteStepOutputSchema = useRecoilCallback( + ({ set }) => + ({ + stepId, + workflowVersionId, + }: { + stepId: string; + workflowVersionId: string; + }) => { + set( + stepsOutputSchemaFamilyState( + getStepOutputSchemaFamilyStateKey(workflowVersionId, stepId), + ), + null, + ); + }, + [], + ); + + return { + populateStepsOutputSchema, + deleteStepOutputSchema, + }; }; diff --git a/packages/twenty-front/src/modules/workflow/states/context/WorkflowStepContext.ts b/packages/twenty-front/src/modules/workflow/states/context/WorkflowStepContext.ts new file mode 100644 index 000000000..3f1962eab --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/states/context/WorkflowStepContext.ts @@ -0,0 +1,8 @@ +import { createRequiredContext } from '~/utils/createRequiredContext'; + +type WorkflowStepContextType = { + workflowVersionId: string; +}; + +export const [WorkflowStepContextProvider, useWorkflowStepContextOrThrow] = + createRequiredContext('WorkflowStepContext'); diff --git a/packages/twenty-front/src/modules/workflow/states/context/WorkflowVersionComponentInstanceContext.ts b/packages/twenty-front/src/modules/workflow/states/context/WorkflowVersionComponentInstanceContext.ts deleted file mode 100644 index dfa548cc9..000000000 --- a/packages/twenty-front/src/modules/workflow/states/context/WorkflowVersionComponentInstanceContext.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext'; - -export const WorkflowVersionComponentInstanceContext = - createComponentInstanceContext(); diff --git a/packages/twenty-front/src/modules/workflow/states/selectors/stepsOutputSchemaFamilySelector.ts b/packages/twenty-front/src/modules/workflow/states/selectors/stepsOutputSchemaFamilySelector.ts new file mode 100644 index 000000000..6e4367ed2 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/states/selectors/stepsOutputSchemaFamilySelector.ts @@ -0,0 +1,26 @@ +import { stepsOutputSchemaFamilyState } from '@/workflow/states/stepsOutputSchemaFamilyState'; +import { getStepOutputSchemaFamilyStateKey } from '@/workflow/utils/getStepOutputSchemaFamilyStateKey'; +import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema'; +import { selectorFamily } from 'recoil'; +import { isDefined } from 'twenty-shared'; + +export const stepsOutputSchemaFamilySelector = selectorFamily< + StepOutputSchema[], + { workflowVersionId: string; stepIds: string[] } +>({ + key: 'stepsOutputSchemaFamilySelector', + get: + ({ workflowVersionId, stepIds }) => + ({ get }) => { + const stepsOutputSchema = stepIds + .map((stepId) => + getStepOutputSchemaFamilyStateKey(workflowVersionId, stepId), + ) + .map((stepOutputSchemaKey) => + get(stepsOutputSchemaFamilyState(stepOutputSchemaKey)), + ) + .filter(isDefined); + + return stepsOutputSchema; + }, +}); diff --git a/packages/twenty-front/src/modules/workflow/states/stepsOutputSchemaFamilyState.ts b/packages/twenty-front/src/modules/workflow/states/stepsOutputSchemaFamilyState.ts index 2713dc708..0e86ad56d 100644 --- a/packages/twenty-front/src/modules/workflow/states/stepsOutputSchemaFamilyState.ts +++ b/packages/twenty-front/src/modules/workflow/states/stepsOutputSchemaFamilyState.ts @@ -1,10 +1,10 @@ -import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState'; import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema'; -export const stepsOutputSchemaComponentFamilyState = - createComponentFamilyStateV2({ - key: 'stepsOutputSchemaComponentFamilyState', - defaultValue: null, - componentInstanceContext: WorkflowVersionComponentInstanceContext, - }); +export const stepsOutputSchemaFamilyState = createFamilyState< + StepOutputSchema | null, + string | undefined +>({ + key: 'stepsOutputSchemaFamilyState', + defaultValue: null, +}); diff --git a/packages/twenty-front/src/modules/workflow/utils/getStepOutputSchemaFamilyStateKey.ts b/packages/twenty-front/src/modules/workflow/utils/getStepOutputSchemaFamilyStateKey.ts new file mode 100644 index 000000000..e4fbc8427 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/utils/getStepOutputSchemaFamilyStateKey.ts @@ -0,0 +1,4 @@ +export const getStepOutputSchemaFamilyStateKey = ( + workflowVersionId: string, + stepId: string, +) => `${workflowVersionId}-${stepId}`; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEffect.tsx index 3735632b4..dbc6de715 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramEffect.tsx @@ -1,4 +1,5 @@ import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; +import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema'; import { flowState } from '@/workflow/states/flowState'; import { workflowLastCreatedStepIdState } from '@/workflow/states/workflowLastCreatedStepIdState'; import { @@ -22,6 +23,7 @@ export const WorkflowDiagramEffect = ({ }) => { const setWorkflowDiagram = useSetRecoilState(workflowDiagramState); const setFlow = useSetRecoilState(flowState); + const { populateStepsOutputSchema } = useStepsOutputSchema(); const computeAndMergeNewWorkflowDiagram = useRecoilCallback( ({ snapshot, set }) => { @@ -66,8 +68,8 @@ export const WorkflowDiagramEffect = ({ [], ); + const currentVersion = workflowWithCurrentVersion?.currentVersion; useEffect(() => { - const currentVersion = workflowWithCurrentVersion?.currentVersion; if (!isDefined(currentVersion)) { setFlow(undefined); setWorkflowDiagram(undefined); @@ -86,8 +88,16 @@ export const WorkflowDiagramEffect = ({ computeAndMergeNewWorkflowDiagram, setFlow, setWorkflowDiagram, - workflowWithCurrentVersion?.currentVersion, + currentVersion, ]); + useEffect(() => { + if (!isDefined(currentVersion)) { + return; + } + + populateStepsOutputSchema(currentVersion); + }, [currentVersion, populateStepsOutputSchema]); + return null; }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizer.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizer.tsx index b4890ede3..3b7b9e69b 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizer.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizer.tsx @@ -1,7 +1,5 @@ import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; -import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion'; import { WorkflowRunDiagramCanvas } from '@/workflow/workflow-diagram/components/WorkflowRunDiagramCanvas'; -import { WorkflowVersionOutputSchemaEffect } from '@/workflow/workflow-diagram/components/WorkflowVersionOutputSchemaEffect'; import styled from '@emotion/styled'; import { isDefined } from 'twenty-shared'; @@ -15,15 +13,13 @@ export const WorkflowRunVisualizer = ({ workflowRunId: string; }) => { const workflowRun = useWorkflowRun({ workflowRunId }); - const workflowVersion = useWorkflowVersion(workflowRun?.workflowVersionId); - if (!isDefined(workflowRun) || !isDefined(workflowVersion)) { + if (!isDefined(workflowRun)) { return null; } return ( - ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx index 7db1186b1..293d7452d 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx @@ -1,4 +1,6 @@ +import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema'; import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; +import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion'; import { flowState } from '@/workflow/states/flowState'; import { workflowRunIdState } from '@/workflow/states/workflowRunIdState'; import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState'; @@ -13,10 +15,12 @@ export const WorkflowRunVisualizerEffect = ({ workflowRunId: string; }) => { const workflowRun = useWorkflowRun({ workflowRunId }); + const workflowVersion = useWorkflowVersion(workflowRun?.workflowVersionId); const setWorkflowRunId = useSetRecoilState(workflowRunIdState); const setFlow = useSetRecoilState(flowState); const setWorkflowDiagram = useSetRecoilState(workflowDiagramState); + const { populateStepsOutputSchema } = useStepsOutputSchema(); useEffect(() => { setWorkflowRunId(workflowRunId); @@ -50,5 +54,13 @@ export const WorkflowRunVisualizerEffect = ({ workflowRun?.workflowVersionId, ]); + useEffect(() => { + if (!isDefined(workflowVersion)) { + return; + } + + populateStepsOutputSchema(workflowVersion); + }, [populateStepsOutputSchema, workflowVersion]); + return null; }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionOutputSchemaEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionOutputSchemaEffect.tsx deleted file mode 100644 index 53e86178c..000000000 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionOutputSchemaEffect.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { usePopulateStepsOutputSchema } from '@/workflow/hooks/usePopulateStepsOutputSchema'; -import { WorkflowVersion } from '@/workflow/types/Workflow'; -import { useEffect } from 'react'; - -export const WorkflowVersionOutputSchemaEffect = ({ - workflowVersion, -}: { - workflowVersion: WorkflowVersion; -}) => { - const { populateStepsOutputSchema } = usePopulateStepsOutputSchema({ - workflowVersionId: workflowVersion.id, - }); - - useEffect(() => { - populateStepsOutputSchema(workflowVersion); - }, [populateStepsOutputSchema, workflowVersion]); - - return null; -}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizer.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizer.tsx index 349812afa..c4946ecb4 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizer.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizer.tsx @@ -1,6 +1,5 @@ import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion'; import { WorkflowDiagramCanvasReadonly } from '@/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonly'; -import { WorkflowVersionOutputSchemaEffect } from '@/workflow/workflow-diagram/components/WorkflowVersionOutputSchemaEffect'; import '@xyflow/react/dist/style.css'; import { isDefined } from 'twenty-shared'; @@ -11,10 +10,11 @@ export const WorkflowVersionVisualizer = ({ }) => { const workflowVersion = useWorkflowVersion(workflowVersionId); - return isDefined(workflowVersion) ? ( - <> - - - - ) : null; + if (!isDefined(workflowVersion)) { + return null; + } + + return ( + + ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizerEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizerEffect.tsx index e73cafc95..b1b673304 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizerEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVersionVisualizerEffect.tsx @@ -1,3 +1,4 @@ +import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema'; import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion'; import { flowState } from '@/workflow/states/flowState'; import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState'; @@ -16,7 +17,7 @@ export const WorkflowVersionVisualizerEffect = ({ const setFlow = useSetRecoilState(flowState); const setWorkflowDiagram = useSetRecoilState(workflowDiagramState); - + const { populateStepsOutputSchema } = useStepsOutputSchema(); useEffect(() => { if (!isDefined(workflowVersion)) { setFlow(undefined); @@ -45,5 +46,13 @@ export const WorkflowVersionVisualizerEffect = ({ setWorkflowDiagram(nextWorkflowDiagram); }, [setWorkflowDiagram, workflowVersion]); + useEffect(() => { + if (!isDefined(workflowVersion)) { + return; + } + + populateStepsOutputSchema(workflowVersion); + }, [populateStepsOutputSchema, workflowVersion]); + return null; }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVisualizer.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVisualizer.tsx index 8bbb4032f..94d3b6993 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVisualizer.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowVisualizer.tsx @@ -1,28 +1,24 @@ import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; import { WorkflowDiagramCanvasEditable } from '@/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable'; import { WorkflowDiagramEffect } from '@/workflow/workflow-diagram/components/WorkflowDiagramEffect'; -import { WorkflowVersionOutputSchemaEffect } from '@/workflow/workflow-diagram/components/WorkflowVersionOutputSchemaEffect'; import '@xyflow/react/dist/style.css'; import { isDefined } from 'twenty-shared'; export const WorkflowVisualizer = ({ workflowId }: { workflowId: string }) => { const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(workflowId); - const workflowVersion = workflowWithCurrentVersion?.currentVersion; + + if (!isDefined(workflowWithCurrentVersion)) { + return null; + } return ( <> - {isDefined(workflowVersion) && ( - - )} - - {isDefined(workflowWithCurrentVersion) ? ( - - ) : null} + ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowEditStep.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowEditStep.tsx index a9a2f6cb7..acd9c20f8 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowEditStep.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowEditStep.tsx @@ -1,5 +1,5 @@ import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { WorkflowStepContextProvider } from '@/workflow/states/context/WorkflowStepContext'; import { workflowIdState } from '@/workflow/states/workflowIdState'; import { RightDrawerWorkflowEditStepContent } from '@/workflow/workflow-steps/components/RightDrawerWorkflowEditStepContent'; import { useRecoilValue } from 'recoil'; @@ -14,10 +14,10 @@ export const RightDrawerWorkflowEditStep = () => { } return ( - - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx index bb628304f..b9ffcc93c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep.tsx @@ -4,7 +4,7 @@ import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { WorkflowStepContextProvider } from '@/workflow/states/context/WorkflowStepContext'; import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; import { WorkflowRunStepInputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepInputDetail'; import { WorkflowRunStepOutputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepOutputDetail'; @@ -66,8 +66,8 @@ export const RightDrawerWorkflowRunViewStep = () => { } return ( - { {activeTabId === 'output' ? ( ) : null} - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowViewStep.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowViewStep.tsx index 727ddc656..95a1dfc70 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowViewStep.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/RightDrawerWorkflowViewStep.tsx @@ -1,5 +1,5 @@ import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { WorkflowStepContextProvider } from '@/workflow/states/context/WorkflowStepContext'; import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail'; @@ -8,8 +8,8 @@ export const RightDrawerWorkflowViewStep = () => { const workflowSelectedNode = useWorkflowSelectedNodeOrThrow(); return ( - { steps={flow.steps} readonly /> - + ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useDeleteStep.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useDeleteStep.ts index bb5008497..4fa6adaea 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useDeleteStep.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useDeleteStep.ts @@ -4,6 +4,7 @@ import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { useDeleteWorkflowVersionStep } from '@/workflow/hooks/useDeleteWorkflowVersionStep'; import { useGetUpdatableWorkflowVersion } from '@/workflow/hooks/useGetUpdatableWorkflowVersion'; +import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema'; import { WorkflowVersion, WorkflowWithCurrentVersion, @@ -20,6 +21,7 @@ export const useDeleteStep = ({ useUpdateOneRecord({ objectNameSingular: CoreObjectNameSingular.WorkflowVersion, }); + const { deleteStepOutputSchema } = useStepsOutputSchema(); const { getUpdatableWorkflowVersion } = useGetUpdatableWorkflowVersion(); const { closeRightDrawer } = useRightDrawer(); @@ -36,11 +38,15 @@ export const useDeleteStep = ({ trigger: null, }, }); - return; + } else { + await deleteWorkflowVersionStep({ + workflowVersionId, + stepId, + }); } - await deleteWorkflowVersionStep({ - workflowVersionId, + deleteStepOutputSchema({ stepId, + workflowVersionId, }); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useAvailableVariablesInWorkflowStep.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useAvailableVariablesInWorkflowStep.ts index 30544f0c5..2ed636550 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useAvailableVariablesInWorkflowStep.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/hooks/useAvailableVariablesInWorkflowStep.ts @@ -1,5 +1,5 @@ import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; -import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema'; +import { stepsOutputSchemaFamilySelector } from '@/workflow/states/selectors/stepsOutputSchemaFamilySelector'; import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; import { @@ -8,6 +8,7 @@ import { } from '@/workflow/workflow-variables/types/StepOutputSchema'; import { filterOutputSchema } from '@/workflow/workflow-variables/utils/filterOutputSchema'; import { isEmptyObject } from '@tiptap/core'; +import { useRecoilValue } from 'recoil'; import { isDefined } from 'twenty-shared'; export const useAvailableVariablesInWorkflowStep = ({ @@ -17,7 +18,6 @@ export const useAvailableVariablesInWorkflowStep = ({ }): StepOutputSchema[] => { const workflowSelectedNode = useWorkflowSelectedNodeOrThrow(); const flow = useFlowOrThrow(); - const { getStepsOutputSchema } = useStepsOutputSchema({}); const steps = flow.steps ?? []; @@ -30,17 +30,14 @@ export const useAvailableVariablesInWorkflowStep = ({ previousStepIds.push(step.id); } - const availableStepsOutputSchema: StepOutputSchema[] = - getStepsOutputSchema(previousStepIds).filter(isDefined); + const availableStepsOutputSchema: StepOutputSchema[] = useRecoilValue( + stepsOutputSchemaFamilySelector({ + workflowVersionId: flow.workflowVersionId, + stepIds: [TRIGGER_STEP_ID, ...previousStepIds], + }), + ); - const triggersOutputSchema: StepOutputSchema[] = isDefined(flow.trigger) - ? getStepsOutputSchema([TRIGGER_STEP_ID]).filter(isDefined) - : []; - - const availableVariablesInWorkflowStep = [ - ...availableStepsOutputSchema, - ...triggersOutputSchema, - ] + const availableVariablesInWorkflowStep = availableStepsOutputSchema .map((stepOutputSchema) => { const outputSchema = filterOutputSchema( stepOutputSchema.outputSchema, diff --git a/packages/twenty-front/src/testing/decorators/WorkflowStepDecorator.tsx b/packages/twenty-front/src/testing/decorators/WorkflowStepDecorator.tsx index f0f0458ae..56c71bf33 100644 --- a/packages/twenty-front/src/testing/decorators/WorkflowStepDecorator.tsx +++ b/packages/twenty-front/src/testing/decorators/WorkflowStepDecorator.tsx @@ -1,5 +1,5 @@ -import { usePopulateStepsOutputSchema } from '@/workflow/hooks/usePopulateStepsOutputSchema'; -import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema'; +import { WorkflowStepContextProvider } from '@/workflow/states/context/WorkflowStepContext'; import { workflowIdState } from '@/workflow/states/workflowIdState'; import { WorkflowVersion } from '@/workflow/types/Workflow'; import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState'; @@ -16,9 +16,7 @@ export const WorkflowStepDecorator: Decorator = (Story) => { const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState); const workflowVersion = getWorkflowMock().versions.edges[0] .node as WorkflowVersion; - const { populateStepsOutputSchema } = usePopulateStepsOutputSchema({ - workflowVersionId: workflowVersion.id, - }); + const { populateStepsOutputSchema } = useStepsOutputSchema(); const [ready, setReady] = useState(false); useEffect(() => { @@ -34,10 +32,10 @@ export const WorkflowStepDecorator: Decorator = (Story) => { ]); return ( - {ready && } - + ); };