diff --git a/client/src/components/Workflow/Editor/modules/model.ts b/client/src/components/Workflow/Editor/modules/model.ts index 20500f71fa39..0ea90f078a03 100644 --- a/client/src/components/Workflow/Editor/modules/model.ts +++ b/client/src/components/Workflow/Editor/modules/model.ts @@ -2,7 +2,12 @@ import reportDefault from "@/components/Workflow/Editor/reportDefault"; import { useWorkflowCommentStore, type WorkflowComment } from "@/stores/workflowEditorCommentStore"; import { useWorkflowStateStore } from "@/stores/workflowEditorStateStore"; import { useWorkflowEditorToolbarStore } from "@/stores/workflowEditorToolbarStore"; -import { type ConnectionOutputLink, type Steps, useWorkflowStepStore } from "@/stores/workflowStepStore"; +import { + type ConnectionOutputLink, + type StepInputConnection, + type Steps, + useWorkflowStepStore, +} from "@/stores/workflowStepStore"; export interface Workflow { name: string; @@ -48,13 +53,19 @@ export async function fromSimple( // If workflow being copied into another, wipe UUID and let // Galaxy assign new ones. if (options?.reassignIds ?? appendData) { - const highestStepId = stepStore.getStepIndex; - + const stepIdOffset = stepStore.getStepIndex + 1; const stepArray = Object.values(data.steps); - const stepIds = Object.keys(data.steps).map((id) => parseInt(id)); - const lowestStepId = Math.min(...stepIds); - const stepIdOffset = highestStepId - lowestStepId + 1; + // Since we are resigning IDs based on index, ensure correct ordering + stepArray.sort((a, b) => a.id - b.id); + + const stepIdMapOldToNew = new Map(); + + stepArray.forEach((step, index) => { + const oldId = step.id; + step.id = index + stepIdOffset; + stepIdMapOldToNew.set(oldId, step.id); + }); stepArray.forEach((step) => { delete step.uuid; @@ -63,10 +74,12 @@ export async function fromSimple( // good enough for a first pass IMO. step.position = { top: step.id * 100, left: step.id * 100 }; } - step.id += stepIdOffset; step.position.left += defaultPosition.left; step.position.top += defaultPosition.top; - Object.values(step.input_connections).forEach((link) => { + + const newInputConnections: StepInputConnection = {}; + + Object.entries(step.input_connections).forEach(([key, link]) => { if (link === undefined) { console.error("input connections invalid", step.input_connections); } else { @@ -76,11 +89,25 @@ export async function fromSimple( } else { linkArray = link; } - linkArray.forEach((link) => { - link.id += stepIdOffset; + + const remappedLinkArray = linkArray.map((link) => { + const newId = stepIdMapOldToNew.get(link.id); + + return { + ...link, + id: newId, + }; }); + + // id may be undefined, if the partial Workflow does not contain the step + // in that case, remove the link + const newLinkArray = remappedLinkArray.filter((link) => link.id) as ConnectionOutputLink[]; + + newInputConnections[key] = newLinkArray; } }); + + step.input_connections = newInputConnections; }); data.comments.forEach((comment, index) => {