Remove before-after + fix header label (#9932)

- Fix header label on step

Before
<img width="224" alt="Capture d’écran 2025-01-30 à 12 11 27"
src="https://github.com/user-attachments/assets/e04e2d83-2414-4a92-a307-159e1ca16c64"
/> <img width="224" alt="Capture d’écran 2025-01-30 à 13 27 40"
src="https://github.com/user-attachments/assets/72e2c567-7ee0-43ff-9ae2-898e46d677c1"
/>

After
<img width="224" alt="Capture d’écran 2025-01-30 à 13 29 00"
src="https://github.com/user-attachments/assets/e7e458ab-458d-4e84-98a2-63596f44e0e7"
/> <img width="224" alt="Capture d’écran 2025-01-30 à 13 29 25"
src="https://github.com/user-attachments/assets/df1b0cbd-c8f2-44f6-b2f6-944e5ec8e14f"
/>



- Remove before - after when there is only one of them
This commit is contained in:
Thomas Trompette
2025-01-30 17:19:47 +01:00
committed by GitHub
parent a5273732b3
commit afed36ef5b
7 changed files with 178 additions and 72 deletions

View File

@ -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' }}
>
<OverflowingTextWithTooltip text={getHeaderLabel()} />
<OverflowingTextWithTooltip
text={getStepHeaderLabel(step, currentPath)}
/>
</DropdownMenuHeader>
<DropdownMenuSearchInput
autoFocus

View File

@ -2,10 +2,9 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import {
OutputSchema,
StepOutputSchema,
} from '@/workflow/workflow-variables/types/StepOutputSchema';
import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema';
import { getCurrentSubStepFromPath } from '@/workflow/workflow-variables/utils/getCurrentSubStepFromPath';
import { getStepHeaderLabel } from '@/workflow/workflow-variables/utils/getStepHeaderLabel';
import { isBaseOutputSchema } from '@/workflow/workflow-variables/utils/isBaseOutputSchema';
import { isRecordOutputSchema } from '@/workflow/workflow-variables/utils/isRecordOutputSchema';
@ -32,22 +31,8 @@ export const WorkflowVariablesDropdownObjectItems = ({
const [searchInputValue, setSearchInputValue] = useState('');
const { getIcon } = useIcons();
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 (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 (
<>
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={goBack}>
<OverflowingTextWithTooltip text={headerLabel} />
<OverflowingTextWithTooltip
text={getStepHeaderLabel(step, currentPath)}
/>
</DropdownMenuHeader>
<DropdownMenuSearchInput
autoFocus

View File

@ -0,0 +1,39 @@
import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema';
import { getCurrentSubStepFromPath } from '@/workflow/workflow-variables/utils/getCurrentSubStepFromPath';
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 },
},
_outputSchemaType: 'RECORD',
},
},
},
} satisfies StepOutputSchema;
describe('getCurrentSubStepFromPath', () => {
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);
});
});

View File

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

View File

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

View File

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

View File

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