Set steps output schema in a recoil family state (#10688)

- Create a workflow version component family state for each workflow
version : `stepId` => `StepOutputSchema`
- Populate this state when reaching the workflow visualizer of the
workflow version
- Wrap the right drawer when in edit mode with the context. It is the
only one who needs this schema

Next step:
- read this state from the variables
This commit is contained in:
Thomas Trompette
2025-03-06 14:31:35 +01:00
committed by GitHub
parent 17b488dd3b
commit 5ddf7c6475
8 changed files with 195 additions and 81 deletions

View File

@ -1,111 +1,64 @@
import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { workflowIdState } from '@/workflow/states/workflowIdState';
import { getStepDefinitionOrThrow } from '@/workflow/utils/getStepDefinitionOrThrow';
import { splitWorkflowTriggerEventName } from '@/workflow/utils/splitWorkflowTriggerEventName';
import { useStepsOutputSchema } from '@/workflow/hooks/useStepsOutputSchema';
import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow';
import { getActionIcon } from '@/workflow/workflow-steps/workflow-actions/utils/getActionIcon';
import { getTriggerIcon } from '@/workflow/workflow-trigger/utils/getTriggerIcon';
import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId';
import {
OutputSchema,
StepOutputSchema,
} from '@/workflow/workflow-variables/types/StepOutputSchema';
import { filterOutputSchema } from '@/workflow/workflow-variables/utils/filterOutputSchema';
import { getTriggerStepName } from '@/workflow/workflow-variables/utils/getTriggerStepName';
import isEmpty from 'lodash.isempty';
import { useRecoilValue } from 'recoil';
import { isEmptyObject } from '@tiptap/core';
import { isDefined } from 'twenty-shared';
import { isEmptyObject } from '~/utils/isEmptyObject';
export const useAvailableVariablesInWorkflowStep = ({
objectNameSingularToSelect,
}: {
objectNameSingularToSelect?: string;
}): StepOutputSchema[] => {
const workflowId = useRecoilValue(workflowIdState);
const workflow = useWorkflowWithCurrentVersion(workflowId);
const workflowSelectedNode = useWorkflowSelectedNodeOrThrow();
const flow = useFlowOrThrow();
const { getStepsOutputSchema } = useStepsOutputSchema({});
if (!isDefined(workflow)) {
return [];
}
const steps = flow.steps ?? [];
const trigger = flow.trigger;
const steps = flow.steps;
const stepDefinition = getStepDefinitionOrThrow({
stepId: workflowSelectedNode,
trigger,
steps,
});
if (
!isDefined(stepDefinition) ||
stepDefinition.type === 'trigger' ||
!isDefined(steps)
) {
return [];
}
const previousSteps = [];
const previousStepIds: string[] = [];
for (const step of steps) {
if (step.id === workflowSelectedNode) {
break;
}
previousSteps.push(step);
previousStepIds.push(step.id);
}
const result = [];
const availableStepsOutputSchema: StepOutputSchema[] =
getStepsOutputSchema(previousStepIds).filter(isDefined);
const filteredTriggerOutputSchema = filterOutputSchema(
trigger?.settings?.outputSchema as OutputSchema | undefined,
objectNameSingularToSelect,
);
const triggersOutputSchema: StepOutputSchema[] = getStepsOutputSchema([
TRIGGER_STEP_ID,
]).filter(isDefined);
if (
isDefined(trigger) &&
isDefined(filteredTriggerOutputSchema) &&
!isEmptyObject(filteredTriggerOutputSchema)
) {
const triggerIconKey =
trigger.type === 'DATABASE_EVENT'
? getTriggerIcon({
type: trigger.type,
eventName: splitWorkflowTriggerEventName(
trigger.settings?.eventName,
).event,
})
: getTriggerIcon({
type: trigger.type,
});
const availableVariablesInWorkflowStep = [
...availableStepsOutputSchema,
...triggersOutputSchema,
]
.map((stepOutputSchema) => {
const outputSchema = filterOutputSchema(
stepOutputSchema.outputSchema,
objectNameSingularToSelect,
) as OutputSchema;
result.push({
id: 'trigger',
name: isDefined(trigger.name)
? trigger.name
: getTriggerStepName(trigger),
icon: triggerIconKey,
outputSchema: filteredTriggerOutputSchema,
});
}
if (!isDefined(outputSchema) || isEmptyObject(outputSchema)) {
return undefined;
}
previousSteps.forEach((previousStep) => {
const filteredOutputSchema = filterOutputSchema(
previousStep.settings.outputSchema as OutputSchema,
objectNameSingularToSelect,
);
return {
id: stepOutputSchema.id,
name: stepOutputSchema.name,
icon: stepOutputSchema.icon,
outputSchema,
};
})
.filter(isDefined);
if (isDefined(filteredOutputSchema) && !isEmpty(filteredOutputSchema)) {
result.push({
id: previousStep.id,
name: previousStep.name,
icon: getActionIcon(previousStep.type),
outputSchema: filteredOutputSchema,
});
}
});
return result;
return availableVariablesInWorkflowStep;
};