From e34cd6238c2e9d82fa47a80a659eb1e7266032a0 Mon Sep 17 00:00:00 2001 From: mbeaulne Date: Fri, 5 Dec 2025 13:06:02 -0500 Subject: [PATCH] Abstracts artifacts list --- src/components/Editor/PipelineDetails.tsx | 159 +++++------------- src/components/PipelineRun/RunDetails.tsx | 67 ++------ .../shared/ArtifactsList/ArtifactsList.tsx | 105 ++++++++++++ 3 files changed, 158 insertions(+), 173 deletions(-) create mode 100644 src/components/shared/ArtifactsList/ArtifactsList.tsx diff --git a/src/components/Editor/PipelineDetails.tsx b/src/components/Editor/PipelineDetails.tsx index e344af60b..767f6cd7a 100644 --- a/src/components/Editor/PipelineDetails.tsx +++ b/src/components/Editor/PipelineDetails.tsx @@ -3,6 +3,7 @@ import { useEffect, useState } from "react"; import { PipelineValidationList } from "@/components/Editor/components/PipelineValidationList/PipelineValidationList"; import { useValidationIssueNavigation } from "@/components/Editor/hooks/useValidationIssueNavigation"; +import { ArtifactsList } from "@/components/shared/ArtifactsList/ArtifactsList"; import { CopyText } from "@/components/shared/CopyText/CopyText"; import { Button } from "@/components/ui/button"; import { Icon } from "@/components/ui/icon"; @@ -98,18 +99,6 @@ const PipelineDetails = () => { ); }; - const handleInputCopy = (input: InputSpec) => { - const value = input.value ?? input.default; - - if (!value) { - notify("Copy failed: Input has no value", "error"); - return; - } - - void navigator.clipboard.writeText(value); - notify("Input value copied to clipboard", "success"); - }; - const handleDigestCopy = () => { navigator.clipboard.writeText(digest); notify("Digest copied to clipboard", "success"); @@ -232,112 +221,46 @@ const PipelineDetails = () => { )} - {/* Artifacts (Inputs & Outputs) */} - - - Artifacts - - - - - Inputs - - {componentSpec.inputs && componentSpec.inputs.length > 0 ? ( -
- {componentSpec.inputs.map((input) => { - return ( -
-
- {input.name}:{" "} - {input.value || input.default || "No value"} -
- -
- Type:{" "} - {typeSpecToString(input?.type)} -
- - - - - -
- ); - })} -
- ) : ( -
No inputs
- )} -
- - - Outputs - - {componentSpec.outputs && componentSpec.outputs.length > 0 ? ( -
- {componentSpec.outputs.map((output) => ( -
-
- {output.name}:{" "} - { - getOutputConnectedDetails(graphSpec, output.name) - .outputName - } -
-
- Type:{" "} - {typeSpecToString( - getOutputConnectedDetails(graphSpec, output.name) - .outputType, - )} -
- - - - -
- ))} -
- ) : ( -
No outputs
- )} -
-
-
+ ({ + name: input.name, + type: typeSpecToString(input?.type), + value: input.value || input.default, + actions: ( + + ), + }))} + outputs={(componentSpec.outputs ?? []).map((output) => { + const connectedDetails = getOutputConnectedDetails( + graphSpec, + output.name, + ); + return { + name: output.name, + type: typeSpecToString(connectedDetails.outputType), + value: connectedDetails.outputName, + actions: ( + + ), + }; + })} + /> {/* Validations */} diff --git a/src/components/PipelineRun/RunDetails.tsx b/src/components/PipelineRun/RunDetails.tsx index 292424b6b..617facaac 100644 --- a/src/components/PipelineRun/RunDetails.tsx +++ b/src/components/PipelineRun/RunDetails.tsx @@ -1,5 +1,6 @@ import { Frown } from "lucide-react"; +import { ArtifactsList } from "@/components/shared/ArtifactsList/ArtifactsList"; import { CopyText } from "@/components/shared/CopyText/CopyText"; import { BlockStack, InlineStack } from "@/components/ui/layout"; import { Spinner } from "@/components/ui/spinner"; @@ -201,61 +202,17 @@ export const RunDetails = () => { )} - - - Artifacts - - - - - Inputs - - {componentSpec.inputs && componentSpec.inputs.length > 0 ? ( -
- {componentSpec.inputs.map((input) => ( -
-
- {input.name} -
-
- {typeof input.type === "string" ? input.type : "object"} -
-
- ))} -
- ) : ( -
No inputs
- )} -
- - - Outputs - - {componentSpec.outputs && componentSpec.outputs.length > 0 ? ( -
- {componentSpec.outputs.map((output) => ( -
-
- {output.name} -
-
- {typeof output.type === "string" ? output.type : "object"} -
-
- ))} -
- ) : ( -
No outputs
- )} -
-
-
+ ({ + name: input.name, + type: typeof input.type === "string" ? input.type : "object", + value: input.value ?? input.default, + }))} + outputs={(componentSpec.outputs ?? []).map((output) => ({ + name: output.name, + type: typeof output.type === "string" ? output.type : "object", + }))} + /> ); }; diff --git a/src/components/shared/ArtifactsList/ArtifactsList.tsx b/src/components/shared/ArtifactsList/ArtifactsList.tsx new file mode 100644 index 000000000..a73027a52 --- /dev/null +++ b/src/components/shared/ArtifactsList/ArtifactsList.tsx @@ -0,0 +1,105 @@ +import { type ReactNode } from "react"; + +import { CopyText } from "@/components/shared/CopyText/CopyText"; +import { BlockStack, InlineStack } from "@/components/ui/layout"; +import { Text } from "@/components/ui/typography"; + +interface ArtifactItem { + name: string; + type: string; + value?: string; + actions?: ReactNode; +} + +interface ArtifactsSectionProps { + title: string; + items: ArtifactItem[]; + emptyMessage?: string; + disableCopy?: boolean; +} + +const ArtifactsSection = ({ + title, + items, + emptyMessage = "None", + disableCopy = false, +}: ArtifactsSectionProps) => ( + + + {title} + + {items.length > 0 ? ( + + {items.map((item) => ( + + + + {item.name}: + + {item.value !== undefined ? ( + !disableCopy ? ( + + {item.value || "No value"} + + ) : ( + + {item.value || "No value"} + + ) + ) : ( + + — + + )} + + + {item.type} + + {item.actions} + + ))} + + ) : ( + + {emptyMessage} + + )} + +); + +interface ArtifactsListProps { + inputs: ArtifactItem[]; + outputs: ArtifactItem[]; +} + +export const ArtifactsList = ({ inputs, outputs }: ArtifactsListProps) => ( + + + Artifacts + + + + + + +);