From e23f81228da7893d0cced80ff3c442179c8f586c Mon Sep 17 00:00:00 2001 From: Yota Hamada Date: Mon, 20 Apr 2026 02:25:20 +0900 Subject: [PATCH 1/4] feat: show cockpit run artifacts --- api/v1/api.gen.go | 903 +++++++++--------- api/v1/api.yaml | 8 +- .../service/frontend/api/v1/transformer.go | 31 +- .../frontend/api/v1/transformer_test.go | 2 + ui/src/api/v1/schema.ts | 4 +- .../cockpit/components/ArtifactListModal.tsx | 372 ++++++++ .../cockpit/components/DateKanbanList.tsx | 19 +- .../cockpit/components/DateKanbanSection.tsx | 16 +- .../cockpit/components/KanbanBoard.tsx | 11 +- .../cockpit/components/KanbanCard.tsx | 71 +- .../cockpit/components/KanbanColumn.tsx | 3 + .../cockpit/components/MobileKanbanBoard.tsx | 3 + .../__tests__/ArtifactListModal.test.tsx | 91 ++ .../__tests__/DateKanbanList.test.tsx | 15 +- .../__tests__/DateKanbanSection.test.tsx | 3 + .../components/__tests__/KanbanCard.test.tsx | 55 +- .../__tests__/KanbanCounts.test.tsx | 36 +- .../common/__tests__/DAGRunActions.test.tsx | 2 + .../__tests__/DAGRunGroupedView.test.tsx | 3 + .../__tests__/DAGRunTable.test.tsx | 3 + .../__tests__/useBulkDAGRunSelection.test.tsx | 1 + .../common/__tests__/DAGActions.test.tsx | 2 + 22 files changed, 1141 insertions(+), 513 deletions(-) create mode 100644 ui/src/features/cockpit/components/ArtifactListModal.tsx create mode 100644 ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx diff --git a/api/v1/api.gen.go b/api/v1/api.gen.go index 6d41e794fc..5fa38feece 100644 --- a/api/v1/api.gen.go +++ b/api/v1/api.gen.go @@ -1450,6 +1450,9 @@ type DAGRunOutputs struct { // DAGRunSummary Current status of a DAG-run type DAGRunSummary struct { + // ArtifactsAvailable Whether artifact endpoints are available for this DAG-run + ArtifactsAvailable bool `json:"artifactsAvailable"` + // AutoRetryCount Number of scheduler-issued DAG auto-retries already consumed for this DAG-run AutoRetryCount int `json:"autoRetryCount"` @@ -28408,456 +28411,456 @@ var swaggerSpec = []string{ "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", - "i/wDAA==", + "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", + "q8qL/AMA", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/api.yaml b/api/v1/api.yaml index 352c9ba924..b3d5084841 100644 --- a/api/v1/api.yaml +++ b/api/v1/api.yaml @@ -8473,6 +8473,9 @@ components: finishedAt: type: string description: "RFC 3339 timestamp when the DAG-run finished" + artifactsAvailable: + type: boolean + description: "Whether artifact endpoints are available for this DAG-run" params: type: string description: "Runtime parameters passed to the DAG-run in JSON format" @@ -8499,6 +8502,7 @@ components: - statusLabel - startedAt - finishedAt + - artifactsAvailable - autoRetryCount DAGRunDetails: @@ -8526,9 +8530,6 @@ components: log: type: string description: "Path to the log file" - artifactsAvailable: - type: boolean - description: "Whether artifact endpoints are available for this DAG-run" nodes: type: array description: "Status of individual steps within the DAG-run" @@ -8557,7 +8558,6 @@ components: - rootDAGRunName - rootDAGRunId - log - - artifactsAvailable - nodes ArtifactNodeType: diff --git a/internal/service/frontend/api/v1/transformer.go b/internal/service/frontend/api/v1/transformer.go index b4b3d14c52..33524417a1 100644 --- a/internal/service/frontend/api/v1/transformer.go +++ b/internal/service/frontend/api/v1/transformer.go @@ -192,21 +192,22 @@ func toDAGRunSummary(s exec.DAGRunStatus) api.DAGRunSummary { } return api.DAGRunSummary{ - Name: s.Name, - DagRunId: s.DAGRunID, - Params: ptrOf(s.Params), - QueuedAt: ptrOf(s.QueuedAt), - AutoRetryCount: s.AutoRetryCount, - AutoRetryLimit: autoRetryLimit, - ScheduleTime: ptrOf(s.ScheduleTime), - StartedAt: s.StartedAt, - FinishedAt: s.FinishedAt, - Status: api.Status(s.Status), - StatusLabel: api.StatusLabel(s.Status.String()), - WorkerId: ptrOf(s.WorkerID), - TriggerType: toTriggerType(s.TriggerType), - Labels: &s.Labels, - Tags: &s.Labels, + Name: s.Name, + DagRunId: s.DAGRunID, + Params: ptrOf(s.Params), + QueuedAt: ptrOf(s.QueuedAt), + AutoRetryCount: s.AutoRetryCount, + AutoRetryLimit: autoRetryLimit, + ScheduleTime: ptrOf(s.ScheduleTime), + StartedAt: s.StartedAt, + FinishedAt: s.FinishedAt, + ArtifactsAvailable: s.ArchiveDir != "", + Status: api.Status(s.Status), + StatusLabel: api.StatusLabel(s.Status.String()), + WorkerId: ptrOf(s.WorkerID), + TriggerType: toTriggerType(s.TriggerType), + Labels: &s.Labels, + Tags: &s.Labels, } } diff --git a/internal/service/frontend/api/v1/transformer_test.go b/internal/service/frontend/api/v1/transformer_test.go index 83b6b8f7c6..f37c1a60a0 100644 --- a/internal/service/frontend/api/v1/transformer_test.go +++ b/internal/service/frontend/api/v1/transformer_test.go @@ -20,6 +20,7 @@ func TestToDAGRunSummaryIncludesScheduleTime(t *testing.T) { DAGRunID: "run-1", AutoRetryCount: 2, AutoRetryLimit: 5, + ArchiveDir: "/tmp/artifacts/test-dag/run-1", Status: core.Queued, ScheduleTime: "2026-03-13T00:00:00Z", } @@ -30,6 +31,7 @@ func TestToDAGRunSummaryIncludesScheduleTime(t *testing.T) { assert.Equal(t, status.AutoRetryCount, summary.AutoRetryCount) require.NotNil(t, summary.AutoRetryLimit) assert.Equal(t, status.AutoRetryLimit, *summary.AutoRetryLimit) + assert.True(t, summary.ArtifactsAvailable) } func TestToDAGRunDetailsIncludesScheduleTime(t *testing.T) { diff --git a/ui/src/api/v1/schema.ts b/ui/src/api/v1/schema.ts index faf67f32d0..cfd1d2257b 100644 --- a/ui/src/api/v1/schema.ts +++ b/ui/src/api/v1/schema.ts @@ -3443,6 +3443,8 @@ export interface components { startedAt: string; /** @description RFC 3339 timestamp when the DAG-run finished */ finishedAt: string; + /** @description Whether artifact endpoints are available for this DAG-run */ + artifactsAvailable: boolean; /** @description Runtime parameters passed to the DAG-run in JSON format */ params?: string; /** @description ID of the worker that executed this DAG-run ('local' for local execution) */ @@ -3466,8 +3468,6 @@ export interface components { parentDAGRunId?: components["schemas"]["DAGRunId"] & unknown; /** @description Path to the log file */ log: string; - /** @description Whether artifact endpoints are available for this DAG-run */ - artifactsAvailable: boolean; /** @description Status of individual steps within the DAG-run */ nodes: components["schemas"]["Node"][]; onExit?: components["schemas"]["Node"]; diff --git a/ui/src/features/cockpit/components/ArtifactListModal.tsx b/ui/src/features/cockpit/components/ArtifactListModal.tsx new file mode 100644 index 0000000000..6e121479a8 --- /dev/null +++ b/ui/src/features/cockpit/components/ArtifactListModal.tsx @@ -0,0 +1,372 @@ +// Copyright (C) 2026 Yota Hamada +// SPDX-License-Identifier: GPL-3.0-or-later + +import React, { useContext, useEffect, useMemo, useState } from 'react'; +import { + AlertCircle, + Download, + File, + FileImage, + FileText, + Folder, + RefreshCw, +} from 'lucide-react'; +import { components } from '@/api/v1/schema'; +import { Button } from '@/components/ui/button'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog'; +import { AppBarContext } from '@/contexts/AppBarContext'; +import { useClient } from '@/hooks/api'; +import { cn } from '@/lib/utils'; + +type DAGRunSummary = components['schemas']['DAGRunSummary']; +type ArtifactTreeNode = components['schemas']['ArtifactTreeNode']; + +interface Props { + run: DAGRunSummary | null; + isOpen: boolean; + onClose: () => void; +} + +function flattenNodes(nodes: ArtifactTreeNode[]): ArtifactTreeNode[] { + const flat: ArtifactTreeNode[] = []; + for (const node of nodes) { + flat.push(node); + if (node.children) { + flat.push(...flattenNodes(node.children)); + } + } + return flat; +} + +function formatBytes(size: number | undefined): string { + if (size == null) { + return ''; + } + if (size < 1024) { + return `${size} B`; + } + + const units = ['KB', 'MB', 'GB', 'TB']; + let value = size / 1024; + let unitIndex = 0; + while (value >= 1024 && unitIndex < units.length - 1) { + value /= 1024; + unitIndex += 1; + } + + return `${value >= 10 ? value.toFixed(0) : value.toFixed(1)} ${units[unitIndex]}`; +} + +function fileIconFor(node: ArtifactTreeNode) { + if (node.type === 'directory') { + return Folder; + } + if (node.path.match(/\.(png|jpe?g|gif|webp|svg|bmp|ico)$/i)) { + return FileImage; + } + if (node.path.match(/\.(md|markdown|mdown|mkd|txt|log|json|ya?ml|csv)$/i)) { + return FileText; + } + return File; +} + +function ArtifactRow({ + node, + depth, + downloadingPath, + onDownload, +}: { + node: ArtifactTreeNode; + depth: number; + downloadingPath: string | null; + onDownload: (node: ArtifactTreeNode) => void; +}) { + const Icon = fileIconFor(node); + const isDirectory = node.type === 'directory'; + const isDownloading = downloadingPath === node.path; + + return ( +
+
+ +
+
{node.name}
+
+ {node.path} +
+
+ {!isDirectory && ( + <> + {node.size != null && ( + + {formatBytes(node.size)} + + )} + + + )} +
+ {isDirectory && node.children && node.children.length > 0 && ( +
+ {node.children.map((child) => ( + + ))} +
+ )} +
+ ); +} + +export function ArtifactListModal({ + run, + isOpen, + onClose, +}: Props): React.ReactElement { + const client = useClient(); + const appBarContext = useContext(AppBarContext); + const remoteNode = appBarContext.selectedRemoteNode || 'local'; + const runName = run?.name; + const runId = run?.dagRunId; + + const [tree, setTree] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + const [downloadError, setDownloadError] = useState(null); + const [refreshKey, setRefreshKey] = useState(0); + const [downloadingPath, setDownloadingPath] = useState(null); + + const flatNodes = useMemo(() => flattenNodes(tree), [tree]); + const fileCount = flatNodes.filter((node) => node.type === 'file').length; + const totalSize = flatNodes.reduce( + (sum, node) => sum + (node.type === 'file' ? node.size || 0 : 0), + 0 + ); + + useEffect(() => { + if (!isOpen || !runName || !runId) { + setTree([]); + setError(null); + setDownloadError(null); + setIsLoading(false); + return; + } + + let cancelled = false; + const controller = new AbortController(); + + const fetchTree = async () => { + setIsLoading(true); + setError(null); + setDownloadError(null); + + try { + const request = await client.GET( + '/dag-runs/{name}/{dagRunId}/artifacts', + { + params: { + path: { + name: runName, + dagRunId: runId, + }, + query: { remoteNode, recursive: true }, + }, + signal: controller.signal, + } + ); + + if (cancelled) { + return; + } + + if (request.error) { + setTree([]); + setError(request.error.message || 'Failed to load artifacts'); + return; + } + + setTree(request.data?.items ?? []); + } catch (err: unknown) { + if (cancelled || controller.signal.aborted) { + return; + } + setTree([]); + setError( + err instanceof Error ? err.message : 'Failed to load artifacts' + ); + } finally { + if (!cancelled) { + setIsLoading(false); + } + } + }; + + void fetchTree(); + + return () => { + cancelled = true; + controller.abort(); + }; + }, [client, isOpen, refreshKey, remoteNode, runId, runName]); + + const handleDownload = async (node: ArtifactTreeNode) => { + if (!run || node.type !== 'file') { + return; + } + + setDownloadingPath(node.path); + setDownloadError(null); + + try { + const request = await client.GET( + '/dag-runs/{name}/{dagRunId}/artifacts/download', + { + params: { + path: { + name: run.name, + dagRunId: run.dagRunId, + }, + query: { remoteNode, path: node.path }, + }, + parseAs: 'blob', + } + ); + + if (request.error) { + throw new Error( + request.error.message || + request.response.statusText || + 'Download failed' + ); + } + + const blob = request.data; + const objectUrl = URL.createObjectURL(blob); + const link = document.createElement('a'); + const fileName = + request.response.headers + .get('Content-Disposition') + ?.match(/filename="(.+)"/)?.[1] || node.name; + + link.href = objectUrl; + link.download = fileName; + link.click(); + URL.revokeObjectURL(objectUrl); + } catch (err: unknown) { + setDownloadError(err instanceof Error ? err.message : 'Download failed'); + } finally { + setDownloadingPath(null); + } + }; + + return ( + !open && onClose()}> + + + + + Artifacts + + + {run ? `${run.name} / ${run.dagRunId}` : 'DAG run artifacts'} + + + +
+
+ {fileCount}{' '} + + {fileCount === 1 ? 'file' : 'files'} + + {totalSize > 0 && ( + + {' '} + ยท {formatBytes(totalSize)} + + )} +
+ +
+ +
+ {error ? ( +
+ + {error} +
+ ) : downloadError ? ( +
+ + {downloadError} +
+ ) : null} + + {isLoading ? ( +
+ Loading artifacts... +
+ ) : !error && tree.length === 0 ? ( +
+ No artifact files were found for this run. +
+ ) : !error ? ( +
+ {tree.map((node) => ( + + ))} +
+ ) : null} +
+
+
+ ); +} diff --git a/ui/src/features/cockpit/components/DateKanbanList.tsx b/ui/src/features/cockpit/components/DateKanbanList.tsx index cd9f5f026d..372b019d51 100644 --- a/ui/src/features/cockpit/components/DateKanbanList.tsx +++ b/ui/src/features/cockpit/components/DateKanbanList.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { components } from '@/api/v1/schema'; import DAGRunDetailsModal from '@/features/dag-runs/components/dag-run-details/DAGRunDetailsModal'; import { useInfiniteKanban } from '../hooks/useInfiniteKanban'; +import { ArtifactListModal } from './ArtifactListModal'; import { DateKanbanSection } from './DateKanbanSection'; type DAGRunSummary = components['schemas']['DAGRunSummary']; @@ -15,8 +16,10 @@ export function DateKanbanList({ selectedWorkspace, suspendLoadMore = false, }: Props): React.ReactElement { - const { loadedDates, todayStr, hasMore, loadNextDate } = useInfiniteKanban(selectedWorkspace); + const { loadedDates, todayStr, hasMore, loadNextDate } = + useInfiniteKanban(selectedWorkspace); const [selectedRun, setSelectedRun] = useState(null); + const [artifactRun, setArtifactRun] = useState(null); const containerRef = useRef(null); const sentinelRef = useRef(null); const awaitingSentinelExitRef = useRef(false); @@ -29,6 +32,14 @@ export function DateKanbanList({ setSelectedRun(null); }, []); + const handleArtifactsClick = useCallback((run: DAGRunSummary) => { + setArtifactRun(run); + }, []); + + const handleCloseArtifactsModal = useCallback(() => { + setArtifactRun(null); + }, []); + const triggerLoadNextDate = useCallback(() => { if (!hasMore || suspendLoadMore) { return; @@ -84,6 +95,7 @@ export function DateKanbanList({ todayStr={todayStr} selectedWorkspace={selectedWorkspace} onCardClick={handleCardClick} + onArtifactsClick={handleArtifactsClick} /> ))} {hasMore && ( @@ -108,6 +120,11 @@ export function DateKanbanList({ onClose={handleCloseModal} /> )} + ); } diff --git a/ui/src/features/cockpit/components/DateKanbanSection.tsx b/ui/src/features/cockpit/components/DateKanbanSection.tsx index 6a0cdf6d83..ef3d148d1a 100644 --- a/ui/src/features/cockpit/components/DateKanbanSection.tsx +++ b/ui/src/features/cockpit/components/DateKanbanSection.tsx @@ -11,6 +11,7 @@ interface Props { todayStr: string; selectedWorkspace: string; onCardClick: (run: DAGRunSummary) => void; + onArtifactsClick: (run: DAGRunSummary) => void; } function formatDateHeader(date: string): string { @@ -22,6 +23,7 @@ export function DateKanbanSection({ todayStr, selectedWorkspace, onCardClick, + onArtifactsClick, }: Props): React.ReactElement { const yesterdayStr = useMemo( () => dayjs(todayStr).subtract(1, 'day').format('YYYY-MM-DD'), @@ -44,10 +46,14 @@ export function DateKanbanSection({ {isLoading ? ( -
Loading runs...
+
+ Loading runs... +
) : error ? (
- {error.message || 'Failed to load runs'} + + {error.message || 'Failed to load runs'} +
); diff --git a/ui/src/features/cockpit/components/KanbanBoard.tsx b/ui/src/features/cockpit/components/KanbanBoard.tsx index 37fcacc49a..c676cf4c71 100644 --- a/ui/src/features/cockpit/components/KanbanBoard.tsx +++ b/ui/src/features/cockpit/components/KanbanBoard.tsx @@ -13,6 +13,7 @@ type DAGRunSummary = components['schemas']['DAGRunSummary']; interface Props { columns: KanbanColumns; onCardClick: (run: DAGRunSummary) => void; + onArtifactsClick: (run: DAGRunSummary) => void; } type ColumnEntry = { @@ -23,6 +24,7 @@ type ColumnEntry = { export function KanbanBoard({ columns, onCardClick, + onArtifactsClick, }: Props): React.ReactElement { const isMobile = useIsMobile(); const columnEntries: ColumnEntry[] = [ @@ -34,7 +36,13 @@ export function KanbanBoard({ ]; if (isMobile) { - return ; + return ( + + ); } return ( @@ -45,6 +53,7 @@ export function KanbanBoard({ title={column.title} column={column.data} onCardClick={onCardClick} + onArtifactsClick={onArtifactsClick} /> ))} diff --git a/ui/src/features/cockpit/components/KanbanCard.tsx b/ui/src/features/cockpit/components/KanbanCard.tsx index 8fa81f17c7..8941fe182e 100644 --- a/ui/src/features/cockpit/components/KanbanCard.tsx +++ b/ui/src/features/cockpit/components/KanbanCard.tsx @@ -1,6 +1,12 @@ import React, { useMemo } from 'react'; import { motion } from 'framer-motion'; +import { Archive } from 'lucide-react'; import { components, Status } from '@/api/v1/schema'; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from '@/components/ui/tooltip'; import AutoRetryBadge from '@/features/dag-runs/components/common/AutoRetryBadge'; import dayjs from '@/lib/dayjs'; import StatusChip from '@/ui/StatusChip'; @@ -11,6 +17,7 @@ type DAGRunSummary = components['schemas']['DAGRunSummary']; interface Props { run: DAGRunSummary; onClick: () => void; + onArtifactsClick?: () => void; } function formatElapsed(run: DAGRunSummary): string { @@ -45,12 +52,27 @@ function formatScheduleTime(scheduleTime: string | undefined): string { return parsed.format('MMM D, HH:mm:ss'); } -export function KanbanCard({ run, onClick }: Props): React.ReactElement { +export function KanbanCard({ + run, + onClick, + onArtifactsClick, +}: Props): React.ReactElement { const params = useMemo(() => truncateParams(run.params), [run.params]); const scheduleTime = useMemo( () => formatScheduleTime(run.scheduleTime), [run.scheduleTime] ); + const showArtifacts = run.artifactsAvailable && !!onArtifactsClick; + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (event.target !== event.currentTarget) { + return; + } + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + onClick(); + } + }; return ( - + + View artifacts + + )} +
+ + {run.statusLabel} + + +
{run.startedAt && @@ -105,7 +150,7 @@ export function KanbanCard({ run, onClick }: Props): React.ReactElement { {params} )} - +
); } diff --git a/ui/src/features/cockpit/components/KanbanColumn.tsx b/ui/src/features/cockpit/components/KanbanColumn.tsx index 6c413a6c23..9fcb858e15 100644 --- a/ui/src/features/cockpit/components/KanbanColumn.tsx +++ b/ui/src/features/cockpit/components/KanbanColumn.tsx @@ -10,6 +10,7 @@ interface Props { title: string; column: KanbanColumnData; onCardClick: (run: DAGRunSummary) => void; + onArtifactsClick: (run: DAGRunSummary) => void; hideHeader?: boolean; } @@ -17,6 +18,7 @@ export function KanbanColumn({ title, column, onCardClick, + onArtifactsClick, hideHeader, }: Props): React.ReactElement { const scrollRef = useRef(null); @@ -99,6 +101,7 @@ export function KanbanColumn({ key={run.dagRunId} run={run} onClick={() => onCardClick(run)} + onArtifactsClick={() => onArtifactsClick(run)} /> ))} diff --git a/ui/src/features/cockpit/components/MobileKanbanBoard.tsx b/ui/src/features/cockpit/components/MobileKanbanBoard.tsx index 99b6ed87d1..44a7645bc5 100644 --- a/ui/src/features/cockpit/components/MobileKanbanBoard.tsx +++ b/ui/src/features/cockpit/components/MobileKanbanBoard.tsx @@ -33,11 +33,13 @@ function getInitialTab(): ColumnKey { interface Props { columns: KanbanColumns; onCardClick: (run: DAGRunSummary) => void; + onArtifactsClick: (run: DAGRunSummary) => void; } export function MobileKanbanBoard({ columns, onCardClick, + onArtifactsClick, }: Props): React.ReactElement { const [activeTab, setActiveTab] = useState(getInitialTab); @@ -74,6 +76,7 @@ export function MobileKanbanBoard({ title={COLUMN_LABELS[activeTab]} column={columns[activeTab]} onCardClick={onCardClick} + onArtifactsClick={onArtifactsClick} hideHeader /> diff --git a/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx b/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx new file mode 100644 index 0000000000..6cea359069 --- /dev/null +++ b/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx @@ -0,0 +1,91 @@ +// Copyright (C) 2026 Yota Hamada +// SPDX-License-Identifier: GPL-3.0-or-later + +import { render, screen, waitFor } from '@testing-library/react'; +import React from 'react'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { Status, StatusLabel, TriggerType } from '@/api/v1/schema'; +import { AppBarContext } from '@/contexts/AppBarContext'; +import { useClient } from '@/hooks/api'; +import { ArtifactListModal } from '../ArtifactListModal'; + +vi.mock('@/hooks/api', () => ({ + useClient: vi.fn(), +})); + +const appBarValue = { + title: 'Cockpit', + setTitle: vi.fn(), + remoteNodes: ['local', 'edge'], + setRemoteNodes: vi.fn(), + selectedRemoteNode: 'edge', + selectRemoteNode: vi.fn(), +}; + +const run = { + dagRunId: 'run-1', + name: 'artifact-dag', + status: Status.Success, + statusLabel: StatusLabel.succeeded, + artifactsAvailable: true, + autoRetryCount: 0, + triggerType: TriggerType.manual, + queuedAt: '', + scheduleTime: '', + startedAt: '2026-03-16T00:00:00Z', + finishedAt: '2026-03-16T00:01:00Z', +}; + +afterEach(() => { + vi.clearAllMocks(); +}); + +describe('ArtifactListModal', () => { + it('loads and renders the run artifact tree for the selected remote node', async () => { + const get = vi.fn(async () => ({ + data: { + items: [ + { + type: 'directory', + name: 'reports', + path: 'reports', + children: [ + { + type: 'file', + name: 'summary.md', + path: 'reports/summary.md', + size: 12, + }, + ], + }, + ], + }, + error: undefined, + })); + + vi.mocked(useClient).mockReturnValue({ GET: get } as never); + + render( + + {}} /> + + ); + + expect((await screen.findAllByText('reports')).length).toBeGreaterThan(0); + expect(screen.getByText('summary.md')).toBeInTheDocument(); + expect(screen.getByText('12 B')).toBeInTheDocument(); + + await waitFor(() => { + expect(get).toHaveBeenCalledWith( + '/dag-runs/{name}/{dagRunId}/artifacts', + { + params: { + path: { name: 'artifact-dag', dagRunId: 'run-1' }, + query: { remoteNode: 'edge', recursive: true }, + }, + signal: expect.any(AbortSignal), + } + ); + }); + }); +}); diff --git a/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx b/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx index 6fbc62257d..8d1b55023f 100644 --- a/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx +++ b/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx @@ -15,10 +15,17 @@ vi.mock('../DateKanbanSection', () => ({ DateKanbanSection: ({ date }: { date: string }) =>
{date}
, })); -vi.mock('@/features/dag-runs/components/dag-run-details/DAGRunDetailsModal', () => ({ - default: () => null, +vi.mock('../ArtifactListModal', () => ({ + ArtifactListModal: () => null, })); +vi.mock( + '@/features/dag-runs/components/dag-run-details/DAGRunDetailsModal', + () => ({ + default: () => null, + }) +); + const useInfiniteKanbanMock = useInfiniteKanban as unknown as { mockReturnValue: (value: unknown) => void; }; @@ -56,7 +63,9 @@ describe('DateKanbanList', () => { render(); - expect(screen.getByRole('button', { name: 'Load older day' })).toBeDisabled(); + expect( + screen.getByRole('button', { name: 'Load older day' }) + ).toBeDisabled(); fireEvent.click(screen.getByRole('button', { name: 'Load older day' })); expect(loadNextDate).not.toHaveBeenCalled(); }); diff --git a/ui/src/features/cockpit/components/__tests__/DateKanbanSection.test.tsx b/ui/src/features/cockpit/components/__tests__/DateKanbanSection.test.tsx index f5ac1593e6..d072a6831e 100644 --- a/ui/src/features/cockpit/components/__tests__/DateKanbanSection.test.tsx +++ b/ui/src/features/cockpit/components/__tests__/DateKanbanSection.test.tsx @@ -91,6 +91,7 @@ describe('DateKanbanSection live-update flags', () => { todayStr="2026-03-22" selectedWorkspace="" onCardClick={() => {}} + onArtifactsClick={() => {}} /> ); @@ -111,6 +112,7 @@ describe('DateKanbanSection live-update flags', () => { todayStr="2026-03-22" selectedWorkspace="" onCardClick={() => {}} + onArtifactsClick={() => {}} /> ); @@ -131,6 +133,7 @@ describe('DateKanbanSection live-update flags', () => { todayStr="2026-03-22" selectedWorkspace="" onCardClick={() => {}} + onArtifactsClick={() => {}} /> ); diff --git a/ui/src/features/cockpit/components/__tests__/KanbanCard.test.tsx b/ui/src/features/cockpit/components/__tests__/KanbanCard.test.tsx index 07bb05badf..dc9cb7c6f7 100644 --- a/ui/src/features/cockpit/components/__tests__/KanbanCard.test.tsx +++ b/ui/src/features/cockpit/components/__tests__/KanbanCard.test.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import { describe, expect, it, vi } from 'vitest'; import { Status, StatusLabel, TriggerType } from '@/api/v1/schema'; import { KanbanCard } from '../KanbanCard'; @@ -11,16 +11,17 @@ vi.mock('framer-motion', () => ({ motion: { div: ({ children, - layoutId: _layoutId, - layout: _layout, - initial: _initial, - animate: _animate, - exit: _exit, - transition: _transition, ...props - }: React.ComponentProps<'div'> & Record) => ( -
{children}
- ), + }: React.ComponentProps<'div'> & Record) => { + const divProps = { ...props }; + delete divProps.layoutId; + delete divProps.layout; + delete divProps.initial; + delete divProps.animate; + delete divProps.exit; + delete divProps.transition; + return
{children}
; + }, }, })); @@ -33,6 +34,7 @@ describe('KanbanCard', () => { name: 'retry-dag', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 1, autoRetryLimit: 3, triggerType: TriggerType.manual, @@ -56,6 +58,7 @@ describe('KanbanCard', () => { name: 'retry-dag', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 3, autoRetryLimit: 3, triggerType: TriggerType.manual, @@ -70,4 +73,36 @@ describe('KanbanCard', () => { expect(screen.getByText('auto retries exhausted')).toBeInTheDocument(); }); + + it('opens artifacts without opening the run details', () => { + const handleClick = vi.fn(); + const handleArtifactsClick = vi.fn(); + + render( + + ); + + fireEvent.click( + screen.getByRole('button', { name: 'View artifacts for artifact-dag' }) + ); + + expect(handleArtifactsClick).toHaveBeenCalledTimes(1); + expect(handleClick).not.toHaveBeenCalled(); + }); }); diff --git a/ui/src/features/cockpit/components/__tests__/KanbanCounts.test.tsx b/ui/src/features/cockpit/components/__tests__/KanbanCounts.test.tsx index e115e71a9e..f13397e8ad 100644 --- a/ui/src/features/cockpit/components/__tests__/KanbanCounts.test.tsx +++ b/ui/src/features/cockpit/components/__tests__/KanbanCounts.test.tsx @@ -20,16 +20,17 @@ vi.mock('framer-motion', () => ({ motion: { div: ({ children, - layoutId: _layoutId, - layout: _layout, - initial: _initial, - animate: _animate, - exit: _exit, - transition: _transition, ...props - }: React.ComponentProps<'div'> & Record) => ( -
{children}
- ), + }: React.ComponentProps<'div'> & Record) => { + const divProps = { ...props }; + delete divProps.layoutId; + delete divProps.layout; + delete divProps.initial; + delete divProps.animate; + delete divProps.exit; + delete divProps.transition; + return
{children}
; + }, }, })); @@ -49,6 +50,7 @@ function createColumn( name: 'example', status: Status.Running, statusLabel: StatusLabel.running, + artifactsAvailable: false, autoRetryCount: 0, triggerType: TriggerType.manual, queuedAt: '', @@ -61,6 +63,7 @@ function createColumn( name: 'example', status: Status.Running, statusLabel: StatusLabel.running, + artifactsAvailable: false, autoRetryCount: 0, triggerType: TriggerType.manual, queuedAt: '', @@ -87,6 +90,7 @@ describe('cockpit count labels', () => { title="Running" column={createColumn({ hasMore: true })} onCardClick={() => {}} + onArtifactsClick={() => {}} /> ); @@ -102,7 +106,13 @@ describe('cockpit count labels', () => { failed: createColumn({ runs: [] }), }; - render( {}} />); + render( + {}} + onArtifactsClick={() => {}} + /> + ); expect(screen.getByRole('button', { name: /Running/ })).toHaveTextContent( 'Running2+' @@ -119,7 +129,11 @@ describe('cockpit count labels', () => { }; const { container } = render( - {}} /> + {}} + onArtifactsClick={() => {}} + /> ); const boardRoot = container.firstElementChild; diff --git a/ui/src/features/dag-runs/components/common/__tests__/DAGRunActions.test.tsx b/ui/src/features/dag-runs/components/common/__tests__/DAGRunActions.test.tsx index 23e90e6989..3f5dd97734 100644 --- a/ui/src/features/dag-runs/components/common/__tests__/DAGRunActions.test.tsx +++ b/ui/src/features/dag-runs/components/common/__tests__/DAGRunActions.test.tsx @@ -125,6 +125,7 @@ describe('DAGRunActions', () => { dagRunId: 'run-1', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 1, autoRetryLimit: 3, startedAt: '', @@ -146,6 +147,7 @@ describe('DAGRunActions', () => { dagRunId: 'run-1', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 1, autoRetryLimit: 3, startedAt: '', diff --git a/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunGroupedView.test.tsx b/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunGroupedView.test.tsx index a8e9e0778f..2821e00f0f 100644 --- a/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunGroupedView.test.tsx +++ b/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunGroupedView.test.tsx @@ -27,6 +27,7 @@ describe('DAGRunGroupedView', () => { name: 'scheduled-dag', status: Status.Queued, statusLabel: StatusLabel.queued, + artifactsAvailable: false, autoRetryCount: 0, autoRetryLimit: 0, triggerType: TriggerType.scheduler, @@ -40,6 +41,7 @@ describe('DAGRunGroupedView', () => { name: 'scheduled-dag', status: Status.Queued, statusLabel: StatusLabel.queued, + artifactsAvailable: false, autoRetryCount: 0, autoRetryLimit: 0, triggerType: TriggerType.scheduler, @@ -72,6 +74,7 @@ describe('DAGRunGroupedView', () => { name: 'grouped-dag', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 0, autoRetryLimit: 0, triggerType: TriggerType.manual, diff --git a/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunTable.test.tsx b/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunTable.test.tsx index 71213499cf..bc695e57c7 100644 --- a/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunTable.test.tsx +++ b/ui/src/features/dag-runs/components/dag-run-list/__tests__/DAGRunTable.test.tsx @@ -78,6 +78,7 @@ describe('DAGRunTable', () => { name: 'scheduled-dag', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 1, autoRetryLimit: 3, triggerType: TriggerType.scheduler, @@ -113,6 +114,7 @@ describe('DAGRunTable', () => { name: 'bulk-dag', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 0, autoRetryLimit: 0, triggerType: TriggerType.manual, @@ -154,6 +156,7 @@ describe('DAGRunTable', () => { name: 'alpha', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 0, autoRetryLimit: 0, triggerType: TriggerType.manual, diff --git a/ui/src/features/dag-runs/hooks/__tests__/useBulkDAGRunSelection.test.tsx b/ui/src/features/dag-runs/hooks/__tests__/useBulkDAGRunSelection.test.tsx index 5be641dd65..5806450077 100644 --- a/ui/src/features/dag-runs/hooks/__tests__/useBulkDAGRunSelection.test.tsx +++ b/ui/src/features/dag-runs/hooks/__tests__/useBulkDAGRunSelection.test.tsx @@ -11,6 +11,7 @@ const buildDagRun = (name: string, dagRunId: string) => ({ dagRunId, status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 0, autoRetryLimit: 0, triggerType: TriggerType.manual, diff --git a/ui/src/features/dags/components/common/__tests__/DAGActions.test.tsx b/ui/src/features/dags/components/common/__tests__/DAGActions.test.tsx index da8e50bfa0..b9ce42fe90 100644 --- a/ui/src/features/dags/components/common/__tests__/DAGActions.test.tsx +++ b/ui/src/features/dags/components/common/__tests__/DAGActions.test.tsx @@ -46,6 +46,7 @@ describe('DAGActions', () => { dagRunId: 'run-1', status: Status.Failed, statusLabel: StatusLabel.failed, + artifactsAvailable: false, autoRetryCount: 1, autoRetryLimit: 3, startedAt: '', @@ -68,6 +69,7 @@ describe('DAGActions', () => { dagRunId: 'run-1', status: Status.Running, statusLabel: StatusLabel.running, + artifactsAvailable: false, autoRetryCount: 0, startedAt: '', finishedAt: '', From e94cec0cf6191cac5e11f3d9998f9a3aa5fd80f1 Mon Sep 17 00:00:00 2001 From: Yota Hamada Date: Mon, 20 Apr 2026 02:44:26 +0900 Subject: [PATCH 2/4] fix: address cockpit artifact review feedback --- api/v1/api.gen.go | 884 +++++++++--------- api/v1/api.yaml | 2 +- .../service/frontend/api/v1/transformer.go | 32 +- .../frontend/api/v1/transformer_test.go | 17 +- ui/src/api/v1/schema.ts | 2 +- .../cockpit/components/ArtifactListModal.tsx | 127 ++- .../cockpit/components/KanbanCard.tsx | 103 +- .../__tests__/ArtifactListModal.test.tsx | 72 +- 8 files changed, 725 insertions(+), 514 deletions(-) diff --git a/api/v1/api.gen.go b/api/v1/api.gen.go index 5fa38feece..8f49e5d818 100644 --- a/api/v1/api.gen.go +++ b/api/v1/api.gen.go @@ -1342,7 +1342,7 @@ type DAGRunCreateId = string // DAGRunDetails defines model for DAGRunDetails. type DAGRunDetails struct { - // ArtifactsAvailable Whether artifact endpoints are available for this DAG-run + // ArtifactsAvailable Whether artifact files are available for this DAG-run ArtifactsAvailable bool `json:"artifactsAvailable"` // AutoRetryCount Number of scheduler-issued DAG auto-retries already consumed for this DAG-run @@ -1450,7 +1450,7 @@ type DAGRunOutputs struct { // DAGRunSummary Current status of a DAG-run type DAGRunSummary struct { - // ArtifactsAvailable Whether artifact endpoints are available for this DAG-run + // ArtifactsAvailable Whether artifact files are available for this DAG-run ArtifactsAvailable bool `json:"artifactsAvailable"` // AutoRetryCount Number of scheduler-issued DAG auto-retries already consumed for this DAG-run @@ -28421,446 +28421,446 @@ var swaggerSpec = []string{ "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", - "q8qL/AMA", + "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", + "hlqbi4f8AwA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/api/v1/api.yaml b/api/v1/api.yaml index b3d5084841..f153e2128a 100644 --- a/api/v1/api.yaml +++ b/api/v1/api.yaml @@ -8475,7 +8475,7 @@ components: description: "RFC 3339 timestamp when the DAG-run finished" artifactsAvailable: type: boolean - description: "Whether artifact endpoints are available for this DAG-run" + description: "Whether artifact files are available for this DAG-run" params: type: string description: "Runtime parameters passed to the DAG-run in JSON format" diff --git a/internal/service/frontend/api/v1/transformer.go b/internal/service/frontend/api/v1/transformer.go index 33524417a1..15815c2767 100644 --- a/internal/service/frontend/api/v1/transformer.go +++ b/internal/service/frontend/api/v1/transformer.go @@ -4,7 +4,10 @@ package api import ( + "os" + "github.com/dagucloud/dagu/api/v1" + "github.com/dagucloud/dagu/internal/cmn/fileutil" "github.com/dagucloud/dagu/internal/core" "github.com/dagucloud/dagu/internal/core/exec" ) @@ -190,6 +193,7 @@ func toDAGRunSummary(s exec.DAGRunStatus) api.DAGRunSummary { if s.AutoRetryLimit > 0 { autoRetryLimit = ptrOf(s.AutoRetryLimit) } + artifactsAvailable := hasArtifactEntries(s.ArchiveDir) return api.DAGRunSummary{ Name: s.Name, @@ -201,7 +205,7 @@ func toDAGRunSummary(s exec.DAGRunStatus) api.DAGRunSummary { ScheduleTime: ptrOf(s.ScheduleTime), StartedAt: s.StartedAt, FinishedAt: s.FinishedAt, - ArtifactsAvailable: s.ArchiveDir != "", + ArtifactsAvailable: artifactsAvailable, Status: api.Status(s.Status), StatusLabel: api.StatusLabel(s.Status.String()), WorkerId: ptrOf(s.WorkerID), @@ -245,13 +249,14 @@ func ToDAGRunDetails(s exec.DAGRunStatus) api.DAGRunDetails { if s.AutoRetryLimit > 0 { autoRetryLimit = ptrOf(s.AutoRetryLimit) } + artifactsAvailable := hasArtifactEntries(s.ArchiveDir) return api.DAGRunDetails{ RootDAGRunName: s.Root.Name, RootDAGRunId: s.Root.ID, ParentDAGRunName: ptrOf(s.Parent.Name), ParentDAGRunId: ptrOf(s.Parent.ID), - ArtifactsAvailable: s.ArchiveDir != "", + ArtifactsAvailable: artifactsAvailable, Log: s.Log, Name: s.Name, Params: ptrOf(s.Params), @@ -277,6 +282,29 @@ func ToDAGRunDetails(s exec.DAGRunStatus) api.DAGRunDetails { } } +func hasArtifactEntries(archiveDir string) bool { + if archiveDir == "" { + return false + } + + info, err := os.Stat(archiveDir) + if err != nil || !info.IsDir() { + return false + } + + entries, err := os.ReadDir(archiveDir) + if err != nil { + return false + } + + for _, entry := range entries { + if !fileutil.IsSymlinkDirEntry(entry) { + return true + } + } + return false +} + func toNode(node *exec.Node) api.Node { if node == nil { return api.Node{} diff --git a/internal/service/frontend/api/v1/transformer_test.go b/internal/service/frontend/api/v1/transformer_test.go index f37c1a60a0..2f6f70102e 100644 --- a/internal/service/frontend/api/v1/transformer_test.go +++ b/internal/service/frontend/api/v1/transformer_test.go @@ -4,6 +4,8 @@ package api import ( + "os" + "path/filepath" "testing" "time" @@ -14,13 +16,22 @@ import ( "github.com/stretchr/testify/require" ) +func writeArtifactFile(t *testing.T) string { + t.Helper() + + dir := t.TempDir() + err := os.WriteFile(filepath.Join(dir, "artifact.txt"), []byte("artifact"), 0o600) + require.NoError(t, err) + return dir +} + func TestToDAGRunSummaryIncludesScheduleTime(t *testing.T) { status := exec.DAGRunStatus{ Name: "test-dag", DAGRunID: "run-1", AutoRetryCount: 2, AutoRetryLimit: 5, - ArchiveDir: "/tmp/artifacts/test-dag/run-1", + ArchiveDir: writeArtifactFile(t), Status: core.Queued, ScheduleTime: "2026-03-13T00:00:00Z", } @@ -40,6 +51,7 @@ func TestToDAGRunDetailsIncludesScheduleTime(t *testing.T) { DAGRunID: "run-1", AutoRetryCount: 3, AutoRetryLimit: 5, + ArchiveDir: writeArtifactFile(t), Status: core.Queued, QueuedAt: "2026-03-13T00:01:00Z", ScheduleTime: "2026-03-13T00:00:00Z", @@ -53,6 +65,7 @@ func TestToDAGRunDetailsIncludesScheduleTime(t *testing.T) { assert.Equal(t, status.AutoRetryCount, details.AutoRetryCount) require.NotNil(t, details.AutoRetryLimit) assert.Equal(t, status.AutoRetryLimit, *details.AutoRetryLimit) + assert.True(t, details.ArtifactsAvailable) } func TestToDAGRunSummaryOmitsAutoRetryLimitWhenUnconfigured(t *testing.T) { @@ -66,6 +79,7 @@ func TestToDAGRunSummaryOmitsAutoRetryLimitWhenUnconfigured(t *testing.T) { summary := toDAGRunSummary(status) assert.Nil(t, summary.AutoRetryLimit) + assert.False(t, summary.ArtifactsAvailable) } func TestToDAGRunDetailsOmitsAutoRetryLimitWhenUnconfigured(t *testing.T) { @@ -79,6 +93,7 @@ func TestToDAGRunDetailsOmitsAutoRetryLimitWhenUnconfigured(t *testing.T) { details := ToDAGRunDetails(status) assert.Nil(t, details.AutoRetryLimit) + assert.False(t, details.ArtifactsAvailable) } func TestToDAGDetailsIncludesParamDefDescriptions(t *testing.T) { diff --git a/ui/src/api/v1/schema.ts b/ui/src/api/v1/schema.ts index cfd1d2257b..b96425481d 100644 --- a/ui/src/api/v1/schema.ts +++ b/ui/src/api/v1/schema.ts @@ -3443,7 +3443,7 @@ export interface components { startedAt: string; /** @description RFC 3339 timestamp when the DAG-run finished */ finishedAt: string; - /** @description Whether artifact endpoints are available for this DAG-run */ + /** @description Whether artifact files are available for this DAG-run */ artifactsAvailable: boolean; /** @description Runtime parameters passed to the DAG-run in JSON format */ params?: string; diff --git a/ui/src/features/cockpit/components/ArtifactListModal.tsx b/ui/src/features/cockpit/components/ArtifactListModal.tsx index 6e121479a8..b8d5a123c2 100644 --- a/ui/src/features/cockpit/components/ArtifactListModal.tsx +++ b/ui/src/features/cockpit/components/ArtifactListModal.tsx @@ -1,7 +1,7 @@ // Copyright (C) 2026 Yota Hamada // SPDX-License-Identifier: GPL-3.0-or-later -import React, { useContext, useEffect, useMemo, useState } from 'react'; +import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { AlertCircle, Download, @@ -76,6 +76,38 @@ function fileIconFor(node: ArtifactTreeNode) { return File; } +function trimDispositionValue(value: string): string { + const trimmed = value.trim(); + if (trimmed.startsWith('"') && trimmed.endsWith('"')) { + return trimmed.slice(1, -1).replace(/\\"/g, '"'); + } + return trimmed; +} + +function filenameFromContentDisposition(header: string | null): string | null { + if (!header) { + return null; + } + + const encoded = header.match(/(?:^|;)\s*filename\*\s*=\s*([^;]+)/i)?.[1]; + if (encoded) { + const value = trimDispositionValue(encoded); + const encodedFilename = value.includes("''") + ? value.split("''").slice(1).join("''") + : value; + try { + return decodeURIComponent(encodedFilename); + } catch { + return encodedFilename; + } + } + + const filename = header.match( + /(?:^|;)\s*filename\s*=\s*("[^"]*"|[^;]*)/i + )?.[1]; + return filename ? trimDispositionValue(filename) : null; +} + function ArtifactRow({ node, depth, @@ -169,6 +201,10 @@ export function ArtifactListModal({ const [downloadError, setDownloadError] = useState(null); const [refreshKey, setRefreshKey] = useState(0); const [downloadingPath, setDownloadingPath] = useState(null); + const [isRefreshing, setIsRefreshing] = useState(false); + const treeRef = useRef([]); + const downloadControllerRef = useRef(null); + const mountedRef = useRef(true); const flatNodes = useMemo(() => flattenNodes(tree), [tree]); const fileCount = flatNodes.filter((node) => node.type === 'file').length; @@ -177,20 +213,44 @@ export function ArtifactListModal({ 0 ); + useEffect(() => { + treeRef.current = tree; + }, [tree]); + + useEffect(() => { + return () => { + mountedRef.current = false; + downloadControllerRef.current?.abort(); + }; + }, []); + + useEffect(() => { + if (isOpen) { + return; + } + + downloadControllerRef.current?.abort(); + downloadControllerRef.current = null; + setDownloadingPath(null); + }, [isOpen]); + useEffect(() => { if (!isOpen || !runName || !runId) { setTree([]); setError(null); setDownloadError(null); setIsLoading(false); + setIsRefreshing(false); return; } let cancelled = false; const controller = new AbortController(); + const isInitialLoad = treeRef.current.length === 0; const fetchTree = async () => { - setIsLoading(true); + setIsLoading(isInitialLoad); + setIsRefreshing(!isInitialLoad); setError(null); setDownloadError(null); @@ -214,7 +274,9 @@ export function ArtifactListModal({ } if (request.error) { - setTree([]); + if (isInitialLoad) { + setTree([]); + } setError(request.error.message || 'Failed to load artifacts'); return; } @@ -224,13 +286,18 @@ export function ArtifactListModal({ if (cancelled || controller.signal.aborted) { return; } - setTree([]); + if (isInitialLoad) { + setTree([]); + } setError( err instanceof Error ? err.message : 'Failed to load artifacts' ); } finally { if (!cancelled) { - setIsLoading(false); + if (isInitialLoad) { + setIsLoading(false); + } + setIsRefreshing(false); } } }; @@ -248,6 +315,14 @@ export function ArtifactListModal({ return; } + downloadControllerRef.current?.abort(); + const controller = new AbortController(); + downloadControllerRef.current = controller; + const isCurrentDownload = () => + mountedRef.current && + downloadControllerRef.current === controller && + !controller.signal.aborted; + setDownloadingPath(node.path); setDownloadError(null); @@ -263,9 +338,14 @@ export function ArtifactListModal({ query: { remoteNode, path: node.path }, }, parseAs: 'blob', + signal: controller.signal, } ); + if (!isCurrentDownload()) { + return; + } + if (request.error) { throw new Error( request.error.message || @@ -275,21 +355,37 @@ export function ArtifactListModal({ } const blob = request.data; + if (!blob) { + throw new Error('Empty response'); + } const objectUrl = URL.createObjectURL(blob); const link = document.createElement('a'); const fileName = - request.response.headers - .get('Content-Disposition') - ?.match(/filename="(.+)"/)?.[1] || node.name; + filenameFromContentDisposition( + request.response.headers.get('Content-Disposition') + ) || node.name; link.href = objectUrl; link.download = fileName; + link.style.display = 'none'; + document.body.appendChild(link); link.click(); - URL.revokeObjectURL(objectUrl); + setTimeout(() => { + URL.revokeObjectURL(objectUrl); + link.remove(); + }, 0); } catch (err: unknown) { + if (!isCurrentDownload()) { + return; + } setDownloadError(err instanceof Error ? err.message : 'Download failed'); } finally { - setDownloadingPath(null); + if (downloadControllerRef.current === controller) { + downloadControllerRef.current = null; + if (mountedRef.current) { + setDownloadingPath(null); + } + } } }; @@ -324,9 +420,14 @@ export function ArtifactListModal({ variant="ghost" size="sm" onClick={() => setRefreshKey((current) => current + 1)} - disabled={isLoading || !run} + disabled={isLoading || isRefreshing || !run} > - + Refresh @@ -344,7 +445,7 @@ export function ArtifactListModal({ ) : null} - {isLoading ? ( + {isLoading && tree.length === 0 ? (
Loading artifacts...
diff --git a/ui/src/features/cockpit/components/KanbanCard.tsx b/ui/src/features/cockpit/components/KanbanCard.tsx index 8941fe182e..1828745002 100644 --- a/ui/src/features/cockpit/components/KanbanCard.tsx +++ b/ui/src/features/cockpit/components/KanbanCard.tsx @@ -83,37 +83,19 @@ export function KanbanCard({ exit={{ opacity: 0, scale: 0.95 }} transition={{ duration: 0.2, ease: 'easeOut' }} > -
-
- - {run.name} - -
- {showArtifacts && ( - - - - - View artifacts - - )} -
+
+
+
+ + {run.name} + +
{run.statusLabel} @@ -125,30 +107,45 @@ export function KanbanCard({ />
-
- {run.startedAt && - (run.status === Status.Running ? ( - - {() => ( -
- {formatElapsed(run)} -
- )} -
- ) : ( + {run.startedAt && + (run.status === Status.Running ? ( + + {() => ( +
+ {formatElapsed(run)} +
+ )} +
+ ) : ( +
+ {formatElapsed(run)} +
+ ))} + {scheduleTime && (
- {formatElapsed(run)} + Scheduled {scheduleTime}
- ))} - {scheduleTime && ( -
- Scheduled {scheduleTime} -
- )} - {params && ( -
- {params} -
+ )} + {params && ( +
+ {params} +
+ )} +
+ {showArtifacts && ( + + + + + View artifacts + )}
diff --git a/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx b/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx index 6cea359069..e59b0a324f 100644 --- a/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx +++ b/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx @@ -1,7 +1,7 @@ // Copyright (C) 2026 Yota Hamada // SPDX-License-Identifier: GPL-3.0-or-later -import { render, screen, waitFor } from '@testing-library/react'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import React from 'react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { Status, StatusLabel, TriggerType } from '@/api/v1/schema'; @@ -38,6 +38,8 @@ const run = { afterEach(() => { vi.clearAllMocks(); + vi.restoreAllMocks(); + vi.unstubAllGlobals(); }); describe('ArtifactListModal', () => { @@ -88,4 +90,72 @@ describe('ArtifactListModal', () => { ); }); }); + + it('downloads artifacts with the encoded response filename', async () => { + const createObjectURL = vi.fn(() => 'blob:artifact'); + const revokeObjectURL = vi.fn(); + vi.stubGlobal('URL', { + createObjectURL, + revokeObjectURL, + }); + const click = vi + .spyOn(HTMLAnchorElement.prototype, 'click') + .mockImplementation(() => {}); + const appendChild = vi.spyOn(document.body, 'appendChild'); + const get = vi.fn(async (path: string) => { + if (path.endsWith('/download')) { + return { + data: new Blob(['artifact']), + error: undefined, + response: new Response(null, { + headers: { + 'Content-Disposition': + "attachment; filename*=UTF-8''summary%20report.md", + }, + }), + }; + } + + return { + data: { + items: [ + { + type: 'file', + name: 'summary.md', + path: 'summary.md', + size: 12, + }, + ], + }, + error: undefined, + }; + }); + + vi.mocked(useClient).mockReturnValue({ GET: get } as never); + + render( + + {}} /> + + ); + + fireEvent.click( + await screen.findByRole('button', { name: 'Download summary.md' }) + ); + + await waitFor(() => { + expect(click).toHaveBeenCalledTimes(1); + }); + + const link = appendChild.mock.calls.find( + ([node]) => node instanceof HTMLAnchorElement + )?.[0] as HTMLAnchorElement | undefined; + expect(link?.download).toBe('summary report.md'); + expect(link?.href).toBe('blob:artifact'); + expect(createObjectURL).toHaveBeenCalledWith(expect.any(Blob)); + + await waitFor(() => { + expect(revokeObjectURL).toHaveBeenCalledWith('blob:artifact'); + }); + }); }); From 51de424992a26ced364d582c737a9510339ba95a Mon Sep 17 00:00:00 2001 From: Yota Hamada Date: Mon, 20 Apr 2026 09:28:14 +0900 Subject: [PATCH 3/4] fix: improve cockpit artifact preview --- .../ui/doc-markdown-preview.css} | 3 +- ui/src/components/ui/doc-markdown-preview.tsx | 60 ++ .../cockpit/components/ArtifactListModal.tsx | 596 ++++++------------ .../__tests__/ArtifactListModal.test.tsx | 156 ++--- .../components/artifacts/ArtifactsTab.tsx | 58 +- ui/src/pages/docs/components/DocEditor.tsx | 58 +- 6 files changed, 340 insertions(+), 591 deletions(-) rename ui/src/{pages/docs/components/DocPreview.css => components/ui/doc-markdown-preview.css} (97%) create mode 100644 ui/src/components/ui/doc-markdown-preview.tsx diff --git a/ui/src/pages/docs/components/DocPreview.css b/ui/src/components/ui/doc-markdown-preview.css similarity index 97% rename from ui/src/pages/docs/components/DocPreview.css rename to ui/src/components/ui/doc-markdown-preview.css index ac0a55c028..8114adaea0 100644 --- a/ui/src/pages/docs/components/DocPreview.css +++ b/ui/src/components/ui/doc-markdown-preview.css @@ -88,7 +88,8 @@ /* Inline code */ .doc-preview code { - font-family: 'JetBrains Mono', 'Fira Code', Menlo, Monaco, 'Courier New', monospace; + font-family: + 'JetBrains Mono', 'Fira Code', Menlo, Monaco, 'Courier New', monospace; font-size: 0.85em; color: var(--foreground); background: var(--muted); diff --git a/ui/src/components/ui/doc-markdown-preview.tsx b/ui/src/components/ui/doc-markdown-preview.tsx new file mode 100644 index 0000000000..b333201067 --- /dev/null +++ b/ui/src/components/ui/doc-markdown-preview.tsx @@ -0,0 +1,60 @@ +import { MermaidBlock } from '@/components/ui/mermaid-block'; +import { cn } from '@/lib/utils'; +import { slugifyHeading } from '@/lib/text-utils'; +import type { ReactElement, ReactNode } from 'react'; +import ReactMarkdown from 'react-markdown'; +import remarkGfm from 'remark-gfm'; +import './doc-markdown-preview.css'; + +type DocMarkdownPreviewProps = { + content: string | null | undefined; + className?: string; +}; + +function headingId(children: ReactNode): string { + const text = + typeof children === 'string' + ? children + : Array.isArray(children) + ? children + .map((child) => (typeof child === 'string' ? child : '')) + .join('') + : String(children ?? ''); + return slugifyHeading(text); +} + +export function DocMarkdownPreview({ + content, + className, +}: DocMarkdownPreviewProps) { + return ( +
+

{children}

, + h2: ({ children }) =>

{children}

, + h3: ({ children }) =>

{children}

, + h4: ({ children }) =>

{children}

, + h5: ({ children }) =>
{children}
, + h6: ({ children }) =>
{children}
, + code({ className: codeClassName, children }) { + if (codeClassName === 'language-mermaid') { + return ; + } + return {children}; + }, + pre({ children }) { + const child = children as ReactElement; + if (child?.type === MermaidBlock) { + return <>{children}; + } + return
{children}
; + }, + }} + > + {content ?? ''} +
+
+ ); +} diff --git a/ui/src/features/cockpit/components/ArtifactListModal.tsx b/ui/src/features/cockpit/components/ArtifactListModal.tsx index b8d5a123c2..3a461b6ca1 100644 --- a/ui/src/features/cockpit/components/ArtifactListModal.tsx +++ b/ui/src/features/cockpit/components/ArtifactListModal.tsx @@ -2,30 +2,22 @@ // SPDX-License-Identifier: GPL-3.0-or-later import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; -import { - AlertCircle, - Download, - File, - FileImage, - FileText, - Folder, - RefreshCw, -} from 'lucide-react'; +import { createPortal } from 'react-dom'; +import { AlertCircle, Archive, Loader2, X } from 'lucide-react'; import { components } from '@/api/v1/schema'; import { Button } from '@/components/ui/button'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, -} from '@/components/ui/dialog'; import { AppBarContext } from '@/contexts/AppBarContext'; -import { useClient } from '@/hooks/api'; +import { useBoundedDAGRunDetails } from '@/features/dag-runs/hooks/useBoundedDAGRunDetails'; +import { + type DAGRunDetailsRequestTarget, + matchesRequestedDAGRunDetails, +} from '@/features/dag-runs/hooks/dagRunDetailsRequest'; +import ArtifactsTab from '@/features/dags/components/artifacts/ArtifactsTab'; import { cn } from '@/lib/utils'; +import LoadingIndicator from '@/ui/LoadingIndicator'; type DAGRunSummary = components['schemas']['DAGRunSummary']; -type ArtifactTreeNode = components['schemas']['ArtifactTreeNode']; +const CLOSE_ANIMATION_MS = 200; interface Props { run: DAGRunSummary | null; @@ -33,441 +25,233 @@ interface Props { onClose: () => void; } -function flattenNodes(nodes: ArtifactTreeNode[]): ArtifactTreeNode[] { - const flat: ArtifactTreeNode[] = []; - for (const node of nodes) { - flat.push(node); - if (node.children) { - flat.push(...flattenNodes(node.children)); - } - } - return flat; -} - -function formatBytes(size: number | undefined): string { - if (size == null) { - return ''; - } - if (size < 1024) { - return `${size} B`; - } - - const units = ['KB', 'MB', 'GB', 'TB']; - let value = size / 1024; - let unitIndex = 0; - while (value >= 1024 && unitIndex < units.length - 1) { - value /= 1024; - unitIndex += 1; - } - - return `${value >= 10 ? value.toFixed(0) : value.toFixed(1)} ${units[unitIndex]}`; -} - -function fileIconFor(node: ArtifactTreeNode) { - if (node.type === 'directory') { - return Folder; - } - if (node.path.match(/\.(png|jpe?g|gif|webp|svg|bmp|ico)$/i)) { - return FileImage; - } - if (node.path.match(/\.(md|markdown|mdown|mkd|txt|log|json|ya?ml|csv)$/i)) { - return FileText; - } - return File; -} - -function trimDispositionValue(value: string): string { - const trimmed = value.trim(); - if (trimmed.startsWith('"') && trimmed.endsWith('"')) { - return trimmed.slice(1, -1).replace(/\\"/g, '"'); - } - return trimmed; -} - -function filenameFromContentDisposition(header: string | null): string | null { - if (!header) { - return null; - } - - const encoded = header.match(/(?:^|;)\s*filename\*\s*=\s*([^;]+)/i)?.[1]; - if (encoded) { - const value = trimDispositionValue(encoded); - const encodedFilename = value.includes("''") - ? value.split("''").slice(1).join("''") - : value; - try { - return decodeURIComponent(encodedFilename); - } catch { - return encodedFilename; - } - } - - const filename = header.match( - /(?:^|;)\s*filename\s*=\s*("[^"]*"|[^;]*)/i - )?.[1]; - return filename ? trimDispositionValue(filename) : null; -} - -function ArtifactRow({ - node, - depth, - downloadingPath, - onDownload, -}: { - node: ArtifactTreeNode; - depth: number; - downloadingPath: string | null; - onDownload: (node: ArtifactTreeNode) => void; -}) { - const Icon = fileIconFor(node); - const isDirectory = node.type === 'directory'; - const isDownloading = downloadingPath === node.path; - - return ( -
-
- -
-
{node.name}
-
- {node.path} -
-
- {!isDirectory && ( - <> - {node.size != null && ( - - {formatBytes(node.size)} - - )} - - - )} -
- {isDirectory && node.children && node.children.length > 0 && ( -
- {node.children.map((child) => ( - - ))} -
- )} -
- ); -} - export function ArtifactListModal({ run, isOpen, onClose, -}: Props): React.ReactElement { - const client = useClient(); +}: Props): React.ReactElement | null { const appBarContext = useContext(AppBarContext); const remoteNode = appBarContext.selectedRemoteNode || 'local'; - const runName = run?.name; - const runId = run?.dagRunId; - - const [tree, setTree] = useState([]); - const [isLoading, setIsLoading] = useState(false); - const [error, setError] = useState(null); - const [downloadError, setDownloadError] = useState(null); - const [refreshKey, setRefreshKey] = useState(0); - const [downloadingPath, setDownloadingPath] = useState(null); - const [isRefreshing, setIsRefreshing] = useState(false); - const treeRef = useRef([]); - const downloadControllerRef = useRef(null); - const mountedRef = useRef(true); - - const flatNodes = useMemo(() => flattenNodes(tree), [tree]); - const fileCount = flatNodes.filter((node) => node.type === 'file').length; - const totalSize = flatNodes.reduce( - (sum, node) => sum + (node.type === 'file' ? node.size || 0 : 0), - 0 - ); + const [shouldRender, setShouldRender] = useState(isOpen); + const [isVisible, setIsVisible] = useState(false); + const [renderedRun, setRenderedRun] = useState(run); + const drawerRef = useRef(null); + const closeButtonRef = useRef(null); + const previouslyFocusedRef = useRef(null); + const visibleRun = isOpen ? run : renderedRun; useEffect(() => { - treeRef.current = tree; - }, [tree]); + let closeTimer: number | undefined; + let animationFrame: number | undefined; + + if (isOpen && run) { + previouslyFocusedRef.current = + document.activeElement instanceof HTMLElement + ? document.activeElement + : null; + setRenderedRun(run); + setShouldRender(true); + animationFrame = window.requestAnimationFrame(() => { + setIsVisible(true); + closeButtonRef.current?.focus(); + }); + } else { + setIsVisible(false); + closeTimer = window.setTimeout(() => { + setShouldRender(false); + setRenderedRun(null); + previouslyFocusedRef.current?.focus(); + previouslyFocusedRef.current = null; + }, CLOSE_ANIMATION_MS); + } - useEffect(() => { return () => { - mountedRef.current = false; - downloadControllerRef.current?.abort(); + if (animationFrame !== undefined) { + window.cancelAnimationFrame(animationFrame); + } + if (closeTimer !== undefined) { + window.clearTimeout(closeTimer); + } }; - }, []); - - useEffect(() => { - if (isOpen) { - return; - } - - downloadControllerRef.current?.abort(); - downloadControllerRef.current = null; - setDownloadingPath(null); - }, [isOpen]); + }, [isOpen, run]); useEffect(() => { - if (!isOpen || !runName || !runId) { - setTree([]); - setError(null); - setDownloadError(null); - setIsLoading(false); - setIsRefreshing(false); + if (!isOpen) { return; } - let cancelled = false; - const controller = new AbortController(); - const isInitialLoad = treeRef.current.length === 0; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + onClose(); + return; + } - const fetchTree = async () => { - setIsLoading(isInitialLoad); - setIsRefreshing(!isInitialLoad); - setError(null); - setDownloadError(null); + if (event.key !== 'Tab') { + return; + } - try { - const request = await client.GET( - '/dag-runs/{name}/{dagRunId}/artifacts', - { - params: { - path: { - name: runName, - dagRunId: runId, - }, - query: { remoteNode, recursive: true }, - }, - signal: controller.signal, - } + const focusableElements = + drawerRef.current?.querySelectorAll( + [ + 'a[href]', + 'button:not([disabled])', + 'textarea:not([disabled])', + 'input:not([disabled])', + 'select:not([disabled])', + '[tabindex]:not([tabindex="-1"])', + ].join(',') ); + if (!focusableElements || focusableElements.length === 0) { + event.preventDefault(); + return; + } - if (cancelled) { - return; - } - - if (request.error) { - if (isInitialLoad) { - setTree([]); - } - setError(request.error.message || 'Failed to load artifacts'); - return; - } + const firstElement = focusableElements.item(0); + const lastElement = focusableElements.item(focusableElements.length - 1); + if (!firstElement || !lastElement) { + event.preventDefault(); + return; + } - setTree(request.data?.items ?? []); - } catch (err: unknown) { - if (cancelled || controller.signal.aborted) { - return; - } - if (isInitialLoad) { - setTree([]); - } - setError( - err instanceof Error ? err.message : 'Failed to load artifacts' - ); - } finally { - if (!cancelled) { - if (isInitialLoad) { - setIsLoading(false); - } - setIsRefreshing(false); - } + if (event.shiftKey && document.activeElement === firstElement) { + event.preventDefault(); + lastElement.focus(); + } else if (!event.shiftKey && document.activeElement === lastElement) { + event.preventDefault(); + firstElement.focus(); } }; - void fetchTree(); - - return () => { - cancelled = true; - controller.abort(); - }; - }, [client, isOpen, refreshKey, remoteNode, runId, runName]); + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [isOpen, onClose]); - const handleDownload = async (node: ArtifactTreeNode) => { - if (!run || node.type !== 'file') { + useEffect(() => { + if (!shouldRender) { return; } - downloadControllerRef.current?.abort(); - const controller = new AbortController(); - downloadControllerRef.current = controller; - const isCurrentDownload = () => - mountedRef.current && - downloadControllerRef.current === controller && - !controller.signal.aborted; - - setDownloadingPath(node.path); - setDownloadError(null); - - try { - const request = await client.GET( - '/dag-runs/{name}/{dagRunId}/artifacts/download', - { - params: { - path: { - name: run.name, - dagRunId: run.dagRunId, - }, - query: { remoteNode, path: node.path }, - }, - parseAs: 'blob', - signal: controller.signal, - } - ); + const appRoot = document.getElementById('root'); + const previousAriaHidden = appRoot?.getAttribute('aria-hidden') ?? null; + appRoot?.setAttribute('aria-hidden', 'true'); - if (!isCurrentDownload()) { + return () => { + if (!appRoot) { return; } - - if (request.error) { - throw new Error( - request.error.message || - request.response.statusText || - 'Download failed' - ); - } - - const blob = request.data; - if (!blob) { - throw new Error('Empty response'); + if (previousAriaHidden === null) { + appRoot.removeAttribute('aria-hidden'); + } else { + appRoot.setAttribute('aria-hidden', previousAriaHidden); } - const objectUrl = URL.createObjectURL(blob); - const link = document.createElement('a'); - const fileName = - filenameFromContentDisposition( - request.response.headers.get('Content-Disposition') - ) || node.name; + }; + }, [shouldRender]); - link.href = objectUrl; - link.download = fileName; - link.style.display = 'none'; - document.body.appendChild(link); - link.click(); - setTimeout(() => { - URL.revokeObjectURL(objectUrl); - link.remove(); - }, 0); - } catch (err: unknown) { - if (!isCurrentDownload()) { - return; - } - setDownloadError(err instanceof Error ? err.message : 'Download failed'); - } finally { - if (downloadControllerRef.current === controller) { - downloadControllerRef.current = null; - if (mountedRef.current) { - setDownloadingPath(null); - } - } + const target = useMemo(() => { + if (!isOpen || !run) { + return null; } - }; - return ( - !open && onClose()}> - - - - - Artifacts - - - {run ? `${run.name} / ${run.dagRunId}` : 'DAG run artifacts'} - - + return { + remoteNode, + name: run.name, + dagRunId: run.dagRunId, + }; + }, [isOpen, remoteNode, run]); + + const { + data: details, + error, + isLoading, + isValidating, + } = useBoundedDAGRunDetails({ + target, + enabled: target !== null, + pollIntervalMs: isOpen ? 2000 : 0, + }); + + const displayDetails = matchesRequestedDAGRunDetails( + details, + visibleRun?.dagRunId ?? '' + ) + ? details + : null; + + if (!shouldRender || !visibleRun) { + return null; + } -
-
- {fileCount}{' '} - - {fileCount === 1 ? 'file' : 'files'} - - {totalSize > 0 && ( - - {' '} - ยท {formatBytes(totalSize)} - - )} + return createPortal( +
+ -
+ -
- {error ? ( -
- - {error} +
+ {isLoading && !displayDetails ? ( +
+
- ) : downloadError ? ( -
+ ) : error && !displayDetails ? ( +
- {downloadError} -
- ) : null} - - {isLoading && tree.length === 0 ? ( -
- Loading artifacts... -
- ) : !error && tree.length === 0 ? ( -
- No artifact files were found for this run. -
- ) : !error ? ( -
- {tree.map((node) => ( - - ))} + {error.message || 'Failed to load DAG run details'}
+ ) : displayDetails ? ( + ) : null}
- -
+ +
, + document.body ); } diff --git a/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx b/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx index e59b0a324f..f31d4fdc3f 100644 --- a/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx +++ b/ui/src/features/cockpit/components/__tests__/ArtifactListModal.test.tsx @@ -1,16 +1,23 @@ // Copyright (C) 2026 Yota Hamada // SPDX-License-Identifier: GPL-3.0-or-later -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React from 'react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { Status, StatusLabel, TriggerType } from '@/api/v1/schema'; import { AppBarContext } from '@/contexts/AppBarContext'; -import { useClient } from '@/hooks/api'; +import { useBoundedDAGRunDetails } from '@/features/dag-runs/hooks/useBoundedDAGRunDetails'; +import ArtifactsTab from '@/features/dags/components/artifacts/ArtifactsTab'; import { ArtifactListModal } from '../ArtifactListModal'; -vi.mock('@/hooks/api', () => ({ - useClient: vi.fn(), +vi.mock('@/features/dag-runs/hooks/useBoundedDAGRunDetails', () => ({ + useBoundedDAGRunDetails: vi.fn(), +})); + +vi.mock('@/features/dags/components/artifacts/ArtifactsTab', () => ({ + default: vi.fn(({ dagRun }) => ( +
{dagRun.name}
+ )), })); const appBarValue = { @@ -36,36 +43,26 @@ const run = { finishedAt: '2026-03-16T00:01:00Z', }; +const details = { + ...run, + rootDAGRunName: 'artifact-dag', + rootDAGRunId: 'run-1', + nodes: [], +}; + afterEach(() => { vi.clearAllMocks(); - vi.restoreAllMocks(); - vi.unstubAllGlobals(); }); describe('ArtifactListModal', () => { - it('loads and renders the run artifact tree for the selected remote node', async () => { - const get = vi.fn(async () => ({ - data: { - items: [ - { - type: 'directory', - name: 'reports', - path: 'reports', - children: [ - { - type: 'file', - name: 'summary.md', - path: 'reports/summary.md', - size: 12, - }, - ], - }, - ], - }, - error: undefined, - })); - - vi.mocked(useClient).mockReturnValue({ GET: get } as never); + it('loads DAG-run details and renders the shared artifact preview tab', () => { + vi.mocked(useBoundedDAGRunDetails).mockReturnValue({ + data: details, + error: null, + isLoading: false, + isValidating: false, + refresh: vi.fn(), + } as never); render( @@ -73,89 +70,26 @@ describe('ArtifactListModal', () => { ); - expect((await screen.findAllByText('reports')).length).toBeGreaterThan(0); - expect(screen.getByText('summary.md')).toBeInTheDocument(); - expect(screen.getByText('12 B')).toBeInTheDocument(); - - await waitFor(() => { - expect(get).toHaveBeenCalledWith( - '/dag-runs/{name}/{dagRunId}/artifacts', - { - params: { - path: { name: 'artifact-dag', dagRunId: 'run-1' }, - query: { remoteNode: 'edge', recursive: true }, - }, - signal: expect.any(AbortSignal), - } - ); - }); - }); - - it('downloads artifacts with the encoded response filename', async () => { - const createObjectURL = vi.fn(() => 'blob:artifact'); - const revokeObjectURL = vi.fn(); - vi.stubGlobal('URL', { - createObjectURL, - revokeObjectURL, - }); - const click = vi - .spyOn(HTMLAnchorElement.prototype, 'click') - .mockImplementation(() => {}); - const appendChild = vi.spyOn(document.body, 'appendChild'); - const get = vi.fn(async (path: string) => { - if (path.endsWith('/download')) { - return { - data: new Blob(['artifact']), - error: undefined, - response: new Response(null, { - headers: { - 'Content-Disposition': - "attachment; filename*=UTF-8''summary%20report.md", - }, - }), - }; - } - - return { - data: { - items: [ - { - type: 'file', - name: 'summary.md', - path: 'summary.md', - size: 12, - }, - ], - }, - error: undefined, - }; - }); - - vi.mocked(useClient).mockReturnValue({ GET: get } as never); - - render( - - {}} /> - - ); - - fireEvent.click( - await screen.findByRole('button', { name: 'Download summary.md' }) + expect(screen.getByTestId('artifact-preview-tab')).toHaveTextContent( + 'artifact-dag' ); - - await waitFor(() => { - expect(click).toHaveBeenCalledTimes(1); - }); - - const link = appendChild.mock.calls.find( - ([node]) => node instanceof HTMLAnchorElement - )?.[0] as HTMLAnchorElement | undefined; - expect(link?.download).toBe('summary report.md'); - expect(link?.href).toBe('blob:artifact'); - expect(createObjectURL).toHaveBeenCalledWith(expect.any(Blob)); - - await waitFor(() => { - expect(revokeObjectURL).toHaveBeenCalledWith('blob:artifact'); + expect(useBoundedDAGRunDetails).toHaveBeenCalledWith({ + target: { + remoteNode: 'edge', + name: 'artifact-dag', + dagRunId: 'run-1', + }, + enabled: true, + pollIntervalMs: 2000, }); + expect(ArtifactsTab).toHaveBeenCalledWith( + expect.objectContaining({ + dagRun: details, + artifactEnabled: true, + className: 'h-full', + fillHeight: true, + }), + undefined + ); }); }); diff --git a/ui/src/features/dags/components/artifacts/ArtifactsTab.tsx b/ui/src/features/dags/components/artifacts/ArtifactsTab.tsx index 03d694ca56..133fc30f4b 100644 --- a/ui/src/features/dags/components/artifacts/ArtifactsTab.tsx +++ b/ui/src/features/dags/components/artifacts/ArtifactsTab.tsx @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later import { Button } from '@/components/ui/button'; +import { DocMarkdownPreview } from '@/components/ui/doc-markdown-preview'; import { AppBarContext } from '@/contexts/AppBarContext'; import { useClient } from '@/hooks/api'; import { cn } from '@/lib/utils'; @@ -16,8 +17,6 @@ import { RefreshCw, } from 'lucide-react'; import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; -import ReactMarkdown from 'react-markdown'; -import remarkGfm from 'remark-gfm'; import { components } from '../../../../api/v1/schema'; type ArtifactTreeNode = components['schemas']['ArtifactTreeNode']; @@ -27,6 +26,8 @@ type DAGRunDetails = components['schemas']['DAGRunDetails']; type Props = { dagRun: DAGRunDetails; artifactEnabled?: boolean; + className?: string; + fillHeight?: boolean; }; function collectDirectoryPaths(nodes: ArtifactTreeNode[]): string[] { @@ -68,14 +69,6 @@ function flattenNodes(nodes: ArtifactTreeNode[]): ArtifactTreeNode[] { return flat; } -function ArtifactMarkdown({ content }: { content: string }) { - return ( -
- {content} -
- ); -} - function TreeNode({ node, depth, @@ -154,6 +147,8 @@ function TreeNode({ export default function ArtifactsTab({ dagRun, artifactEnabled = false, + className, + fillHeight = false, }: Props) { const client = useClient(); const appBarContext = useContext(AppBarContext); @@ -548,8 +543,19 @@ export default function ArtifactsTab({ } return ( -
-
+
+

Artifacts

@@ -573,7 +579,12 @@ export default function ArtifactsTab({
-
+
{treeLoading ? (
Loading artifacts... @@ -615,7 +626,12 @@ export default function ArtifactsTab({
-
+

@@ -642,7 +658,12 @@ export default function ArtifactsTab({

-
+
{!selectedPath ? (
Select a file to preview it. @@ -681,7 +702,7 @@ export default function ArtifactsTab({
) : preview.kind === 'markdown' ? ( - + ) : preview.kind === 'text' ? (
               {preview.content || ''}
@@ -691,7 +712,10 @@ export default function ArtifactsTab({
               {preview.name}
             ) : (
               
diff --git a/ui/src/pages/docs/components/DocEditor.tsx b/ui/src/pages/docs/components/DocEditor.tsx index 21afe42c40..77572a3de5 100644 --- a/ui/src/pages/docs/components/DocEditor.tsx +++ b/ui/src/pages/docs/components/DocEditor.tsx @@ -1,10 +1,6 @@ import MarkdownEditor from '@/components/editors/MarkdownEditor'; -import { MermaidBlock } from '@/components/ui/mermaid-block'; +import { DocMarkdownPreview } from '@/components/ui/doc-markdown-preview'; import { useSimpleToast } from '@/components/ui/simple-toast'; -import React from 'react'; -import ReactMarkdown from 'react-markdown'; -import remarkGfm from 'remark-gfm'; -import './DocPreview.css'; import { useCanWrite } from '@/contexts/AuthContext'; import { useDocTabContext } from '@/contexts/DocTabContext'; import { useClient, useQuery } from '@/hooks/api'; @@ -12,7 +8,6 @@ import { useContentEditor } from '@/hooks/useContentEditor'; import { useDocSSE } from '@/hooks/useDocSSE'; import { sseFallbackOptions, useSSECacheSync } from '@/hooks/useSSECacheSync'; import { cn } from '@/lib/utils'; -import { slugifyHeading } from '@/lib/text-utils'; import { AppBarContext } from '@/contexts/AppBarContext'; import { Check, @@ -26,16 +21,6 @@ import { import { useCallback, useContext, useEffect, useRef, useState } from 'react'; import DocExternalChangeDialog from './DocExternalChangeDialog'; -function headingId(children: React.ReactNode): string { - const text = - typeof children === 'string' - ? children - : Array.isArray(children) - ? children.map((c) => (typeof c === 'string' ? c : '')).join('') - : String(children ?? ''); - return slugifyHeading(text); -} - type Props = { tabId: string; docPath: string; @@ -367,46 +352,7 @@ function DocEditor({ tabId, docPath, onDeleteDoc, onContentChange }: Props) { /> ) : (
-
- ( -

{children}

- ), - h2: ({ children }) => ( -

{children}

- ), - h3: ({ children }) => ( -

{children}

- ), - h4: ({ children }) => ( -

{children}

- ), - h5: ({ children }) => ( -
{children}
- ), - h6: ({ children }) => ( -
{children}
- ), - code({ className: codeClassName, children }) { - if (codeClassName === 'language-mermaid') { - return ; - } - return {children}; - }, - pre({ children }) { - const child = children as React.ReactElement; - if (child?.type === MermaidBlock) { - return <>{children}; - } - return
{children}
; - }, - }} - > - {currentValue} -
-
+
)}
From 9db05c9139b68220239ac6a37b3d942b403a1dbe Mon Sep 17 00:00:00 2001 From: Yota Hamada Date: Mon, 20 Apr 2026 09:57:22 +0900 Subject: [PATCH 4/4] fix: polish cockpit artifact interactions --- .../cockpit/components/DateKanbanList.tsx | 19 ++-- .../cockpit/components/KanbanCard.tsx | 26 ++++-- .../__tests__/DateKanbanList.test.tsx | 89 ++++++++++++++++++- .../dag-run-details/DAGRunDetailsContent.tsx | 19 +++- .../dag-run-details/DAGRunDetailsModal.tsx | 50 ++++++++--- ui/src/features/dags/components/DAGStatus.tsx | 80 ++++++++++++----- 6 files changed, 230 insertions(+), 53 deletions(-) diff --git a/ui/src/features/cockpit/components/DateKanbanList.tsx b/ui/src/features/cockpit/components/DateKanbanList.tsx index 372b019d51..166f56201b 100644 --- a/ui/src/features/cockpit/components/DateKanbanList.tsx +++ b/ui/src/features/cockpit/components/DateKanbanList.tsx @@ -19,6 +19,7 @@ export function DateKanbanList({ const { loadedDates, todayStr, hasMore, loadNextDate } = useInfiniteKanban(selectedWorkspace); const [selectedRun, setSelectedRun] = useState(null); + const [isDetailsOpen, setIsDetailsOpen] = useState(false); const [artifactRun, setArtifactRun] = useState(null); const containerRef = useRef(null); const sentinelRef = useRef(null); @@ -26,10 +27,11 @@ export function DateKanbanList({ const handleCardClick = useCallback((run: DAGRunSummary) => { setSelectedRun(run); + setIsDetailsOpen(true); }, []); const handleCloseModal = useCallback(() => { - setSelectedRun(null); + setIsDetailsOpen(false); }, []); const handleArtifactsClick = useCallback((run: DAGRunSummary) => { @@ -112,14 +114,13 @@ export function DateKanbanList({
)}
- {selectedRun && ( - - )} + -
+
@@ -111,23 +113,31 @@ export function KanbanCard({ (run.status === Status.Running ? ( {() => ( -
+
{formatElapsed(run)}
)} ) : ( -
+
{formatElapsed(run)}
))} {scheduleTime && ( -
+
Scheduled {scheduleTime}
)} {params && ( -
+
{params}
)} @@ -138,10 +148,10 @@ export function KanbanCard({ View artifacts diff --git a/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx b/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx index 8d1b55023f..78d6142d42 100644 --- a/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx +++ b/ui/src/features/cockpit/components/__tests__/DateKanbanList.test.tsx @@ -1,18 +1,48 @@ // Copyright (C) 2026 Yota Hamada // SPDX-License-Identifier: GPL-3.0-or-later -import { cleanup, fireEvent, render, screen } from '@testing-library/react'; +import { + act, + cleanup, + fireEvent, + render, + screen, +} from '@testing-library/react'; import React from 'react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import { DateKanbanList } from '../DateKanbanList'; import { useInfiniteKanban } from '../../hooks/useInfiniteKanban'; +const dagRunDetailsModalMock = vi.hoisted(() => vi.fn()); + vi.mock('../../hooks/useInfiniteKanban', () => ({ useInfiniteKanban: vi.fn(), })); vi.mock('../DateKanbanSection', () => ({ - DateKanbanSection: ({ date }: { date: string }) =>
{date}
, + DateKanbanSection: ({ + date, + onCardClick, + }: { + date: string; + onCardClick: (run: unknown) => void; + }) => ( +
+ {date} + +
+ ), })); vi.mock('../ArtifactListModal', () => ({ @@ -22,7 +52,10 @@ vi.mock('../ArtifactListModal', () => ({ vi.mock( '@/features/dag-runs/components/dag-run-details/DAGRunDetailsModal', () => ({ - default: () => null, + default: (props: unknown) => { + dagRunDetailsModalMock(props); + return null; + }, }) ); @@ -30,6 +63,17 @@ const useInfiniteKanbanMock = useInfiniteKanban as unknown as { mockReturnValue: (value: unknown) => void; }; +function latestModalProps() { + const calls = dagRunDetailsModalMock.mock.calls; + return calls[calls.length - 1]?.[0] as { + name: string; + dagRunId: string; + isOpen: boolean; + initialTab: string; + onClose: () => void; + }; +} + afterEach(() => { cleanup(); vi.clearAllMocks(); @@ -69,4 +113,43 @@ describe('DateKanbanList', () => { fireEvent.click(screen.getByRole('button', { name: 'Load older day' })); expect(loadNextDate).not.toHaveBeenCalled(); }); + + it('opens artifact runs on the artifacts tab and keeps props during close', () => { + useInfiniteKanbanMock.mockReturnValue({ + loadedDates: ['2026-03-21'], + todayStr: '2026-03-21', + hasMore: false, + loadNextDate: vi.fn(), + }); + + render(); + + fireEvent.click( + screen.getByRole('button', { name: 'Open run 2026-03-21' }) + ); + + let modalProps = latestModalProps(); + expect(modalProps).toEqual( + expect.objectContaining({ + name: 'artifact-dag', + dagRunId: 'run-with-artifacts', + isOpen: true, + initialTab: 'artifacts', + }) + ); + + act(() => { + modalProps.onClose(); + }); + + modalProps = latestModalProps(); + expect(modalProps).toEqual( + expect.objectContaining({ + name: 'artifact-dag', + dagRunId: 'run-with-artifacts', + isOpen: false, + initialTab: 'artifacts', + }) + ); + }); }); diff --git a/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsContent.tsx b/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsContent.tsx index e975438fc5..785daed0b1 100644 --- a/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsContent.tsx +++ b/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsContent.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { components } from '../../../../api/v1/schema'; import { DAGStatus } from '../../../../features/dags/components'; +import type { StatusTab } from '../../../../features/dags/components/DAGStatus'; +import { cn } from '../../../../lib/utils'; import { DAGRunContext } from '../../contexts/DAGRunContext'; import DAGRunHeader from './DAGRunHeader'; @@ -9,6 +11,8 @@ type DAGRunDetailsContentProps = { dagRun: components['schemas']['DAGRunDetails']; refreshFn: () => void; dagRunId?: string; + initialTab?: StatusTab; + fillHeight?: boolean; }; const DAGRunDetailsContent: React.FC = ({ @@ -16,6 +20,8 @@ const DAGRunDetailsContent: React.FC = ({ dagRun, refreshFn, dagRunId = 'latest', + initialTab = 'status', + fillHeight = false, }) => { return ( = ({ dagRunId: dagRunId || '', }} > -
+
{/* Display breadcrumbs and DAG-run details in the header */} -
- +
+
diff --git a/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsModal.tsx b/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsModal.tsx index 041c62565b..f21239d729 100644 --- a/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsModal.tsx +++ b/ui/src/features/dag-runs/components/dag-run-details/DAGRunDetailsModal.tsx @@ -1,8 +1,16 @@ -import React, { useCallback, useContext, useEffect, useRef, useState } from 'react'; +import React, { + useCallback, + useContext, + useEffect, + useRef, + useState, +} from 'react'; import { useNavigate } from 'react-router-dom'; import { Loader2, Maximize2, X } from 'lucide-react'; import { Button } from '@/components/ui/button'; +import type { StatusTab } from '@/features/dags/components/DAGStatus'; +import { cn } from '@/lib/utils'; import { components } from '../../../../api/v1/schema'; import { AppBarContext } from '../../../../contexts/AppBarContext'; import { usePageContext } from '../../../../contexts/PageContext'; @@ -18,6 +26,7 @@ type DAGRunDetailsModalProps = { dagRunId: string; isOpen: boolean; onClose: () => void; + initialTab?: StatusTab; }; type PreviousData = { @@ -31,6 +40,7 @@ function DAGRunDetailsModal({ dagRunId, isOpen, onClose, + initialTab = 'status', }: DAGRunDetailsModalProps): React.ReactElement | null { const navigate = useNavigate(); const appBarContext = useContext(AppBarContext); @@ -101,14 +111,23 @@ function DAGRunDetailsModal({ pollIntervalMs: isOpen ? 2000 : 0, }); - const expectedDagRunId = canQuerySubDag ? (subDAGRunId ?? '') : (dagRunId || 'latest'); - const freshDetails = - matchesRequestedDAGRunDetails(latestDetails, expectedDagRunId) - ? latestDetails - : null; + const expectedDagRunId = canQuerySubDag + ? (subDAGRunId ?? '') + : dagRunId || 'latest'; + const freshDetails = matchesRequestedDAGRunDetails( + latestDetails, + expectedDagRunId + ) + ? latestDetails + : null; const displayData = freshDetails ?? previousDataRef.current?.dagRunDetails; - const displayName = freshDetails ? name : (previousDataRef.current?.name ?? name); - const displayDagRunId = freshDetails ? dagRunId : (previousDataRef.current?.dagRunId ?? dagRunId); + const displayName = freshDetails + ? name + : (previousDataRef.current?.name ?? name); + const displayDagRunId = freshDetails + ? dagRunId + : (previousDataRef.current?.dagRunId ?? dagRunId); + const fillContentHeight = initialTab === 'artifacts'; useEffect(() => { if (freshDetails) { @@ -192,7 +211,11 @@ function DAGRunDetailsModal({
-
+
{isTransitioning && (
@@ -266,6 +294,8 @@ function DAGRunDetailsModal({ dagRun={displayData} refreshFn={refreshFn} dagRunId={displayDagRunId} + initialTab={initialTab} + fillHeight={fillContentHeight} /> )}
diff --git a/ui/src/features/dags/components/DAGStatus.tsx b/ui/src/features/dags/components/DAGStatus.tsx index 176e06cd21..b2ee95a5a1 100644 --- a/ui/src/features/dags/components/DAGStatus.tsx +++ b/ui/src/features/dags/components/DAGStatus.tsx @@ -23,7 +23,7 @@ import { components, NodeStatus, Status, Stream } from '../../../api/v1/schema'; import { AppBarContext } from '../../../contexts/AppBarContext'; import { useConfig } from '../../../contexts/ConfigContext'; import { useClient } from '../../../hooks/api'; -import { toMermaidNodeId } from '../../../lib/utils'; +import { cn, toMermaidNodeId } from '../../../lib/utils'; import BorderedBox from '../../../ui/BorderedBox'; import { DAGRunOutputs } from '../../dag-runs/components/dag-run-details'; import { DAGContext } from '../contexts/DAGContext'; @@ -44,9 +44,11 @@ type Props = { dagRun: components['schemas']['DAGRunDetails']; fileName: string; artifactEnabled?: boolean; + initialTab?: StatusTab; + fillHeight?: boolean; }; -type StatusTab = +export type StatusTab = | 'status' | 'timeline' | 'outputs' @@ -64,13 +66,19 @@ function isSubDAGRun(dagRun: components['schemas']['DAGRunDetails']): boolean { ); } -function DAGStatus({ dagRun, fileName, artifactEnabled = false }: Props) { +function DAGStatus({ + dagRun, + fileName, + artifactEnabled = false, + initialTab = 'status', + fillHeight = false, +}: Props) { const appBarContext = React.useContext(AppBarContext); const config = useConfig(); const navigate = useNavigate(); const { showError } = useErrorModal(); const [modal, setModal] = useState(false); - const [activeTab, setActiveTab] = useState('status'); + const [activeTab, setActiveTab] = useState(initialTab); // Flowchart direction preference stored in cookies const [cookie, setCookie] = useCookies(['flowchart']); @@ -327,6 +335,10 @@ function DAGStatus({ dagRun, fileName, artifactEnabled = false }: Props) { const hasWaitingSteps = waitingStepCount > 0; const hasArtifacts = artifactEnabled || !!dagRun.artifactsAvailable; + useEffect(() => { + setActiveTab(initialTab); + }, [dagRun.dagRunId, initialTab]); + // Reset to status tab if selected tab is not available useEffect(() => { if (activeTab === 'timeline' && !showTimeline) { @@ -350,10 +362,19 @@ function DAGStatus({ dagRun, fileName, artifactEnabled = false }: Props) { } }, [hasWaitingSteps]); + const scrollPaneClassName = fillHeight + ? 'min-h-0 flex-1 overflow-auto pr-1' + : ''; + return ( -
+
{/* Status Detail Tabs */} - + setActiveTab('status')} @@ -425,7 +446,7 @@ function DAGStatus({ dagRun, fileName, artifactEnabled = false }: Props) { {/* Status Tab Content */} {activeTab === 'status' && ( -
+
{/* DAG Graph Visualization */} {dagRun.nodes && dagRun.nodes.length > 0 && (
@@ -523,36 +544,55 @@ function DAGStatus({ dagRun, fileName, artifactEnabled = false }: Props) { {/* Approval Tab Content */} {activeTab === 'approval' && hasWaitingSteps && ( - +
+ +
)} {/* Timeline Tab Content */} {activeTab === 'timeline' && showTimeline && ( - +
+ +
)} {/* Outputs Tab Content */} {activeTab === 'outputs' && ( - +
+ +
)} {activeTab === 'artifacts' && hasArtifacts && ( - + )} {/* Chat Tab Content */} - {activeTab === 'chat' && } + {activeTab === 'chat' && ( +
+ +
+ )} {/* Spec Tab Content */} {activeTab === 'spec' && ( - +
+ +
)}