Skip to content

Commit 22badcd

Browse files
committed
feat: copy submit pipeline arguments from custom run id
1 parent 6f6daa8 commit 22badcd

File tree

1 file changed

+122
-40
lines changed

1 file changed

+122
-40
lines changed

src/components/shared/Submitters/Oasis/components/SubmitTaskArgumentsDialog.tsx

Lines changed: 122 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useMutation } from "@tanstack/react-query";
2-
import { type ChangeEvent, useState } from "react";
2+
import { type ChangeEvent, type KeyboardEvent, useState } from "react";
33

4+
import type { TaskSpecOutput } from "@/api/types.gen";
45
import { PipelineRunsList } from "@/components/shared/PipelineRunDisplay/PipelineRunsList";
56
import { typeSpecToString } from "@/components/shared/ReactFlow/FlowCanvas/TaskNode/ArgumentsEditor/utils";
67
import { getArgumentsFromInputs } from "@/components/shared/ReactFlow/FlowCanvas/utils/getArgumentsFromInputs";
@@ -22,14 +23,20 @@ import {
2223
PopoverTrigger,
2324
} from "@/components/ui/popover";
2425
import { ScrollArea } from "@/components/ui/scroll-area";
26+
import { Spinner } from "@/components/ui/spinner";
2527
import { Paragraph } from "@/components/ui/typography";
2628
import { cn } from "@/lib/utils";
2729
import { useBackend } from "@/providers/BackendProvider";
28-
import { fetchExecutionDetails } from "@/services/executionService";
30+
import {
31+
fetchExecutionDetails,
32+
fetchPipelineRun,
33+
} from "@/services/executionService";
2934
import type { PipelineRun } from "@/types/pipelineRun";
3035
import type { ComponentSpec, InputSpec } from "@/utils/componentSpec";
3136
import { getArgumentValue } from "@/utils/nodes/taskArguments";
3237

38+
type TaskArguments = TaskSpecOutput["arguments"];
39+
3340
interface SubmitTaskArgumentsDialogProps {
3441
open: boolean;
3542
onCancel: () => void;
@@ -85,7 +92,12 @@ export const SubmitTaskArgumentsDialog = ({
8592
<InlineStack align="end" className="w-full">
8693
<CopyFromRunPopover
8794
componentSpec={componentSpec}
88-
onCopy={setTaskArguments}
95+
onCopy={(newArgs) => {
96+
setTaskArguments((prev) => ({
97+
...prev,
98+
...newArgs,
99+
}));
100+
}}
89101
/>
90102
</InlineStack>
91103
</BlockStack>
@@ -133,34 +145,69 @@ const CopyFromRunPopover = ({
133145
const pipelineName = componentSpec.name;
134146

135147
const [popoverOpen, setPopoverOpen] = useState(false);
148+
const [customRunId, setCustomRunId] = useState("");
136149

137-
const { mutate: copyFromRunMutation, isPending: isCopyingFromRun } =
138-
useMutation({
139-
mutationFn: async (run: PipelineRun) => {
140-
const executionDetails = await fetchExecutionDetails(
141-
String(run.root_execution_id),
142-
backendUrl,
150+
const {
151+
mutate: copyFromRunMutation,
152+
isPending: isCopyingFromRun,
153+
isError,
154+
} = useMutation({
155+
/**
156+
* @param run - The run to copy arguments from. Can be a run ID or a run object.
157+
* @returns
158+
*/
159+
mutationFn: async (run: PipelineRun | string) => {
160+
const executionId =
161+
typeof run === "string"
162+
? (await fetchPipelineRun(run, backendUrl)).root_execution_id
163+
: String(run.root_execution_id);
164+
165+
const executionDetails = await fetchExecutionDetails(
166+
executionId,
167+
backendUrl,
168+
);
169+
return executionDetails.task_spec.arguments;
170+
},
171+
onSuccess: (runArguments: TaskArguments) => {
172+
if (runArguments) {
173+
const componentSpecInputs = new Set(
174+
componentSpec.inputs?.map((input) => input.name) ?? [],
143175
);
144-
return executionDetails.task_spec.arguments;
145-
},
146-
onSuccess: (runArguments) => {
147-
if (runArguments) {
148-
const newArgs = Object.fromEntries(
149-
Object.entries(runArguments)
150-
.map(([name, _]) => [name, getArgumentValue(runArguments, name)])
151-
.filter(
152-
(entry): entry is [string, string] => entry[1] !== undefined,
153-
),
154-
);
155-
onCopy(newArgs);
156-
}
157-
setPopoverOpen(false);
158-
},
159-
onError: (error) => {
160-
console.error("Failed to fetch run arguments:", error);
161-
setPopoverOpen(false);
162-
},
163-
});
176+
177+
const newArgs = Object.fromEntries(
178+
Object.entries(runArguments)
179+
.map(
180+
([name, _]) =>
181+
[name, getArgumentValue(runArguments, name)] as const,
182+
)
183+
.filter(
184+
(entry): entry is [string, string] =>
185+
entry[1] !== undefined && componentSpecInputs.has(entry[0]),
186+
),
187+
);
188+
189+
onCopy(newArgs);
190+
}
191+
setPopoverOpen(false);
192+
setCustomRunId("");
193+
},
194+
onError: (error) => {
195+
console.error("Failed to fetch run arguments:", error);
196+
},
197+
});
198+
199+
const handleCustomRunIdSubmit = () => {
200+
const trimmedId = customRunId.trim();
201+
if (trimmedId) {
202+
copyFromRunMutation(trimmedId);
203+
}
204+
};
205+
206+
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
207+
if (e.key === "Enter") {
208+
handleCustomRunIdSubmit();
209+
}
210+
};
164211

165212
return (
166213
<Popover open={popoverOpen} onOpenChange={setPopoverOpen}>
@@ -171,17 +218,52 @@ const CopyFromRunPopover = ({
171218
</Button>
172219
</PopoverTrigger>
173220
<PopoverContent className="w-100" align="end">
174-
<PipelineRunsList
175-
pipelineName={pipelineName}
176-
onRunClick={copyFromRunMutation}
177-
showTitle={false}
178-
showMoreButton={true}
179-
overviewConfig={{
180-
showName: false,
181-
showTaskStatusBar: false,
182-
}}
183-
disabled={isCopyingFromRun}
184-
/>
221+
<BlockStack gap="4">
222+
<BlockStack gap="2">
223+
<Paragraph size="sm" weight="semibold">
224+
Enter run ID
225+
</Paragraph>
226+
<InlineStack gap="2" fill>
227+
<Input
228+
placeholder="Run ID"
229+
value={customRunId}
230+
onChange={(e) => setCustomRunId(e.target.value)}
231+
onKeyDown={handleKeyDown}
232+
disabled={isCopyingFromRun}
233+
className={cn(isError && "border-red-300", "flex-1")}
234+
/>
235+
<Button
236+
size="sm"
237+
onClick={handleCustomRunIdSubmit}
238+
disabled={isCopyingFromRun || !customRunId.trim()}
239+
>
240+
{isCopyingFromRun ? <Spinner /> : <Icon name="ArrowRight" />}
241+
</Button>
242+
</InlineStack>
243+
{isError && (
244+
<Paragraph size="xs" tone="critical">
245+
Failed to fetch run. Please check the run ID.
246+
</Paragraph>
247+
)}
248+
</BlockStack>
249+
250+
<BlockStack gap="2">
251+
<Paragraph size="sm" weight="semibold">
252+
Or select from recent runs
253+
</Paragraph>
254+
<PipelineRunsList
255+
pipelineName={pipelineName}
256+
onRunClick={copyFromRunMutation}
257+
showTitle={false}
258+
showMoreButton={true}
259+
overviewConfig={{
260+
showName: false,
261+
showTaskStatusBar: false,
262+
}}
263+
disabled={isCopyingFromRun}
264+
/>
265+
</BlockStack>
266+
</BlockStack>
185267
</PopoverContent>
186268
</Popover>
187269
);

0 commit comments

Comments
 (0)