Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import LoadingIcon from '@/components/LoadingIcon';
import {Button} from '@/components/ui/button';
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from '@/components/ui/select';
import {Skeleton} from '@/components/ui/skeleton';
import {Tooltip, TooltipContent, TooltipTrigger} from '@/components/ui/tooltip';
import Properties from '@/pages/platform/workflow-editor/components/Properties/Properties';
import DataStreamComponentsTab from '@/pages/platform/workflow-editor/components/node-details-tabs/DataStreamComponentsTab';
import {
ActionDefinitionApi,
ComponentDefinition,
ComponentDefinitionBasic,
GetComponentActionDefinitionRequest,
GetComponentTriggerDefinitionRequest,
TriggerDefinitionApi,
WorkflowConnection,
WorkflowNodeOutput,
WorkflowTask,
} from '@/shared/middleware/platform/configuration';
import {useDeleteWorkflowNodeTestOutputMutation} from '@/shared/mutations/platform/workflowNodeTestOutputs.mutations';
import {
Expand All @@ -31,6 +34,7 @@ import {useGetWorkflowTestConfigurationConnectionsQuery} from '@/shared/queries/
import {
ComponentPropertiesType,
DataPillType,
NodeDataType,
PropertyAllType,
UpdateWorkflowMutationType,
WorkflowDefinitionType,
Expand All @@ -48,6 +52,7 @@ import getAllTaskNames from '../utils/getAllTaskNames';
import getDataPillsFromProperties from '../utils/getDataPillsFromProperties';
import getParametersWithDefaultValues from '../utils/getParametersWithDefaultValues';
import saveWorkflowDefinition from '../utils/saveWorkflowDefinition';
import updateConditionSubtask from '../utils/updateRootConditionNode';
import CurrentOperationSelect from './CurrentOperationSelect';
import ConnectionTab from './node-details-tabs/ConnectionTab';
import DescriptionTab from './node-details-tabs/DescriptionTab';
Expand Down Expand Up @@ -94,7 +99,7 @@ const WorkflowNodeDetailsPanel = ({
const {currentComponent, currentNode, setCurrentComponent, setCurrentNode, workflowNodeDetailsPanelOpen} =
useWorkflowNodeDetailsPanelStore();

const {componentActions, setDataPills, workflow} = useWorkflowDataStore();
const {componentActions, nodes, setDataPills, workflow} = useWorkflowDataStore();

const {data: currentComponentDefinition} = useGetComponentDefinitionQuery(
{
Expand Down Expand Up @@ -267,19 +272,72 @@ const WorkflowNodeDetailsPanel = ({

const {componentName, description, label, workflowNodeName} = currentComponent;

let nodeData = {
componentName,
description,
label,
name: workflowNodeName || currentNode?.name || '',
operationName: newOperationName,
parameters: getParametersWithDefaultValues({
properties: operationData.properties as Array<PropertyAllType>,
}),
trigger: currentNode?.trigger,
type: `${componentName}/v${currentComponentDefinition.version}/${newOperationName}`,
};

if (currentNode?.conditionData) {
const parentConditionNode = nodes.find(
(node) => node.data.name === currentNode?.conditionData?.conditionId
);

if (!parentConditionNode) {
return;
}

const conditionCase = currentNode.conditionData.conditionCase;
const conditionParameters: Array<WorkflowTask> = parentConditionNode.data.parameters[conditionCase];

if (conditionParameters) {
const nodeIndex = conditionParameters.findIndex((subtask) => subtask.name === currentNode.name);

if (nodeIndex !== -1) {
conditionParameters[nodeIndex] = {
...conditionParameters[nodeIndex],
type: `${componentName}/v${currentComponentDefinition.version}/${newOperationName}`,
};

if (!workflow.definition) {
return;
}

const tasks = JSON.parse(workflow.definition).tasks;

const updatedParentConditionTask = workflow.tasks?.find(
(task) => task.name === currentNode.conditionData?.conditionId
);

if (!updatedParentConditionTask) {
return;
}

const updatedRootConditionNode = updateConditionSubtask({
conditionCase,
conditionId: currentNode.conditionData.conditionId,
nodeIndex,
nodes,
tasks,
updatedParentConditionNodeData: parentConditionNode.data,
updatedParentConditionTask,
workflow,
});

nodeData = updatedRootConditionNode.data ?? (updatedRootConditionNode as NodeDataType);
}
}
}

saveWorkflowDefinition({
nodeData: {
componentName,
description,
label,
name: workflowNodeName || currentNode?.name || '',
operationName: newOperationName,
parameters: getParametersWithDefaultValues({
properties: operationData.properties as Array<PropertyAllType>,
}),
trigger: currentNode?.trigger,
type: `${componentName}/v${currentComponentDefinition.version}/${newOperationName}`,
},
nodeData,
onSuccess: () => {
setCurrentComponent({
...currentComponent,
Expand All @@ -293,6 +351,7 @@ const WorkflowNodeDetailsPanel = ({
});
},
queryClient,
subtask: !!currentNode?.conditionData,
updateWorkflowMutation,
workflow,
});
Expand Down Expand Up @@ -446,6 +505,10 @@ const WorkflowNodeDetailsPanel = ({
}, [componentActions, currentNode?.name]);

const currentTaskData = currentComponentDefinition || currentTaskDispatcherDefinition;
const currentOperationFetched = currentActionFetched || currentTriggerFetched;

const operationDataMissing =
currentComponent?.operationName && (!matchingOperation?.name || !currentOperationFetched);

if (!workflowNodeDetailsPanelOpen || !currentNode?.name || !currentTaskData) {
return <></>;
Expand Down Expand Up @@ -496,44 +559,65 @@ const WorkflowNodeDetailsPanel = ({
</header>

<main className="flex h-full flex-col">
<CurrentOperationSelect
description={
currentNode?.trigger
? currentTriggerDefinition?.description
: currentActionDefinition?.description
}
handleValueChange={handleOperationSelectChange}
operations={
(currentNode?.trigger
? currentComponentDefinition?.triggers
: currentComponentDefinition?.actions)!
}
triggerSelect={currentNode?.trigger}
value={currentOperationName}
/>
{operationDataMissing && (
<div className="flex flex-col border-b border-muted p-4">
<span className="text-sm leading-6">Actions</span>

<Skeleton className="h-9 w-full" />
</div>
)}

{(!!(currentTaskData as ComponentDefinition).actions?.length ||
!!(currentTaskData as ComponentDefinition).triggers?.length) &&
!operationDataMissing && (
<CurrentOperationSelect
description={
currentNode?.trigger
? currentTriggerDefinition?.description
: currentActionDefinition?.description
}
handleValueChange={handleOperationSelectChange}
operations={
(currentNode?.trigger
? currentComponentDefinition?.triggers
: currentComponentDefinition?.actions)!
}
triggerSelect={currentNode?.trigger}
value={currentOperationName}
/>
)}

{((!currentNode?.trigger && !currentNode?.taskDispatcher && currentActionFetched) ||
currentNode?.taskDispatcher ||
(currentNode?.trigger && currentTriggerFetched)) &&
nodeTabs.length > 1 && (
<div className="flex justify-center">
{nodeTabs.map((tab) => (
<Button
className={twMerge(
'grow justify-center whitespace-nowrap rounded-none border-0 border-b border-gray-200 bg-white text-sm font-medium py-5 text-gray-500 hover:border-blue-500 hover:text-blue-500 focus:border-blue-500 focus:text-blue-500 focus:outline-none',
activeTab === tab?.name &&
'border-blue-500 text-blue-500 hover:text-blue-500'
)}
key={tab.name}
name={tab.name}
onClick={() => setActiveTab(tab.name)}
variant="ghost"
>
{tab.label}
</Button>
))}
</div>
)}
nodeTabs.length > 1 ? (
<div className="flex justify-center">
{nodeTabs.map((tab) => (
<Button
className={twMerge(
'grow justify-center whitespace-nowrap rounded-none border-0 border-b border-gray-200 bg-white text-sm font-medium py-5 text-gray-500 hover:border-blue-500 hover:text-blue-500 focus:border-blue-500 focus:text-blue-500 focus:outline-none',
activeTab === tab?.name && 'border-blue-500 text-blue-500 hover:text-blue-500'
)}
key={tab.name}
name={tab.name}
onClick={() => setActiveTab(tab.name)}
variant="ghost"
>
{tab.label}
</Button>
))}
</div>
) : (
<div className="flex justify-center space-x-2 border-b border-gray-200 p-2">
<Skeleton className="h-6 w-1/4" />

<Skeleton className="h-6 w-1/4" />

<Skeleton className="h-6 w-1/4" />

<Skeleton className="h-6 w-1/4" />
</div>
)}

<div className="relative h-full overflow-y-scroll">
{currentTaskData && (
Expand Down Expand Up @@ -563,6 +647,7 @@ const WorkflowNodeDetailsPanel = ({

{activeTab === 'properties' &&
currentTaskData &&
!operationDataMissing &&
(currentOperationProperties?.length ? (
<Properties
customClassName="p-4"
Expand Down
12 changes: 11 additions & 1 deletion client/src/pages/platform/workflow-editor/hooks/useLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ export default function useLayout({
nodes = taskNodes?.length ? [...triggerAndTaskNodes] : [triggerNode, finalPlaceholderNode];
}

nodes.forEach((node) => {
nodes.forEach((node, index) => {
let height = NODE_HEIGHT;

if (node.id.includes('placeholder')) {
Expand All @@ -516,6 +516,16 @@ export default function useLayout({
height = NODE_HEIGHT * 1.2;
}

if (index === nodes.length - 1) {
height = 20;

const penultimateNode = nodes[nodes.length - 2];

if (penultimateNode.id.includes('bottom-placeholder')) {
height = 90;
}
}

dagreGraph.setNode(node.id, {height, width: NODE_WIDTH});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import {WorkflowTask} from '@/shared/middleware/automation/configuration';

import getParentConditionTask from './getParentConditionTask';

interface AddConditionChildNodeProps {
interface GetUpdatedConditionSubtasksProps {
conditionId: string;
tasks: Array<WorkflowTask>;
newTask: WorkflowTask;
placeholderId: string;
}

export default function getTasksWithConditionChildNode({
export default function insertNewConditionSubtask({
conditionId,
newTask,
placeholderId,
tasks,
}: AddConditionChildNodeProps): Array<WorkflowTask> {
}: GetUpdatedConditionSubtasksProps): Array<WorkflowTask> {
let conditionTask = tasks.find((task) => task.name === conditionId);

if (!conditionTask) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {TaskDispatcherKeys} from '@/shared/queries/platform/taskDispatcherDefini
import {NodeDataType, WorkflowDefinitionType} from '@/shared/types';
import {QueryClient, UseMutationResult} from '@tanstack/react-query';

import getTasksWithConditionChildNode from './getTasksWithConditionChildNode';
import insertNewConditionSubtask from './insertNewConditionSubtask';

const SPACE = 4;

Expand All @@ -27,6 +27,7 @@ interface SaveWorkflowDefinitionProps {
onSuccess?: () => void;
placeholderId?: string;
queryClient: QueryClient;
subtask?: boolean;
updateWorkflowMutation: UseMutationResult<void, Error, UpdateWorkflowRequestType, unknown>;
workflow: Workflow;
}
Expand All @@ -39,6 +40,7 @@ export default async function saveWorkflowDefinition({
onSuccess,
placeholderId,
queryClient,
subtask,
updateWorkflowMutation,
workflow,
}: SaveWorkflowDefinitionProps) {
Expand Down Expand Up @@ -130,6 +132,7 @@ export default async function saveWorkflowDefinition({
if (
existingWorkflowTask &&
!decorative &&
!subtask &&
(!operationName ||
(existingWorkflowTask.parameters &&
JSON.stringify(existingWorkflowTask.parameters) === JSON.stringify(newTask.parameters))) &&
Expand Down Expand Up @@ -171,7 +174,7 @@ export default async function saveWorkflowDefinition({
tasks = [...(workflowDefinition.tasks || [])];

if (conditionId && placeholderId) {
tasks = getTasksWithConditionChildNode({conditionId, newTask, placeholderId, tasks});
tasks = insertNewConditionSubtask({conditionId, newTask, placeholderId, tasks});
} else if (nodeIndex !== undefined && nodeIndex > -1) {
const tasksAfterCurrent = tasks.slice(nodeIndex);

Expand Down
Loading