Skip to content

Commit fe22383

Browse files
committed
4474 - add 'Group connections' switch to workflow test configuration and project deployment (edit workflow) dialog
1 parent e52f2f2 commit fe22383

3 files changed

Lines changed: 131 additions & 37 deletions

File tree

client/src/pages/automation/project-deployments/components/ProjectDeploymentEditWorkflowDialog.tsx

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Button from '@/components/Button/Button';
2+
import Switch from '@/components/Switch/Switch';
23
import {
34
Dialog,
45
DialogClose,
@@ -9,9 +10,10 @@ import {
910
DialogTitle,
1011
} from '@/components/ui/dialog';
1112
import {Form} from '@/components/ui/form';
13+
import {Tooltip, TooltipContent, TooltipTrigger} from '@/components/ui/tooltip';
1214
import ProjectDeploymentDialogWorkflowsStepItem from '@/pages/automation/project-deployments/components/project-deployment-dialog/ProjectDeploymentDialogWorkflowsStepItem';
15+
import getWorkflowComponentConnections from '@/pages/automation/project-deployments/components/project-deployment-dialog/projectDeploymentDialog-utils';
1316
import {
14-
ComponentConnection,
1517
ProjectDeployment,
1618
ProjectDeploymentWorkflow,
1719
ProjectDeploymentWorkflowConnection,
@@ -20,6 +22,7 @@ import {
2022
import {useUpdateProjectDeploymentWorkflowMutation} from '@/shared/mutations/automation/projectDeploymentWorkflows.mutations';
2123
import {ProjectDeploymentKeys} from '@/shared/queries/automation/projectDeployments.queries';
2224
import {useQueryClient} from '@tanstack/react-query';
25+
import {InfoIcon} from 'lucide-react';
2326
import {useEffect, useState} from 'react';
2427
import {useForm} from 'react-hook-form';
2528

@@ -35,6 +38,9 @@ const ProjectDeploymentEditWorkflowDialog = ({
3538
workflow,
3639
}: ProjectDeploymentEditWorkflowDialogProps) => {
3740
const [isOpen, setIsOpen] = useState(true);
41+
const [groupConnections, setGroupConnections] = useState(false);
42+
43+
const componentConnections = getWorkflowComponentConnections(workflow);
3844

3945
const form = useForm<ProjectDeployment>({
4046
defaultValues: {
@@ -80,10 +86,6 @@ const ProjectDeploymentEditWorkflowDialog = ({
8086
useEffect(() => {
8187
let newProjectDeploymentWorkflowConnections: ProjectDeploymentWorkflowConnection[] = [];
8288

83-
const componentConnections: ComponentConnection[] = (workflow?.tasks ?? [])
84-
.flatMap((task) => task.connections ?? [])
85-
.concat((workflow?.triggers ?? []).flatMap((trigger) => trigger.connections ?? []));
86-
8789
for (const workflowConnection of componentConnections) {
8890
let projectDeploymentWorkflowConnection = projectDeploymentWorkflow?.connections?.find(
8991
(projectDeploymentWorkflowConnection) =>
@@ -143,6 +145,7 @@ const ProjectDeploymentEditWorkflowDialog = ({
143145
<ProjectDeploymentDialogWorkflowsStepItem
144146
control={control}
145147
formState={formState}
148+
groupConnections={groupConnections}
146149
key={workflow.id!}
147150
setValue={setValue}
148151
switchHidden={true}
@@ -151,7 +154,23 @@ const ProjectDeploymentEditWorkflowDialog = ({
151154
/>
152155
</div>
153156

154-
<DialogFooter className="px-6 pb-6 pt-4">
157+
<DialogFooter className="flex items-center px-6 pb-6 pt-4">
158+
{componentConnections.length > 1 && (
159+
<div className="mr-auto flex items-center gap-2">
160+
<Switch checked={groupConnections} onCheckedChange={setGroupConnections} />
161+
162+
<span className="text-sm font-semibold">Group Connections</span>
163+
164+
<Tooltip>
165+
<TooltipTrigger asChild>
166+
<InfoIcon className="size-4 cursor-default text-gray-400" />
167+
</TooltipTrigger>
168+
169+
<TooltipContent>Connections grouped by their app.</TooltipContent>
170+
</Tooltip>
171+
</div>
172+
)}
173+
155174
<DialogClose asChild>
156175
<Button label="Cancel" variant="outline" />
157176
</DialogClose>

client/src/pages/automation/project-deployments/components/project-deployment-dialog/ProjectDeploymentDialogWorkflowsStepItemConnection.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@ const ProjectDeploymentDialogWorkflowsStepItemConnection = ({
8080
</span>
8181

8282
{!connectionGrouping && (
83-
<span className="text-xs text-gray-500">({componentConnection.workflowNodeName})</span>
83+
<span className="text-xs text-content-neutral-secondary">
84+
({componentConnection.workflowNodeName})
85+
</span>
8486
)}
8587
</FormLabel>
8688

@@ -146,7 +148,7 @@ const ProjectDeploymentDialogWorkflowsStepItemConnection = ({
146148
<div className="flex items-center space-x-1">
147149
<span>{connection.name}</span>
148150

149-
<span className="text-xs text-gray-500">
151+
<span className="text-xs text-content-neutral-secondary">
150152
{connection?.tags?.map((tag) => tag.name).join(', ')}
151153
</span>
152154

@@ -162,17 +164,17 @@ const ProjectDeploymentDialogWorkflowsStepItemConnection = ({
162164
<span>Loading component details…</span>
163165
) : componentDefinition?.title ? (
164166
<>
165-
<span>{`Choose connection for the ${componentDefinition.title}`}</span>
167+
<span>{`Choose connection for the ${componentDefinition.title}`} component</span>
166168

167169
{connectionGrouping ? (
168-
<span className="mx-1 text-xs text-gray-500">
169-
(applies to {connectionGrouping.indices.length} nodes)
170+
<span className="mx-1 text-xs text-content-neutral-secondary">
171+
(applies to {connectionGrouping.indices.length} nodes).
170172
</span>
171173
) : (
172-
<span className="mx-1 text-xs text-gray-500">({componentConnection.key})</span>
174+
<span className="mx-1 text-xs text-content-neutral-secondary">
175+
({componentConnection.key})
176+
</span>
173177
)}
174-
175-
<span> component.</span>
176178
</>
177179
) : (
178180
<span>Choose a connection for this component.</span>

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

Lines changed: 96 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Button from '@/components/Button/Button';
2+
import Switch from '@/components/Switch/Switch';
23
import {
34
Dialog,
45
DialogClose,
@@ -12,6 +13,7 @@ import {
1213
import {Form, FormControl, FormField, FormItem, FormLabel, FormMessage} from '@/components/ui/form';
1314
import {Label} from '@/components/ui/label';
1415
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from '@/components/ui/select';
16+
import {Tooltip, TooltipContent, TooltipTrigger} from '@/components/ui/tooltip';
1517
import Properties from '@/pages/platform/workflow-editor/components/properties/Properties';
1618
import {ConnectionI, useWorkflowEditor} from '@/pages/platform/workflow-editor/providers/workflowEditorProvider';
1719
import useWorkflowNodeDetailsPanelStore from '@/pages/platform/workflow-editor/stores/useWorkflowNodeDetailsPanelStore';
@@ -30,7 +32,7 @@ import {WorkflowTestConfigurationKeys} from '@/shared/queries/platform/workflowT
3032
import {PropertyAllType} from '@/shared/types';
3133
import * as Portal from '@radix-ui/react-portal';
3234
import {useQueryClient} from '@tanstack/react-query';
33-
import {PlusIcon} from 'lucide-react';
35+
import {InfoIcon, PlusIcon} from 'lucide-react';
3436
import {Dispatch, SetStateAction, useState} from 'react';
3537
import {UseFormReturn, useForm} from 'react-hook-form';
3638
import InlineSVG from 'react-inlinesvg';
@@ -41,23 +43,27 @@ interface WorkflowTestConfigurationDialogProps {
4143
workflowTestConfiguration?: WorkflowTestConfiguration;
4244
}
4345

46+
interface WorkflowTestConfigurationFormFieldProps {
47+
componentConnection: ComponentConnection;
48+
connectionDialogAllowed: boolean;
49+
connections: ConnectionI[];
50+
form: UseFormReturn<WorkflowTestConfiguration>;
51+
groupedIndices?: number[];
52+
index: number;
53+
setComponentConnection: Dispatch<SetStateAction<ComponentConnection | undefined>>;
54+
setShowNewConnectionDialog: Dispatch<SetStateAction<boolean>>;
55+
}
56+
4457
const WorkflowTestConfigurationFormField = ({
4558
componentConnection,
4659
connectionDialogAllowed,
4760
connections,
4861
form,
62+
groupedIndices,
4963
index,
5064
setComponentConnection,
5165
setShowNewConnectionDialog,
52-
}: {
53-
componentConnection: ComponentConnection;
54-
connectionDialogAllowed: boolean;
55-
connections: ConnectionI[];
56-
form: UseFormReturn<WorkflowTestConfiguration>;
57-
index: number;
58-
setShowNewConnectionDialog: Dispatch<SetStateAction<boolean>>;
59-
setComponentConnection: Dispatch<SetStateAction<ComponentConnection | undefined>>;
60-
}) => {
66+
}: WorkflowTestConfigurationFormFieldProps) => {
6167
const {data: componentDefinition} = useGetComponentDefinitionQuery({
6268
componentName: componentConnection.componentName,
6369
componentVersion: componentConnection.componentVersion,
@@ -78,13 +84,32 @@ const WorkflowTestConfigurationFormField = ({
7884

7985
<span className="ml-1">{componentDefinition?.title} Connection</span>
8086

81-
<span className="ml-0.5 text-xs text-gray-500">
82-
{`(${componentConnection.workflowNodeName} - ${componentConnection.key})`}
83-
</span>
87+
{groupedIndices ? (
88+
<span className="ml-0.5 text-xs text-content-neutral-secondary">
89+
(applies to {groupedIndices.length} nodes)
90+
</span>
91+
) : (
92+
<span className="ml-0.5 text-xs text-content-neutral-secondary">
93+
{`(${componentConnection.workflowNodeName} - ${componentConnection.key})`}
94+
</span>
95+
)}
8496
</FormLabel>
8597

8698
<Select
87-
onValueChange={field.onChange}
99+
onValueChange={(value) => {
100+
field.onChange(value);
101+
102+
if (groupedIndices) {
103+
for (const groupedIndex of groupedIndices) {
104+
if (groupedIndex !== index) {
105+
form.setValue(
106+
`connections.${groupedIndex}.connectionId`,
107+
Number(value)
108+
);
109+
}
110+
}
111+
}
112+
}}
88113
value={field.value ? field.value.toString() : undefined}
89114
>
90115
<FormControl>
@@ -151,6 +176,7 @@ const WorkflowTestConfigurationDialog = ({
151176
}: WorkflowTestConfigurationDialogProps) => {
152177
const [showNewConnectionDialog, setShowNewConnectionDialog] = useState(false);
153178
const [componentConnection, setComponentConnection] = useState<ComponentConnection | undefined>();
179+
const [groupConnections, setGroupConnections] = useState(false);
154180

155181
const connectionDialogAllowed = useWorkflowNodeDetailsPanelStore((state) => state.connectionDialogAllowed);
156182

@@ -229,6 +255,36 @@ const WorkflowTestConfigurationDialog = ({
229255
});
230256
}
231257

258+
const getConnectionsToRender = (): Array<{
259+
connection: ComponentConnection;
260+
groupedIndices?: number[];
261+
index: number;
262+
}> => {
263+
if (!groupConnections) {
264+
return componentConnections.map((connection, index) => ({connection, index}));
265+
}
266+
267+
const connectionGroupMap = new Map<string, number[]>();
268+
269+
for (const [index, connection] of componentConnections.entries()) {
270+
const componentName = connection.componentName;
271+
272+
if (!connectionGroupMap.has(componentName)) {
273+
connectionGroupMap.set(componentName, []);
274+
}
275+
276+
connectionGroupMap.get(componentName)!.push(index);
277+
}
278+
279+
return Array.from(connectionGroupMap.values()).map((indices) => ({
280+
connection: componentConnections[indices[0]],
281+
groupedIndices: indices.length > 1 ? indices : undefined,
282+
index: indices[0],
283+
}));
284+
};
285+
286+
const connectionsToRender = getConnectionsToRender();
287+
232288
return (
233289
<Dialog onOpenChange={onClose} open={true}>
234290
<DialogContent
@@ -253,7 +309,7 @@ const WorkflowTestConfigurationDialog = ({
253309
<div className="space-y-4 py-4">
254310
{inputs && inputs.length > 0 && (
255311
<div className="space-y-2">
256-
<Label className="text-gray-500">Inputs</Label>
312+
<Label className="text-content-neutral-secondary">Inputs</Label>
257313

258314
<Properties
259315
control={control}
@@ -285,21 +341,20 @@ const WorkflowTestConfigurationDialog = ({
285341

286342
{componentConnections && componentConnections.length > 0 && (
287343
<div className="space-y-2">
288-
<Label className="text-gray-500">Connections</Label>
344+
<Label className="text-content-neutral-secondary">Connections</Label>
289345

290346
<div className="space-y-4">
291-
{componentConnections.map(
292-
(workflowConnection, index) =>
347+
{connectionsToRender.map(
348+
({connection, groupedIndices, index}) =>
293349
connections && (
294350
<WorkflowTestConfigurationFormField
295-
componentConnection={workflowConnection}
351+
componentConnection={connection}
296352
connectionDialogAllowed={connectionDialogAllowed}
297353
connections={connections}
298354
form={form}
355+
groupedIndices={groupedIndices}
299356
index={index}
300-
key={`${workflowConnection.workflowNodeName}_${
301-
workflowConnection.key
302-
}`}
357+
key={`${connection.workflowNodeName}_${connection.key}`}
303358
setComponentConnection={setComponentConnection}
304359
setShowNewConnectionDialog={setShowNewConnectionDialog}
305360
/>
@@ -311,7 +366,25 @@ const WorkflowTestConfigurationDialog = ({
311366
</div>
312367
</div>
313368

314-
<DialogFooter>
369+
<DialogFooter className="flex items-center">
370+
<div className="mr-auto flex items-center gap-2">
371+
{componentConnections.length > 1 && (
372+
<>
373+
<Switch checked={groupConnections} onCheckedChange={setGroupConnections} />
374+
375+
<span className="text-sm font-semibold">Group Connections</span>
376+
377+
<Tooltip>
378+
<TooltipTrigger asChild>
379+
<InfoIcon className="size-4 cursor-default text-content-onsurface-primary" />
380+
</TooltipTrigger>
381+
382+
<TooltipContent>Connections grouped by their app.</TooltipContent>
383+
</Tooltip>
384+
</>
385+
)}
386+
</div>
387+
315388
<DialogClose asChild>
316389
<Button label="Cancel" type="button" variant="outline" />
317390
</DialogClose>

0 commit comments

Comments
 (0)