From afed36ef5b1a1629a98e709c9148c75c48828c87 Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Thu, 30 Jan 2025 17:19:47 +0100 Subject: [PATCH] Remove before-after + fix header label (#9932) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix header label on step Before Capture d’écran 2025-01-30 à 12 11 27 Capture d’écran 2025-01-30 à 13 27 40 After Capture d’écran 2025-01-30 à 13 29 00 Capture d’écran 2025-01-30 à 13 29 25 - Remove before - after when there is only one of them --- .../WorkflowVariablesDropdownFieldItems.tsx | 39 +++----------- .../WorkflowVariablesDropdownObjectItems.tsx | 33 ++++-------- .../getCurrentSubStepFromPath.test.ts | 39 ++++++++++++++ .../__tests__/getStepHeaderLabel.test.ts | 54 +++++++++++++++++++ .../utils/getCurrentSubStepFromPath.ts | 23 ++++++++ .../utils/getStepHeaderLabel.ts | 40 ++++++++++++++ .../generate-fake-object-record-event.ts | 22 +++----- 7 files changed, 178 insertions(+), 72 deletions(-) create mode 100644 packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getCurrentSubStepFromPath.test.ts create mode 100644 packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts create mode 100644 packages/twenty-front/src/modules/workflow/workflow-variables/utils/getCurrentSubStepFromPath.ts create mode 100644 packages/twenty-front/src/modules/workflow/workflow-variables/utils/getStepHeaderLabel.ts diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx b/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx index fe4947fdb..8026fdf62 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/components/WorkflowVariablesDropdownFieldItems.tsx @@ -5,7 +5,6 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM import { BaseOutputSchema, LinkOutputSchema, - OutputSchema, StepOutputSchema, } from '@/workflow/workflow-variables/types/StepOutputSchema'; import { isBaseOutputSchema } from '@/workflow/workflow-variables/utils/isBaseOutputSchema'; @@ -15,6 +14,8 @@ import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionState'; import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState'; import { WORKFLOW_SERVERLESS_FUNCTION_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/workflow-actions/constants/WorkflowServerlessFunctionTabListComponentId'; +import { getCurrentSubStepFromPath } from '@/workflow/workflow-variables/utils/getCurrentSubStepFromPath'; +import { getStepHeaderLabel } from '@/workflow/workflow-variables/utils/getStepHeaderLabel'; import { isLinkOutputSchema } from '@/workflow/workflow-variables/utils/isLinkOutputSchema'; import { useState } from 'react'; import { useSetRecoilState } from 'recoil'; @@ -48,22 +49,8 @@ export const WorkflowVariablesDropdownFieldItems = ({ workflowDiagramTriggerNodeSelectionState, ); - const getCurrentSubStep = (): OutputSchema => { - let currentSubStep = step.outputSchema; - - for (const key of currentPath) { - if (isRecordOutputSchema(currentSubStep)) { - currentSubStep = currentSubStep.fields[key]?.value; - } else if (isBaseOutputSchema(currentSubStep)) { - currentSubStep = currentSubStep[key]?.value; - } - } - - return currentSubStep; - }; - const getDisplayedSubStepFields = () => { - const currentSubStep = getCurrentSubStep(); + const currentSubStep = getCurrentSubStepFromPath(step, currentPath); if (isLinkOutputSchema(currentSubStep)) { return { link: currentSubStep.link }; @@ -75,7 +62,7 @@ export const WorkflowVariablesDropdownFieldItems = ({ }; const handleSelectField = (key: string) => { - const currentSubStep = getCurrentSubStep(); + const currentSubStep = getCurrentSubStepFromPath(step, currentPath); const handleSelectBaseOutputSchema = ( baseOutputSchema: BaseOutputSchema, @@ -115,20 +102,6 @@ export const WorkflowVariablesDropdownFieldItems = ({ } }; - const getHeaderLabel = () => { - if (currentPath.length === 0) { - return step.name; - } - - const subStepName = currentPath.at(-1); - - if (isDefined(subStepName) && isRecordOutputSchema(step.outputSchema)) { - return step.outputSchema.fields[subStepName].label; - } - - return subStepName; - }; - const displayedObject = getDisplayedSubStepFields(); const options = displayedObject ? Object.entries(displayedObject) : []; @@ -147,7 +120,9 @@ export const WorkflowVariablesDropdownFieldItems = ({ onClick={goBack} style={{ position: 'fixed' }} > - + { - let currentSubStep = step.outputSchema; - - for (const key of currentPath) { - if (isRecordOutputSchema(currentSubStep)) { - currentSubStep = currentSubStep.fields[key]?.value; - } else if (isBaseOutputSchema(currentSubStep)) { - currentSubStep = currentSubStep[key]?.value; - } - } - - return currentSubStep; - }; - const getDisplayedSubStepFields = () => { - const currentSubStep = getCurrentSubStep(); + const currentSubStep = getCurrentSubStepFromPath(step, currentPath); if (isRecordOutputSchema(currentSubStep)) { return currentSubStep.fields; @@ -57,7 +42,7 @@ export const WorkflowVariablesDropdownObjectItems = ({ }; const getDisplayedSubStepObject = () => { - const currentSubStep = getCurrentSubStep(); + const currentSubStep = getCurrentSubStepFromPath(step, currentPath); if (!isRecordOutputSchema(currentSubStep)) { return; @@ -67,7 +52,7 @@ export const WorkflowVariablesDropdownObjectItems = ({ }; const handleSelectObject = () => { - const currentSubStep = getCurrentSubStep(); + const currentSubStep = getCurrentSubStepFromPath(step, currentPath); if (!isRecordOutputSchema(currentSubStep)) { return; @@ -91,8 +76,6 @@ export const WorkflowVariablesDropdownObjectItems = ({ } }; - const headerLabel = currentPath.length === 0 ? step.name : currentPath.at(-1); - const displayedSubStepObject = getDisplayedSubStepObject(); const shouldDisplaySubStepObject = searchInputValue @@ -116,7 +99,9 @@ export const WorkflowVariablesDropdownObjectItems = ({ return ( <> - + { + it('should return the current sub step from the path', () => { + const path = ['company', 'name']; + expect(getCurrentSubStepFromPath(mockStep, path)).toBe('Twenty'); + }); + + it('should return undefined when the path is not valid', () => { + const path = ['company', 'unknown']; + expect(getCurrentSubStepFromPath(mockStep, path)).toBe(undefined); + }); +}); diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts new file mode 100644 index 000000000..28a4da3e6 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/__tests__/getStepHeaderLabel.test.ts @@ -0,0 +1,54 @@ +import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema'; +import { getStepHeaderLabel } from '@/workflow/workflow-variables/utils/getStepHeaderLabel'; + +const mockStep = { + id: 'step-1', + name: 'Step 1', + outputSchema: { + company: { + isLeaf: false, + icon: 'company', + label: 'Company', + value: { + object: { + nameSingular: 'company', + fieldIdName: 'id', + label: 'Company', + value: 'John', + isLeaf: true, + }, + fields: { + name: { label: 'Name', value: 'Twenty', isLeaf: true }, + address: { + label: 'Address', + value: { + street: { label: 'Street', value: '123 Main St', isLeaf: true }, + city: { label: 'City', value: 'New York', isLeaf: true }, + state: { label: 'State', value: 'NY', isLeaf: true }, + zip: { label: 'Zip', value: '10001', isLeaf: true }, + }, + isLeaf: false, + }, + }, + _outputSchemaType: 'RECORD', + }, + }, + }, +} satisfies StepOutputSchema; + +describe('getStepHeaderLabel', () => { + it('should return the step name when the path is empty', () => { + const currentPath: string[] = []; + expect(getStepHeaderLabel(mockStep, currentPath)).toBe('Step 1'); + }); + + it('should return the field label when the path is not empty', () => { + const currentPath: string[] = ['company']; + expect(getStepHeaderLabel(mockStep, currentPath)).toBe('Company'); + }); + + it('should return the nested field label when the path is not empty', () => { + const currentPath: string[] = ['company', 'address']; + expect(getStepHeaderLabel(mockStep, currentPath)).toBe('Address'); + }); +}); diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/getCurrentSubStepFromPath.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/getCurrentSubStepFromPath.ts new file mode 100644 index 000000000..3ccbb4182 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/getCurrentSubStepFromPath.ts @@ -0,0 +1,23 @@ +import { + OutputSchema, + StepOutputSchema, +} from '@/workflow/workflow-variables/types/StepOutputSchema'; +import { isBaseOutputSchema } from '@/workflow/workflow-variables/utils/isBaseOutputSchema'; +import { isRecordOutputSchema } from '@/workflow/workflow-variables/utils/isRecordOutputSchema'; + +export const getCurrentSubStepFromPath = ( + step: StepOutputSchema, + path: string[], +): OutputSchema => { + let currentSubStep = step.outputSchema; + + for (const key of path) { + if (isRecordOutputSchema(currentSubStep)) { + currentSubStep = currentSubStep.fields[key]?.value; + } else if (isBaseOutputSchema(currentSubStep)) { + currentSubStep = currentSubStep[key]?.value; + } + } + + return currentSubStep; +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-variables/utils/getStepHeaderLabel.ts b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/getStepHeaderLabel.ts new file mode 100644 index 000000000..3b734eaab --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-variables/utils/getStepHeaderLabel.ts @@ -0,0 +1,40 @@ +import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema'; +import { getCurrentSubStepFromPath } from '@/workflow/workflow-variables/utils/getCurrentSubStepFromPath'; +import { isBaseOutputSchema } from '@/workflow/workflow-variables/utils/isBaseOutputSchema'; +import { isRecordOutputSchema } from '@/workflow/workflow-variables/utils/isRecordOutputSchema'; +import { isDefined } from '~/utils/isDefined'; + +export const getStepHeaderLabel = ( + step: StepOutputSchema, + currentPath: string[], +) => { + if (currentPath.length === 0) { + return step.name; + } + + const subStepName = currentPath.at(-1); + const previousSubStep = getCurrentSubStepFromPath( + step, + currentPath.slice(0, -1), + ); + + if (!subStepName) { + return step.name; + } + + if ( + isRecordOutputSchema(previousSubStep) && + isDefined(previousSubStep.fields[subStepName]?.label) + ) { + return previousSubStep.fields[subStepName].label; + } + + if ( + isBaseOutputSchema(previousSubStep) && + isDefined(previousSubStep[subStepName]?.label) + ) { + return previousSubStep[subStepName].label; + } + + return subStepName; +}; diff --git a/packages/twenty-server/src/modules/workflow/workflow-builder/utils/generate-fake-object-record-event.ts b/packages/twenty-server/src/modules/workflow/workflow-builder/utils/generate-fake-object-record-event.ts index be7a3f86e..a18c4d098 100644 --- a/packages/twenty-server/src/modules/workflow/workflow-builder/utils/generate-fake-object-record-event.ts +++ b/packages/twenty-server/src/modules/workflow/workflow-builder/utils/generate-fake-object-record-event.ts @@ -46,11 +46,9 @@ export const generateFakeObjectRecordEvent = ( if (action === DatabaseEventAction.CREATED) { return { ...baseResult, - properties: { + 'properties.after': { isLeaf: false, - value: { - after: { isLeaf: false, value: after, label: 'After Creation' }, - }, + value: after, label: 'Record Fields', }, }; @@ -75,11 +73,9 @@ export const generateFakeObjectRecordEvent = ( if (action === DatabaseEventAction.DELETED) { return { ...baseResult, - properties: { + 'properties.before': { isLeaf: false, - value: { - before: { isLeaf: false, value: before, label: 'Before Deletion' }, - }, + value: before, label: 'Record Fields', }, }; @@ -88,15 +84,9 @@ export const generateFakeObjectRecordEvent = ( if (action === DatabaseEventAction.DESTROYED) { return { ...baseResult, - properties: { + 'properties.before': { isLeaf: false, - value: { - before: { - isLeaf: false, - value: before, - label: 'Before Permanent Deletion', - }, - }, + value: before, label: 'Record Fields', }, };