@contraagent/ui 0.0.0-stage → 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/README.md +137 -2
- package/custom-elements.json +7286 -0
- package/dist/adapters/check-rows.d.ts +20 -0
- package/dist/adapters/check-rows.d.ts.map +1 -0
- package/dist/adapters/check-rows.js +77 -0
- package/dist/adapters/check-rows.js.map +1 -0
- package/dist/adapters/filters.d.ts +29 -0
- package/dist/adapters/filters.d.ts.map +1 -0
- package/dist/adapters/filters.js +74 -0
- package/dist/adapters/filters.js.map +1 -0
- package/dist/adapters/graph/compound.d.ts +93 -0
- package/dist/adapters/graph/compound.d.ts.map +1 -0
- package/dist/adapters/graph/compound.js +322 -0
- package/dist/adapters/graph/compound.js.map +1 -0
- package/dist/adapters/graph/flow-index.d.ts +54 -0
- package/dist/adapters/graph/flow-index.d.ts.map +1 -0
- package/dist/adapters/graph/flow-index.js +129 -0
- package/dist/adapters/graph/flow-index.js.map +1 -0
- package/dist/adapters/graph/highlight.d.ts +14 -0
- package/dist/adapters/graph/highlight.d.ts.map +1 -0
- package/dist/adapters/graph/highlight.js +33 -0
- package/dist/adapters/graph/highlight.js.map +1 -0
- package/dist/adapters/graph/input.d.ts +50 -0
- package/dist/adapters/graph/input.d.ts.map +1 -0
- package/dist/adapters/graph/input.js +201 -0
- package/dist/adapters/graph/input.js.map +1 -0
- package/dist/adapters/graph/layer.d.ts +33 -0
- package/dist/adapters/graph/layer.d.ts.map +1 -0
- package/dist/adapters/graph/layer.js +94 -0
- package/dist/adapters/graph/layer.js.map +1 -0
- package/dist/adapters/graph/matrix.d.ts +62 -0
- package/dist/adapters/graph/matrix.d.ts.map +1 -0
- package/dist/adapters/graph/matrix.js +96 -0
- package/dist/adapters/graph/matrix.js.map +1 -0
- package/dist/adapters/graph/project.d.ts +49 -0
- package/dist/adapters/graph/project.d.ts.map +1 -0
- package/dist/adapters/graph/project.js +319 -0
- package/dist/adapters/graph/project.js.map +1 -0
- package/dist/adapters/graph/selection.d.ts +31 -0
- package/dist/adapters/graph/selection.d.ts.map +1 -0
- package/dist/adapters/graph/selection.js +48 -0
- package/dist/adapters/graph/selection.js.map +1 -0
- package/dist/adapters/graph/states.d.ts +6 -0
- package/dist/adapters/graph/states.d.ts.map +1 -0
- package/dist/adapters/graph/states.js +5 -0
- package/dist/adapters/graph/states.js.map +1 -0
- package/dist/adapters/graph/types.d.ts +141 -0
- package/dist/adapters/graph/types.d.ts.map +1 -0
- package/dist/adapters/graph/types.js +3 -0
- package/dist/adapters/graph/types.js.map +1 -0
- package/dist/adapters/graph/words.d.ts +48 -0
- package/dist/adapters/graph/words.d.ts.map +1 -0
- package/dist/adapters/graph/words.js +128 -0
- package/dist/adapters/graph/words.js.map +1 -0
- package/dist/adapters/index.d.ts +18 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +23 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/journal-columns.d.ts +21 -0
- package/dist/adapters/journal-columns.d.ts.map +1 -0
- package/dist/adapters/journal-columns.js +179 -0
- package/dist/adapters/journal-columns.js.map +1 -0
- package/dist/adapters/kpi-tiles.d.ts +47 -0
- package/dist/adapters/kpi-tiles.d.ts.map +1 -0
- package/dist/adapters/kpi-tiles.js +173 -0
- package/dist/adapters/kpi-tiles.js.map +1 -0
- package/dist/adapters/lanes.d.ts +31 -0
- package/dist/adapters/lanes.d.ts.map +1 -0
- package/dist/adapters/lanes.js +75 -0
- package/dist/adapters/lanes.js.map +1 -0
- package/dist/adapters/model-shares.d.ts +27 -0
- package/dist/adapters/model-shares.d.ts.map +1 -0
- package/dist/adapters/model-shares.js +52 -0
- package/dist/adapters/model-shares.js.map +1 -0
- package/dist/adapters/panel-body.d.ts +34 -0
- package/dist/adapters/panel-body.d.ts.map +1 -0
- package/dist/adapters/panel-body.js +90 -0
- package/dist/adapters/panel-body.js.map +1 -0
- package/dist/adapters/preflight.d.ts +12 -0
- package/dist/adapters/preflight.d.ts.map +1 -0
- package/dist/adapters/preflight.js +15 -0
- package/dist/adapters/preflight.js.map +1 -0
- package/dist/adapters/task-columns.d.ts +19 -0
- package/dist/adapters/task-columns.d.ts.map +1 -0
- package/dist/adapters/task-columns.js +107 -0
- package/dist/adapters/task-columns.js.map +1 -0
- package/dist/adapters/transcript/index.d.ts +6 -0
- package/dist/adapters/transcript/index.d.ts.map +1 -0
- package/dist/adapters/transcript/index.js +8 -0
- package/dist/adapters/transcript/index.js.map +1 -0
- package/dist/adapters/transcript/model.d.ts +42 -0
- package/dist/adapters/transcript/model.d.ts.map +1 -0
- package/dist/adapters/transcript/model.js +128 -0
- package/dist/adapters/transcript/model.js.map +1 -0
- package/dist/adapters/transcript/rounds.d.ts +15 -0
- package/dist/adapters/transcript/rounds.d.ts.map +1 -0
- package/dist/adapters/transcript/rounds.js +74 -0
- package/dist/adapters/transcript/rounds.js.map +1 -0
- package/dist/adapters/transcript/sections.d.ts +18 -0
- package/dist/adapters/transcript/sections.d.ts.map +1 -0
- package/dist/adapters/transcript/sections.js +69 -0
- package/dist/adapters/transcript/sections.js.map +1 -0
- package/dist/adapters/transcript/web.d.ts +12 -0
- package/dist/adapters/transcript/web.d.ts.map +1 -0
- package/dist/adapters/transcript/web.js +39 -0
- package/dist/adapters/transcript/web.js.map +1 -0
- package/dist/adapters/transcript/who.d.ts +15 -0
- package/dist/adapters/transcript/who.d.ts.map +1 -0
- package/dist/adapters/transcript/who.js +42 -0
- package/dist/adapters/transcript/who.js.map +1 -0
- package/dist/adapters/trends.d.ts +11 -0
- package/dist/adapters/trends.d.ts.map +1 -0
- package/dist/adapters/trends.js +316 -0
- package/dist/adapters/trends.js.map +1 -0
- package/dist/contraagent-ui.js +1028 -0
- package/dist/controllers/locale.d.ts +25 -0
- package/dist/controllers/locale.d.ts.map +1 -0
- package/dist/controllers/locale.js +33 -0
- package/dist/controllers/locale.js.map +1 -0
- package/dist/controllers/shortcuts.d.ts +29 -0
- package/dist/controllers/shortcuts.d.ts.map +1 -0
- package/dist/controllers/shortcuts.js +51 -0
- package/dist/controllers/shortcuts.js.map +1 -0
- package/dist/controllers/stream.d.ts +41 -0
- package/dist/controllers/stream.d.ts.map +1 -0
- package/dist/controllers/stream.js +90 -0
- package/dist/controllers/stream.js.map +1 -0
- package/dist/controllers/task-detail.d.ts +22 -0
- package/dist/controllers/task-detail.d.ts.map +1 -0
- package/dist/controllers/task-detail.js +50 -0
- package/dist/controllers/task-detail.js.map +1 -0
- package/dist/controllers/theme.d.ts +32 -0
- package/dist/controllers/theme.d.ts.map +1 -0
- package/dist/controllers/theme.js +56 -0
- package/dist/controllers/theme.js.map +1 -0
- package/dist/core/events.d.ts +107 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +5 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/i18n.d.ts +21 -0
- package/dist/core/i18n.d.ts.map +1 -0
- package/dist/core/i18n.js +71 -0
- package/dist/core/i18n.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +7 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/memory.d.ts +51 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +174 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/scroll.d.ts +21 -0
- package/dist/core/scroll.d.ts.map +1 -0
- package/dist/core/scroll.js +74 -0
- package/dist/core/scroll.js.map +1 -0
- package/dist/core/view-route.d.ts +62 -0
- package/dist/core/view-route.d.ts.map +1 -0
- package/dist/core/view-route.js +143 -0
- package/dist/core/view-route.js.map +1 -0
- package/dist/core/view-router.d.ts +27 -0
- package/dist/core/view-router.d.ts.map +1 -0
- package/dist/core/view-router.js +57 -0
- package/dist/core/view-router.js.map +1 -0
- package/dist/define/all.d.ts +13 -0
- package/dist/define/all.d.ts.map +1 -0
- package/dist/define/all.js +14 -0
- package/dist/define/all.js.map +1 -0
- package/dist/define/contracts.d.ts +2 -0
- package/dist/define/contracts.d.ts.map +1 -0
- package/dist/define/contracts.js +3 -0
- package/dist/define/contracts.js.map +1 -0
- package/dist/define/definitions.d.ts +3 -0
- package/dist/define/definitions.d.ts.map +1 -0
- package/dist/define/definitions.js +4 -0
- package/dist/define/definitions.js.map +1 -0
- package/dist/define/journal-table.d.ts +2 -0
- package/dist/define/journal-table.d.ts.map +1 -0
- package/dist/define/journal-table.js +3 -0
- package/dist/define/journal-table.js.map +1 -0
- package/dist/define/kpis.d.ts +2 -0
- package/dist/define/kpis.d.ts.map +1 -0
- package/dist/define/kpis.js +3 -0
- package/dist/define/kpis.js.map +1 -0
- package/dist/define/monitor.d.ts +2 -0
- package/dist/define/monitor.d.ts.map +1 -0
- package/dist/define/monitor.js +3 -0
- package/dist/define/monitor.js.map +1 -0
- package/dist/define/overview.d.ts +2 -0
- package/dist/define/overview.d.ts.map +1 -0
- package/dist/define/overview.js +3 -0
- package/dist/define/overview.js.map +1 -0
- package/dist/define/pipeline-graph.d.ts +2 -0
- package/dist/define/pipeline-graph.d.ts.map +1 -0
- package/dist/define/pipeline-graph.js +3 -0
- package/dist/define/pipeline-graph.js.map +1 -0
- package/dist/define/procs.d.ts +3 -0
- package/dist/define/procs.d.ts.map +1 -0
- package/dist/define/procs.js +4 -0
- package/dist/define/procs.js.map +1 -0
- package/dist/define/task-table.d.ts +2 -0
- package/dist/define/task-table.d.ts.map +1 -0
- package/dist/define/task-table.js +3 -0
- package/dist/define/task-table.js.map +1 -0
- package/dist/define/task-view.d.ts +2 -0
- package/dist/define/task-view.d.ts.map +1 -0
- package/dist/define/task-view.js +3 -0
- package/dist/define/task-view.js.map +1 -0
- package/dist/define/timeline.d.ts +2 -0
- package/dist/define/timeline.d.ts.map +1 -0
- package/dist/define/timeline.js +3 -0
- package/dist/define/timeline.js.map +1 -0
- package/dist/define/transcript.d.ts +2 -0
- package/dist/define/transcript.d.ts.map +1 -0
- package/dist/define/transcript.js +3 -0
- package/dist/define/transcript.js.map +1 -0
- package/dist/elements/lists/ca-contracts.d.ts +46 -0
- package/dist/elements/lists/ca-contracts.d.ts.map +1 -0
- package/dist/elements/lists/ca-contracts.js +199 -0
- package/dist/elements/lists/ca-contracts.js.map +1 -0
- package/dist/elements/lists/ca-definitions.d.ts +41 -0
- package/dist/elements/lists/ca-definitions.d.ts.map +1 -0
- package/dist/elements/lists/ca-definitions.js +182 -0
- package/dist/elements/lists/ca-definitions.js.map +1 -0
- package/dist/elements/lists/ca-journal-table.d.ts +37 -0
- package/dist/elements/lists/ca-journal-table.d.ts.map +1 -0
- package/dist/elements/lists/ca-journal-table.js +170 -0
- package/dist/elements/lists/ca-journal-table.js.map +1 -0
- package/dist/elements/lists/ca-panel-body.d.ts +42 -0
- package/dist/elements/lists/ca-panel-body.d.ts.map +1 -0
- package/dist/elements/lists/ca-panel-body.js +210 -0
- package/dist/elements/lists/ca-panel-body.js.map +1 -0
- package/dist/elements/lists/ca-panel-view.d.ts +21 -0
- package/dist/elements/lists/ca-panel-view.d.ts.map +1 -0
- package/dist/elements/lists/ca-panel-view.js +59 -0
- package/dist/elements/lists/ca-panel-view.js.map +1 -0
- package/dist/elements/lists/ca-proc-tree.d.ts +16 -0
- package/dist/elements/lists/ca-proc-tree.d.ts.map +1 -0
- package/dist/elements/lists/ca-proc-tree.js +63 -0
- package/dist/elements/lists/ca-proc-tree.js.map +1 -0
- package/dist/elements/lists/ca-procs-view.d.ts +27 -0
- package/dist/elements/lists/ca-procs-view.d.ts.map +1 -0
- package/dist/elements/lists/ca-procs-view.js +91 -0
- package/dist/elements/lists/ca-procs-view.js.map +1 -0
- package/dist/elements/lists/ca-task-table.d.ts +33 -0
- package/dist/elements/lists/ca-task-table.d.ts.map +1 -0
- package/dist/elements/lists/ca-task-table.js +115 -0
- package/dist/elements/lists/ca-task-table.js.map +1 -0
- package/dist/elements/lists/index.d.ts +9 -0
- package/dist/elements/lists/index.d.ts.map +1 -0
- package/dist/elements/lists/index.js +9 -0
- package/dist/elements/lists/index.js.map +1 -0
- package/dist/elements/overview/ca-kpis.d.ts +32 -0
- package/dist/elements/overview/ca-kpis.d.ts.map +1 -0
- package/dist/elements/overview/ca-kpis.js +62 -0
- package/dist/elements/overview/ca-kpis.js.map +1 -0
- package/dist/elements/overview/ca-model-usage.d.ts +25 -0
- package/dist/elements/overview/ca-model-usage.d.ts.map +1 -0
- package/dist/elements/overview/ca-model-usage.js +118 -0
- package/dist/elements/overview/ca-model-usage.js.map +1 -0
- package/dist/elements/overview/ca-overview.d.ts +67 -0
- package/dist/elements/overview/ca-overview.d.ts.map +1 -0
- package/dist/elements/overview/ca-overview.js +463 -0
- package/dist/elements/overview/ca-overview.js.map +1 -0
- package/dist/elements/overview/ca-pipeline-graph.d.ts +211 -0
- package/dist/elements/overview/ca-pipeline-graph.d.ts.map +1 -0
- package/dist/elements/overview/ca-pipeline-graph.js +616 -0
- package/dist/elements/overview/ca-pipeline-graph.js.map +1 -0
- package/dist/elements/overview/ca-quota.d.ts +42 -0
- package/dist/elements/overview/ca-quota.d.ts.map +1 -0
- package/dist/elements/overview/ca-quota.js +179 -0
- package/dist/elements/overview/ca-quota.js.map +1 -0
- package/dist/elements/overview/ca-run-driver.d.ts +33 -0
- package/dist/elements/overview/ca-run-driver.d.ts.map +1 -0
- package/dist/elements/overview/ca-run-driver.js +146 -0
- package/dist/elements/overview/ca-run-driver.js.map +1 -0
- package/dist/elements/overview/ca-services.d.ts +25 -0
- package/dist/elements/overview/ca-services.d.ts.map +1 -0
- package/dist/elements/overview/ca-services.js +77 -0
- package/dist/elements/overview/ca-services.js.map +1 -0
- package/dist/elements/overview/ca-spend-breakdown.d.ts +24 -0
- package/dist/elements/overview/ca-spend-breakdown.d.ts.map +1 -0
- package/dist/elements/overview/ca-spend-breakdown.js +108 -0
- package/dist/elements/overview/ca-spend-breakdown.js.map +1 -0
- package/dist/elements/overview/ca-timeline.d.ts +28 -0
- package/dist/elements/overview/ca-timeline.d.ts.map +1 -0
- package/dist/elements/overview/ca-timeline.js +72 -0
- package/dist/elements/overview/ca-timeline.js.map +1 -0
- package/dist/elements/overview/ca-workers.d.ts +23 -0
- package/dist/elements/overview/ca-workers.d.ts.map +1 -0
- package/dist/elements/overview/ca-workers.js +86 -0
- package/dist/elements/overview/ca-workers.js.map +1 -0
- package/dist/elements/overview/index.d.ts +11 -0
- package/dist/elements/overview/index.d.ts.map +1 -0
- package/dist/elements/overview/index.js +11 -0
- package/dist/elements/overview/index.js.map +1 -0
- package/dist/elements/overview/pipeline-graph/actions.d.ts +16 -0
- package/dist/elements/overview/pipeline-graph/actions.d.ts.map +1 -0
- package/dist/elements/overview/pipeline-graph/actions.js +42 -0
- package/dist/elements/overview/pipeline-graph/actions.js.map +1 -0
- package/dist/elements/overview/pipeline-graph/crumbs.d.ts +15 -0
- package/dist/elements/overview/pipeline-graph/crumbs.d.ts.map +1 -0
- package/dist/elements/overview/pipeline-graph/crumbs.js +70 -0
- package/dist/elements/overview/pipeline-graph/crumbs.js.map +1 -0
- package/dist/elements/overview/pipeline-graph/host.d.ts +24 -0
- package/dist/elements/overview/pipeline-graph/host.d.ts.map +1 -0
- package/dist/elements/overview/pipeline-graph/host.js +2 -0
- package/dist/elements/overview/pipeline-graph/host.js.map +1 -0
- package/dist/elements/overview/pipeline-graph/inspector.d.ts +5 -0
- package/dist/elements/overview/pipeline-graph/inspector.d.ts.map +1 -0
- package/dist/elements/overview/pipeline-graph/inspector.js +100 -0
- package/dist/elements/overview/pipeline-graph/inspector.js.map +1 -0
- package/dist/elements/overview/pipeline-graph/outline.d.ts +53 -0
- package/dist/elements/overview/pipeline-graph/outline.d.ts.map +1 -0
- package/dist/elements/overview/pipeline-graph/outline.js +111 -0
- package/dist/elements/overview/pipeline-graph/outline.js.map +1 -0
- package/dist/elements/overview/pipeline-graph/strings.d.ts +11 -0
- package/dist/elements/overview/pipeline-graph/strings.d.ts.map +1 -0
- package/dist/elements/overview/pipeline-graph/strings.js +49 -0
- package/dist/elements/overview/pipeline-graph/strings.js.map +1 -0
- package/dist/elements/overview/pipeline-graph/styles.d.ts +4 -0
- package/dist/elements/overview/pipeline-graph/styles.d.ts.map +1 -0
- package/dist/elements/overview/pipeline-graph/styles.js +96 -0
- package/dist/elements/overview/pipeline-graph/styles.js.map +1 -0
- package/dist/elements/shared/ca-definition.d.ts +26 -0
- package/dist/elements/shared/ca-definition.d.ts.map +1 -0
- package/dist/elements/shared/ca-definition.js +202 -0
- package/dist/elements/shared/ca-definition.js.map +1 -0
- package/dist/elements/shared/contract-parts.d.ts +35 -0
- package/dist/elements/shared/contract-parts.d.ts.map +1 -0
- package/dist/elements/shared/contract-parts.js +167 -0
- package/dist/elements/shared/contract-parts.js.map +1 -0
- package/dist/elements/shared/file-card.d.ts +17 -0
- package/dist/elements/shared/file-card.d.ts.map +1 -0
- package/dist/elements/shared/file-card.js +37 -0
- package/dist/elements/shared/file-card.js.map +1 -0
- package/dist/elements/shared/prompt-text.d.ts +5 -0
- package/dist/elements/shared/prompt-text.d.ts.map +1 -0
- package/dist/elements/shared/prompt-text.js +13 -0
- package/dist/elements/shared/prompt-text.js.map +1 -0
- package/dist/elements/shared/task-chip.d.ts +10 -0
- package/dist/elements/shared/task-chip.d.ts.map +1 -0
- package/dist/elements/shared/task-chip.js +19 -0
- package/dist/elements/shared/task-chip.js.map +1 -0
- package/dist/elements/shell/ca-clock.d.ts +13 -0
- package/dist/elements/shell/ca-clock.d.ts.map +1 -0
- package/dist/elements/shell/ca-clock.js +30 -0
- package/dist/elements/shell/ca-clock.js.map +1 -0
- package/dist/elements/shell/ca-hosts.d.ts +21 -0
- package/dist/elements/shell/ca-hosts.d.ts.map +1 -0
- package/dist/elements/shell/ca-hosts.js +97 -0
- package/dist/elements/shell/ca-hosts.js.map +1 -0
- package/dist/elements/shell/ca-monitor.d.ts +182 -0
- package/dist/elements/shell/ca-monitor.d.ts.map +1 -0
- package/dist/elements/shell/ca-monitor.js +549 -0
- package/dist/elements/shell/ca-monitor.js.map +1 -0
- package/dist/elements/shell/ca-run-picker.d.ts +71 -0
- package/dist/elements/shell/ca-run-picker.d.ts.map +1 -0
- package/dist/elements/shell/ca-run-picker.js +313 -0
- package/dist/elements/shell/ca-run-picker.js.map +1 -0
- package/dist/elements/shell/ca-theme-switch.d.ts +36 -0
- package/dist/elements/shell/ca-theme-switch.d.ts.map +1 -0
- package/dist/elements/shell/ca-theme-switch.js +186 -0
- package/dist/elements/shell/ca-theme-switch.js.map +1 -0
- package/dist/elements/shell/ca-toasts.d.ts +23 -0
- package/dist/elements/shell/ca-toasts.d.ts.map +1 -0
- package/dist/elements/shell/ca-toasts.js +88 -0
- package/dist/elements/shell/ca-toasts.js.map +1 -0
- package/dist/elements/shell/header.d.ts +13 -0
- package/dist/elements/shell/header.d.ts.map +1 -0
- package/dist/elements/shell/header.js +38 -0
- package/dist/elements/shell/header.js.map +1 -0
- package/dist/elements/shell/styles.d.ts +2 -0
- package/dist/elements/shell/styles.d.ts.map +1 -0
- package/dist/elements/shell/styles.js +72 -0
- package/dist/elements/shell/styles.js.map +1 -0
- package/dist/elements/shell/tabs.d.ts +32 -0
- package/dist/elements/shell/tabs.d.ts.map +1 -0
- package/dist/elements/shell/tabs.js +125 -0
- package/dist/elements/shell/tabs.js.map +1 -0
- package/dist/elements/shell/views.d.ts +27 -0
- package/dist/elements/shell/views.d.ts.map +1 -0
- package/dist/elements/shell/views.js +55 -0
- package/dist/elements/shell/views.js.map +1 -0
- package/dist/elements/task/ca-task-view.d.ts +55 -0
- package/dist/elements/task/ca-task-view.d.ts.map +1 -0
- package/dist/elements/task/ca-task-view.js +199 -0
- package/dist/elements/task/ca-task-view.js.map +1 -0
- package/dist/elements/task/ca-transcript.d.ts +74 -0
- package/dist/elements/task/ca-transcript.d.ts.map +1 -0
- package/dist/elements/task/ca-transcript.js +241 -0
- package/dist/elements/task/ca-transcript.js.map +1 -0
- package/dist/elements/task/context.d.ts +57 -0
- package/dist/elements/task/context.d.ts.map +1 -0
- package/dist/elements/task/context.js +61 -0
- package/dist/elements/task/context.js.map +1 -0
- package/dist/elements/task/header.d.ts +9 -0
- package/dist/elements/task/header.d.ts.map +1 -0
- package/dist/elements/task/header.js +291 -0
- package/dist/elements/task/header.js.map +1 -0
- package/dist/elements/task/index.d.ts +3 -0
- package/dist/elements/task/index.d.ts.map +1 -0
- package/dist/elements/task/index.js +3 -0
- package/dist/elements/task/index.js.map +1 -0
- package/dist/elements/task/inputs.d.ts +28 -0
- package/dist/elements/task/inputs.d.ts.map +1 -0
- package/dist/elements/task/inputs.js +27 -0
- package/dist/elements/task/inputs.js.map +1 -0
- package/dist/elements/task/panes/definition.d.ts +5 -0
- package/dist/elements/task/panes/definition.d.ts.map +1 -0
- package/dist/elements/task/panes/definition.js +5 -0
- package/dist/elements/task/panes/definition.js.map +1 -0
- package/dist/elements/task/panes/io.d.ts +8 -0
- package/dist/elements/task/panes/io.d.ts.map +1 -0
- package/dist/elements/task/panes/io.js +184 -0
- package/dist/elements/task/panes/io.js.map +1 -0
- package/dist/elements/task/panes/transcript.d.ts +5 -0
- package/dist/elements/task/panes/transcript.d.ts.map +1 -0
- package/dist/elements/task/panes/transcript.js +29 -0
- package/dist/elements/task/panes/transcript.js.map +1 -0
- package/dist/elements/task/styles.d.ts +2 -0
- package/dist/elements/task/styles.d.ts.map +1 -0
- package/dist/elements/task/styles.js +66 -0
- package/dist/elements/task/styles.js.map +1 -0
- package/dist/elements/trends/ca-trends.d.ts +55 -0
- package/dist/elements/trends/ca-trends.d.ts.map +1 -0
- package/dist/elements/trends/ca-trends.js +213 -0
- package/dist/elements/trends/ca-trends.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/tone.d.ts +29 -0
- package/dist/lib/tone.d.ts.map +1 -0
- package/dist/lib/tone.js +97 -0
- package/dist/lib/tone.js.map +1 -0
- package/dist/lib/trends.d.ts +15 -0
- package/dist/lib/trends.d.ts.map +1 -0
- package/dist/lib/trends.js +36 -0
- package/dist/lib/trends.js.map +1 -0
- package/dist/locales/codes.d.ts +14 -0
- package/dist/locales/codes.d.ts.map +1 -0
- package/dist/locales/codes.js +21 -0
- package/dist/locales/codes.js.map +1 -0
- package/dist/locales/ja.d.ts +785 -0
- package/dist/locales/ja.d.ts.map +1 -0
- package/dist/locales/ja.js +791 -0
- package/dist/locales/ja.js.map +1 -0
- package/dist/words/api-error.d.ts +4 -0
- package/dist/words/api-error.d.ts.map +1 -0
- package/dist/words/api-error.js +13 -0
- package/dist/words/api-error.js.map +1 -0
- package/dist/words/attempts.d.ts +17 -0
- package/dist/words/attempts.d.ts.map +1 -0
- package/dist/words/attempts.js +26 -0
- package/dist/words/attempts.js.map +1 -0
- package/dist/words/causes.d.ts +33 -0
- package/dist/words/causes.d.ts.map +1 -0
- package/dist/words/causes.js +58 -0
- package/dist/words/causes.js.map +1 -0
- package/dist/words/changes.d.ts +9 -0
- package/dist/words/changes.d.ts.map +1 -0
- package/dist/words/changes.js +23 -0
- package/dist/words/changes.js.map +1 -0
- package/dist/words/claims.d.ts +9 -0
- package/dist/words/claims.d.ts.map +1 -0
- package/dist/words/claims.js +12 -0
- package/dist/words/claims.js.map +1 -0
- package/dist/words/context.d.ts +18 -0
- package/dist/words/context.d.ts.map +1 -0
- package/dist/words/context.js +39 -0
- package/dist/words/context.js.map +1 -0
- package/dist/words/contract.d.ts +25 -0
- package/dist/words/contract.d.ts.map +1 -0
- package/dist/words/contract.js +52 -0
- package/dist/words/contract.js.map +1 -0
- package/dist/words/credential.d.ts +5 -0
- package/dist/words/credential.d.ts.map +1 -0
- package/dist/words/credential.js +7 -0
- package/dist/words/credential.js.map +1 -0
- package/dist/words/executor.d.ts +12 -0
- package/dist/words/executor.d.ts.map +1 -0
- package/dist/words/executor.js +20 -0
- package/dist/words/executor.js.map +1 -0
- package/dist/words/export.d.ts +8 -0
- package/dist/words/export.d.ts.map +1 -0
- package/dist/words/export.js +17 -0
- package/dist/words/export.js.map +1 -0
- package/dist/words/format.d.ts +36 -0
- package/dist/words/format.d.ts.map +1 -0
- package/dist/words/format.js +109 -0
- package/dist/words/format.js.map +1 -0
- package/dist/words/hops.d.ts +12 -0
- package/dist/words/hops.d.ts.map +1 -0
- package/dist/words/hops.js +27 -0
- package/dist/words/hops.js.map +1 -0
- package/dist/words/hosts.d.ts +18 -0
- package/dist/words/hosts.d.ts.map +1 -0
- package/dist/words/hosts.js +22 -0
- package/dist/words/hosts.js.map +1 -0
- package/dist/words/index.d.ts +28 -0
- package/dist/words/index.d.ts.map +1 -0
- package/dist/words/index.js +32 -0
- package/dist/words/index.js.map +1 -0
- package/dist/words/models.d.ts +10 -0
- package/dist/words/models.d.ts.map +1 -0
- package/dist/words/models.js +45 -0
- package/dist/words/models.js.map +1 -0
- package/dist/words/outcome.d.ts +14 -0
- package/dist/words/outcome.d.ts.map +1 -0
- package/dist/words/outcome.js +58 -0
- package/dist/words/outcome.js.map +1 -0
- package/dist/words/panels.d.ts +17 -0
- package/dist/words/panels.d.ts.map +1 -0
- package/dist/words/panels.js +63 -0
- package/dist/words/panels.js.map +1 -0
- package/dist/words/passes.d.ts +11 -0
- package/dist/words/passes.d.ts.map +1 -0
- package/dist/words/passes.js +13 -0
- package/dist/words/passes.js.map +1 -0
- package/dist/words/preflight.d.ts +28 -0
- package/dist/words/preflight.d.ts.map +1 -0
- package/dist/words/preflight.js +30 -0
- package/dist/words/preflight.js.map +1 -0
- package/dist/words/priority.d.ts +5 -0
- package/dist/words/priority.d.ts.map +1 -0
- package/dist/words/priority.js +7 -0
- package/dist/words/priority.js.map +1 -0
- package/dist/words/prompt.d.ts +10 -0
- package/dist/words/prompt.d.ts.map +1 -0
- package/dist/words/prompt.js +17 -0
- package/dist/words/prompt.js.map +1 -0
- package/dist/words/quota.d.ts +35 -0
- package/dist/words/quota.d.ts.map +1 -0
- package/dist/words/quota.js +102 -0
- package/dist/words/quota.js.map +1 -0
- package/dist/words/rests.d.ts +26 -0
- package/dist/words/rests.d.ts.map +1 -0
- package/dist/words/rests.js +77 -0
- package/dist/words/rests.js.map +1 -0
- package/dist/words/rounds.d.ts +14 -0
- package/dist/words/rounds.d.ts.map +1 -0
- package/dist/words/rounds.js +60 -0
- package/dist/words/rounds.js.map +1 -0
- package/dist/words/row-extras.d.ts +7 -0
- package/dist/words/row-extras.d.ts.map +1 -0
- package/dist/words/row-extras.js +26 -0
- package/dist/words/row-extras.js.map +1 -0
- package/dist/words/run-line.d.ts +40 -0
- package/dist/words/run-line.d.ts.map +1 -0
- package/dist/words/run-line.js +66 -0
- package/dist/words/run-line.js.map +1 -0
- package/dist/words/services.d.ts +16 -0
- package/dist/words/services.d.ts.map +1 -0
- package/dist/words/services.js +45 -0
- package/dist/words/services.js.map +1 -0
- package/dist/words/stop.d.ts +6 -0
- package/dist/words/stop.d.ts.map +1 -0
- package/dist/words/stop.js +69 -0
- package/dist/words/stop.js.map +1 -0
- package/dist/words/table.d.ts +4 -0
- package/dist/words/table.d.ts.map +1 -0
- package/dist/words/table.js +8 -0
- package/dist/words/table.js.map +1 -0
- package/dist/words/task-definition.d.ts +23 -0
- package/dist/words/task-definition.d.ts.map +1 -0
- package/dist/words/task-definition.js +27 -0
- package/dist/words/task-definition.js.map +1 -0
- package/dist/words/time-box.d.ts +8 -0
- package/dist/words/time-box.d.ts.map +1 -0
- package/dist/words/time-box.js +12 -0
- package/dist/words/time-box.js.map +1 -0
- package/dist/words/trends.d.ts +86 -0
- package/dist/words/trends.d.ts.map +1 -0
- package/dist/words/trends.js +104 -0
- package/dist/words/trends.js.map +1 -0
- package/docs/embed.md +121 -0
- package/docs/events.md +38 -0
- package/docs/examples/embed.html +31 -0
- package/docs/examples/journal.ts +32 -0
- package/docs/examples/live-transcript.ts +22 -0
- package/docs/examples/vite/index.html +30 -0
- package/docs/examples/vite/main.ts +23 -0
- package/docs/languages.md +48 -0
- package/docs/live-data.md +17 -0
- package/docs/theming.md +21 -0
- package/docs/tsconfig.json +14 -0
- package/package.json +131 -4
- package/src/adapters/check-rows.ts +81 -0
- package/src/adapters/filters.ts +76 -0
- package/src/adapters/graph/compound.ts +359 -0
- package/src/adapters/graph/flow-index.ts +154 -0
- package/src/adapters/graph/highlight.ts +40 -0
- package/src/adapters/graph/input.ts +236 -0
- package/src/adapters/graph/layer.ts +92 -0
- package/src/adapters/graph/matrix.ts +133 -0
- package/src/adapters/graph/plans.fixture.ts +194 -0
- package/src/adapters/graph/project.ts +358 -0
- package/src/adapters/graph/selection.ts +54 -0
- package/src/adapters/graph/states.ts +10 -0
- package/src/adapters/graph/types.ts +148 -0
- package/src/adapters/graph/words.ts +146 -0
- package/src/adapters/index.ts +22 -0
- package/src/adapters/journal-columns.ts +200 -0
- package/src/adapters/kpi-tiles.ts +211 -0
- package/src/adapters/lanes.ts +98 -0
- package/src/adapters/model-shares.ts +62 -0
- package/src/adapters/panel-body.ts +112 -0
- package/src/adapters/preflight.ts +27 -0
- package/src/adapters/task-columns.ts +120 -0
- package/src/adapters/transcript/index.ts +14 -0
- package/src/adapters/transcript/model.ts +156 -0
- package/src/adapters/transcript/rounds.ts +86 -0
- package/src/adapters/transcript/sections.ts +82 -0
- package/src/adapters/transcript/web.ts +40 -0
- package/src/adapters/transcript/who.ts +53 -0
- package/src/adapters/trends.ts +337 -0
- package/src/controllers/locale.ts +47 -0
- package/src/controllers/shortcuts.ts +69 -0
- package/src/controllers/stream.ts +103 -0
- package/src/controllers/task-detail.ts +54 -0
- package/src/controllers/theme.ts +73 -0
- package/src/core/events.ts +120 -0
- package/src/core/i18n.ts +76 -0
- package/src/core/index.ts +6 -0
- package/src/core/memory.ts +177 -0
- package/src/core/scroll.ts +73 -0
- package/src/core/view-route.ts +177 -0
- package/src/core/view-router.ts +66 -0
- package/src/define/all.ts +13 -0
- package/src/define/contracts.ts +2 -0
- package/src/define/definitions.ts +3 -0
- package/src/define/journal-table.ts +2 -0
- package/src/define/kpis.ts +2 -0
- package/src/define/monitor.ts +2 -0
- package/src/define/overview.ts +2 -0
- package/src/define/pipeline-graph.ts +2 -0
- package/src/define/procs.ts +3 -0
- package/src/define/task-table.ts +2 -0
- package/src/define/task-view.ts +2 -0
- package/src/define/timeline.ts +2 -0
- package/src/define/transcript.ts +2 -0
- package/src/elements/lists/ca-contracts.ts +204 -0
- package/src/elements/lists/ca-definitions.ts +170 -0
- package/src/elements/lists/ca-journal-table.ts +141 -0
- package/src/elements/lists/ca-panel-body.ts +200 -0
- package/src/elements/lists/ca-panel-view.ts +50 -0
- package/src/elements/lists/ca-proc-tree.ts +57 -0
- package/src/elements/lists/ca-procs-view.ts +89 -0
- package/src/elements/lists/ca-task-table.ts +94 -0
- package/src/elements/lists/index.ts +8 -0
- package/src/elements/overview/ca-kpis.ts +51 -0
- package/src/elements/overview/ca-model-usage.ts +113 -0
- package/src/elements/overview/ca-overview.ts +499 -0
- package/src/elements/overview/ca-pipeline-graph.ts +617 -0
- package/src/elements/overview/ca-quota.ts +164 -0
- package/src/elements/overview/ca-run-driver.ts +140 -0
- package/src/elements/overview/ca-services.ts +66 -0
- package/src/elements/overview/ca-spend-breakdown.ts +107 -0
- package/src/elements/overview/ca-timeline.ts +57 -0
- package/src/elements/overview/ca-workers.ts +82 -0
- package/src/elements/overview/index.ts +10 -0
- package/src/elements/overview/pipeline-graph/actions.ts +45 -0
- package/src/elements/overview/pipeline-graph/crumbs.ts +75 -0
- package/src/elements/overview/pipeline-graph/host.ts +26 -0
- package/src/elements/overview/pipeline-graph/inspector.ts +104 -0
- package/src/elements/overview/pipeline-graph/outline.ts +150 -0
- package/src/elements/overview/pipeline-graph/strings.ts +53 -0
- package/src/elements/overview/pipeline-graph/styles.ts +97 -0
- package/src/elements/shared/ca-definition.ts +206 -0
- package/src/elements/shared/contract-parts.ts +174 -0
- package/src/elements/shared/file-card.ts +49 -0
- package/src/elements/shared/prompt-text.ts +13 -0
- package/src/elements/shared/task-chip.ts +18 -0
- package/src/elements/shell/ca-clock.ts +27 -0
- package/src/elements/shell/ca-hosts.ts +93 -0
- package/src/elements/shell/ca-monitor.ts +528 -0
- package/src/elements/shell/ca-run-picker.ts +284 -0
- package/src/elements/shell/ca-theme-switch.ts +170 -0
- package/src/elements/shell/ca-toasts.ts +100 -0
- package/src/elements/shell/header.ts +45 -0
- package/src/elements/shell/styles.ts +72 -0
- package/src/elements/shell/tabs.ts +143 -0
- package/src/elements/shell/views.ts +67 -0
- package/src/elements/task/ca-task-view.ts +157 -0
- package/src/elements/task/ca-transcript.ts +214 -0
- package/src/elements/task/context.ts +105 -0
- package/src/elements/task/header.ts +296 -0
- package/src/elements/task/index.ts +2 -0
- package/src/elements/task/inputs.ts +46 -0
- package/src/elements/task/panes/definition.ts +7 -0
- package/src/elements/task/panes/io.ts +190 -0
- package/src/elements/task/panes/transcript.ts +29 -0
- package/src/elements/task/styles.ts +66 -0
- package/src/elements/trends/ca-trends.ts +204 -0
- package/src/index.ts +23 -0
- package/src/lib/tone.ts +109 -0
- package/src/lib/trends.ts +44 -0
- package/src/locales/codes.ts +23 -0
- package/src/locales/ja.ts +795 -0
- package/src/words/api-error.ts +17 -0
- package/src/words/attempts.ts +28 -0
- package/src/words/causes.ts +67 -0
- package/src/words/changes.ts +29 -0
- package/src/words/claims.ts +16 -0
- package/src/words/context.ts +47 -0
- package/src/words/contract.ts +63 -0
- package/src/words/credential.ts +8 -0
- package/src/words/executor.ts +22 -0
- package/src/words/export.ts +22 -0
- package/src/words/format.ts +107 -0
- package/src/words/hops.ts +30 -0
- package/src/words/hosts.ts +37 -0
- package/src/words/index.ts +31 -0
- package/src/words/models.ts +50 -0
- package/src/words/outcome.ts +61 -0
- package/src/words/panels.ts +71 -0
- package/src/words/passes.ts +18 -0
- package/src/words/preflight.ts +53 -0
- package/src/words/priority.ts +8 -0
- package/src/words/prompt.ts +20 -0
- package/src/words/quota.ts +108 -0
- package/src/words/rests.ts +96 -0
- package/src/words/rounds.ts +56 -0
- package/src/words/row-extras.ts +24 -0
- package/src/words/run-line.ts +77 -0
- package/src/words/services.ts +57 -0
- package/src/words/stop.ts +65 -0
- package/src/words/table.ts +10 -0
- package/src/words/task-definition.ts +37 -0
- package/src/words/time-box.ts +21 -0
- package/src/words/trends.ts +118 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { elapsedS, hostGroups, hostOf, runActivity, runIdOf, type HostSummary, type RunSummary } from '@contraagent/api';
|
|
2
|
+
import { localized, msg, str } from '@lit/localize';
|
|
3
|
+
import { LitElement, css, html, nothing } from 'lit';
|
|
4
|
+
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
5
|
+
import { emit } from '../../core/events.js';
|
|
6
|
+
import type { Page } from '../../core/view-route.js';
|
|
7
|
+
import { trendsTitle, trendsTip } from '../../words/trends.js';
|
|
8
|
+
import { facts, fmtDur, localTime, relAgo, usd } from '../../words/format.js';
|
|
9
|
+
import { runMark, stateCount } from '../../words/index.js';
|
|
10
|
+
import { accountsLine, accountsTip } from '../../words/quota.js';
|
|
11
|
+
import { hostFact, noReportLabel, hostStateSince, hostsLine, lastReport, runCount } from '../../words/hosts.js';
|
|
12
|
+
import { runTone } from '../../lib/tone.js';
|
|
13
|
+
import { toneAttr } from '@contraagent/elements';
|
|
14
|
+
import { pill, statusWord } from '@contraagent/elements/primitives';
|
|
15
|
+
import { base } from '@contraagent/elements/styles';
|
|
16
|
+
|
|
17
|
+
const took = (r: RunSummary) => elapsedS(r);
|
|
18
|
+
|
|
19
|
+
/** The id of the option at `i` in the visible list. */
|
|
20
|
+
const optionId = (i: number) => `run-${i}`;
|
|
21
|
+
|
|
22
|
+
const ago = (r: RunSummary) => {
|
|
23
|
+
const t = Date.parse(r.last_ts || '');
|
|
24
|
+
return Number.isNaN(t) ? Infinity : (Date.now() - t) / 1000;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The run switcher: runs grouped by recency, searchable, keyboard driven. A
|
|
29
|
+
* dialog: its search field (a combobox) holds the focus while it is open (Tab
|
|
30
|
+
* stays in it), and the arrow keys move through the list
|
|
31
|
+
* (`aria-activedescendant`). Sends `ca-select-run` for a pick and `ca-close`
|
|
32
|
+
* when it should be closed (Escape, or a pick); the host returns the focus.
|
|
33
|
+
*
|
|
34
|
+
* While nothing is searched, the first options are the pages of no run: the
|
|
35
|
+
* trends, and on a hub the hosts. On a hub (`hub`), the runs are grouped by host,
|
|
36
|
+
* each group headed by its host's state; a host filter (a select, the dialog's
|
|
37
|
+
* second Tab stop) shows one host's runs.
|
|
38
|
+
*
|
|
39
|
+
* @fires ca-select-run - `{run}`: a run was picked
|
|
40
|
+
* @fires ca-navigate - `{page, run: ''}`: a page of no run was picked (`trends`, or on a hub `hosts`)
|
|
41
|
+
* @fires ca-close - the picker should close
|
|
42
|
+
*/
|
|
43
|
+
@customElement('ca-run-picker')
|
|
44
|
+
@localized()
|
|
45
|
+
export class CaRunPicker extends LitElement {
|
|
46
|
+
static override styles = [
|
|
47
|
+
base,
|
|
48
|
+
css`
|
|
49
|
+
:host { position: absolute; top: 50px; width: min(580px, calc(100cqi - 24px)); max-height: min(72vh, 660px);
|
|
50
|
+
display: flex; flex-direction: column; background: var(--panel); border: 1px solid var(--line2); border-radius: 14px;
|
|
51
|
+
box-shadow: 0 24px 70px color-mix(in srgb, var(--shadow) 70%, transparent); opacity: 0; transform: translateY(-6px) scale(0.985);
|
|
52
|
+
pointer-events: none; z-index: 40; visibility: hidden; container-type: inline-size;
|
|
53
|
+
transition: opacity 0.16s var(--ease), transform 0.16s var(--ease), visibility 0s linear 0.16s; }
|
|
54
|
+
/* Visible (and focusable) at once when it opens; hidden only after it has faded out. */
|
|
55
|
+
:host([open]) { opacity: 1; transform: none; pointer-events: auto; visibility: visible; transition-delay: 0s; }
|
|
56
|
+
.search { padding: 10px; border-bottom: 1px solid var(--line); }
|
|
57
|
+
input, select { background: var(--well); border: 1px solid var(--line); color: var(--text); border-radius: 9px; font: inherit; outline: none; }
|
|
58
|
+
input { width: 100%; padding: 8px 11px; }
|
|
59
|
+
input:focus, select:focus { border-color: var(--accent); }
|
|
60
|
+
.list { overflow: auto; padding: 6px; }
|
|
61
|
+
.group { font-size: 11.5px; font-weight: 600; color: var(--text-muted); padding: 10px 9px 4px; }
|
|
62
|
+
.group .n { font-weight: 400; margin-left: 4px; }
|
|
63
|
+
.keys { margin-top: 6px; display: flex; gap: 4px; align-items: center; }
|
|
64
|
+
.item { display: grid; grid-template-columns: 12px minmax(0, 1fr) auto; gap: 3px 10px; align-items: center;
|
|
65
|
+
padding: 7px 9px; border-radius: 9px; cursor: pointer; }
|
|
66
|
+
.item:hover, .item.kb { background: var(--raise); }
|
|
67
|
+
.item.cur { box-shadow: inset 2px 0 0 var(--accent); background: var(--accent-bg); }
|
|
68
|
+
.nm { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
69
|
+
.when { font-size: 11px; color: var(--text-muted); white-space: nowrap; }
|
|
70
|
+
/* A narrow picker (the host is a container): what a page shows goes under its name. */
|
|
71
|
+
@container (max-width: 480px) {
|
|
72
|
+
.when.page { grid-column: 2 / 4; white-space: normal; }
|
|
73
|
+
}
|
|
74
|
+
.sub { grid-column: 2 / 4; display: flex; gap: 7px; flex-wrap: wrap; font-size: 11px; color: var(--text-muted); }
|
|
75
|
+
/* a hub: the host filter beside the search field, a header per host, the hosts page as the first option */
|
|
76
|
+
.row { display: flex; gap: 8px; }
|
|
77
|
+
select { max-width: 40%; padding: 0 8px; }
|
|
78
|
+
.host { display: flex; gap: 8px; flex-wrap: wrap; color: var(--text-2); border-top: 1px solid var(--line); margin-top: 6px; }
|
|
79
|
+
.host b { font-family: var(--mono); color: var(--text); }
|
|
80
|
+
.host .n { margin-left: auto; }
|
|
81
|
+
.when[data-tone] { color: var(--tone); font-weight: 600; }
|
|
82
|
+
`,
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
@property({ attribute: false }) runs: RunSummary[] = [];
|
|
86
|
+
/** The run shown now. */
|
|
87
|
+
@property() current = '';
|
|
88
|
+
@property({ type: Boolean, reflect: true }) open = false;
|
|
89
|
+
/** The runs come from many hosts (`Info.hosts`): group them by host, with a host filter and the hosts page. */
|
|
90
|
+
@property({ type: Boolean }) hub = false;
|
|
91
|
+
/** The host list (a hub). */
|
|
92
|
+
@property({ attribute: false }) hosts: HostSummary[] = [];
|
|
93
|
+
/** The page of no run shown now (`trends`, `hosts`; it is the current option); '' while a run is shown. */
|
|
94
|
+
@property() page: Page = '';
|
|
95
|
+
@state() private q = '';
|
|
96
|
+
/** A hub: only this host's runs; '' for every host. */
|
|
97
|
+
@state() private host = '';
|
|
98
|
+
/** The keyboard's place in the visible list; -1 for none. */
|
|
99
|
+
@state() private kb = -1;
|
|
100
|
+
@query('input') private input!: HTMLInputElement;
|
|
101
|
+
@query('select') private select!: HTMLSelectElement | null;
|
|
102
|
+
|
|
103
|
+
override connectedCallback(): void {
|
|
104
|
+
super.connectedCallback();
|
|
105
|
+
this.setAttribute('role', 'dialog');
|
|
106
|
+
this.setAttribute('aria-modal', 'true');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
protected override willUpdate(): void {
|
|
110
|
+
this.setAttribute('aria-label', msg('Runs'));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
protected override updated(changed: Map<string, unknown>): void {
|
|
114
|
+
if (changed.has('open') && this.open) {
|
|
115
|
+
this.q = '';
|
|
116
|
+
this.kb = -1;
|
|
117
|
+
setTimeout(() => this.input?.focus(), 30);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The runs the search and the host filter leave, in groups, in list order:
|
|
123
|
+
* by host on a hub, each headed by its host's id, its state (attention once
|
|
124
|
+
* its reports stopped) and how many of its runs are listed; else by recency.
|
|
125
|
+
* Each group: its accessible name, its header, its runs.
|
|
126
|
+
*/
|
|
127
|
+
private groups(): [string, unknown, RunSummary[]][] {
|
|
128
|
+
const q = this.q.toLowerCase().trim();
|
|
129
|
+
const rows = this.runs.filter(
|
|
130
|
+
(r) => (!q || r.run.toLowerCase().includes(q) || (r.run_group || '').toLowerCase().includes(q)) && (!this.host || r.host_id === this.host),
|
|
131
|
+
);
|
|
132
|
+
if (this.hub) {
|
|
133
|
+
return hostGroups(rows, this.hosts).map(({ hostId, host: h, runs }) => {
|
|
134
|
+
const id = hostId || hostFact('');
|
|
135
|
+
const state = h ? hostStateSince(h) : '';
|
|
136
|
+
const n = runCount(runs.length);
|
|
137
|
+
return [facts(id, state, n), html`<b>${id}</b>${h ? statusWord({ text: state, tone: h.up ? 'done' : 'attention', title: lastReport(h) }) : nothing}<span class="n">${n}</span>`, runs];
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
const old = (r: RunSummary) => !r.running && ago(r) >= 86400;
|
|
141
|
+
return (
|
|
142
|
+
[
|
|
143
|
+
[msg('Running'), rows.filter((r) => r.running)],
|
|
144
|
+
[msg('Last 24 hours'), rows.filter((r) => !r.running && !old(r))],
|
|
145
|
+
[msg('Older'), rows.filter(old)],
|
|
146
|
+
] as const
|
|
147
|
+
).map(([name, rs]) => [name, html`${name} <span class="n">${rs.length}</span>`, rs]);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** A run, or a page of no run. */
|
|
151
|
+
private pick(r: Option): void {
|
|
152
|
+
this.close();
|
|
153
|
+
if (typeof r === 'string') {
|
|
154
|
+
if (r !== this.page) emit(this, 'ca-navigate', { page: r, run: '' });
|
|
155
|
+
} else if (r.run !== this.current || this.page) emit(this, 'ca-select-run', { run: r.run });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private close(): void {
|
|
159
|
+
emit(this, 'ca-close', {});
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/** The dialog's keys: Escape closes; Tab stays in the dialog, between the search field and (on a hub) the host filter. */
|
|
163
|
+
private onDialogKey(e: KeyboardEvent): void {
|
|
164
|
+
if (e.key === 'Escape') this.close();
|
|
165
|
+
else if (e.key === 'Tab') {
|
|
166
|
+
e.preventDefault();
|
|
167
|
+
(e.target === this.input && this.hub ? this.select : this.input)?.focus();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/** The search field's keys: the arrow keys move through the options, Enter picks one. */
|
|
172
|
+
private onKey(e: KeyboardEvent, opts: Option[]): void {
|
|
173
|
+
if (e.key === 'ArrowDown') this.kb = Math.min(opts.length - 1, this.kb + 1);
|
|
174
|
+
else if (e.key === 'ArrowUp') this.kb = Math.max(0, this.kb - 1);
|
|
175
|
+
else if (e.key === 'Enter') {
|
|
176
|
+
// The focus goes back to the button that opened the picker: this Enter must not press it.
|
|
177
|
+
e.preventDefault();
|
|
178
|
+
const r = opts[Math.max(0, this.kb)];
|
|
179
|
+
if (r !== undefined) this.pick(r);
|
|
180
|
+
return;
|
|
181
|
+
} else return;
|
|
182
|
+
e.preventDefault();
|
|
183
|
+
void this.updateComplete.then(() => this.renderRoot.querySelector('.item.kb')?.scrollIntoView({ block: 'nearest' }));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
override render() {
|
|
187
|
+
const groups = this.groups().filter((g) => g[2].length);
|
|
188
|
+
const rows = groups.flatMap((g) => g[2]);
|
|
189
|
+
// While nothing is searched, the pages of no run come first: the trends, and on a hub the hosts.
|
|
190
|
+
const pages: Exclude<Page, ''>[] = this.q.trim() ? [] : this.hub ? ['trends', 'hosts'] : ['trends'];
|
|
191
|
+
const opts: Option[] = [...pages, ...rows];
|
|
192
|
+
const active = opts[this.kb] !== undefined ? optionId(this.kb) : nothing;
|
|
193
|
+
const search = html`<input placeholder=${msg('Search runs')} aria-label=${msg('Search runs')} autocomplete="off" .value=${this.q}
|
|
194
|
+
role="combobox" aria-expanded=${opts.length ? 'true' : 'false'} aria-controls="runs" aria-autocomplete="list" aria-activedescendant=${active}
|
|
195
|
+
@input=${(e: Event) => { this.q = (e.target as HTMLInputElement).value; this.kb = 0; }}
|
|
196
|
+
@keydown=${(e: KeyboardEvent) => this.onKey(e, opts)} />`;
|
|
197
|
+
let i = 0;
|
|
198
|
+
return html`<div class="search" @keydown=${(e: KeyboardEvent) => this.onDialogKey(e)}>
|
|
199
|
+
${this.hub ? html`<div class="row">${search}${this.hostFilter()}</div>` : search}
|
|
200
|
+
<div class="keys meta" aria-hidden="true"><span class="kbd">↑</span><span class="kbd">↓</span> <span class="kbd">Enter</span> <span class="kbd">Esc</span></div>
|
|
201
|
+
</div>
|
|
202
|
+
<div class="list" @mousedown=${(e: MouseEvent) => e.preventDefault()}>
|
|
203
|
+
${opts.length
|
|
204
|
+
? html`<div id="runs" role="listbox" aria-label=${msg('Runs')}>
|
|
205
|
+
${pages.map((p) => this.item(p, i++))}
|
|
206
|
+
${groups.map(
|
|
207
|
+
([name, head, rs]) => html`<div role="group" aria-label=${name}>
|
|
208
|
+
<div class="group${this.hub ? ' host' : ''}" aria-hidden="true">${head}</div>
|
|
209
|
+
${rs.map((r) => this.item(r, i++))}
|
|
210
|
+
</div>`,
|
|
211
|
+
)}
|
|
212
|
+
</div>`
|
|
213
|
+
: html`<div class="blank"><span>${msg('No runs match the search')}</span></div>`}
|
|
214
|
+
</div>`;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** The host filter: every host with runs. */
|
|
218
|
+
private hostFilter() {
|
|
219
|
+
return html`<select aria-label=${msg('Host')} title=${msg('Host')}
|
|
220
|
+
@change=${(e: Event) => { this.host = (e.target as HTMLSelectElement).value; this.kb = -1; }}>
|
|
221
|
+
<option value="" ?selected=${!this.host}>${msg('All hosts')}</option>
|
|
222
|
+
${hostGroups(this.runs, this.hosts).map((g) => html`<option value=${g.hostId} ?selected=${g.hostId === this.host}>${g.hostId || hostFact('')}</option>`)}
|
|
223
|
+
</select>`;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** Tasks by how they ended, as the run's own page counts them, and how long it took: one line. */
|
|
227
|
+
private counts(r: RunSummary): string {
|
|
228
|
+
const t = r.tasks;
|
|
229
|
+
const parts = [msg(str`${t.done} of ${t.total} tasks done`)];
|
|
230
|
+
if (t.failed) parts.push(stateCount('failed', t.failed));
|
|
231
|
+
if (t.not_started) parts.push(stateCount('not_started', t.not_started));
|
|
232
|
+
if (t.partial) parts.push(stateCount('partial', t.partial));
|
|
233
|
+
if (t.skipped) parts.push(stateCount('skipped', t.skipped));
|
|
234
|
+
if (t.running) parts.push(stateCount('running', t.running));
|
|
235
|
+
if (t.waiting) parts.push(stateCount('waiting', t.waiting));
|
|
236
|
+
if (t.not_run) parts.push(stateCount('not_run', t.not_run));
|
|
237
|
+
const s = took(r);
|
|
238
|
+
if (s != null) parts.push(msg(str`took ${fmtDur(s)}`));
|
|
239
|
+
if (r.cost_usd !== null && r.cost_usd !== undefined) parts.push(usd(r.cost_usd));
|
|
240
|
+
const usage = accountsLine(r.quota ?? []);
|
|
241
|
+
if (usage) parts.push(usage);
|
|
242
|
+
return facts(...parts);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** The run's state where its age goes: running, no report from its host (a hub), or how long ago it was last active. */
|
|
246
|
+
private when(r: RunSummary) {
|
|
247
|
+
const a = runActivity(r);
|
|
248
|
+
const at = localTime(r.last_ts, true);
|
|
249
|
+
const quiet = a === 'unresponsive';
|
|
250
|
+
return html`<span class="when" data-tone=${quiet ? 'attention' : nothing} data-mark=${quiet ? 'pending' : nothing}
|
|
251
|
+
title=${quiet ? facts(lastReport(hostOf(this.hosts, r)), msg(str`Last activity ${at}`)) : at}
|
|
252
|
+
>${a === 'running' ? msg('running') : quiet ? noReportLabel() : relAgo(r.last_ts)}</span>`;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** An option: a run, or a page of no run. */
|
|
256
|
+
private item(r: Option, i: number) {
|
|
257
|
+
const page = typeof r === 'string' ? r : null;
|
|
258
|
+
const cur = page ? page === this.page : !this.page && (r as RunSummary).run === this.current;
|
|
259
|
+
const cls = `item${cur ? ' cur' : ''}${i === this.kb ? ' kb' : ''}`;
|
|
260
|
+
// An option of the listbox: the search field keeps the focus and names the active option (`aria-activedescendant`).
|
|
261
|
+
return html`<div class=${cls} id=${optionId(i)} role="option" aria-selected=${i === this.kb ? 'true' : 'false'}
|
|
262
|
+
aria-current=${cur ? (page ? 'page' : 'true') : nothing} @click=${() => this.pick(r)}>
|
|
263
|
+
${typeof r !== 'string'
|
|
264
|
+
? html`<span class="dot" data-tone=${toneAttr(runTone(runActivity(r), r.tasks))} aria-hidden="true"></span><span class="nm"
|
|
265
|
+
title=${this.hub ? r.run : nothing}>${this.hub ? runIdOf(r) : r.run}${runMark(r) ? html` ${pill({ ...runMark(r)!, tone: 'muted' })}` : nothing}</span>
|
|
266
|
+
${this.when(r)}
|
|
267
|
+
<span class="sub">
|
|
268
|
+
${r.run_group && r.run_group !== runIdOf(r) ? html`<span>${msg(str`Run group ${r.run_group}`)}</span>` : nothing} <span title=${accountsTip(r.quota ?? [])}>${this.counts(r)}</span>
|
|
269
|
+
</span>`
|
|
270
|
+
: page === 'hosts'
|
|
271
|
+
? html`<span aria-hidden="true">⊞</span><span class="nm">${msg('Hosts')}</span><span class="when page">${hostsLine(this.hosts)}</span>`
|
|
272
|
+
: html`<span aria-hidden="true">▥</span><span class="nm">${trendsTitle()}</span><span class="when page">${trendsTip()}</span>`}
|
|
273
|
+
</div>`;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/** An option of the list: a run, or a page of no run. */
|
|
278
|
+
type Option = RunSummary | Exclude<Page, ''>;
|
|
279
|
+
|
|
280
|
+
declare global {
|
|
281
|
+
interface HTMLElementTagNameMap {
|
|
282
|
+
'ca-run-picker': CaRunPicker;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { localized, msg, str } from '@lit/localize';
|
|
2
|
+
import { LitElement, css, html, nothing, type PropertyValues } from 'lit';
|
|
3
|
+
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
4
|
+
import { emit } from '../../core/events.js';
|
|
5
|
+
import { base } from '@contraagent/elements/styles';
|
|
6
|
+
import { EDITOR_THEMES, THEMES, THEME_CHOICES, type ThemeChoice, type ThemeName } from '@contraagent/elements/themes';
|
|
7
|
+
|
|
8
|
+
/** A choice's name in the control: a theme's own name stays as it is; `system` and High contrast are words. */
|
|
9
|
+
export function themeLabel(choice: ThemeChoice): string {
|
|
10
|
+
if (choice === 'system') return msg('System');
|
|
11
|
+
if (choice === 'high-contrast') return msg('High contrast');
|
|
12
|
+
return THEMES[choice].label;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A small picture of a theme: its panel, its accent and two of its code colours. */
|
|
16
|
+
const swatch = (n: ThemeName) => {
|
|
17
|
+
const t = THEMES[n].tokens;
|
|
18
|
+
return html`<span class="sw" style="background:${t.card};border-color:${t.line2}"
|
|
19
|
+
><i style="background:${t.accent}"></i><i style="background:${t['code-string']}"></i><i style="background:${t['code-keyword']}"></i
|
|
20
|
+
></span>`;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The theme control in the monitor's header: a button that opens a menu of
|
|
25
|
+
* the themes. Arrow keys, Home and End move in the menu; Enter or Space
|
|
26
|
+
* chooses; Escape closes it.
|
|
27
|
+
*
|
|
28
|
+
* @fires ca-choose-theme - `{theme}`: a theme (or `system`) was chosen
|
|
29
|
+
*/
|
|
30
|
+
@customElement('ca-theme-switch')
|
|
31
|
+
@localized()
|
|
32
|
+
export class CaThemeSwitch extends LitElement {
|
|
33
|
+
static override styles = [
|
|
34
|
+
base,
|
|
35
|
+
css`
|
|
36
|
+
:host { position: relative; display: inline-flex; }
|
|
37
|
+
.trig { display: inline-flex; align-items: center; gap: 6px; background: none; border: 1px solid var(--line); border-radius: 999px;
|
|
38
|
+
padding: 2px 10px 2px 7px; font-size: 11px; color: var(--text-muted); cursor: pointer; }
|
|
39
|
+
.trig:hover, .trig[aria-expanded='true'] { color: var(--text); border-color: var(--line2); }
|
|
40
|
+
.trig svg { width: 13px; height: 13px; }
|
|
41
|
+
.menu { position: absolute; right: 0; top: calc(100% + 8px); min-width: 236px; padding: 6px; z-index: 50;
|
|
42
|
+
background: var(--panel); border: 1px solid var(--line2); border-radius: 12px;
|
|
43
|
+
box-shadow: 0 18px 48px color-mix(in srgb, var(--shadow) 65%, transparent); animation: enter 0.16s var(--ease) both; }
|
|
44
|
+
.grp { font-size: 11px; color: var(--text-muted); padding: 8px 9px 4px; }
|
|
45
|
+
[role='separator'] { height: 1px; background: var(--line); margin: 6px 4px; }
|
|
46
|
+
.item { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px; width: 100%;
|
|
47
|
+
background: none; border: 0; border-radius: 8px; padding: 6px 9px; text-align: left; cursor: pointer; color: var(--text-2); font-size: 12px; }
|
|
48
|
+
.item:hover { background: var(--raise); color: var(--text); }
|
|
49
|
+
.item:focus-visible { outline-offset: -2px; }
|
|
50
|
+
.item[aria-checked='true'] { background: var(--accent-bg); color: var(--text); font-weight: 600; }
|
|
51
|
+
.item .meta { font-weight: 400; }
|
|
52
|
+
.item .sub { display: block; }
|
|
53
|
+
/* a radio mark: a ring, filled for the current choice */
|
|
54
|
+
.rd { width: 12px; height: 12px; border-radius: 50%; border: 1.5px solid var(--line2); display: grid; place-items: center; }
|
|
55
|
+
[aria-checked='true'] .rd { border-color: var(--accent); }
|
|
56
|
+
[aria-checked='true'] .rd::after { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
|
|
57
|
+
.sw { display: inline-flex; gap: 2px; align-items: flex-end; width: 30px; height: 18px; border-radius: 5px; border: 1px solid; padding: 3px 4px; }
|
|
58
|
+
.sw i { flex: 1; height: 4px; border-radius: 2px; }
|
|
59
|
+
.sw i:first-child { height: 8px; }
|
|
60
|
+
.sw.split { padding: 0; overflow: hidden; gap: 0; }
|
|
61
|
+
.sw.split > span { flex: 1; height: 100%; display: flex; gap: 2px; align-items: flex-end; padding: 3px 2px; }
|
|
62
|
+
`,
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
/** The current choice. */
|
|
66
|
+
@property() value: ThemeChoice = 'contraagent-dark';
|
|
67
|
+
/** The theme `system` shows now, by the system's colour scheme. */
|
|
68
|
+
@property() system: ThemeName = 'contraagent-dark';
|
|
69
|
+
@state() private open = false;
|
|
70
|
+
@query('.trig') private trig!: HTMLButtonElement;
|
|
71
|
+
|
|
72
|
+
private readonly onDocDown = (e: PointerEvent) => {
|
|
73
|
+
if (this.open && !e.composedPath().includes(this)) this.open = false;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
override disconnectedCallback(): void {
|
|
77
|
+
super.disconnectedCallback();
|
|
78
|
+
document.removeEventListener('pointerdown', this.onDocDown);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private items(): HTMLButtonElement[] {
|
|
82
|
+
return [...this.renderRoot.querySelectorAll<HTMLButtonElement>('.item')];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
protected override updated(changed: PropertyValues<this>): void {
|
|
86
|
+
// A press outside the open menu closes it: listened for on the document only while it is open.
|
|
87
|
+
if (changed.has('open' as keyof CaThemeSwitch)) {
|
|
88
|
+
if (this.open) document.addEventListener('pointerdown', this.onDocDown);
|
|
89
|
+
else document.removeEventListener('pointerdown', this.onDocDown);
|
|
90
|
+
}
|
|
91
|
+
if (changed.has('open' as keyof CaThemeSwitch) && this.open) {
|
|
92
|
+
(this.items().find((b) => b.getAttribute('aria-checked') === 'true') ?? this.items()[0])?.focus();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private close(focusTrigger: boolean): void {
|
|
97
|
+
this.open = false;
|
|
98
|
+
if (focusTrigger) this.trig?.focus();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private choose(choice: ThemeChoice): void {
|
|
102
|
+
this.value = choice;
|
|
103
|
+
emit(this, 'ca-choose-theme', { theme: choice });
|
|
104
|
+
this.close(true);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private onTrigKey(e: KeyboardEvent): void {
|
|
108
|
+
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
|
109
|
+
e.preventDefault();
|
|
110
|
+
this.open = true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
private onMenuKey(e: KeyboardEvent): void {
|
|
115
|
+
const items = this.items();
|
|
116
|
+
const i = items.indexOf(e.composedPath()[0] as HTMLButtonElement);
|
|
117
|
+
const go = (n: number) => items[(n + items.length) % items.length]?.focus();
|
|
118
|
+
if (e.key === 'ArrowDown') go(i + 1);
|
|
119
|
+
else if (e.key === 'ArrowUp') go(i - 1);
|
|
120
|
+
else if (e.key === 'Home') go(0);
|
|
121
|
+
else if (e.key === 'End') go(items.length - 1);
|
|
122
|
+
else if (e.key === 'Escape') this.close(true);
|
|
123
|
+
else if (e.key === 'Tab') {
|
|
124
|
+
this.open = false;
|
|
125
|
+
return;
|
|
126
|
+
} else return;
|
|
127
|
+
e.preventDefault();
|
|
128
|
+
e.stopPropagation();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
private item(choice: ThemeChoice) {
|
|
132
|
+
const on = choice === this.value;
|
|
133
|
+
const pic =
|
|
134
|
+
choice === 'system'
|
|
135
|
+
? html`<span class="sw split" style="border-color:${THEMES['contraagent-dark'].tokens.line2}"
|
|
136
|
+
><span style="background:${THEMES['contraagent-dark'].tokens.card}"><i style="background:${THEMES['contraagent-dark'].tokens.accent}"></i></span
|
|
137
|
+
><span style="background:${THEMES['contraagent-light'].tokens.card}"><i style="background:${THEMES['contraagent-light'].tokens.accent}"></i></span
|
|
138
|
+
></span>`
|
|
139
|
+
: swatch(choice);
|
|
140
|
+
return html`<button type="button" class="item" role="menuitemradio" aria-checked=${on ? 'true' : 'false'} tabindex="-1"
|
|
141
|
+
data-theme=${choice} @click=${() => this.choose(choice)}>
|
|
142
|
+
${pic}<span>${themeLabel(choice)}${choice === 'system' ? html`<span class="meta sub">${THEMES[this.system].label}</span>` : nothing}</span><span class="rd" aria-hidden="true"></span>
|
|
143
|
+
</button>`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override render() {
|
|
147
|
+
const own = THEME_CHOICES.filter((c) => c === 'system' || !(EDITOR_THEMES as readonly string[]).includes(c));
|
|
148
|
+
return html`<button type="button" class="trig" aria-haspopup="menu" aria-expanded=${this.open ? 'true' : 'false'} aria-controls="menu"
|
|
149
|
+
title=${msg(str`Theme: ${themeLabel(this.value)}`)} @click=${() => (this.open = !this.open)} @keydown=${(e: KeyboardEvent) => this.onTrigKey(e)}>
|
|
150
|
+
<svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="6.25" fill="none" stroke="currentColor" stroke-width="1.5" /><path d="M8 1.75a6.25 6.25 0 0 1 0 12.5z" fill="currentColor" /></svg>
|
|
151
|
+
${msg('Theme')}
|
|
152
|
+
</button>
|
|
153
|
+
${this.open
|
|
154
|
+
? html`<div id="menu" class="menu" role="menu" aria-label=${msg('Theme')} @keydown=${(e: KeyboardEvent) => this.onMenuKey(e)}>
|
|
155
|
+
${own.map((c) => this.item(c))}
|
|
156
|
+
<div role="separator"></div>
|
|
157
|
+
<div role="group" aria-labelledby="grp-editor">
|
|
158
|
+
<div class="grp" id="grp-editor">${msg('Editor themes')}</div>
|
|
159
|
+
${EDITOR_THEMES.map((c) => this.item(c))}
|
|
160
|
+
</div>
|
|
161
|
+
</div>`
|
|
162
|
+
: nothing}`;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
declare global {
|
|
167
|
+
interface HTMLElementTagNameMap {
|
|
168
|
+
'ca-theme-switch': CaThemeSwitch;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { isBad, runRelative, type JournalRow } from '@contraagent/api';
|
|
2
|
+
import { msg, str } from '@lit/localize';
|
|
3
|
+
import { LitElement, css, html, nothing } from 'lit';
|
|
4
|
+
import { customElement, state } from 'lit/decorators.js';
|
|
5
|
+
import { repeat } from 'lit/directives/repeat.js';
|
|
6
|
+
import { base } from '@contraagent/elements/styles';
|
|
7
|
+
import { facts, fmtDur, kindUnit } from '../../words/format.js';
|
|
8
|
+
import { modelSwitch, stopLabel } from '../../words/index.js';
|
|
9
|
+
|
|
10
|
+
/** The notice's status (its mark and the colour of its edge); `agent` is a model switch, which is not a status. */
|
|
11
|
+
export type ToastKind = 'done' | 'failed' | 'attention' | 'running' | 'agent';
|
|
12
|
+
|
|
13
|
+
interface Toast {
|
|
14
|
+
id: number;
|
|
15
|
+
kind: ToastKind;
|
|
16
|
+
title: string;
|
|
17
|
+
sub: string;
|
|
18
|
+
out: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** The notice for a journal row that just arrived: its kind, title and line (`CaToasts.show`'s arguments). */
|
|
22
|
+
export function rowToast(row: JournalRow, run: string): [kind: ToastKind, title: string, sub: string] {
|
|
23
|
+
const name = kindUnit(row);
|
|
24
|
+
const reason = runRelative(row.reason, run).slice(0, 110);
|
|
25
|
+
if (row.stop === 'invalid_input') return ['attention', msg(str`${name}: not started`), reason];
|
|
26
|
+
if (isBad(row)) return ['failed', msg(str`${name}: ${stopLabel(row.stop)}`), reason];
|
|
27
|
+
if (row.stop === 'partial') return ['attention', msg(str`${name}: ${stopLabel(row.stop)}`), reason];
|
|
28
|
+
const sw = modelSwitch(row.hops, row.wall_s, row.skipped_hops);
|
|
29
|
+
if (sw) return ['agent', msg(str`${name}: model switch`), sw.slice(0, 110)];
|
|
30
|
+
return ['done', msg(str`${name}: done`), facts(fmtDur(row.wall_s), row.model)];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const ICON: Record<ToastKind, string> = { done: '✓', failed: '✕', attention: '◌', running: '●', agent: '✦' };
|
|
34
|
+
const SHOW_MS = 5200;
|
|
35
|
+
const MAX = 4;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Short notices in a corner; each leaves on its own after a few seconds. A
|
|
39
|
+
* screen reader hears each one: a failure at once, the others when it is idle.
|
|
40
|
+
*/
|
|
41
|
+
@customElement('ca-toasts')
|
|
42
|
+
export class CaToasts extends LitElement {
|
|
43
|
+
static override styles = [
|
|
44
|
+
base,
|
|
45
|
+
css`
|
|
46
|
+
:host { position: fixed; right: 18px; bottom: 18px; display: flex; flex-direction: column; gap: 8px; z-index: 60; pointer-events: none; }
|
|
47
|
+
.toast { pointer-events: auto; min-width: 240px; max-width: 380px; padding: 10px 14px; border-radius: 11px;
|
|
48
|
+
background: var(--panel2); border: 1px solid var(--line2); box-shadow: 0 18px 40px color-mix(in srgb, var(--shadow) 60%, transparent);
|
|
49
|
+
display: flex; gap: 10px; align-items: flex-start; animation: toast-in 0.35s var(--ease) both; }
|
|
50
|
+
.toast.out { animation: toast-out 0.35s var(--ease) both; }
|
|
51
|
+
.ti { font-size: 16px; line-height: 1.2; }
|
|
52
|
+
b { display: block; font-size: 12.5px; }
|
|
53
|
+
span.sub { font-size: 11.5px; color: var(--text-muted); }
|
|
54
|
+
.ti { color: var(--text-muted); }
|
|
55
|
+
.toast[data-tone] .ti { color: var(--tone); }
|
|
56
|
+
.toast[data-tone='failed'], .toast[data-tone='attention'] { border-color: color-mix(in srgb, var(--tone) 50%, var(--line2)); }
|
|
57
|
+
.agent .ti { color: var(--agent); }
|
|
58
|
+
`,
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
@state() private toasts: Toast[] = [];
|
|
62
|
+
private next = 0;
|
|
63
|
+
|
|
64
|
+
show(kind: ToastKind, title: string, sub = ''): void {
|
|
65
|
+
const t: Toast = { id: this.next++, kind, title, sub, out: false };
|
|
66
|
+
this.toasts = [...this.toasts, t].slice(-MAX);
|
|
67
|
+
setTimeout(() => {
|
|
68
|
+
this.toasts = this.toasts.map((x) => (x.id === t.id ? { ...x, out: true } : x));
|
|
69
|
+
setTimeout(() => (this.toasts = this.toasts.filter((x) => x.id !== t.id)), 400);
|
|
70
|
+
}, SHOW_MS);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
override render() {
|
|
74
|
+
// The notices as a screen reader hears them: failures at once (`role="alert"`), the others when it is idle (`role="status"`).
|
|
75
|
+
const said = (urgent: boolean) =>
|
|
76
|
+
repeat(
|
|
77
|
+
this.toasts.filter((t) => !t.out && (t.kind === 'failed') === urgent),
|
|
78
|
+
(t) => t.id,
|
|
79
|
+
(t) => html`<p>${facts(t.title, t.sub)}</p>`,
|
|
80
|
+
);
|
|
81
|
+
return html`<div class="sr" role="status" aria-live="polite">${said(false)}</div>
|
|
82
|
+
<div class="sr" role="alert" aria-live="assertive">${said(true)}</div>
|
|
83
|
+
<div aria-hidden="true" style="display:contents">
|
|
84
|
+
${repeat(
|
|
85
|
+
this.toasts,
|
|
86
|
+
(t) => t.id,
|
|
87
|
+
(t) => html`<div class="toast ${t.kind === 'agent' ? 'agent' : ''} ${t.out ? 'out' : ''}" data-tone=${t.kind === 'agent' ? nothing : t.kind}>
|
|
88
|
+
<span class="ti">${ICON[t.kind]}</span>
|
|
89
|
+
<div><b>${t.title}</b>${t.sub ? html`<span class="sub">${t.sub}</span>` : nothing}</div>
|
|
90
|
+
</div>`,
|
|
91
|
+
)}
|
|
92
|
+
</div>`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declare global {
|
|
97
|
+
interface HTMLElementTagNameMap {
|
|
98
|
+
'ca-toasts': CaToasts;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Parts of the monitor's header: the name, what is running now, and the
|
|
2
|
+
// connection to the monitor server.
|
|
3
|
+
import type { Activity } from '@contraagent/api';
|
|
4
|
+
import { msg } from '@lit/localize';
|
|
5
|
+
import { html, nothing, type TemplateResult } from 'lit';
|
|
6
|
+
import { kindUnit } from '../../words/format.js';
|
|
7
|
+
import { taskChip } from '../shared/task-chip.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The brand mark (braces around a spark, the favicon's drawing) and the monitor's title.
|
|
11
|
+
* The braces take the text colour and the spark goes from the accent to the agent colour,
|
|
12
|
+
* so the mark follows the theme; the gradient's id is unique in the element's shadow root.
|
|
13
|
+
*/
|
|
14
|
+
export const brand = (title: string): TemplateResult =>
|
|
15
|
+
html`<div class="brand">
|
|
16
|
+
<svg viewBox="12 12 96 96" aria-hidden="true">
|
|
17
|
+
<defs>
|
|
18
|
+
<linearGradient id="brand-spark" x1="0" y1="0" x2="1" y2="1">
|
|
19
|
+
<stop offset="0" class="spark-a" />
|
|
20
|
+
<stop offset="1" class="spark-b" />
|
|
21
|
+
</linearGradient>
|
|
22
|
+
</defs>
|
|
23
|
+
<g class="logo-braces" fill="none" stroke-width="14" stroke-linecap="round" stroke-linejoin="round">
|
|
24
|
+
<path d="M48 22 C36 22 36 30 36 38 L36 50 C36 56 32 60 26 60 C32 60 36 64 36 70 L36 82 C36 90 36 98 48 98" />
|
|
25
|
+
<path d="M72 22 C84 22 84 30 84 38 L84 50 C84 56 88 60 94 60 C88 60 84 64 84 70 L84 82 C84 90 84 98 72 98" />
|
|
26
|
+
</g>
|
|
27
|
+
<g class="logo-spark">
|
|
28
|
+
<path d="M60 45 C61.6 56 64 58.4 75 60 C64 61.6 61.6 64 60 75 C58.4 64 56 61.6 45 60 C56 58.4 58.4 56 60 45 Z"
|
|
29
|
+
fill="url(#brand-spark)" transform="translate(60 60) scale(1.15) translate(-60 -60)" />
|
|
30
|
+
</g>
|
|
31
|
+
</svg>
|
|
32
|
+
<span title=${title}>${title}</span>
|
|
33
|
+
</div>`;
|
|
34
|
+
|
|
35
|
+
/** The tasks running now, the first three by name; each chip opens its task (sent from `host`). */
|
|
36
|
+
export const nowLine = (host: EventTarget, acts: readonly Activity[]): TemplateResult =>
|
|
37
|
+
html`<span class="nowline">${acts.length
|
|
38
|
+
? msg(html`Running ${acts.slice(0, 3).map((a) => taskChip(host, kindUnit(a), { key: a.key }))}${acts.length > 3 ? html` <span>+${acts.length - 3}</span>` : nothing}`)
|
|
39
|
+
: nothing}</span>`;
|
|
40
|
+
|
|
41
|
+
/** Whether the feed is connected: a dot, with its words as its accessible name and its tooltip. */
|
|
42
|
+
export const connection = (connected: boolean): TemplateResult => {
|
|
43
|
+
const words = connected ? msg('Connected to the monitor server') : msg('Not connected to the monitor server');
|
|
44
|
+
return html`<span role="img" aria-label=${words} title=${words}><span class="live-dot ${connected ? '' : 'off'}"></span></span>`;
|
|
45
|
+
};
|