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
This commit is contained in:
Thomas Trompette
2025-03-11 17:38:47 +01:00
committed by GitHub
parent 680935e605
commit ddeba39a2c
24 changed files with 242 additions and 215 deletions

View File

@ -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 (
<WorkflowVersionComponentInstanceContext.Provider
value={{ instanceId: workflow.currentVersion.id }}
<WorkflowStepContextProvider
value={{ workflowVersionId: workflow.currentVersion.id }}
>
<CommandMenuWorkflowEditStepContent workflow={workflow} />
</WorkflowVersionComponentInstanceContext.Provider>
</WorkflowStepContextProvider>
);
};

View File

@ -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 (
<WorkflowVersionComponentInstanceContext.Provider
value={{ instanceId: workflowRun.workflowVersionId }}
<WorkflowStepContextProvider
value={{ workflowVersionId: workflowRun.workflowVersionId }}
>
<StyledTabListContainer>
<TabList
@ -93,6 +93,6 @@ export const CommandMenuWorkflowRunViewStep = () => {
{activeTabId === 'output' ? (
<WorkflowRunStepOutputDetail stepId={workflowSelectedNode} />
) : null}
</WorkflowVersionComponentInstanceContext.Provider>
</WorkflowStepContextProvider>
);
};

View File

@ -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 (
<WorkflowVersionComponentInstanceContext.Provider
value={{ instanceId: flow.workflowVersionId }}
<WorkflowStepContextProvider
value={{ workflowVersionId: flow.workflowVersionId }}
>
<WorkflowStepDetail
stepId={workflowSelectedNode}
@ -16,6 +16,6 @@ export const CommandMenuWorkflowViewStep = () => {
steps={flow.steps}
readonly
/>
</WorkflowVersionComponentInstanceContext.Provider>
</WorkflowStepContextProvider>
);
};

View File

@ -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,
});

View File

@ -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,
};
};

View File

@ -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,
};
};

View File

@ -0,0 +1,8 @@
import { createRequiredContext } from '~/utils/createRequiredContext';
type WorkflowStepContextType = {
workflowVersionId: string;
};
export const [WorkflowStepContextProvider, useWorkflowStepContextOrThrow] =
createRequiredContext<WorkflowStepContextType>('WorkflowStepContext');

View File

@ -1,4 +0,0 @@
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
export const WorkflowVersionComponentInstanceContext =
createComponentInstanceContext();

View File

@ -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;
},
});

View File

@ -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<StepOutputSchema | null, string>({
key: 'stepsOutputSchemaComponentFamilyState',
defaultValue: null,
componentInstanceContext: WorkflowVersionComponentInstanceContext,
});
export const stepsOutputSchemaFamilyState = createFamilyState<
StepOutputSchema | null,
string | undefined
>({
key: 'stepsOutputSchemaFamilyState',
defaultValue: null,
});

View File

@ -0,0 +1,4 @@
export const getStepOutputSchemaFamilyStateKey = (
workflowVersionId: string,
stepId: string,
) => `${workflowVersionId}-${stepId}`;

View File

@ -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;
};

View File

@ -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 (
<StyledContainer>
<WorkflowVersionOutputSchemaEffect workflowVersion={workflowVersion} />
<WorkflowRunDiagramCanvas workflowRunStatus={workflowRun.status} />
</StyledContainer>
);

View File

@ -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;
};

View File

@ -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;
};

View File

@ -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) ? (
<>
<WorkflowVersionOutputSchemaEffect workflowVersion={workflowVersion} />
<WorkflowDiagramCanvasReadonly versionStatus={workflowVersion.status} />
</>
) : null;
if (!isDefined(workflowVersion)) {
return null;
}
return (
<WorkflowDiagramCanvasReadonly versionStatus={workflowVersion.status} />
);
};

View File

@ -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;
};

View File

@ -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 (
<>
<WorkflowDiagramEffect
workflowWithCurrentVersion={workflowWithCurrentVersion}
/>
{isDefined(workflowVersion) && (
<WorkflowVersionOutputSchemaEffect workflowVersion={workflowVersion} />
)}
{isDefined(workflowWithCurrentVersion) ? (
<WorkflowDiagramCanvasEditable
versionStatus={workflowWithCurrentVersion.currentVersion.status}
/>
) : null}
<WorkflowDiagramCanvasEditable
versionStatus={workflowWithCurrentVersion.currentVersion.status}
/>
</>
);
};

View File

@ -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 (
<WorkflowVersionComponentInstanceContext.Provider
value={{ instanceId: workflow.currentVersion.id }}
<WorkflowStepContextProvider
value={{ workflowVersionId: workflow.currentVersion.id }}
>
<RightDrawerWorkflowEditStepContent workflow={workflow} />
</WorkflowVersionComponentInstanceContext.Provider>
</WorkflowStepContextProvider>
);
};

View File

@ -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 (
<WorkflowVersionComponentInstanceContext.Provider
value={{ instanceId: flow.workflowVersionId }}
<WorkflowStepContextProvider
value={{ workflowVersionId: flow.workflowVersionId }}
>
<StyledTabListContainer>
<TabList
@ -93,6 +93,6 @@ export const RightDrawerWorkflowRunViewStep = () => {
{activeTabId === 'output' ? (
<WorkflowRunStepOutputDetail stepId={workflowSelectedNode} />
) : null}
</WorkflowVersionComponentInstanceContext.Provider>
</WorkflowStepContextProvider>
);
};

View File

@ -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 (
<WorkflowVersionComponentInstanceContext.Provider
value={{ instanceId: flow.workflowVersionId }}
<WorkflowStepContextProvider
value={{ workflowVersionId: flow.workflowVersionId }}
>
<WorkflowStepDetail
stepId={workflowSelectedNode}
@ -17,6 +17,6 @@ export const RightDrawerWorkflowViewStep = () => {
steps={flow.steps}
readonly
/>
</WorkflowVersionComponentInstanceContext.Provider>
</WorkflowStepContextProvider>
);
};

View File

@ -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<WorkflowVersion>({
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,
});
};

View File

@ -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,

View File

@ -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 (
<WorkflowVersionComponentInstanceContext.Provider
value={{ instanceId: workflowVersion.id }}
<WorkflowStepContextProvider
value={{ workflowVersionId: workflowVersion.id }}
>
{ready && <Story />}
</WorkflowVersionComponentInstanceContext.Provider>
</WorkflowStepContextProvider>
);
};