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:
@ -5,7 +5,6 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
|
|||||||
import {
|
import {
|
||||||
BaseOutputSchema,
|
BaseOutputSchema,
|
||||||
LinkOutputSchema,
|
LinkOutputSchema,
|
||||||
OutputSchema,
|
|
||||||
StepOutputSchema,
|
StepOutputSchema,
|
||||||
} from '@/workflow/workflow-variables/types/StepOutputSchema';
|
} from '@/workflow/workflow-variables/types/StepOutputSchema';
|
||||||
import { isBaseOutputSchema } from '@/workflow/workflow-variables/utils/isBaseOutputSchema';
|
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 { workflowDiagramTriggerNodeSelectionState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionState';
|
||||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
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 { 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 { isLinkOutputSchema } from '@/workflow/workflow-variables/utils/isLinkOutputSchema';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useSetRecoilState } from 'recoil';
|
import { useSetRecoilState } from 'recoil';
|
||||||
@ -48,22 +49,8 @@ export const WorkflowVariablesDropdownFieldItems = ({
|
|||||||
workflowDiagramTriggerNodeSelectionState,
|
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 getDisplayedSubStepFields = () => {
|
||||||
const currentSubStep = getCurrentSubStep();
|
const currentSubStep = getCurrentSubStepFromPath(step, currentPath);
|
||||||
|
|
||||||
if (isLinkOutputSchema(currentSubStep)) {
|
if (isLinkOutputSchema(currentSubStep)) {
|
||||||
return { link: currentSubStep.link };
|
return { link: currentSubStep.link };
|
||||||
@ -75,7 +62,7 @@ export const WorkflowVariablesDropdownFieldItems = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectField = (key: string) => {
|
const handleSelectField = (key: string) => {
|
||||||
const currentSubStep = getCurrentSubStep();
|
const currentSubStep = getCurrentSubStepFromPath(step, currentPath);
|
||||||
|
|
||||||
const handleSelectBaseOutputSchema = (
|
const handleSelectBaseOutputSchema = (
|
||||||
baseOutputSchema: BaseOutputSchema,
|
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 displayedObject = getDisplayedSubStepFields();
|
||||||
const options = displayedObject ? Object.entries(displayedObject) : [];
|
const options = displayedObject ? Object.entries(displayedObject) : [];
|
||||||
|
|
||||||
@ -147,7 +120,9 @@ export const WorkflowVariablesDropdownFieldItems = ({
|
|||||||
onClick={goBack}
|
onClick={goBack}
|
||||||
style={{ position: 'fixed' }}
|
style={{ position: 'fixed' }}
|
||||||
>
|
>
|
||||||
<OverflowingTextWithTooltip text={getHeaderLabel()} />
|
<OverflowingTextWithTooltip
|
||||||
|
text={getStepHeaderLabel(step, currentPath)}
|
||||||
|
/>
|
||||||
</DropdownMenuHeader>
|
</DropdownMenuHeader>
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -2,10 +2,9 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
|
|||||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||||
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
|
||||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||||
import {
|
import { StepOutputSchema } from '@/workflow/workflow-variables/types/StepOutputSchema';
|
||||||
OutputSchema,
|
import { getCurrentSubStepFromPath } from '@/workflow/workflow-variables/utils/getCurrentSubStepFromPath';
|
||||||
StepOutputSchema,
|
import { getStepHeaderLabel } from '@/workflow/workflow-variables/utils/getStepHeaderLabel';
|
||||||
} from '@/workflow/workflow-variables/types/StepOutputSchema';
|
|
||||||
import { isBaseOutputSchema } from '@/workflow/workflow-variables/utils/isBaseOutputSchema';
|
import { isBaseOutputSchema } from '@/workflow/workflow-variables/utils/isBaseOutputSchema';
|
||||||
import { isRecordOutputSchema } from '@/workflow/workflow-variables/utils/isRecordOutputSchema';
|
import { isRecordOutputSchema } from '@/workflow/workflow-variables/utils/isRecordOutputSchema';
|
||||||
|
|
||||||
@ -32,22 +31,8 @@ export const WorkflowVariablesDropdownObjectItems = ({
|
|||||||
const [searchInputValue, setSearchInputValue] = useState('');
|
const [searchInputValue, setSearchInputValue] = useState('');
|
||||||
const { getIcon } = useIcons();
|
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 getDisplayedSubStepFields = () => {
|
||||||
const currentSubStep = getCurrentSubStep();
|
const currentSubStep = getCurrentSubStepFromPath(step, currentPath);
|
||||||
|
|
||||||
if (isRecordOutputSchema(currentSubStep)) {
|
if (isRecordOutputSchema(currentSubStep)) {
|
||||||
return currentSubStep.fields;
|
return currentSubStep.fields;
|
||||||
@ -57,7 +42,7 @@ export const WorkflowVariablesDropdownObjectItems = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDisplayedSubStepObject = () => {
|
const getDisplayedSubStepObject = () => {
|
||||||
const currentSubStep = getCurrentSubStep();
|
const currentSubStep = getCurrentSubStepFromPath(step, currentPath);
|
||||||
|
|
||||||
if (!isRecordOutputSchema(currentSubStep)) {
|
if (!isRecordOutputSchema(currentSubStep)) {
|
||||||
return;
|
return;
|
||||||
@ -67,7 +52,7 @@ export const WorkflowVariablesDropdownObjectItems = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectObject = () => {
|
const handleSelectObject = () => {
|
||||||
const currentSubStep = getCurrentSubStep();
|
const currentSubStep = getCurrentSubStepFromPath(step, currentPath);
|
||||||
|
|
||||||
if (!isRecordOutputSchema(currentSubStep)) {
|
if (!isRecordOutputSchema(currentSubStep)) {
|
||||||
return;
|
return;
|
||||||
@ -91,8 +76,6 @@ export const WorkflowVariablesDropdownObjectItems = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const headerLabel = currentPath.length === 0 ? step.name : currentPath.at(-1);
|
|
||||||
|
|
||||||
const displayedSubStepObject = getDisplayedSubStepObject();
|
const displayedSubStepObject = getDisplayedSubStepObject();
|
||||||
|
|
||||||
const shouldDisplaySubStepObject = searchInputValue
|
const shouldDisplaySubStepObject = searchInputValue
|
||||||
@ -116,7 +99,9 @@ export const WorkflowVariablesDropdownObjectItems = ({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={goBack}>
|
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={goBack}>
|
||||||
<OverflowingTextWithTooltip text={headerLabel} />
|
<OverflowingTextWithTooltip
|
||||||
|
text={getStepHeaderLabel(step, currentPath)}
|
||||||
|
/>
|
||||||
</DropdownMenuHeader>
|
</DropdownMenuHeader>
|
||||||
<DropdownMenuSearchInput
|
<DropdownMenuSearchInput
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -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');
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -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;
|
||||||
|
};
|
||||||
@ -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;
|
||||||
|
};
|
||||||
@ -46,11 +46,9 @@ export const generateFakeObjectRecordEvent = (
|
|||||||
if (action === DatabaseEventAction.CREATED) {
|
if (action === DatabaseEventAction.CREATED) {
|
||||||
return {
|
return {
|
||||||
...baseResult,
|
...baseResult,
|
||||||
properties: {
|
'properties.after': {
|
||||||
isLeaf: false,
|
isLeaf: false,
|
||||||
value: {
|
value: after,
|
||||||
after: { isLeaf: false, value: after, label: 'After Creation' },
|
|
||||||
},
|
|
||||||
label: 'Record Fields',
|
label: 'Record Fields',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -75,11 +73,9 @@ export const generateFakeObjectRecordEvent = (
|
|||||||
if (action === DatabaseEventAction.DELETED) {
|
if (action === DatabaseEventAction.DELETED) {
|
||||||
return {
|
return {
|
||||||
...baseResult,
|
...baseResult,
|
||||||
properties: {
|
'properties.before': {
|
||||||
isLeaf: false,
|
isLeaf: false,
|
||||||
value: {
|
value: before,
|
||||||
before: { isLeaf: false, value: before, label: 'Before Deletion' },
|
|
||||||
},
|
|
||||||
label: 'Record Fields',
|
label: 'Record Fields',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -88,15 +84,9 @@ export const generateFakeObjectRecordEvent = (
|
|||||||
if (action === DatabaseEventAction.DESTROYED) {
|
if (action === DatabaseEventAction.DESTROYED) {
|
||||||
return {
|
return {
|
||||||
...baseResult,
|
...baseResult,
|
||||||
properties: {
|
'properties.before': {
|
||||||
isLeaf: false,
|
isLeaf: false,
|
||||||
value: {
|
value: before,
|
||||||
before: {
|
|
||||||
isLeaf: false,
|
|
||||||
value: before,
|
|
||||||
label: 'Before Permanent Deletion',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
label: 'Record Fields',
|
label: 'Record Fields',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user