@@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
33
44import { PipelineValidationList } from "@/components/Editor/components/PipelineValidationList/PipelineValidationList" ;
55import { useValidationIssueNavigation } from "@/components/Editor/hooks/useValidationIssueNavigation" ;
6+ import { ArtifactsList } from "@/components/shared/ArtifactsList/ArtifactsList" ;
67import { CopyText } from "@/components/shared/CopyText/CopyText" ;
78import { Button } from "@/components/ui/button" ;
89import { Icon } from "@/components/ui/icon" ;
@@ -98,18 +99,6 @@ const PipelineDetails = () => {
9899 ) ;
99100 } ;
100101
101- const handleInputCopy = ( input : InputSpec ) => {
102- const value = input . value ?? input . default ;
103-
104- if ( ! value ) {
105- notify ( "Copy failed: Input has no value" , "error" ) ;
106- return ;
107- }
108-
109- void navigator . clipboard . writeText ( value ) ;
110- notify ( "Input value copied to clipboard" , "success" ) ;
111- } ;
112-
113102 const handleDigestCopy = ( ) => {
114103 navigator . clipboard . writeText ( digest ) ;
115104 notify ( "Digest copied to clipboard" , "success" ) ;
@@ -134,7 +123,7 @@ const PipelineDetails = () => {
134123 className = "p-2 h-full"
135124 data-context-panel = "pipeline-details"
136125 >
137- < CopyText className = "text-lg font-semibold" showButton = { false } >
126+ < CopyText className = "text-lg font-semibold" >
138127 { componentSpec . name ?? "Unnamed Pipeline" }
139128 </ CopyText >
140129 < InlineStack gap = "2" >
@@ -149,38 +138,38 @@ const PipelineDetails = () => {
149138 { ( fileMeta . createdBy ||
150139 fileMeta . creationTime ||
151140 fileMeta . modificationTime ) && (
152- < BlockStack >
153- < Text as = "h3" size = "md" weight = "semibold" className = "mb-1" >
154- Pipeline Info
155- </ Text >
156- < dl className = "flex flex-col gap-1 text-xs text-secondary-foreground" >
157- { fileMeta . createdBy && (
158- < InlineStack as = "div" gap = "1" blockAlign = "center" >
159- < Text as = "dt" weight = "semibold" >
160- Created by:
161- </ Text >
162- < dd > { fileMeta . createdBy } </ dd >
163- </ InlineStack >
164- ) }
165- { fileMeta . creationTime && (
166- < InlineStack as = "div" gap = "1" blockAlign = "center" >
167- < Text as = "dt" weight = "semibold" >
168- Created at:
169- </ Text >
170- < dd > { new Date ( fileMeta . creationTime ) . toLocaleString ( ) } </ dd >
171- </ InlineStack >
172- ) }
173- { fileMeta . modificationTime && (
174- < InlineStack as = "div" gap = "1" blockAlign = "center" >
175- < Text as = "dt" weight = "semibold" >
176- Last updated:
177- </ Text >
178- < dd > { new Date ( fileMeta . modificationTime ) . toLocaleString ( ) } </ dd >
179- </ InlineStack >
180- ) }
181- </ dl >
182- </ BlockStack >
183- ) }
141+ < BlockStack >
142+ < Text as = "h3" size = "md" weight = "semibold" className = "mb-1" >
143+ Pipeline Info
144+ </ Text >
145+ < dl className = "flex flex-col gap-1 text-xs text-secondary-foreground" >
146+ { fileMeta . createdBy && (
147+ < InlineStack as = "div" gap = "1" blockAlign = "center" >
148+ < Text as = "dt" weight = "semibold" >
149+ Created by:
150+ </ Text >
151+ < dd > { fileMeta . createdBy } </ dd >
152+ </ InlineStack >
153+ ) }
154+ { fileMeta . creationTime && (
155+ < InlineStack as = "div" gap = "1" blockAlign = "center" >
156+ < Text as = "dt" weight = "semibold" >
157+ Created at:
158+ </ Text >
159+ < dd > { new Date ( fileMeta . creationTime ) . toLocaleString ( ) } </ dd >
160+ </ InlineStack >
161+ ) }
162+ { fileMeta . modificationTime && (
163+ < InlineStack as = "div" gap = "1" blockAlign = "center" >
164+ < Text as = "dt" weight = "semibold" >
165+ Last updated:
166+ </ Text >
167+ < dd > { new Date ( fileMeta . modificationTime ) . toLocaleString ( ) } </ dd >
168+ </ InlineStack >
169+ ) }
170+ </ dl >
171+ </ BlockStack >
172+ ) }
184173
185174 { componentSpec . description && (
186175 < BlockStack >
@@ -232,112 +221,46 @@ const PipelineDetails = () => {
232221 </ BlockStack >
233222 ) }
234223
235- { /* Artifacts (Inputs & Outputs) */ }
236- < BlockStack >
237- < Text as = "h3" size = "md" weight = "semibold" className = "mb-1" >
238- Artifacts
239- </ Text >
240- < BlockStack gap = "4" >
241- < BlockStack >
242- < Text as = "h4" size = "sm" weight = "semibold" className = "mb-1" >
243- Inputs
244- </ Text >
245- { componentSpec . inputs && componentSpec . inputs . length > 0 ? (
246- < div className = "flex flex-col" >
247- { componentSpec . inputs . map ( ( input ) => {
248- return (
249- < div
250- className = "flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-1 rounded-xs items-center"
251- key = { input . name }
252- >
253- < div className = "text-xs flex-1 truncate max-w-[200px]" >
254- < span className = "font-semibold" > { input . name } :</ span > { " " }
255- { input . value || input . default || "No value" }
256- </ div >
257-
258- < div className = "text-xs flex-1 font-mono truncate max-w-[100px]" >
259- < span className = "font-semibold" > Type:</ span > { " " }
260- { typeSpecToString ( input ?. type ) }
261- </ div >
262- < InlineStack
263- className = "min-w-24"
264- align = "end"
265- blockAlign = "center"
266- >
267- < Button
268- type = "button"
269- variant = "ghost"
270- size = "min"
271- onClick = { ( ) => handleInputCopy ( input ) }
272- className = "text-muted-foreground hover:text-foreground"
273- >
274- < Icon name = "Copy" className = "size-3" />
275- </ Button >
276-
277- < Button
278- type = "button"
279- variant = "ghost"
280- className = "text-xs text-muted-foreground cursor-pointer hover:bg-transparent"
281- size = "sm"
282- onClick = { ( ) => handleInputEdit ( input ) }
283- >
284- Edit
285- </ Button >
286- </ InlineStack >
287- </ div >
288- ) ;
289- } ) }
290- </ div >
291- ) : (
292- < div className = "text-xs text-muted-foreground" > No inputs</ div >
293- ) }
294- </ BlockStack >
295- < BlockStack >
296- < Text as = "h4" size = "sm" weight = "semibold" className = "mb-1" >
297- Outputs
298- </ Text >
299- { componentSpec . outputs && componentSpec . outputs . length > 0 ? (
300- < div className = "flex flex-col" >
301- { componentSpec . outputs . map ( ( output ) => (
302- < div
303- className = "flex flex-row justify-between even:bg-white odd:bg-gray-100 gap-1 px-2 py-1 rounded-xs items-center"
304- key = { output . name }
305- >
306- < div className = "text-xs flex-1 truncate max-w-[200px]" >
307- < span className = "font-semibold" > { output . name } :</ span > { " " }
308- {
309- getOutputConnectedDetails ( graphSpec , output . name )
310- . outputName
311- }
312- </ div >
313- < div className = "text-xs" >
314- < span className = "font-semibold" > Type:</ span > { " " }
315- { typeSpecToString (
316- getOutputConnectedDetails ( graphSpec , output . name )
317- . outputType ,
318- ) }
319- </ div >
320-
321- < InlineStack className = "min-w-24" align = { "end" } >
322- < Button
323- type = "button"
324- variant = "ghost"
325- className = "text-xs text-muted-foreground cursor-pointer hover:bg-transparent"
326- size = "sm"
327- onClick = { ( ) => handleOutputEdit ( output ) }
328- >
329- Edit
330- </ Button >
331- </ InlineStack >
332- </ div >
333- ) ) }
334- </ div >
335- ) : (
336- < div className = "text-xs text-muted-foreground" > No outputs</ div >
337- ) }
338- </ BlockStack >
339- </ BlockStack >
340- </ BlockStack >
224+ < ArtifactsList
225+ inputs = { ( componentSpec . inputs ?? [ ] ) . map ( ( input ) => ( {
226+ name : input . name ,
227+ type : typeSpecToString ( input ?. type ) ,
228+ value : input . value || input . default ,
229+ actions : (
230+ < Button
231+ type = "button"
232+ variant = "ghost"
233+ size = "min"
234+ onClick = { ( ) => handleInputEdit ( input ) }
235+ className = "text-muted-foreground hover:text-foreground h-4 w-4"
236+ >
237+ < Icon name = "Pencil" className = "size-2.5" />
238+ </ Button >
239+ ) ,
240+ } ) ) }
241+ outputs = { ( componentSpec . outputs ?? [ ] ) . map ( ( output ) => {
242+ const connectedDetails = getOutputConnectedDetails (
243+ graphSpec ,
244+ output . name ,
245+ ) ;
246+ return {
247+ name : output . name ,
248+ type : typeSpecToString ( connectedDetails . outputType ) ,
249+ value : connectedDetails . outputName ,
250+ actions : (
251+ < Button
252+ type = "button"
253+ variant = "ghost"
254+ size = "min"
255+ onClick = { ( ) => handleOutputEdit ( output ) }
256+ className = "text-muted-foreground hover:text-foreground h-4 w-4"
257+ >
258+ < Icon name = "Pencil" className = "size-2.5" />
259+ </ Button >
260+ ) ,
261+ } ;
262+ } ) }
263+ />
341264
342265 { /* Validations */ }
343266 < BlockStack >
0 commit comments