Skip to content

Commit 7b34403

Browse files
committed
2030 - improve displayCondition skeleton and loading indicator
1 parent db74752 commit 7b34403

File tree

4 files changed

+114
-84
lines changed

4 files changed

+114
-84
lines changed

client/src/pages/platform/workflow-editor/components/Properties/Properties.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {Collapsible, CollapsibleContent, CollapsibleTrigger} from '@/components/ui/collapsible';
2+
import {GetWorkflowNodeParameterDisplayConditions200Response} from '@/shared/middleware/platform/configuration';
23
import {PropertyAllType} from '@/shared/types';
4+
import {UseQueryResult} from '@tanstack/react-query';
35
import {ChevronDownIcon} from 'lucide-react';
46
import {Fragment} from 'react';
57
import {FieldValues} from 'react-hook-form/dist/types';
@@ -13,6 +15,7 @@ interface PropertiesProps {
1315
/* eslint-disable @typescript-eslint/no-explicit-any */
1416
control?: Control<any, any>;
1517
controlPath?: string;
18+
displayConditionsQuery?: UseQueryResult<GetWorkflowNodeParameterDisplayConditions200Response, Error>;
1619
customClassName?: string;
1720
operationName?: string;
1821
formState?: FormState<FieldValues>;
@@ -24,6 +27,7 @@ const Properties = ({
2427
control,
2528
controlPath,
2629
customClassName,
30+
displayConditionsQuery,
2731
formState,
2832
operationName,
2933
path,
@@ -55,6 +59,7 @@ const Properties = ({
5559
<Property
5660
control={control}
5761
controlPath={controlPath}
62+
displayConditionsQuery={displayConditionsQuery}
5863
formState={formState}
5964
key={`${currentNode?.workflowNodeName}_${currentNode?.operationName}_${property.name}_${index}`}
6065
operationName={operationName}
@@ -78,6 +83,7 @@ const Properties = ({
7883
<Property
7984
control={control}
8085
controlPath={controlPath}
86+
displayConditionsQuery={displayConditionsQuery}
8187
formState={formState}
8288
key={`${property.name}_${currentNode?.operationName}_${index}`}
8389
operationName={operationName}

client/src/pages/platform/workflow-editor/components/Properties/Property.tsx

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ import useWorkflowNodeDetailsPanelStore from '@/pages/platform/workflow-editor/s
2121
import deleteProperty from '@/pages/platform/workflow-editor/utils/deleteProperty';
2222
import getInputHTMLType from '@/pages/platform/workflow-editor/utils/getInputHTMLType';
2323
import saveProperty from '@/pages/platform/workflow-editor/utils/saveProperty';
24-
import {Option} from '@/shared/middleware/platform/configuration';
25-
import {useGetWorkflowNodeParameterDisplayConditionsQuery} from '@/shared/queries/platform/workflowNodeParameters.queries';
24+
import {GetWorkflowNodeParameterDisplayConditions200Response, Option} from '@/shared/middleware/platform/configuration';
2625
import {ArrayPropertyType, PropertyAllType} from '@/shared/types';
2726
import {QuestionMarkCircledIcon} from '@radix-ui/react-icons';
2827
import {TooltipPortal} from '@radix-ui/react-tooltip';
28+
import {UseQueryResult} from '@tanstack/react-query';
2929
import {Editor} from '@tiptap/react';
3030
import {usePrevious} from '@uidotdev/usehooks';
3131
import {decode} from 'html-entities';
@@ -64,6 +64,7 @@ interface PropertyProps {
6464
controlPath?: string;
6565
customClassName?: string;
6666
deletePropertyButton?: ReactNode;
67+
displayConditionsQuery?: UseQueryResult<GetWorkflowNodeParameterDisplayConditions200Response, Error>;
6768
formState?: FormState<FieldValues>;
6869
objectName?: string;
6970
operationName?: string;
@@ -81,6 +82,7 @@ const Property = ({
8182
controlPath = 'parameters',
8283
customClassName,
8384
deletePropertyButton,
85+
displayConditionsQuery,
8486
formState,
8587
objectName,
8688
operationName,
@@ -114,7 +116,7 @@ const Property = ({
114116
const [showInputTypeSwitchButton, setShowInputTypeSwitchButton] = useState(
115117
(property.type !== 'STRING' && property.expressionEnabled) || false
116118
);
117-
const [isFetchingCurrentDisplayCondition, setIsFetchingCurrentDisplayCondition] = useState(false);
119+
const [isFetchingCurrentDisplayCondition, setIsFetchingCurrentDisplayCondition] = useState(true);
118120

119121
const editorRef = useRef<Editor>(null);
120122
const inputRef = useRef<HTMLInputElement>(null);
@@ -125,14 +127,11 @@ const Property = ({
125127
const {setDataPillPanelOpen} = useDataPillPanelStore();
126128
const {workflow} = useWorkflowDataStore();
127129

128-
const {isFetchedAfterMount: isDisplayConditionFetched} = useGetWorkflowNodeParameterDisplayConditionsQuery(
129-
{
130-
id: workflow.id!,
131-
// eslint-disable-next-line @typescript-eslint/no-non-null-asserted-optional-chain
132-
workflowNodeName: currentNode?.workflowNodeName!,
133-
},
134-
!!currentNode?.workflowNodeName
135-
);
130+
const {isFetchedAfterMount: isDisplayConditionsFetched, isPending: isDisplayConditionsPending} =
131+
displayConditionsQuery ?? {
132+
isFetchedAfterMount: false,
133+
isPending: false,
134+
};
136135

137136
const previousOperationName = usePrevious(currentNode?.operationName);
138137

@@ -433,39 +432,51 @@ const Property = ({
433432
});
434433
};
435434

436-
const handleSelectChange = (value: string, name: string) => {
437-
if (!currentComponent || !workflow.id || !name || !path || !updateWorkflowNodeParameterMutation) {
438-
return;
439-
}
435+
const handleSelectChange = useCallback(
436+
(value: string, name: string) => {
437+
if (!currentComponent || !workflow.id || !name || !path || !updateWorkflowNodeParameterMutation) {
438+
return;
439+
}
440440

441-
if (value === propertyParameterValue) {
442-
return;
443-
}
441+
if (value === propertyParameterValue) {
442+
return;
443+
}
444444

445-
setSelectValue(value);
446-
setPropertyParameterValue(value);
445+
setSelectValue(value);
446+
setPropertyParameterValue(value);
447447

448-
let actualValue: boolean | null | number | string = type === 'BOOLEAN' ? value === 'true' : value;
448+
let actualValue: boolean | null | number | string = type === 'BOOLEAN' ? value === 'true' : value;
449449

450-
if (type === 'INTEGER' && !mentionInputValue.startsWith('${')) {
451-
actualValue = parseInt(value);
452-
} else if (type === 'NUMBER' && !mentionInputValue.startsWith('${')) {
453-
actualValue = parseFloat(value);
454-
}
450+
if (type === 'INTEGER' && !mentionInputValue.startsWith('${')) {
451+
actualValue = parseInt(value);
452+
} else if (type === 'NUMBER' && !mentionInputValue.startsWith('${')) {
453+
actualValue = parseFloat(value);
454+
}
455455

456-
if (value === 'null' || value === '') {
457-
actualValue = null;
458-
}
456+
if (value === 'null' || value === '') {
457+
actualValue = null;
458+
}
459459

460-
saveProperty({
461-
includeInMetadata: custom,
460+
saveProperty({
461+
includeInMetadata: custom,
462+
path,
463+
type,
464+
updateWorkflowNodeParameterMutation,
465+
value: actualValue,
466+
workflowId: workflow.id,
467+
});
468+
},
469+
[
470+
currentComponent,
471+
custom,
472+
mentionInputValue,
462473
path,
474+
propertyParameterValue,
463475
type,
464476
updateWorkflowNodeParameterMutation,
465-
value: actualValue,
466-
workflowId: workflow.id,
467-
});
468-
};
477+
workflow.id,
478+
]
479+
);
469480

470481
const memoizedWorkflowTask = useMemo(() => {
471482
return [...(workflow.triggers ?? []), ...(workflow.tasks ?? [])].find(
@@ -758,24 +769,30 @@ const Property = ({
758769
if (displayCondition && currentComponent?.displayConditions?.[displayCondition]) {
759770
setIsFetchingCurrentDisplayCondition(true);
760771

761-
if (isDisplayConditionFetched) {
772+
if (isDisplayConditionsFetched) {
762773
setIsFetchingCurrentDisplayCondition(false);
763774
}
764775
}
765-
}, [displayCondition, currentComponent?.displayConditions, isDisplayConditionFetched]);
776+
}, [displayCondition, currentComponent?.displayConditions, isDisplayConditionsFetched]);
766777

767778
if (hidden) {
768779
return <></>;
769780
}
770781

771-
if (displayCondition && !currentComponent?.displayConditions?.[displayCondition]) {
772-
return <></>;
782+
if (displayCondition && isDisplayConditionsPending && type !== 'ARRAY' && type !== 'OBJECT') {
783+
return (
784+
<div className={twMerge('flex flex-col space-y-1', objectName && 'ml-2 mt-1')}>
785+
<Skeleton className="h-5 w-1/4" />
786+
787+
<Skeleton className="h-9 w-full" />
788+
</div>
789+
);
773790
}
774791

775792
if (
776793
displayCondition &&
777794
currentComponent?.displayConditions?.[displayCondition] &&
778-
isFetchingCurrentDisplayCondition &&
795+
(isFetchingCurrentDisplayCondition || isDisplayConditionsPending) &&
779796
type !== 'ARRAY' &&
780797
type !== 'OBJECT'
781798
) {
@@ -788,6 +805,10 @@ const Property = ({
788805
);
789806
}
790807

808+
if (displayCondition && !currentComponent?.displayConditions?.[displayCondition]) {
809+
return <></>;
810+
}
811+
791812
return (
792813
<li
793814
className={twMerge(

client/src/pages/platform/workflow-editor/components/WorkflowEditorLayout.tsx

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import WorkflowTestChatPanel from '@/pages/platform/workflow-editor/components/w
1010
import {useWorkflowMutation} from '@/pages/platform/workflow-editor/providers/workflowMutationProvider';
1111
import {ComponentDefinitionBasic, TaskDispatcherDefinitionBasic} from '@/shared/middleware/platform/configuration';
1212
import {useGetPreviousWorkflowNodeOutputsQuery} from '@/shared/queries/platform/workflowNodeOutputs.queries';
13-
import {useGetWorkflowNodeParameterDisplayConditionsQuery} from '@/shared/queries/platform/workflowNodeParameters.queries';
14-
import {useEffect, useState} from 'react';
13+
import {useEffect} from 'react';
1514

1615
import useWorkflowDataStore from '../stores/useWorkflowDataStore';
1716
import useWorkflowNodeDetailsPanelStore from '../stores/useWorkflowNodeDetailsPanelStore';
@@ -29,27 +28,17 @@ const WorkflowEditorLayout = ({
2928
leftSidebarOpen,
3029
taskDispatcherDefinitions,
3130
}: WorkflowEditorLayoutProps) => {
32-
const [currentNodeName, setCurrentNodeName] = useState<string | undefined>();
33-
3431
const {componentActions, workflow} = useWorkflowDataStore();
35-
const {currentComponent, currentNode, setCurrentComponent, setCurrentNode} = useWorkflowNodeDetailsPanelStore();
32+
const {currentComponent, currentNode} = useWorkflowNodeDetailsPanelStore();
3633

3734
const {updateWorkflowMutation} = useWorkflowMutation();
3835

39-
const {data: workflowNodeParameterDisplayConditions} = useGetWorkflowNodeParameterDisplayConditionsQuery(
40-
{
41-
id: workflow.id!,
42-
workflowNodeName: currentNodeName!,
43-
},
44-
!!currentNodeName && currentNodeName !== 'manual'
45-
);
46-
4736
const {data: workflowNodeOutputs, refetch: refetchWorkflowNodeOutputs} = useGetPreviousWorkflowNodeOutputsQuery(
4837
{
4938
id: workflow.id!,
50-
lastWorkflowNodeName: currentNodeName,
39+
lastWorkflowNodeName: currentNode?.name,
5140
},
52-
!!componentActions?.length && !!currentNodeName && !!currentNode && !currentNode?.trigger
41+
!!componentActions?.length && !!currentNode && !!currentNode?.name && !currentNode?.trigger
5342
);
5443

5544
let previousComponentDefinitions: ComponentDefinitionBasic[] = [];
@@ -73,14 +62,6 @@ const WorkflowEditorLayout = ({
7362
.filter((componentDefinition) => !!componentDefinition);
7463
}
7564

76-
useEffect(() => {
77-
if (currentNode?.name) {
78-
setCurrentNodeName(currentNode?.name);
79-
} else {
80-
setCurrentNodeName(undefined);
81-
}
82-
}, [currentNode?.name]);
83-
8465
// refetch workflowNodeOutputs when a task is opened
8566
useEffect(() => {
8667
if (!currentNode || currentNode?.trigger || workflowNodeOutputs || !workflow?.nodeNames) {
@@ -89,27 +70,7 @@ const WorkflowEditorLayout = ({
8970

9071
refetchWorkflowNodeOutputs();
9172
// eslint-disable-next-line react-hooks/exhaustive-deps
92-
}, [currentNodeName, workflow?.nodeNames.length]);
93-
94-
// update display conditions when currentNode changes
95-
useEffect(() => {
96-
if (currentNode && workflowNodeParameterDisplayConditions?.displayConditions) {
97-
setCurrentNode({
98-
...currentNode,
99-
displayConditions: workflowNodeParameterDisplayConditions.displayConditions,
100-
});
101-
}
102-
103-
if (currentComponent && workflowNodeParameterDisplayConditions?.displayConditions) {
104-
if (currentComponent.workflowNodeName === currentNode?.name) {
105-
setCurrentComponent({
106-
...currentComponent,
107-
displayConditions: workflowNodeParameterDisplayConditions.displayConditions,
108-
});
109-
}
110-
}
111-
// eslint-disable-next-line react-hooks/exhaustive-deps
112-
}, [workflowNodeParameterDisplayConditions?.displayConditions, currentNode?.name]);
73+
}, [currentNode?.name, workflow?.nodeNames.length]);
11374

11475
return (
11576
<ReactFlowProvider>

client/src/pages/platform/workflow-editor/components/WorkflowNodeDetailsPanel.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
} from '@/shared/queries/platform/triggerDefinitions.queries';
3030
import {WorkflowNodeDynamicPropertyKeys} from '@/shared/queries/platform/workflowNodeDynamicProperties.queries';
3131
import {WorkflowNodeOptionKeys} from '@/shared/queries/platform/workflowNodeOptions.queries';
32+
import {useGetWorkflowNodeParameterDisplayConditionsQuery} from '@/shared/queries/platform/workflowNodeParameters.queries';
3233
import {useGetWorkflowTestConfigurationConnectionsQuery} from '@/shared/queries/platform/workflowTestConfigurations.queries';
3334
import {
3435
ComponentPropertiesType,
@@ -89,6 +90,7 @@ const WorkflowNodeDetailsPanel = ({
8990
updateWorkflowMutation: UpdateWorkflowMutationType;
9091
workflowNodeOutputs: WorkflowNodeOutput[];
9192
}) => {
93+
const [currentNodeName, setCurrentNodeName] = useState<string | undefined>();
9294
const [currentOperationName, setCurrentOperationName] = useState('');
9395
const [currentOperationProperties, setCurrentOperationProperties] = useState<Array<PropertyAllType>>([]);
9496

@@ -172,6 +174,16 @@ const WorkflowNodeDetailsPanel = ({
172174
!!currentNode && !!currentNode.taskDispatcher
173175
);
174176

177+
const displayConditionsQuery = useGetWorkflowNodeParameterDisplayConditionsQuery(
178+
{
179+
id: workflow.id!,
180+
workflowNodeName: currentNodeName!,
181+
},
182+
!!currentNodeName && currentNodeName !== 'manual'
183+
);
184+
185+
const {data: workflowNodeParameterDisplayConditions} = displayConditionsQuery;
186+
175187
const currentNodeDefinition = useMemo(() => {
176188
if (currentNode?.trigger) {
177189
return currentTriggerDefinition;
@@ -438,6 +450,15 @@ const WorkflowNodeDetailsPanel = ({
438450

439451
const handlePanelClose = useCallback(() => useWorkflowNodeDetailsPanelStore.getState().reset(), []);
440452

453+
// Set current node name
454+
useEffect(() => {
455+
if (currentNode?.name) {
456+
setCurrentNodeName(currentNode?.name);
457+
} else {
458+
setCurrentNodeName(undefined);
459+
}
460+
}, [currentNode?.name]);
461+
441462
// Set currentOperationProperties depending if the current node is a trigger or an action
442463
useEffect(() => {
443464
if (currentNodeDefinition?.properties) {
@@ -575,6 +596,26 @@ const WorkflowNodeDetailsPanel = ({
575596
// eslint-disable-next-line react-hooks/exhaustive-deps
576597
}, [componentActions, currentNode?.workflowNodeName]);
577598

599+
// Update display conditions when currentNode changes
600+
useEffect(() => {
601+
if (currentNode && workflowNodeParameterDisplayConditions?.displayConditions) {
602+
setCurrentNode({
603+
...currentNode,
604+
displayConditions: workflowNodeParameterDisplayConditions.displayConditions,
605+
});
606+
}
607+
608+
if (currentComponent && workflowNodeParameterDisplayConditions?.displayConditions) {
609+
if (currentComponent.workflowNodeName === currentNode?.name) {
610+
setCurrentComponent({
611+
...currentComponent,
612+
displayConditions: workflowNodeParameterDisplayConditions.displayConditions,
613+
});
614+
}
615+
}
616+
// eslint-disable-next-line react-hooks/exhaustive-deps
617+
}, [workflowNodeParameterDisplayConditions?.displayConditions, currentNode?.name]);
618+
578619
if (!workflowNodeDetailsPanelOpen || !currentNode?.workflowNodeName || !currentTaskData) {
579620
return <></>;
580621
}
@@ -727,6 +768,7 @@ const WorkflowNodeDetailsPanel = ({
727768
(!operationDataMissing && currentOperationProperties?.length ? (
728769
<Properties
729770
customClassName="p-4"
771+
displayConditionsQuery={displayConditionsQuery}
730772
key={`${currentNode?.workflowNodeName}_${currentOperationName}_properties`}
731773
operationName={currentOperationName}
732774
properties={currentOperationProperties}

0 commit comments

Comments
 (0)