Skip to content

Commit 53ab305

Browse files
committed
feat: copy submit pipeline arguments from custom run id
1 parent da4f741 commit 53ab305

File tree

1 file changed

+116
-39
lines changed

1 file changed

+116
-39
lines changed

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

Lines changed: 116 additions & 39 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,15 +23,21 @@ 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 useToastNotification from "@/hooks/useToastNotification";
2729
import { cn } from "@/lib/utils";
2830
import { useBackend } from "@/providers/BackendProvider";
29-
import { fetchExecutionDetails } from "@/services/executionService";
31+
import {
32+
fetchExecutionDetails,
33+
fetchPipelineRun,
34+
} from "@/services/executionService";
3035
import type { PipelineRun } from "@/types/pipelineRun";
3136
import type { ComponentSpec, InputSpec } from "@/utils/componentSpec";
3237
import { getArgumentValue } from "@/utils/nodes/taskArguments";
3338

39+
type TaskArguments = TaskSpecOutput["arguments"];
40+
3441
interface SubmitTaskArgumentsDialogProps {
3542
open: boolean;
3643
onCancel: () => void;
@@ -161,34 +168,69 @@ const CopyFromRunPopover = ({
161168
const pipelineName = componentSpec.name;
162169

163170
const [popoverOpen, setPopoverOpen] = useState(false);
171+
const [customRunId, setCustomRunId] = useState("");
164172

165-
const { mutate: copyFromRunMutation, isPending: isCopyingFromRun } =
166-
useMutation({
167-
mutationFn: async (run: PipelineRun) => {
168-
const executionDetails = await fetchExecutionDetails(
169-
String(run.root_execution_id),
170-
backendUrl,
173+
const {
174+
mutate: copyFromRunMutation,
175+
isPending: isCopyingFromRun,
176+
isError,
177+
} = useMutation({
178+
/**
179+
* @param run - The run to copy arguments from. Can be a run ID or a run object.
180+
* @returns
181+
*/
182+
mutationFn: async (run: PipelineRun | string) => {
183+
const executionId =
184+
typeof run === "string"
185+
? (await fetchPipelineRun(run, backendUrl)).root_execution_id
186+
: String(run.root_execution_id);
187+
188+
const executionDetails = await fetchExecutionDetails(
189+
executionId,
190+
backendUrl,
191+
);
192+
return executionDetails.task_spec.arguments;
193+
},
194+
onSuccess: (runArguments: TaskArguments) => {
195+
if (runArguments) {
196+
const componentSpecInputs = new Set(
197+
componentSpec.inputs?.map((input) => input.name) ?? [],
171198
);
172-
return executionDetails.task_spec.arguments;
173-
},
174-
onSuccess: (runArguments) => {
175-
if (runArguments) {
176-
const newArgs = Object.fromEntries(
177-
Object.entries(runArguments)
178-
.map(([name, _]) => [name, getArgumentValue(runArguments, name)])
179-
.filter(
180-
(entry): entry is [string, string] => entry[1] !== undefined,
181-
),
182-
);
183-
onCopy(newArgs);
184-
}
185-
setPopoverOpen(false);
186-
},
187-
onError: (error) => {
188-
console.error("Failed to fetch run arguments:", error);
189-
setPopoverOpen(false);
190-
},
191-
});
199+
200+
const newArgs = Object.fromEntries(
201+
Object.entries(runArguments)
202+
.map(
203+
([name, _]) =>
204+
[name, getArgumentValue(runArguments, name)] as const,
205+
)
206+
.filter(
207+
(entry): entry is [string, string] =>
208+
entry[1] !== undefined && componentSpecInputs.has(entry[0]),
209+
),
210+
);
211+
212+
onCopy(newArgs);
213+
}
214+
setPopoverOpen(false);
215+
setCustomRunId("");
216+
},
217+
onError: (error) => {
218+
console.error("Failed to fetch run arguments:", error);
219+
},
220+
});
221+
222+
const handleCustomRunIdSubmit = () => {
223+
const trimmedId = customRunId.trim();
224+
if (trimmedId) {
225+
copyFromRunMutation(trimmedId);
226+
}
227+
};
228+
229+
const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
230+
if (e.key === "Enter") {
231+
handleCustomRunIdSubmit();
232+
}
233+
};
192234

193235
return (
194236
<Popover open={popoverOpen} onOpenChange={setPopoverOpen}>
@@ -199,17 +241,52 @@ const CopyFromRunPopover = ({
199241
</Button>
200242
</PopoverTrigger>
201243
<PopoverContent className="w-100" align="end">
202-
<PipelineRunsList
203-
pipelineName={pipelineName}
204-
onRunClick={copyFromRunMutation}
205-
showTitle={false}
206-
showMoreButton={true}
207-
overviewConfig={{
208-
showName: false,
209-
showTaskStatusBar: false,
210-
}}
211-
disabled={isCopyingFromRun}
212-
/>
244+
<BlockStack gap="4">
245+
<BlockStack gap="2">
246+
<Paragraph size="sm" weight="semibold">
247+
Enter run ID
248+
</Paragraph>
249+
<InlineStack gap="2" fill>
250+
<Input
251+
placeholder="Run ID"
252+
value={customRunId}
253+
onChange={(e) => setCustomRunId(e.target.value)}
254+
onKeyDown={handleKeyDown}
255+
disabled={isCopyingFromRun}
256+
className={cn(isError && "border-red-300", "flex-1")}
257+
/>
258+
<Button
259+
size="sm"
260+
onClick={handleCustomRunIdSubmit}
261+
disabled={isCopyingFromRun || !customRunId.trim()}
262+
>
263+
{isCopyingFromRun ? <Spinner /> : <Icon name="ArrowRight" />}
264+
</Button>
265+
</InlineStack>
266+
{isError && (
267+
<Paragraph size="xs" tone="critical">
268+
Failed to fetch run. Please check the run ID.
269+
</Paragraph>
270+
)}
271+
</BlockStack>
272+
273+
<BlockStack gap="2">
274+
<Paragraph size="sm" weight="semibold">
275+
Or select from recent runs
276+
</Paragraph>
277+
<PipelineRunsList
278+
pipelineName={pipelineName}
279+
onRunClick={copyFromRunMutation}
280+
showTitle={false}
281+
showMoreButton={true}
282+
overviewConfig={{
283+
showName: false,
284+
showTaskStatusBar: false,
285+
}}
286+
disabled={isCopyingFromRun}
287+
/>
288+
</BlockStack>
289+
</BlockStack>
213290
</PopoverContent>
214291
</Popover>
215292
);

0 commit comments

Comments
 (0)