@shipfox/client-workflows 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/main.ts +1 -0
- package/.storybook/preview.css +10 -0
- package/.storybook/preview.tsx +97 -0
- package/.swcrc +42 -0
- package/.turbo/turbo-build.log +2 -0
- package/.turbo/turbo-type$colon$emit.log +1 -0
- package/.turbo/turbo-type.log +1 -0
- package/CHANGELOG.md +162 -0
- package/LICENSE +21 -0
- package/dist/components/identifier/identifier.d.ts +6 -0
- package/dist/components/identifier/identifier.d.ts.map +1 -0
- package/dist/components/identifier/identifier.js +144 -0
- package/dist/components/identifier/identifier.js.map +1 -0
- package/dist/components/identifier/index.d.ts +2 -0
- package/dist/components/identifier/index.d.ts.map +1 -0
- package/dist/components/identifier/index.js +3 -0
- package/dist/components/identifier/index.js.map +1 -0
- package/dist/components/job-graph/graph-model.d.ts +27 -0
- package/dist/components/job-graph/graph-model.d.ts.map +1 -0
- package/dist/components/job-graph/graph-model.js +107 -0
- package/dist/components/job-graph/graph-model.js.map +1 -0
- package/dist/components/job-graph/index.d.ts +3 -0
- package/dist/components/job-graph/index.d.ts.map +1 -0
- package/dist/components/job-graph/index.js +3 -0
- package/dist/components/job-graph/index.js.map +1 -0
- package/dist/components/job-graph/job-duration-format.d.ts +4 -0
- package/dist/components/job-graph/job-duration-format.d.ts.map +1 -0
- package/dist/components/job-graph/job-duration-format.js +41 -0
- package/dist/components/job-graph/job-duration-format.js.map +1 -0
- package/dist/components/job-graph/job-duration-label.d.ts +5 -0
- package/dist/components/job-graph/job-duration-label.d.ts.map +1 -0
- package/dist/components/job-graph/job-duration-label.js +33 -0
- package/dist/components/job-graph/job-duration-label.js.map +1 -0
- package/dist/components/job-graph/job-graph-content.d.ts +9 -0
- package/dist/components/job-graph/job-graph-content.d.ts.map +1 -0
- package/dist/components/job-graph/job-graph-content.js +181 -0
- package/dist/components/job-graph/job-graph-content.js.map +1 -0
- package/dist/components/job-graph/job-graph-view.d.ts +11 -0
- package/dist/components/job-graph/job-graph-view.d.ts.map +1 -0
- package/dist/components/job-graph/job-graph-view.js +24 -0
- package/dist/components/job-graph/job-graph-view.js.map +1 -0
- package/dist/components/job-graph/job-graph.d.ts +3 -0
- package/dist/components/job-graph/job-graph.d.ts.map +1 -0
- package/dist/components/job-graph/job-graph.js +21 -0
- package/dist/components/job-graph/job-graph.js.map +1 -0
- package/dist/components/job-graph/job-node.d.ts +16 -0
- package/dist/components/job-graph/job-node.d.ts.map +1 -0
- package/dist/components/job-graph/job-node.js +196 -0
- package/dist/components/job-graph/job-node.js.map +1 -0
- package/dist/components/job-graph/types.d.ts +9 -0
- package/dist/components/job-graph/types.d.ts.map +1 -0
- package/dist/components/job-graph/types.js +3 -0
- package/dist/components/job-graph/types.js.map +1 -0
- package/dist/components/step-list/index.d.ts +3 -0
- package/dist/components/step-list/index.d.ts.map +1 -0
- package/dist/components/step-list/index.js +3 -0
- package/dist/components/step-list/index.js.map +1 -0
- package/dist/components/step-list/step-list-model.d.ts +36 -0
- package/dist/components/step-list/step-list-model.d.ts.map +1 -0
- package/dist/components/step-list/step-list-model.js +135 -0
- package/dist/components/step-list/step-list-model.js.map +1 -0
- package/dist/components/step-list/step-list.d.ts +32 -0
- package/dist/components/step-list/step-list.d.ts.map +1 -0
- package/dist/components/step-list/step-list.js +409 -0
- package/dist/components/step-list/step-list.js.map +1 -0
- package/dist/components/workflow-run-duration-label.d.ts +8 -0
- package/dist/components/workflow-run-duration-label.d.ts.map +1 -0
- package/dist/components/workflow-run-duration-label.js +84 -0
- package/dist/components/workflow-run-duration-label.js.map +1 -0
- package/dist/components/workflow-run-list/index.d.ts +2 -0
- package/dist/components/workflow-run-list/index.d.ts.map +1 -0
- package/dist/components/workflow-run-list/index.js +3 -0
- package/dist/components/workflow-run-list/index.js.map +1 -0
- package/dist/components/workflow-run-list/run-display.d.ts +5 -0
- package/dist/components/workflow-run-list/run-display.d.ts.map +1 -0
- package/dist/components/workflow-run-list/run-display.js +19 -0
- package/dist/components/workflow-run-list/run-display.js.map +1 -0
- package/dist/components/workflow-run-list/types.d.ts +21 -0
- package/dist/components/workflow-run-list/types.d.ts.map +1 -0
- package/dist/components/workflow-run-list/types.js +3 -0
- package/dist/components/workflow-run-list/types.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.d.ts +14 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.js +37 -0
- package/dist/components/workflow-run-list/workflow-run-list-content.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.d.ts +10 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.js +55 -0
- package/dist/components/workflow-run-list/workflow-run-list-header.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.d.ts +15 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.js +103 -0
- package/dist/components/workflow-run-list/workflow-run-list-states.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.d.ts +3 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.js +46 -0
- package/dist/components/workflow-run-list/workflow-run-list-view.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list.d.ts +3 -0
- package/dist/components/workflow-run-list/workflow-run-list.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-list.js +20 -0
- package/dist/components/workflow-run-list/workflow-run-list.js.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-row.d.ts +14 -0
- package/dist/components/workflow-run-list/workflow-run-row.d.ts.map +1 -0
- package/dist/components/workflow-run-list/workflow-run-row.js +172 -0
- package/dist/components/workflow-run-list/workflow-run-row.js.map +1 -0
- package/dist/components/workflow-run-summary/index.d.ts +2 -0
- package/dist/components/workflow-run-summary/index.d.ts.map +1 -0
- package/dist/components/workflow-run-summary/index.js +3 -0
- package/dist/components/workflow-run-summary/index.js.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts +9 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.d.ts.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js +138 -0
- package/dist/components/workflow-run-summary/workflow-run-attempt-switcher.js.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts +20 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.d.ts.map +1 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.js +252 -0
- package/dist/components/workflow-run-summary/workflow-run-summary.js.map +1 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts +7 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.d.ts.map +1 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.js +84 -0
- package/dist/components/workflow-run-view/agent-config-failure-callout.js.map +1 -0
- package/dist/components/workflow-run-view/index.d.ts +3 -0
- package/dist/components/workflow-run-view/index.d.ts.map +1 -0
- package/dist/components/workflow-run-view/index.js +4 -0
- package/dist/components/workflow-run-view/index.js.map +1 -0
- package/dist/components/workflow-run-view/job-card.d.ts +17 -0
- package/dist/components/workflow-run-view/job-card.d.ts.map +1 -0
- package/dist/components/workflow-run-view/job-card.js +476 -0
- package/dist/components/workflow-run-view/job-card.js.map +1 -0
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts +10 -0
- package/dist/components/workflow-run-view/job-execution-switcher.d.ts.map +1 -0
- package/dist/components/workflow-run-view/job-execution-switcher.js +171 -0
- package/dist/components/workflow-run-view/job-execution-switcher.js.map +1 -0
- package/dist/components/workflow-run-view/job-execution-time-text.d.ts +6 -0
- package/dist/components/workflow-run-view/job-execution-time-text.d.ts.map +1 -0
- package/dist/components/workflow-run-view/job-execution-time-text.js +24 -0
- package/dist/components/workflow-run-view/job-execution-time-text.js.map +1 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts +9 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.d.ts.map +1 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.js +152 -0
- package/dist/components/workflow-run-view/step-attempt-log-panel.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-selection.d.ts +14 -0
- package/dist/components/workflow-run-view/workflow-run-selection.d.ts.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-selection.js +56 -0
- package/dist/components/workflow-run-view/workflow-run-selection.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-states.d.ts +12 -0
- package/dist/components/workflow-run-view/workflow-run-states.d.ts.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-states.js +91 -0
- package/dist/components/workflow-run-view/workflow-run-states.js.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-view.d.ts +15 -0
- package/dist/components/workflow-run-view/workflow-run-view.d.ts.map +1 -0
- package/dist/components/workflow-run-view/workflow-run-view.js +285 -0
- package/dist/components/workflow-run-view/workflow-run-view.js.map +1 -0
- package/dist/components/workflow-source-panel/index.d.ts +2 -0
- package/dist/components/workflow-source-panel/index.d.ts.map +1 -0
- package/dist/components/workflow-source-panel/index.js +3 -0
- package/dist/components/workflow-source-panel/index.js.map +1 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.d.ts +13 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.d.ts.map +1 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.js +91 -0
- package/dist/components/workflow-source-panel/workflow-source-panel.js.map +1 -0
- package/dist/components/workflow-status/status-visuals.d.ts +12 -0
- package/dist/components/workflow-status/status-visuals.d.ts.map +1 -0
- package/dist/components/workflow-status/status-visuals.js +54 -0
- package/dist/components/workflow-status/status-visuals.js.map +1 -0
- package/dist/components/workflow-status/workflow-status-icon.d.ts +22 -0
- package/dist/components/workflow-status/workflow-status-icon.d.ts.map +1 -0
- package/dist/components/workflow-status/workflow-status-icon.js +100 -0
- package/dist/components/workflow-status/workflow-status-icon.js.map +1 -0
- package/dist/core/entities/job-execution.d.ts +69 -0
- package/dist/core/entities/job-execution.d.ts.map +1 -0
- package/dist/core/entities/job-execution.js +83 -0
- package/dist/core/entities/job-execution.js.map +1 -0
- package/dist/core/entities/job.d.ts +56 -0
- package/dist/core/entities/job.d.ts.map +1 -0
- package/dist/core/entities/job.js +71 -0
- package/dist/core/entities/job.js.map +1 -0
- package/dist/core/entities/step-attempt.d.ts +49 -0
- package/dist/core/entities/step-attempt.d.ts.map +1 -0
- package/dist/core/entities/step-attempt.js +48 -0
- package/dist/core/entities/step-attempt.js.map +1 -0
- package/dist/core/entities/step.d.ts +41 -0
- package/dist/core/entities/step.d.ts.map +1 -0
- package/dist/core/entities/step.js +51 -0
- package/dist/core/entities/step.js.map +1 -0
- package/dist/core/entities/workflow-run-attempt.d.ts +44 -0
- package/dist/core/entities/workflow-run-attempt.d.ts.map +1 -0
- package/dist/core/entities/workflow-run-attempt.js +51 -0
- package/dist/core/entities/workflow-run-attempt.js.map +1 -0
- package/dist/core/entities/workflow-run.d.ts +61 -0
- package/dist/core/entities/workflow-run.d.ts.map +1 -0
- package/dist/core/entities/workflow-run.js +104 -0
- package/dist/core/entities/workflow-run.js.map +1 -0
- package/dist/core/workflow-run-url-state.d.ts +13 -0
- package/dist/core/workflow-run-url-state.d.ts.map +1 -0
- package/dist/core/workflow-run-url-state.js +43 -0
- package/dist/core/workflow-run-url-state.js.map +1 -0
- package/dist/core/workflow-run.d.ts +13 -0
- package/dist/core/workflow-run.d.ts.map +1 -0
- package/dist/core/workflow-run.js +8 -0
- package/dist/core/workflow-run.js.map +1 -0
- package/dist/env.d.js +2 -0
- package/dist/env.d.js.map +1 -0
- package/dist/feature.d.ts +20 -0
- package/dist/feature.d.ts.map +1 -0
- package/dist/feature.js +27 -0
- package/dist/feature.js.map +1 -0
- package/dist/hooks/api/workflow-runs.d.ts +109 -0
- package/dist/hooks/api/workflow-runs.d.ts.map +1 -0
- package/dist/hooks/api/workflow-runs.js +394 -0
- package/dist/hooks/api/workflow-runs.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/pages/workflow-run-first-time-use.d.ts +6 -0
- package/dist/pages/workflow-run-first-time-use.d.ts.map +1 -0
- package/dist/pages/workflow-run-first-time-use.js +17 -0
- package/dist/pages/workflow-run-first-time-use.js.map +1 -0
- package/dist/pages/workflow-run-page.d.ts +8 -0
- package/dist/pages/workflow-run-page.d.ts.map +1 -0
- package/dist/pages/workflow-run-page.js +83 -0
- package/dist/pages/workflow-run-page.js.map +1 -0
- package/dist/routes/run-detail.d.ts +8 -0
- package/dist/routes/run-detail.d.ts.map +1 -0
- package/dist/routes/run-detail.js +21 -0
- package/dist/routes/run-detail.js.map +1 -0
- package/dist/routes/runs.d.ts +8 -0
- package/dist/routes/runs.d.ts.map +1 -0
- package/dist/routes/runs.js +20 -0
- package/dist/routes/runs.js.map +1 -0
- package/dist/tsconfig.test.tsbuildinfo +1 -0
- package/package.json +114 -0
- package/src/components/identifier/identifier.tsx +178 -0
- package/src/components/identifier/index.ts +1 -0
- package/src/components/job-graph/graph-model.test.ts +189 -0
- package/src/components/job-graph/graph-model.ts +178 -0
- package/src/components/job-graph/index.ts +2 -0
- package/src/components/job-graph/job-duration-format.ts +54 -0
- package/src/components/job-graph/job-duration-label.tsx +29 -0
- package/src/components/job-graph/job-graph-content.tsx +225 -0
- package/src/components/job-graph/job-graph-view.test.tsx +298 -0
- package/src/components/job-graph/job-graph-view.tsx +45 -0
- package/src/components/job-graph/job-graph.stories.tsx +182 -0
- package/src/components/job-graph/job-graph.tsx +24 -0
- package/src/components/job-graph/job-node.stories.tsx +364 -0
- package/src/components/job-graph/job-node.test.tsx +347 -0
- package/src/components/job-graph/job-node.tsx +202 -0
- package/src/components/job-graph/types.ts +9 -0
- package/src/components/step-list/index.ts +6 -0
- package/src/components/step-list/step-list-model.test.ts +369 -0
- package/src/components/step-list/step-list-model.ts +205 -0
- package/src/components/step-list/step-list.stories.tsx +419 -0
- package/src/components/step-list/step-list.test.tsx +566 -0
- package/src/components/step-list/step-list.tsx +494 -0
- package/src/components/workflow-run-duration-label.tsx +118 -0
- package/src/components/workflow-run-list/index.ts +1 -0
- package/src/components/workflow-run-list/run-display.test.ts +53 -0
- package/src/components/workflow-run-list/run-display.ts +22 -0
- package/src/components/workflow-run-list/types.ts +22 -0
- package/src/components/workflow-run-list/workflow-run-list-content.tsx +58 -0
- package/src/components/workflow-run-list/workflow-run-list-header.tsx +53 -0
- package/src/components/workflow-run-list/workflow-run-list-states.tsx +86 -0
- package/src/components/workflow-run-list/workflow-run-list-view.test.tsx +178 -0
- package/src/components/workflow-run-list/workflow-run-list-view.tsx +57 -0
- package/src/components/workflow-run-list/workflow-run-list.stories.tsx +111 -0
- package/src/components/workflow-run-list/workflow-run-list.tsx +29 -0
- package/src/components/workflow-run-list/workflow-run-row.tsx +176 -0
- package/src/components/workflow-run-summary/index.ts +1 -0
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.test.tsx +230 -0
- package/src/components/workflow-run-summary/workflow-run-attempt-switcher.tsx +146 -0
- package/src/components/workflow-run-summary/workflow-run-summary.stories.tsx +414 -0
- package/src/components/workflow-run-summary/workflow-run-summary.test.tsx +354 -0
- package/src/components/workflow-run-summary/workflow-run-summary.tsx +295 -0
- package/src/components/workflow-run-view/agent-config-failure-callout.stories.tsx +140 -0
- package/src/components/workflow-run-view/agent-config-failure-callout.tsx +93 -0
- package/src/components/workflow-run-view/index.ts +2 -0
- package/src/components/workflow-run-view/job-card.stories.tsx +788 -0
- package/src/components/workflow-run-view/job-card.tsx +566 -0
- package/src/components/workflow-run-view/job-execution-switcher.tsx +170 -0
- package/src/components/workflow-run-view/job-execution-time-text.tsx +34 -0
- package/src/components/workflow-run-view/step-attempt-log-panel.test.tsx +290 -0
- package/src/components/workflow-run-view/step-attempt-log-panel.tsx +152 -0
- package/src/components/workflow-run-view/workflow-run-selection.test.ts +280 -0
- package/src/components/workflow-run-view/workflow-run-selection.ts +89 -0
- package/src/components/workflow-run-view/workflow-run-states.tsx +70 -0
- package/src/components/workflow-run-view/workflow-run-view.test.tsx +1214 -0
- package/src/components/workflow-run-view/workflow-run-view.tsx +341 -0
- package/src/components/workflow-source-panel/index.ts +1 -0
- package/src/components/workflow-source-panel/workflow-source-panel.stories.tsx +110 -0
- package/src/components/workflow-source-panel/workflow-source-panel.test.tsx +96 -0
- package/src/components/workflow-source-panel/workflow-source-panel.tsx +136 -0
- package/src/components/workflow-status/status-visuals.test.ts +38 -0
- package/src/components/workflow-status/status-visuals.ts +36 -0
- package/src/components/workflow-status/workflow-status-icon.stories.tsx +90 -0
- package/src/components/workflow-status/workflow-status-icon.tsx +135 -0
- package/src/core/entities/job-execution.ts +139 -0
- package/src/core/entities/job.ts +149 -0
- package/src/core/entities/step-attempt.ts +89 -0
- package/src/core/entities/step.ts +105 -0
- package/src/core/entities/workflow-run-attempt.ts +87 -0
- package/src/core/entities/workflow-run.ts +183 -0
- package/src/core/workflow-run-url-state.ts +61 -0
- package/src/core/workflow-run.test.ts +640 -0
- package/src/core/workflow-run.ts +66 -0
- package/src/env.d.ts +8 -0
- package/src/feature.ts +26 -0
- package/src/hooks/api/workflow-runs.test.tsx +410 -0
- package/src/hooks/api/workflow-runs.ts +485 -0
- package/src/index.ts +45 -0
- package/src/page-harness-budget.test.ts +33 -0
- package/src/pages/workflow-run-first-time-use.tsx +17 -0
- package/src/pages/workflow-run-page.test.tsx +517 -0
- package/src/pages/workflow-run-page.tsx +89 -0
- package/src/routes/run-detail.tsx +15 -0
- package/src/routes/runs.tsx +11 -0
- package/test/fixtures/logs.ts +13 -0
- package/test/fixtures/workflow-run.ts +311 -0
- package/test/pages.tsx +79 -0
- package/test/render.tsx +40 -0
- package/test/setup.ts +3 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.json +3 -0
- package/tsconfig.test.json +8 -0
- package/vercel.json +8 -0
- package/vitest.config.ts +70 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@shipfox/react-ui/accordion';
|
|
3
|
+
import { Badge } from '@shipfox/react-ui/badge';
|
|
4
|
+
import { Dot } from '@shipfox/react-ui/dot';
|
|
5
|
+
import { EmptyState } from '@shipfox/react-ui/empty-state';
|
|
6
|
+
import { Icon } from '@shipfox/react-ui/icon';
|
|
7
|
+
import { TimeTickerProvider, useTimeTick } from '@shipfox/react-ui/time-ticker';
|
|
8
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from '@shipfox/react-ui/tooltip';
|
|
9
|
+
import { Code, Text } from '@shipfox/react-ui/typography';
|
|
10
|
+
import { cn, humanDuration } from '@shipfox/react-ui/utils';
|
|
11
|
+
import { useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
12
|
+
import { WorkflowStatusIcon } from '#components/workflow-status/workflow-status-icon.js';
|
|
13
|
+
import { isWorkflowStatus } from '#core/workflow-run.js';
|
|
14
|
+
import { formatJobExecutionTimeLabel } from '../job-graph/job-duration-format.js';
|
|
15
|
+
import { buildStepListModel, defaultStepListJobExecution, humanizeStatus } from './step-list-model.js';
|
|
16
|
+
export function StepList({ job, jobExecution, selectedAttemptId, defaultSelectedAttemptId, onSelectedAttemptChange, autoSelectActiveAttempt = false, emptyState, renderExpandedStep, showHeader = true, className }) {
|
|
17
|
+
const selectedJobExecution = jobExecution ?? defaultStepListJobExecution(job);
|
|
18
|
+
const model = useMemo(()=>buildStepListModel({
|
|
19
|
+
job,
|
|
20
|
+
jobExecution: selectedJobExecution
|
|
21
|
+
}), [
|
|
22
|
+
job,
|
|
23
|
+
selectedJobExecution
|
|
24
|
+
]);
|
|
25
|
+
return /*#__PURE__*/ _jsx(StepListContent, {
|
|
26
|
+
model: model,
|
|
27
|
+
selectedAttemptId: selectedAttemptId,
|
|
28
|
+
defaultSelectedAttemptId: defaultSelectedAttemptId,
|
|
29
|
+
onSelectedAttemptChange: onSelectedAttemptChange,
|
|
30
|
+
autoSelectActiveAttempt: autoSelectActiveAttempt,
|
|
31
|
+
emptyState: emptyState,
|
|
32
|
+
renderExpandedStep: renderExpandedStep,
|
|
33
|
+
showHeader: showHeader,
|
|
34
|
+
className: className
|
|
35
|
+
}, model.jobExecutionId);
|
|
36
|
+
}
|
|
37
|
+
function StepListContent({ model, selectedAttemptId, defaultSelectedAttemptId, onSelectedAttemptChange, autoSelectActiveAttempt, emptyState, renderExpandedStep, showHeader, className }) {
|
|
38
|
+
const titleId = useId();
|
|
39
|
+
const [localSelectedAttemptIds, setLocalSelectedAttemptIds] = useState(()=>selectedAttemptId ? [
|
|
40
|
+
selectedAttemptId
|
|
41
|
+
] : defaultSelectedAttemptId ? [
|
|
42
|
+
defaultSelectedAttemptId
|
|
43
|
+
] : []);
|
|
44
|
+
const [userSelectedAttempt, setUserSelectedAttempt] = useState(false);
|
|
45
|
+
const lastNotifiedSelectedAttemptId = useRef(null);
|
|
46
|
+
const shouldUseControlledCollapsedState = selectedAttemptId === null && lastNotifiedSelectedAttemptId.current === null;
|
|
47
|
+
const autoSelectedAttemptIds = selectedAttemptId === undefined && autoSelectActiveAttempt && !userSelectedAttempt && model.activeEntryId ? [
|
|
48
|
+
model.activeEntryId
|
|
49
|
+
] : [];
|
|
50
|
+
const selectedAttemptIds = shouldUseControlledCollapsedState ? [] : localSelectedAttemptIds.length > 0 ? localSelectedAttemptIds : autoSelectedAttemptIds;
|
|
51
|
+
const hasExpandedContent = renderExpandedStep !== undefined;
|
|
52
|
+
useEffect(()=>{
|
|
53
|
+
if (selectedAttemptId !== undefined) return;
|
|
54
|
+
setLocalSelectedAttemptIds(defaultSelectedAttemptId ? [
|
|
55
|
+
defaultSelectedAttemptId
|
|
56
|
+
] : []);
|
|
57
|
+
setUserSelectedAttempt(false);
|
|
58
|
+
}, [
|
|
59
|
+
defaultSelectedAttemptId,
|
|
60
|
+
selectedAttemptId
|
|
61
|
+
]);
|
|
62
|
+
useEffect(()=>{
|
|
63
|
+
if (selectedAttemptId === undefined) return;
|
|
64
|
+
const nextSelectedAttemptId = selectedAttemptId ?? null;
|
|
65
|
+
if (lastNotifiedSelectedAttemptId.current === nextSelectedAttemptId) {
|
|
66
|
+
lastNotifiedSelectedAttemptId.current = null;
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
setLocalSelectedAttemptIds(selectedAttemptId ? [
|
|
70
|
+
selectedAttemptId
|
|
71
|
+
] : []);
|
|
72
|
+
setUserSelectedAttempt(true);
|
|
73
|
+
}, [
|
|
74
|
+
selectedAttemptId
|
|
75
|
+
]);
|
|
76
|
+
function selectAttempt(nextAttemptIds) {
|
|
77
|
+
const nextAttemptId = nextSelectedAttemptId(selectedAttemptIds, nextAttemptIds);
|
|
78
|
+
setUserSelectedAttempt(true);
|
|
79
|
+
setLocalSelectedAttemptIds(nextAttemptIds);
|
|
80
|
+
lastNotifiedSelectedAttemptId.current = nextAttemptId ?? null;
|
|
81
|
+
onSelectedAttemptChange?.(nextAttemptId);
|
|
82
|
+
}
|
|
83
|
+
return /*#__PURE__*/ _jsx(TimeTickerProvider, {
|
|
84
|
+
intervalMs: 1000,
|
|
85
|
+
reducedMotionIntervalMs: 10_000,
|
|
86
|
+
children: /*#__PURE__*/ _jsxs("section", {
|
|
87
|
+
"aria-labelledby": showHeader ? titleId : undefined,
|
|
88
|
+
className: cn('flex min-h-0 flex-col rounded-8 border border-border-neutral-base bg-background-components-base', className),
|
|
89
|
+
children: [
|
|
90
|
+
showHeader ? /*#__PURE__*/ _jsx("div", {
|
|
91
|
+
className: "flex min-h-40 items-center border-b border-border-neutral-base px-16 py-8",
|
|
92
|
+
children: /*#__PURE__*/ _jsx(Text, {
|
|
93
|
+
as: "h2",
|
|
94
|
+
id: titleId,
|
|
95
|
+
size: "sm",
|
|
96
|
+
bold: true,
|
|
97
|
+
className: "text-foreground-neutral-base",
|
|
98
|
+
children: model.jobName
|
|
99
|
+
})
|
|
100
|
+
}) : null,
|
|
101
|
+
model.entries.length === 0 ? /*#__PURE__*/ _jsx(StepListEmptyStateView, {
|
|
102
|
+
emptyState: emptyState
|
|
103
|
+
}) : /*#__PURE__*/ _jsx(Accordion, {
|
|
104
|
+
type: "multiple",
|
|
105
|
+
value: selectedAttemptIds,
|
|
106
|
+
onValueChange: selectAttempt,
|
|
107
|
+
asChild: true,
|
|
108
|
+
children: /*#__PURE__*/ _jsx("ol", {
|
|
109
|
+
children: model.entries.map((entry)=>{
|
|
110
|
+
const selected = selectedAttemptIds.includes(entry.id);
|
|
111
|
+
return /*#__PURE__*/ _jsx(StepRow, {
|
|
112
|
+
entry: entry,
|
|
113
|
+
selected: selected,
|
|
114
|
+
hasExpandedContent: hasExpandedContent,
|
|
115
|
+
onSelect: ()=>{
|
|
116
|
+
selectAttempt(hasExpandedContent ? toggleAttemptId(selectedAttemptIds, entry.id) : selected ? [] : [
|
|
117
|
+
entry.id
|
|
118
|
+
]);
|
|
119
|
+
},
|
|
120
|
+
expandedContent: selected ? renderExpandedStep?.({
|
|
121
|
+
step: entry.step,
|
|
122
|
+
stepId: entry.step.id,
|
|
123
|
+
stepLabel: entry.step.label,
|
|
124
|
+
sourceLocation: entry.step.sourceLocation,
|
|
125
|
+
attempt: entry.attempt,
|
|
126
|
+
attemptId: entry.id,
|
|
127
|
+
attemptError: entry.error,
|
|
128
|
+
attemptStatus: entry.statusVisual.kind,
|
|
129
|
+
carriedOver: entry.carriedOver
|
|
130
|
+
}) : null
|
|
131
|
+
}, entry.id);
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
})
|
|
135
|
+
]
|
|
136
|
+
})
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function StepListEmptyStateView({ emptyState = {
|
|
140
|
+
title: 'No steps recorded',
|
|
141
|
+
description: 'This job has not recorded any steps.'
|
|
142
|
+
} }) {
|
|
143
|
+
if (!emptyState.status) {
|
|
144
|
+
return /*#__PURE__*/ _jsx(EmptyState, {
|
|
145
|
+
className: "min-h-120 px-16 py-20",
|
|
146
|
+
icon: "componentLine",
|
|
147
|
+
title: emptyState.title,
|
|
148
|
+
description: emptyState.description,
|
|
149
|
+
variant: "compact"
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
153
|
+
className: "flex min-h-120 flex-col items-center justify-center gap-10 px-16 py-20",
|
|
154
|
+
children: [
|
|
155
|
+
/*#__PURE__*/ _jsx(StepListEmptyStateIcon, {
|
|
156
|
+
status: emptyState.status
|
|
157
|
+
}),
|
|
158
|
+
/*#__PURE__*/ _jsxs("div", {
|
|
159
|
+
className: "text-center",
|
|
160
|
+
children: [
|
|
161
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
162
|
+
size: "sm",
|
|
163
|
+
className: "text-foreground-neutral-subtle",
|
|
164
|
+
children: emptyState.title
|
|
165
|
+
}),
|
|
166
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
167
|
+
size: "xs",
|
|
168
|
+
className: "text-foreground-neutral-muted",
|
|
169
|
+
children: emptyState.description
|
|
170
|
+
})
|
|
171
|
+
]
|
|
172
|
+
})
|
|
173
|
+
]
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function StepListEmptyStateIcon({ status }) {
|
|
177
|
+
if (status !== 'running') {
|
|
178
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
179
|
+
className: "flex size-32 items-center justify-center rounded-6 border border-border-neutral-strong bg-background-neutral-base p-8",
|
|
180
|
+
children: /*#__PURE__*/ _jsx(WorkflowStatusIcon, {
|
|
181
|
+
status: status,
|
|
182
|
+
size: 20,
|
|
183
|
+
tooltip: false
|
|
184
|
+
})
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
188
|
+
className: "flex size-32 items-center justify-center rounded-6 border border-border-neutral-strong bg-background-neutral-base p-8 text-foreground-neutral-muted",
|
|
189
|
+
children: /*#__PURE__*/ _jsx(Icon, {
|
|
190
|
+
name: "timerLine",
|
|
191
|
+
size: 18,
|
|
192
|
+
"aria-hidden": "true"
|
|
193
|
+
})
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
function StepRow({ entry, selected, hasExpandedContent, onSelect, expandedContent }) {
|
|
197
|
+
const shouldShowLabelTooltip = entry.step.label.length > 32;
|
|
198
|
+
const rowContent = /*#__PURE__*/ _jsxs(_Fragment, {
|
|
199
|
+
children: [
|
|
200
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
201
|
+
name: "chevronRight",
|
|
202
|
+
"aria-hidden": "true",
|
|
203
|
+
className: cn('size-14 shrink-0 text-foreground-neutral-muted transition-transform', selected && 'rotate-90')
|
|
204
|
+
}),
|
|
205
|
+
/*#__PURE__*/ _jsx(StepStatusIcon, {
|
|
206
|
+
entry: entry
|
|
207
|
+
}),
|
|
208
|
+
/*#__PURE__*/ _jsx("div", {
|
|
209
|
+
className: "min-w-0 flex-1",
|
|
210
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
211
|
+
className: "flex min-w-0 items-center gap-8",
|
|
212
|
+
children: [
|
|
213
|
+
/*#__PURE__*/ _jsx(Text, {
|
|
214
|
+
size: "sm",
|
|
215
|
+
bold: true,
|
|
216
|
+
className: "truncate text-foreground-neutral-base",
|
|
217
|
+
children: entry.step.label
|
|
218
|
+
}),
|
|
219
|
+
entry.step.attempts.length > 1 ? /*#__PURE__*/ _jsx(StepAttemptChip, {
|
|
220
|
+
attempt: entry
|
|
221
|
+
}) : null,
|
|
222
|
+
entry.carriedOver ? /*#__PURE__*/ _jsx(CarriedOverBadge, {}) : null
|
|
223
|
+
]
|
|
224
|
+
})
|
|
225
|
+
}),
|
|
226
|
+
/*#__PURE__*/ _jsx(StepAttemptDurationLabel, {
|
|
227
|
+
attempt: entry
|
|
228
|
+
})
|
|
229
|
+
]
|
|
230
|
+
});
|
|
231
|
+
const rowClasses = cn('group grid min-h-44 w-full grid-cols-[14px_14px_minmax(0,1fr)_auto] items-center gap-x-8 px-12 py-6 text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-border-interactive-with-active focus-visible:outline-none', selected && 'bg-background-components-hover', entry.carriedOver && 'opacity-[0.55]');
|
|
232
|
+
const button = hasExpandedContent ? /*#__PURE__*/ _jsx(AccordionTrigger, {
|
|
233
|
+
showIcon: false,
|
|
234
|
+
"aria-label": entryAccessibleLabel(entry),
|
|
235
|
+
className: rowClasses,
|
|
236
|
+
children: rowContent
|
|
237
|
+
}) : /*#__PURE__*/ _jsx("button", {
|
|
238
|
+
type: "button",
|
|
239
|
+
"aria-expanded": false,
|
|
240
|
+
"aria-label": entryAccessibleLabel(entry),
|
|
241
|
+
onClick: onSelect,
|
|
242
|
+
className: rowClasses,
|
|
243
|
+
children: rowContent
|
|
244
|
+
});
|
|
245
|
+
const triggerNode = shouldShowLabelTooltip ? /*#__PURE__*/ _jsxs(Tooltip, {
|
|
246
|
+
children: [
|
|
247
|
+
/*#__PURE__*/ _jsx(TooltipTrigger, {
|
|
248
|
+
asChild: true,
|
|
249
|
+
children: button
|
|
250
|
+
}),
|
|
251
|
+
/*#__PURE__*/ _jsx(TooltipContent, {
|
|
252
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
253
|
+
className: "block max-w-320 break-words",
|
|
254
|
+
children: entry.step.label
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
]
|
|
258
|
+
}) : button;
|
|
259
|
+
const row = /*#__PURE__*/ _jsxs(_Fragment, {
|
|
260
|
+
children: [
|
|
261
|
+
triggerNode,
|
|
262
|
+
selected && expandedContent ? /*#__PURE__*/ _jsx(AccordionContent, {
|
|
263
|
+
className: "border-t border-border-neutral-base bg-background-neutral-base px-12 py-12",
|
|
264
|
+
children: /*#__PURE__*/ _jsxs("div", {
|
|
265
|
+
className: "grid grid-cols-[14px_14px_minmax(0,1fr)_auto] gap-x-8",
|
|
266
|
+
children: [
|
|
267
|
+
/*#__PURE__*/ _jsx("span", {
|
|
268
|
+
"aria-hidden": "true"
|
|
269
|
+
}),
|
|
270
|
+
/*#__PURE__*/ _jsx("span", {
|
|
271
|
+
"aria-hidden": "true"
|
|
272
|
+
}),
|
|
273
|
+
/*#__PURE__*/ _jsx("div", {
|
|
274
|
+
className: "min-w-0",
|
|
275
|
+
children: expandedContent
|
|
276
|
+
}),
|
|
277
|
+
/*#__PURE__*/ _jsx("span", {
|
|
278
|
+
"aria-hidden": "true"
|
|
279
|
+
})
|
|
280
|
+
]
|
|
281
|
+
})
|
|
282
|
+
}) : null
|
|
283
|
+
]
|
|
284
|
+
});
|
|
285
|
+
if (hasExpandedContent) {
|
|
286
|
+
return /*#__PURE__*/ _jsx(AccordionItem, {
|
|
287
|
+
value: entry.id,
|
|
288
|
+
asChild: true,
|
|
289
|
+
children: /*#__PURE__*/ _jsx("li", {
|
|
290
|
+
children: row
|
|
291
|
+
})
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return /*#__PURE__*/ _jsx("li", {
|
|
295
|
+
className: "border-b border-border-neutral-base last:border-b-0",
|
|
296
|
+
children: row
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
function CarriedOverBadge() {
|
|
300
|
+
return /*#__PURE__*/ _jsxs(Tooltip, {
|
|
301
|
+
children: [
|
|
302
|
+
/*#__PURE__*/ _jsx(TooltipTrigger, {
|
|
303
|
+
asChild: true,
|
|
304
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
305
|
+
className: "shrink-0",
|
|
306
|
+
children: /*#__PURE__*/ _jsx(Badge, {
|
|
307
|
+
variant: "neutral",
|
|
308
|
+
size: "2xs",
|
|
309
|
+
children: "reused"
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
}),
|
|
313
|
+
/*#__PURE__*/ _jsx(TooltipContent, {
|
|
314
|
+
children: "Carried over from a previous attempt; did not run in this attempt."
|
|
315
|
+
})
|
|
316
|
+
]
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
function toggleAttemptId(selectedAttemptIds, attemptId) {
|
|
320
|
+
if (selectedAttemptIds.includes(attemptId)) {
|
|
321
|
+
return selectedAttemptIds.filter((selectedAttemptId)=>selectedAttemptId !== attemptId);
|
|
322
|
+
}
|
|
323
|
+
return [
|
|
324
|
+
...selectedAttemptIds,
|
|
325
|
+
attemptId
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
function nextSelectedAttemptId(selectedAttemptIds, nextAttemptIds) {
|
|
329
|
+
if (nextAttemptIds.length === 0) return undefined;
|
|
330
|
+
const openedAttemptId = nextAttemptIds.find((attemptId)=>!selectedAttemptIds.includes(attemptId));
|
|
331
|
+
return openedAttemptId ?? nextAttemptIds.at(-1);
|
|
332
|
+
}
|
|
333
|
+
function StepStatusIcon({ entry }) {
|
|
334
|
+
if (isWorkflowStatus(entry.statusVisual.kind)) {
|
|
335
|
+
return /*#__PURE__*/ _jsx(WorkflowStatusIcon, {
|
|
336
|
+
status: entry.statusVisual.kind,
|
|
337
|
+
ripple: entry.statusVisual.ripple,
|
|
338
|
+
size: 14
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
return /*#__PURE__*/ _jsx("span", {
|
|
342
|
+
role: "img",
|
|
343
|
+
"aria-label": entry.statusVisual.label,
|
|
344
|
+
className: "inline-flex shrink-0",
|
|
345
|
+
children: /*#__PURE__*/ _jsx(Dot, {
|
|
346
|
+
variant: entry.statusVisual.dot,
|
|
347
|
+
ripple: entry.statusVisual.ripple,
|
|
348
|
+
className: "size-12 shrink-0"
|
|
349
|
+
})
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
const attemptChipClasses = {
|
|
353
|
+
neutral: 'bg-tag-neutral-bg border-tag-neutral-border',
|
|
354
|
+
info: 'bg-tag-blue-bg border-tag-blue-border',
|
|
355
|
+
feature: 'bg-tag-purple-bg border-tag-purple-border',
|
|
356
|
+
success: 'bg-tag-success-bg border-tag-success-border',
|
|
357
|
+
warning: 'bg-tag-warning-bg border-tag-warning-border',
|
|
358
|
+
error: 'bg-tag-error-bg border-tag-error-border'
|
|
359
|
+
};
|
|
360
|
+
function StepAttemptChip({ attempt }) {
|
|
361
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
362
|
+
className: "flex shrink-0 items-center gap-4",
|
|
363
|
+
"aria-hidden": "true",
|
|
364
|
+
children: /*#__PURE__*/ _jsxs("span", {
|
|
365
|
+
className: cn('inline-flex h-18 min-w-24 items-center justify-center rounded-4 border px-5 font-code text-xs leading-16 text-foreground-neutral-base', attemptChipClasses[attempt.statusVisual.badge ?? 'neutral']),
|
|
366
|
+
children: [
|
|
367
|
+
"#",
|
|
368
|
+
attempt.attempt
|
|
369
|
+
]
|
|
370
|
+
})
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
function entryAccessibleLabel(entry) {
|
|
374
|
+
const parts = [
|
|
375
|
+
entry.step.label,
|
|
376
|
+
entry.statusVisual.label,
|
|
377
|
+
`attempt ${entry.attempt}`
|
|
378
|
+
];
|
|
379
|
+
if (entry.step.error?.category) parts.push(humanizeStatus(entry.step.error.category));
|
|
380
|
+
return parts.join(', ');
|
|
381
|
+
}
|
|
382
|
+
function StepAttemptDurationLabel({ attempt }) {
|
|
383
|
+
const duration = attempt.displayDuration;
|
|
384
|
+
if (duration === null) return null;
|
|
385
|
+
if (duration.state === 'live') {
|
|
386
|
+
return /*#__PURE__*/ _jsx(LiveDurationText, {
|
|
387
|
+
fromIso: duration.fromIso
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
return /*#__PURE__*/ _jsx(DurationText, {
|
|
391
|
+
children: formatJobExecutionTimeLabel(duration)
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
function LiveDurationText({ fromIso }) {
|
|
395
|
+
useTimeTick();
|
|
396
|
+
return /*#__PURE__*/ _jsx(DurationText, {
|
|
397
|
+
children: humanDuration(fromIso)
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function DurationText({ children }) {
|
|
401
|
+
return /*#__PURE__*/ _jsx(Code, {
|
|
402
|
+
as: "span",
|
|
403
|
+
variant: "label",
|
|
404
|
+
className: "shrink-0 tabular-nums text-foreground-neutral-muted",
|
|
405
|
+
children: children
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
//# sourceMappingURL=step-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/step-list/step-list.tsx"],"sourcesContent":["import {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from '@shipfox/react-ui/accordion';\nimport {Badge, type BadgeVariant} from '@shipfox/react-ui/badge';\nimport {Dot} from '@shipfox/react-ui/dot';\nimport {EmptyState} from '@shipfox/react-ui/empty-state';\nimport {Icon} from '@shipfox/react-ui/icon';\nimport {TimeTickerProvider, useTimeTick} from '@shipfox/react-ui/time-ticker';\nimport {Tooltip, TooltipContent, TooltipTrigger} from '@shipfox/react-ui/tooltip';\nimport {Code, Text} from '@shipfox/react-ui/typography';\nimport {cn, humanDuration} from '@shipfox/react-ui/utils';\nimport type {ReactNode} from 'react';\nimport {useEffect, useId, useMemo, useRef, useState} from 'react';\nimport {WorkflowStatusIcon} from '#components/workflow-status/workflow-status-icon.js';\nimport {\n isWorkflowStatus,\n type Job,\n type JobExecution,\n type Step,\n type StepSourceLocation,\n} from '#core/workflow-run.js';\nimport {formatJobExecutionTimeLabel} from '../job-graph/job-duration-format.js';\nimport {\n buildStepListModel,\n defaultStepListJobExecution,\n humanizeStatus,\n type StepAttemptModel,\n type StepListEntryModel,\n type StepListModel,\n} from './step-list-model.js';\n\nexport interface StepExpandedContext {\n step: Step;\n stepId: string;\n stepLabel: string;\n sourceLocation: StepSourceLocation | null;\n attempt: number;\n attemptId: string;\n attemptError: Record<string, unknown> | null;\n attemptStatus: string;\n carriedOver: boolean;\n}\n\nexport interface StepListEmptyState {\n title: string;\n description: string;\n status?: Job['status'] | undefined;\n}\n\nexport interface StepListProps {\n job: Job;\n jobExecution?: JobExecution | undefined;\n selectedAttemptId?: string | null | undefined;\n defaultSelectedAttemptId?: string | undefined;\n onSelectedAttemptChange?: ((attemptId: string | undefined) => void) | undefined;\n autoSelectActiveAttempt?: boolean | undefined;\n emptyState?: StepListEmptyState | undefined;\n renderExpandedStep?: ((context: StepExpandedContext) => ReactNode) | undefined;\n showHeader?: boolean | undefined;\n className?: string | undefined;\n}\n\nexport function StepList({\n job,\n jobExecution,\n selectedAttemptId,\n defaultSelectedAttemptId,\n onSelectedAttemptChange,\n autoSelectActiveAttempt = false,\n emptyState,\n renderExpandedStep,\n showHeader = true,\n className,\n}: StepListProps) {\n const selectedJobExecution = jobExecution ?? defaultStepListJobExecution(job);\n const model = useMemo(\n () => buildStepListModel({job, jobExecution: selectedJobExecution}),\n [job, selectedJobExecution],\n );\n\n return (\n <StepListContent\n key={model.jobExecutionId}\n model={model}\n selectedAttemptId={selectedAttemptId}\n defaultSelectedAttemptId={defaultSelectedAttemptId}\n onSelectedAttemptChange={onSelectedAttemptChange}\n autoSelectActiveAttempt={autoSelectActiveAttempt}\n emptyState={emptyState}\n renderExpandedStep={renderExpandedStep}\n showHeader={showHeader}\n className={className}\n />\n );\n}\n\nfunction StepListContent({\n model,\n selectedAttemptId,\n defaultSelectedAttemptId,\n onSelectedAttemptChange,\n autoSelectActiveAttempt,\n emptyState,\n renderExpandedStep,\n showHeader,\n className,\n}: Omit<StepListProps, 'job' | 'jobExecution'> & {model: StepListModel}) {\n const titleId = useId();\n const [localSelectedAttemptIds, setLocalSelectedAttemptIds] = useState<string[]>(() =>\n selectedAttemptId\n ? [selectedAttemptId]\n : defaultSelectedAttemptId\n ? [defaultSelectedAttemptId]\n : [],\n );\n const [userSelectedAttempt, setUserSelectedAttempt] = useState(false);\n const lastNotifiedSelectedAttemptId = useRef<string | null>(null);\n const shouldUseControlledCollapsedState =\n selectedAttemptId === null && lastNotifiedSelectedAttemptId.current === null;\n const autoSelectedAttemptIds =\n selectedAttemptId === undefined &&\n autoSelectActiveAttempt &&\n !userSelectedAttempt &&\n model.activeEntryId\n ? [model.activeEntryId]\n : [];\n const selectedAttemptIds = shouldUseControlledCollapsedState\n ? []\n : localSelectedAttemptIds.length > 0\n ? localSelectedAttemptIds\n : autoSelectedAttemptIds;\n const hasExpandedContent = renderExpandedStep !== undefined;\n\n useEffect(() => {\n if (selectedAttemptId !== undefined) return;\n\n setLocalSelectedAttemptIds(defaultSelectedAttemptId ? [defaultSelectedAttemptId] : []);\n setUserSelectedAttempt(false);\n }, [defaultSelectedAttemptId, selectedAttemptId]);\n\n useEffect(() => {\n if (selectedAttemptId === undefined) return;\n\n const nextSelectedAttemptId = selectedAttemptId ?? null;\n if (lastNotifiedSelectedAttemptId.current === nextSelectedAttemptId) {\n lastNotifiedSelectedAttemptId.current = null;\n return;\n }\n\n setLocalSelectedAttemptIds(selectedAttemptId ? [selectedAttemptId] : []);\n setUserSelectedAttempt(true);\n }, [selectedAttemptId]);\n\n function selectAttempt(nextAttemptIds: string[]) {\n const nextAttemptId = nextSelectedAttemptId(selectedAttemptIds, nextAttemptIds);\n setUserSelectedAttempt(true);\n setLocalSelectedAttemptIds(nextAttemptIds);\n lastNotifiedSelectedAttemptId.current = nextAttemptId ?? null;\n onSelectedAttemptChange?.(nextAttemptId);\n }\n\n return (\n <TimeTickerProvider intervalMs={1000} reducedMotionIntervalMs={10_000}>\n <section\n aria-labelledby={showHeader ? titleId : undefined}\n className={cn(\n 'flex min-h-0 flex-col rounded-8 border border-border-neutral-base bg-background-components-base',\n className,\n )}\n >\n {showHeader ? (\n <div className=\"flex min-h-40 items-center border-b border-border-neutral-base px-16 py-8\">\n <Text as=\"h2\" id={titleId} size=\"sm\" bold className=\"text-foreground-neutral-base\">\n {model.jobName}\n </Text>\n </div>\n ) : null}\n\n {model.entries.length === 0 ? (\n <StepListEmptyStateView emptyState={emptyState} />\n ) : (\n <Accordion\n type=\"multiple\"\n value={selectedAttemptIds}\n onValueChange={selectAttempt}\n asChild\n >\n <ol>\n {model.entries.map((entry) => {\n const selected = selectedAttemptIds.includes(entry.id);\n return (\n <StepRow\n key={entry.id}\n entry={entry}\n selected={selected}\n hasExpandedContent={hasExpandedContent}\n onSelect={() => {\n selectAttempt(\n hasExpandedContent\n ? toggleAttemptId(selectedAttemptIds, entry.id)\n : selected\n ? []\n : [entry.id],\n );\n }}\n expandedContent={\n selected\n ? renderExpandedStep?.({\n step: entry.step,\n stepId: entry.step.id,\n stepLabel: entry.step.label,\n sourceLocation: entry.step.sourceLocation,\n attempt: entry.attempt,\n attemptId: entry.id,\n attemptError: entry.error,\n attemptStatus: entry.statusVisual.kind,\n carriedOver: entry.carriedOver,\n })\n : null\n }\n />\n );\n })}\n </ol>\n </Accordion>\n )}\n </section>\n </TimeTickerProvider>\n );\n}\n\nfunction StepListEmptyStateView({\n emptyState = {\n title: 'No steps recorded',\n description: 'This job has not recorded any steps.',\n },\n}: {\n emptyState?: StepListEmptyState | undefined;\n}) {\n if (!emptyState.status) {\n return (\n <EmptyState\n className=\"min-h-120 px-16 py-20\"\n icon=\"componentLine\"\n title={emptyState.title}\n description={emptyState.description}\n variant=\"compact\"\n />\n );\n }\n\n return (\n <div className=\"flex min-h-120 flex-col items-center justify-center gap-10 px-16 py-20\">\n <StepListEmptyStateIcon status={emptyState.status} />\n <div className=\"text-center\">\n <Text size=\"sm\" className=\"text-foreground-neutral-subtle\">\n {emptyState.title}\n </Text>\n <Text size=\"xs\" className=\"text-foreground-neutral-muted\">\n {emptyState.description}\n </Text>\n </div>\n </div>\n );\n}\n\nfunction StepListEmptyStateIcon({status}: {status: Job['status']}) {\n if (status !== 'running') {\n return (\n <div className=\"flex size-32 items-center justify-center rounded-6 border border-border-neutral-strong bg-background-neutral-base p-8\">\n <WorkflowStatusIcon status={status} size={20} tooltip={false} />\n </div>\n );\n }\n\n return (\n <div className=\"flex size-32 items-center justify-center rounded-6 border border-border-neutral-strong bg-background-neutral-base p-8 text-foreground-neutral-muted\">\n <Icon name=\"timerLine\" size={18} aria-hidden=\"true\" />\n </div>\n );\n}\n\nfunction StepRow({\n entry,\n selected,\n hasExpandedContent,\n onSelect,\n expandedContent,\n}: {\n entry: StepListEntryModel;\n selected: boolean;\n hasExpandedContent: boolean;\n onSelect: () => void;\n expandedContent: ReactNode;\n}) {\n const shouldShowLabelTooltip = entry.step.label.length > 32;\n const rowContent = (\n <>\n <Icon\n name=\"chevronRight\"\n aria-hidden=\"true\"\n className={cn(\n 'size-14 shrink-0 text-foreground-neutral-muted transition-transform',\n selected && 'rotate-90',\n )}\n />\n <StepStatusIcon entry={entry} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex min-w-0 items-center gap-8\">\n <Text size=\"sm\" bold className=\"truncate text-foreground-neutral-base\">\n {entry.step.label}\n </Text>\n {entry.step.attempts.length > 1 ? <StepAttemptChip attempt={entry} /> : null}\n {entry.carriedOver ? <CarriedOverBadge /> : null}\n </div>\n </div>\n <StepAttemptDurationLabel attempt={entry} />\n </>\n );\n const rowClasses = cn(\n 'group grid min-h-44 w-full grid-cols-[14px_14px_minmax(0,1fr)_auto] items-center gap-x-8 px-12 py-6 text-left transition-colors hover:bg-background-components-hover focus-visible:shadow-border-interactive-with-active focus-visible:outline-none',\n selected && 'bg-background-components-hover',\n entry.carriedOver && 'opacity-[0.55]',\n );\n const button = hasExpandedContent ? (\n <AccordionTrigger\n showIcon={false}\n aria-label={entryAccessibleLabel(entry)}\n className={rowClasses}\n >\n {rowContent}\n </AccordionTrigger>\n ) : (\n <button\n type=\"button\"\n aria-expanded={false}\n aria-label={entryAccessibleLabel(entry)}\n onClick={onSelect}\n className={rowClasses}\n >\n {rowContent}\n </button>\n );\n const triggerNode = shouldShowLabelTooltip ? (\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>\n <span className=\"block max-w-320 break-words\">{entry.step.label}</span>\n </TooltipContent>\n </Tooltip>\n ) : (\n button\n );\n const row = (\n <>\n {triggerNode}\n {selected && expandedContent ? (\n <AccordionContent className=\"border-t border-border-neutral-base bg-background-neutral-base px-12 py-12\">\n <div className=\"grid grid-cols-[14px_14px_minmax(0,1fr)_auto] gap-x-8\">\n <span aria-hidden=\"true\" />\n <span aria-hidden=\"true\" />\n <div className=\"min-w-0\">{expandedContent}</div>\n <span aria-hidden=\"true\" />\n </div>\n </AccordionContent>\n ) : null}\n </>\n );\n\n if (hasExpandedContent) {\n return (\n <AccordionItem value={entry.id} asChild>\n <li>{row}</li>\n </AccordionItem>\n );\n }\n\n return <li className=\"border-b border-border-neutral-base last:border-b-0\">{row}</li>;\n}\n\nfunction CarriedOverBadge() {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <span className=\"shrink-0\">\n <Badge variant=\"neutral\" size=\"2xs\">\n reused\n </Badge>\n </span>\n </TooltipTrigger>\n <TooltipContent>\n Carried over from a previous attempt; did not run in this attempt.\n </TooltipContent>\n </Tooltip>\n );\n}\n\nfunction toggleAttemptId(selectedAttemptIds: readonly string[], attemptId: string): string[] {\n if (selectedAttemptIds.includes(attemptId)) {\n return selectedAttemptIds.filter((selectedAttemptId) => selectedAttemptId !== attemptId);\n }\n return [...selectedAttemptIds, attemptId];\n}\n\nfunction nextSelectedAttemptId(\n selectedAttemptIds: readonly string[],\n nextAttemptIds: readonly string[],\n): string | undefined {\n if (nextAttemptIds.length === 0) return undefined;\n\n const openedAttemptId = nextAttemptIds.find(\n (attemptId) => !selectedAttemptIds.includes(attemptId),\n );\n return openedAttemptId ?? nextAttemptIds.at(-1);\n}\n\nfunction StepStatusIcon({entry}: {entry: StepListEntryModel}) {\n if (isWorkflowStatus(entry.statusVisual.kind)) {\n return (\n <WorkflowStatusIcon\n status={entry.statusVisual.kind}\n ripple={entry.statusVisual.ripple}\n size={14}\n />\n );\n }\n\n return (\n <span role=\"img\" aria-label={entry.statusVisual.label} className=\"inline-flex shrink-0\">\n <Dot\n variant={entry.statusVisual.dot}\n ripple={entry.statusVisual.ripple}\n className=\"size-12 shrink-0\"\n />\n </span>\n );\n}\n\nconst attemptChipClasses: Record<NonNullable<BadgeVariant>, string> = {\n neutral: 'bg-tag-neutral-bg border-tag-neutral-border',\n info: 'bg-tag-blue-bg border-tag-blue-border',\n feature: 'bg-tag-purple-bg border-tag-purple-border',\n success: 'bg-tag-success-bg border-tag-success-border',\n warning: 'bg-tag-warning-bg border-tag-warning-border',\n error: 'bg-tag-error-bg border-tag-error-border',\n};\n\nfunction StepAttemptChip({attempt}: {attempt: StepAttemptModel}) {\n return (\n <div className=\"flex shrink-0 items-center gap-4\" aria-hidden=\"true\">\n <span\n className={cn(\n 'inline-flex h-18 min-w-24 items-center justify-center rounded-4 border px-5 font-code text-xs leading-16 text-foreground-neutral-base',\n attemptChipClasses[attempt.statusVisual.badge ?? 'neutral'],\n )}\n >\n #{attempt.attempt}\n </span>\n </div>\n );\n}\n\nfunction entryAccessibleLabel(entry: StepListEntryModel): string {\n const parts = [entry.step.label, entry.statusVisual.label, `attempt ${entry.attempt}`];\n if (entry.step.error?.category) parts.push(humanizeStatus(entry.step.error.category));\n return parts.join(', ');\n}\n\nfunction StepAttemptDurationLabel({attempt}: {attempt: StepAttemptModel}) {\n const duration = attempt.displayDuration;\n if (duration === null) return null;\n\n if (duration.state === 'live') {\n return <LiveDurationText fromIso={duration.fromIso} />;\n }\n\n return <DurationText>{formatJobExecutionTimeLabel(duration)}</DurationText>;\n}\n\nfunction LiveDurationText({fromIso}: {fromIso: string}) {\n useTimeTick();\n return <DurationText>{humanDuration(fromIso)}</DurationText>;\n}\n\nfunction DurationText({children}: {children: string}) {\n return (\n <Code as=\"span\" variant=\"label\" className=\"shrink-0 tabular-nums text-foreground-neutral-muted\">\n {children}\n </Code>\n );\n}\n"],"names":["Accordion","AccordionContent","AccordionItem","AccordionTrigger","Badge","Dot","EmptyState","Icon","TimeTickerProvider","useTimeTick","Tooltip","TooltipContent","TooltipTrigger","Code","Text","cn","humanDuration","useEffect","useId","useMemo","useRef","useState","WorkflowStatusIcon","isWorkflowStatus","formatJobExecutionTimeLabel","buildStepListModel","defaultStepListJobExecution","humanizeStatus","StepList","job","jobExecution","selectedAttemptId","defaultSelectedAttemptId","onSelectedAttemptChange","autoSelectActiveAttempt","emptyState","renderExpandedStep","showHeader","className","selectedJobExecution","model","StepListContent","jobExecutionId","titleId","localSelectedAttemptIds","setLocalSelectedAttemptIds","userSelectedAttempt","setUserSelectedAttempt","lastNotifiedSelectedAttemptId","shouldUseControlledCollapsedState","current","autoSelectedAttemptIds","undefined","activeEntryId","selectedAttemptIds","length","hasExpandedContent","nextSelectedAttemptId","selectAttempt","nextAttemptIds","nextAttemptId","intervalMs","reducedMotionIntervalMs","section","aria-labelledby","div","as","id","size","bold","jobName","entries","StepListEmptyStateView","type","value","onValueChange","asChild","ol","map","entry","selected","includes","StepRow","onSelect","toggleAttemptId","expandedContent","step","stepId","stepLabel","label","sourceLocation","attempt","attemptId","attemptError","error","attemptStatus","statusVisual","kind","carriedOver","title","description","status","icon","variant","StepListEmptyStateIcon","tooltip","name","aria-hidden","shouldShowLabelTooltip","rowContent","StepStatusIcon","attempts","StepAttemptChip","CarriedOverBadge","StepAttemptDurationLabel","rowClasses","button","showIcon","aria-label","entryAccessibleLabel","aria-expanded","onClick","triggerNode","span","row","li","filter","openedAttemptId","find","at","ripple","role","dot","attemptChipClasses","neutral","info","feature","success","warning","badge","parts","category","push","join","duration","displayDuration","state","LiveDurationText","fromIso","DurationText","children"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WorkflowRunAttemptDisplayDuration } from '#core/workflow-run.js';
|
|
2
|
+
export declare function WorkflowRunDurationLabel({ duration, className, }: {
|
|
3
|
+
duration: WorkflowRunAttemptDisplayDuration | null;
|
|
4
|
+
className?: string | undefined;
|
|
5
|
+
}): import("react").JSX.Element | null;
|
|
6
|
+
export declare function useWorkflowRunDurationAccessibleLabel(duration: WorkflowRunAttemptDisplayDuration | null): string | undefined;
|
|
7
|
+
export declare function workflowRunDurationAccessibleLabel(duration: WorkflowRunAttemptDisplayDuration | null): string | undefined;
|
|
8
|
+
//# sourceMappingURL=workflow-run-duration-label.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-run-duration-label.d.ts","sourceRoot":"","sources":["../../src/components/workflow-run-duration-label.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAC,iCAAiC,EAAC,MAAM,uBAAuB,CAAC;AAE7E,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,iCAAiC,GAAG,IAAI,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,sCAmBA;AAED,wBAAgB,qCAAqC,CACnD,QAAQ,EAAE,iCAAiC,GAAG,IAAI,GACjD,MAAM,GAAG,SAAS,CAGpB;AAED,wBAAgB,kCAAkC,CAChD,QAAQ,EAAE,iCAAiC,GAAG,IAAI,GACjD,MAAM,GAAG,SAAS,CAapB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from '@shipfox/react-ui/icon';
|
|
3
|
+
import { useTimeTick } from '@shipfox/react-ui/time-ticker';
|
|
4
|
+
import { Code } from '@shipfox/react-ui/typography';
|
|
5
|
+
import { cn, humanDuration } from '@shipfox/react-ui/utils';
|
|
6
|
+
export function WorkflowRunDurationLabel({ duration, className }) {
|
|
7
|
+
if (duration === null) return null;
|
|
8
|
+
switch(duration.state){
|
|
9
|
+
case 'fixed':
|
|
10
|
+
{
|
|
11
|
+
const display = formatFixedDurationLabel(duration.elapsed);
|
|
12
|
+
return /*#__PURE__*/ _jsx(DurationText, {
|
|
13
|
+
className: className,
|
|
14
|
+
ariaLabel: `ran ${display}`,
|
|
15
|
+
children: display
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
case 'live':
|
|
19
|
+
return /*#__PURE__*/ _jsx(LiveDurationText, {
|
|
20
|
+
duration: duration,
|
|
21
|
+
className: className
|
|
22
|
+
});
|
|
23
|
+
default:
|
|
24
|
+
{
|
|
25
|
+
const exhaustive = duration;
|
|
26
|
+
return exhaustive;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function useWorkflowRunDurationAccessibleLabel(duration) {
|
|
31
|
+
useTimeTick();
|
|
32
|
+
return workflowRunDurationAccessibleLabel(duration);
|
|
33
|
+
}
|
|
34
|
+
export function workflowRunDurationAccessibleLabel(duration) {
|
|
35
|
+
if (duration === null) return undefined;
|
|
36
|
+
switch(duration.state){
|
|
37
|
+
case 'live':
|
|
38
|
+
return `running ${humanDuration(duration.fromIso)}`;
|
|
39
|
+
case 'fixed':
|
|
40
|
+
return `ran ${formatFixedDurationLabel(duration.elapsed)}`;
|
|
41
|
+
default:
|
|
42
|
+
{
|
|
43
|
+
const exhaustive = duration;
|
|
44
|
+
return exhaustive;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function LiveDurationText({ duration, className }) {
|
|
49
|
+
useTimeTick();
|
|
50
|
+
const display = humanDuration(duration.fromIso);
|
|
51
|
+
return /*#__PURE__*/ _jsx(DurationText, {
|
|
52
|
+
className: className,
|
|
53
|
+
ariaLabel: `running ${display}`,
|
|
54
|
+
children: display
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function DurationText({ children, className, ariaLabel }) {
|
|
58
|
+
return /*#__PURE__*/ _jsxs(Code, {
|
|
59
|
+
as: "span",
|
|
60
|
+
variant: "label",
|
|
61
|
+
"aria-label": ariaLabel,
|
|
62
|
+
className: cn('inline-flex shrink-0 items-center gap-4 tabular-nums text-foreground-neutral-muted', className),
|
|
63
|
+
children: [
|
|
64
|
+
/*#__PURE__*/ _jsx(Icon, {
|
|
65
|
+
name: "timerLine",
|
|
66
|
+
className: "size-12 shrink-0",
|
|
67
|
+
"aria-hidden": "true"
|
|
68
|
+
}),
|
|
69
|
+
children
|
|
70
|
+
]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function formatFixedDurationLabel({ years = 0, months = 0, weeks = 0, days = 0, hours = 0, minutes = 0, seconds = 0 }) {
|
|
74
|
+
const totalDays = years * 365 + months * 30 + weeks * 7 + days;
|
|
75
|
+
const totalHours = totalDays * 24 + hours;
|
|
76
|
+
if (totalHours > 0) return `${totalHours}h ${pad2(minutes)}m`;
|
|
77
|
+
if (minutes > 0) return `${minutes}m ${pad2(seconds)}s`;
|
|
78
|
+
return `${seconds}s`;
|
|
79
|
+
}
|
|
80
|
+
function pad2(value) {
|
|
81
|
+
return value.toString().padStart(2, '0');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//# sourceMappingURL=workflow-run-duration-label.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/workflow-run-duration-label.tsx"],"sourcesContent":["import {Icon} from '@shipfox/react-ui/icon';\nimport {useTimeTick} from '@shipfox/react-ui/time-ticker';\nimport {Code} from '@shipfox/react-ui/typography';\nimport {cn, humanDuration} from '@shipfox/react-ui/utils';\nimport type {WorkflowRunAttemptDisplayDuration} from '#core/workflow-run.js';\n\nexport function WorkflowRunDurationLabel({\n duration,\n className,\n}: {\n duration: WorkflowRunAttemptDisplayDuration | null;\n className?: string | undefined;\n}) {\n if (duration === null) return null;\n\n switch (duration.state) {\n case 'fixed': {\n const display = formatFixedDurationLabel(duration.elapsed);\n return (\n <DurationText className={className} ariaLabel={`ran ${display}`}>\n {display}\n </DurationText>\n );\n }\n case 'live':\n return <LiveDurationText duration={duration} className={className} />;\n default: {\n const exhaustive: never = duration;\n return exhaustive;\n }\n }\n}\n\nexport function useWorkflowRunDurationAccessibleLabel(\n duration: WorkflowRunAttemptDisplayDuration | null,\n): string | undefined {\n useTimeTick();\n return workflowRunDurationAccessibleLabel(duration);\n}\n\nexport function workflowRunDurationAccessibleLabel(\n duration: WorkflowRunAttemptDisplayDuration | null,\n): string | undefined {\n if (duration === null) return undefined;\n\n switch (duration.state) {\n case 'live':\n return `running ${humanDuration(duration.fromIso)}`;\n case 'fixed':\n return `ran ${formatFixedDurationLabel(duration.elapsed)}`;\n default: {\n const exhaustive: never = duration;\n return exhaustive;\n }\n }\n}\n\nfunction LiveDurationText({\n duration,\n className,\n}: {\n duration: Extract<WorkflowRunAttemptDisplayDuration, {state: 'live'}>;\n className?: string | undefined;\n}) {\n useTimeTick();\n const display = humanDuration(duration.fromIso);\n return (\n <DurationText className={className} ariaLabel={`running ${display}`}>\n {display}\n </DurationText>\n );\n}\n\nfunction DurationText({\n children,\n className,\n ariaLabel,\n}: {\n children: string;\n className?: string | undefined;\n ariaLabel?: string | undefined;\n}) {\n return (\n <Code\n as=\"span\"\n variant=\"label\"\n aria-label={ariaLabel}\n className={cn(\n 'inline-flex shrink-0 items-center gap-4 tabular-nums text-foreground-neutral-muted',\n className,\n )}\n >\n <Icon name=\"timerLine\" className=\"size-12 shrink-0\" aria-hidden=\"true\" />\n {children}\n </Code>\n );\n}\n\nfunction formatFixedDurationLabel({\n years = 0,\n months = 0,\n weeks = 0,\n days = 0,\n hours = 0,\n minutes = 0,\n seconds = 0,\n}: Extract<WorkflowRunAttemptDisplayDuration, {state: 'fixed'}>['elapsed']): string {\n const totalDays = years * 365 + months * 30 + weeks * 7 + days;\n const totalHours = totalDays * 24 + hours;\n\n if (totalHours > 0) return `${totalHours}h ${pad2(minutes)}m`;\n if (minutes > 0) return `${minutes}m ${pad2(seconds)}s`;\n return `${seconds}s`;\n}\n\nfunction pad2(value: number): string {\n return value.toString().padStart(2, '0');\n}\n"],"names":["Icon","useTimeTick","Code","cn","humanDuration","WorkflowRunDurationLabel","duration","className","state","display","formatFixedDurationLabel","elapsed","DurationText","ariaLabel","LiveDurationText","exhaustive","useWorkflowRunDurationAccessibleLabel","workflowRunDurationAccessibleLabel","undefined","fromIso","children","as","variant","aria-label","name","aria-hidden","years","months","weeks","days","hours","minutes","seconds","totalDays","totalHours","pad2","value","toString","padStart"],"mappings":";AAAA,SAAQA,IAAI,QAAO,yBAAyB;AAC5C,SAAQC,WAAW,QAAO,gCAAgC;AAC1D,SAAQC,IAAI,QAAO,+BAA+B;AAClD,SAAQC,EAAE,EAAEC,aAAa,QAAO,0BAA0B;AAG1D,OAAO,SAASC,yBAAyB,EACvCC,QAAQ,EACRC,SAAS,EAIV;IACC,IAAID,aAAa,MAAM,OAAO;IAE9B,OAAQA,SAASE,KAAK;QACpB,KAAK;YAAS;gBACZ,MAAMC,UAAUC,yBAAyBJ,SAASK,OAAO;gBACzD,qBACE,KAACC;oBAAaL,WAAWA;oBAAWM,WAAW,CAAC,IAAI,EAAEJ,SAAS;8BAC5DA;;YAGP;QACA,KAAK;YACH,qBAAO,KAACK;gBAAiBR,UAAUA;gBAAUC,WAAWA;;QAC1D;YAAS;gBACP,MAAMQ,aAAoBT;gBAC1B,OAAOS;YACT;IACF;AACF;AAEA,OAAO,SAASC,sCACdV,QAAkD;IAElDL;IACA,OAAOgB,mCAAmCX;AAC5C;AAEA,OAAO,SAASW,mCACdX,QAAkD;IAElD,IAAIA,aAAa,MAAM,OAAOY;IAE9B,OAAQZ,SAASE,KAAK;QACpB,KAAK;YACH,OAAO,CAAC,QAAQ,EAAEJ,cAAcE,SAASa,OAAO,GAAG;QACrD,KAAK;YACH,OAAO,CAAC,IAAI,EAAET,yBAAyBJ,SAASK,OAAO,GAAG;QAC5D;YAAS;gBACP,MAAMI,aAAoBT;gBAC1B,OAAOS;YACT;IACF;AACF;AAEA,SAASD,iBAAiB,EACxBR,QAAQ,EACRC,SAAS,EAIV;IACCN;IACA,MAAMQ,UAAUL,cAAcE,SAASa,OAAO;IAC9C,qBACE,KAACP;QAAaL,WAAWA;QAAWM,WAAW,CAAC,QAAQ,EAAEJ,SAAS;kBAChEA;;AAGP;AAEA,SAASG,aAAa,EACpBQ,QAAQ,EACRb,SAAS,EACTM,SAAS,EAKV;IACC,qBACE,MAACX;QACCmB,IAAG;QACHC,SAAQ;QACRC,cAAYV;QACZN,WAAWJ,GACT,sFACAI;;0BAGF,KAACP;gBAAKwB,MAAK;gBAAYjB,WAAU;gBAAmBkB,eAAY;;YAC/DL;;;AAGP;AAEA,SAASV,yBAAyB,EAChCgB,QAAQ,CAAC,EACTC,SAAS,CAAC,EACVC,QAAQ,CAAC,EACTC,OAAO,CAAC,EACRC,QAAQ,CAAC,EACTC,UAAU,CAAC,EACXC,UAAU,CAAC,EAC6D;IACxE,MAAMC,YAAYP,QAAQ,MAAMC,SAAS,KAAKC,QAAQ,IAAIC;IAC1D,MAAMK,aAAaD,YAAY,KAAKH;IAEpC,IAAII,aAAa,GAAG,OAAO,GAAGA,WAAW,EAAE,EAAEC,KAAKJ,SAAS,CAAC,CAAC;IAC7D,IAAIA,UAAU,GAAG,OAAO,GAAGA,QAAQ,EAAE,EAAEI,KAAKH,SAAS,CAAC,CAAC;IACvD,OAAO,GAAGA,QAAQ,CAAC,CAAC;AACtB;AAEA,SAASG,KAAKC,KAAa;IACzB,OAAOA,MAAMC,QAAQ,GAAGC,QAAQ,CAAC,GAAG;AACtC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/workflow-run-list/index.ts"],"sourcesContent":["export {WorkflowRunList} from './workflow-run-list.js';\n"],"names":["WorkflowRunList"],"mappings":"AAAA,SAAQA,eAAe,QAAO,yBAAyB"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { WorkflowRunListItem, WorkflowRunStatus } from '#core/workflow-run.js';
|
|
2
|
+
import type { WorkflowRunListStatusFilter } from './types.js';
|
|
3
|
+
export declare function runMatchesSearch(run: WorkflowRunListItem, query: string): boolean;
|
|
4
|
+
export declare function runMatchesStatusFilter(status: WorkflowRunStatus, filter: WorkflowRunListStatusFilter): boolean;
|
|
5
|
+
//# sourceMappingURL=run-display.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-display.d.ts","sourceRoot":"","sources":["../../../src/components/workflow-run-list/run-display.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,mBAAmB,EAAE,iBAAiB,EAAC,MAAM,uBAAuB,CAAC;AAClF,OAAO,KAAK,EAAC,2BAA2B,EAAC,MAAM,YAAY,CAAC;AAE5D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAKjF;AAID,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,iBAAiB,EACzB,MAAM,EAAE,2BAA2B,GAClC,OAAO,CAMT"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function runMatchesSearch(run, query) {
|
|
2
|
+
const needle = query.trim().toLowerCase();
|
|
3
|
+
if (needle === '') return true;
|
|
4
|
+
const haystack = `${run.id} ${run.name} ${run.status} ${run.triggerLabel}`.toLowerCase();
|
|
5
|
+
return haystack.includes(needle);
|
|
6
|
+
}
|
|
7
|
+
const IN_PROGRESS_STATUSES = new Set([
|
|
8
|
+
'pending',
|
|
9
|
+
'running'
|
|
10
|
+
]);
|
|
11
|
+
export function runMatchesStatusFilter(status, filter) {
|
|
12
|
+
if (filter === 'all') return true;
|
|
13
|
+
// "Running" reads as in-progress: it covers freshly-queued `pending` runs (including the
|
|
14
|
+
// optimistic manual run inserted on fire) so they are not hidden the moment the filter is on.
|
|
15
|
+
if (filter === 'running') return IN_PROGRESS_STATUSES.has(status);
|
|
16
|
+
return status === filter;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=run-display.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/workflow-run-list/run-display.ts"],"sourcesContent":["import type {WorkflowRunListItem, WorkflowRunStatus} from '#core/workflow-run.js';\nimport type {WorkflowRunListStatusFilter} from './types.js';\n\nexport function runMatchesSearch(run: WorkflowRunListItem, query: string): boolean {\n const needle = query.trim().toLowerCase();\n if (needle === '') return true;\n const haystack = `${run.id} ${run.name} ${run.status} ${run.triggerLabel}`.toLowerCase();\n return haystack.includes(needle);\n}\n\nconst IN_PROGRESS_STATUSES: ReadonlySet<WorkflowRunStatus> = new Set(['pending', 'running']);\n\nexport function runMatchesStatusFilter(\n status: WorkflowRunStatus,\n filter: WorkflowRunListStatusFilter,\n): boolean {\n if (filter === 'all') return true;\n // \"Running\" reads as in-progress: it covers freshly-queued `pending` runs (including the\n // optimistic manual run inserted on fire) so they are not hidden the moment the filter is on.\n if (filter === 'running') return IN_PROGRESS_STATUSES.has(status);\n return status === filter;\n}\n"],"names":["runMatchesSearch","run","query","needle","trim","toLowerCase","haystack","id","name","status","triggerLabel","includes","IN_PROGRESS_STATUSES","Set","runMatchesStatusFilter","filter","has"],"mappings":"AAGA,OAAO,SAASA,iBAAiBC,GAAwB,EAAEC,KAAa;IACtE,MAAMC,SAASD,MAAME,IAAI,GAAGC,WAAW;IACvC,IAAIF,WAAW,IAAI,OAAO;IAC1B,MAAMG,WAAW,GAAGL,IAAIM,EAAE,CAAC,CAAC,EAAEN,IAAIO,IAAI,CAAC,CAAC,EAAEP,IAAIQ,MAAM,CAAC,CAAC,EAAER,IAAIS,YAAY,EAAE,CAACL,WAAW;IACtF,OAAOC,SAASK,QAAQ,CAACR;AAC3B;AAEA,MAAMS,uBAAuD,IAAIC,IAAI;IAAC;IAAW;CAAU;AAE3F,OAAO,SAASC,uBACdL,MAAyB,EACzBM,MAAmC;IAEnC,IAAIA,WAAW,OAAO,OAAO;IAC7B,yFAAyF;IACzF,8FAA8F;IAC9F,IAAIA,WAAW,WAAW,OAAOH,qBAAqBI,GAAG,CAACP;IAC1D,OAAOA,WAAWM;AACpB"}
|