@runwisp/ui 0.12.0 → 0.14.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/package.json +40 -45
- package/src/astro/CTABand.astro +19 -12
- package/src/astro/Hero.astro +3 -3
- package/src/astro/SiteFooter.astro +4 -4
- package/src/astro/SiteHeader.astro +4 -4
- package/src/lib/assets/runwisp-logo.svg +1 -8
- package/src/lib/components/AccordionItem.svelte +4 -10
- package/src/lib/components/Alert.svelte +11 -11
- package/src/lib/components/Avatar.svelte +1 -1
- package/src/lib/components/Badge.svelte +13 -13
- package/src/lib/components/Breadcrumb.svelte +3 -3
- package/src/lib/components/Button.svelte +2 -2
- package/src/lib/components/Card.svelte +4 -4
- package/src/lib/components/Checkbox.svelte +12 -10
- package/src/lib/components/CodeBlock.svelte +7 -13
- package/src/lib/components/CronInput.svelte +12 -11
- package/src/lib/components/DataGrid.svelte +14 -11
- package/src/lib/components/Drawer.svelte +9 -6
- package/src/lib/components/Dropdown.svelte +10 -14
- package/src/lib/components/DurationInput.svelte +10 -14
- package/src/lib/components/EmptyState.svelte +1 -1
- package/src/lib/components/ErrorState.svelte +4 -4
- package/src/lib/components/FeatureCard.svelte +4 -4
- package/src/lib/components/FormField.svelte +11 -6
- package/src/lib/components/Heading.svelte +4 -1
- package/src/lib/components/Input.svelte +10 -12
- package/src/lib/components/Kbd.svelte +1 -1
- package/src/lib/components/Link.svelte +2 -3
- package/src/lib/components/LinkButton.svelte +2 -2
- package/src/lib/components/LogConsole.svelte +22 -21
- package/src/lib/components/Logo.svelte +3 -1
- package/src/lib/components/Modal.svelte +9 -8
- package/src/lib/components/PageContainer.svelte +1 -1
- package/src/lib/components/PageHeader.svelte +1 -1
- package/src/lib/components/Pagination.svelte +4 -4
- package/src/lib/components/Popover.svelte +5 -7
- package/src/lib/components/Progress.svelte +6 -4
- package/src/lib/components/Prose.svelte +4 -4
- package/src/lib/components/Radio.svelte +11 -10
- package/src/lib/components/RadioGroup.svelte +3 -5
- package/src/lib/components/Select.svelte +21 -31
- package/src/lib/components/Separator.svelte +4 -1
- package/src/lib/components/Skeleton.svelte +6 -6
- package/src/lib/components/StatusIndicator.svelte +7 -15
- package/src/lib/components/Table.svelte +1 -1
- package/src/lib/components/TableCell.svelte +1 -1
- package/src/lib/components/TableRow.svelte +1 -5
- package/src/lib/components/Tabs.svelte +10 -11
- package/src/lib/components/TaskCard.svelte +7 -4
- package/src/lib/components/Textarea.svelte +10 -11
- package/src/lib/components/ThemeToggle.svelte +1 -1
- package/src/lib/components/ToastContainer.svelte +3 -3
- package/src/lib/components/Toggle.svelte +2 -3
- package/src/lib/components/Tooltip.svelte +8 -9
- package/src/lib/components/button-styles.ts +17 -18
- package/src/lib/components/dashboard/RunDetailPanel.svelte +61 -49
- package/src/lib/components/dashboard/RunFilterPopover.svelte +17 -11
- package/src/lib/components/dashboard/RunsList.svelte +26 -21
- package/src/lib/theme-tokens.css +179 -114
- package/src/lib/theme.css +49 -35
|
@@ -34,21 +34,21 @@
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
const textareaClasses = `
|
|
37
|
-
w-full px-3.5 py-2.5 rounded-
|
|
37
|
+
w-full px-3.5 py-2.5 rounded-[3px] border font-mono
|
|
38
38
|
text-sm bg-surface-raised text-on-surface placeholder:text-on-surface-faint
|
|
39
|
-
focus:outline-none focus:ring-2 focus:ring-offset-
|
|
39
|
+
focus:outline-none focus:ring-2 focus:ring-offset-2
|
|
40
40
|
disabled:bg-surface-sunken disabled:text-on-surface-muted disabled:cursor-not-allowed
|
|
41
|
-
|
|
42
|
-
`;
|
|
41
|
+
`;
|
|
43
42
|
|
|
44
43
|
const normalBorder =
|
|
45
|
-
"border-outline hover:border-outline-hover focus:border-ring focus:ring-ring
|
|
46
|
-
const errorBorder =
|
|
44
|
+
"border-outline hover:border-outline-hover shadow-sm focus:border-ring focus:ring-ring";
|
|
45
|
+
const errorBorder =
|
|
46
|
+
"border-danger-surface focus:border-danger-surface focus:ring-danger-surface";
|
|
47
47
|
</script>
|
|
48
48
|
|
|
49
49
|
<div class="space-y-1.5 {className}">
|
|
50
50
|
{#if label}
|
|
51
|
-
<label class="block text-
|
|
51
|
+
<label class="block font-mono text-xs font-medium text-on-surface-muted" for={id}>
|
|
52
52
|
{label}
|
|
53
53
|
</label>
|
|
54
54
|
{/if}
|
|
@@ -63,8 +63,7 @@
|
|
|
63
63
|
{disabled}
|
|
64
64
|
{id}
|
|
65
65
|
bind:value
|
|
66
|
-
{...restProps}
|
|
67
|
-
></textarea>
|
|
66
|
+
{...restProps}></textarea>
|
|
68
67
|
|
|
69
68
|
{#if error}
|
|
70
69
|
<div class="pointer-events-none absolute top-3 right-3 text-danger-soft-text">
|
|
@@ -74,8 +73,8 @@
|
|
|
74
73
|
</div>
|
|
75
74
|
|
|
76
75
|
{#if error}
|
|
77
|
-
<p class="text-
|
|
76
|
+
<p class="font-sans text-xs text-danger-soft-text">{error}</p>
|
|
78
77
|
{:else if hint}
|
|
79
|
-
<p class="text-
|
|
78
|
+
<p class="font-sans text-xs text-on-surface-muted">{hint}</p>
|
|
80
79
|
{/if}
|
|
81
80
|
</div>
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
aria-pressed={isDark}
|
|
38
38
|
aria-label={isDark ? "Switch to light theme" : "Switch to dark theme"}
|
|
39
39
|
title={isDark ? "Switch to light theme" : "Switch to dark theme"}
|
|
40
|
-
class="inline-flex h-9 w-9 items-center justify-center rounded-
|
|
40
|
+
class="inline-flex h-9 w-9 items-center justify-center rounded-[3px] border border-outline bg-surface-raised text-on-surface-muted hover:border-outline-hover hover:text-on-surface {className}"
|
|
41
41
|
>
|
|
42
42
|
{#if mounted && isDark}
|
|
43
43
|
<Sun size={16} />
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
<div
|
|
63
63
|
in:fly={{ y: 20, duration: 300 }}
|
|
64
64
|
out:fade={{ duration: 200 }}
|
|
65
|
-
class="pointer-events-auto isolate flex max-w-md min-w-[320px] items-start gap-3 rounded-
|
|
65
|
+
class="pointer-events-auto isolate flex max-w-md min-w-[320px] items-start gap-3 rounded-[4px] border bg-surface-overlay px-4 py-3 shadow-lg {getColorClasses(
|
|
66
66
|
toastItem.type,
|
|
67
67
|
)}"
|
|
68
68
|
role="alert"
|
|
@@ -79,14 +79,14 @@
|
|
|
79
79
|
action.onClick();
|
|
80
80
|
toast.remove(toastItem.id);
|
|
81
81
|
}}
|
|
82
|
-
class="flex-shrink-0 rounded-
|
|
82
|
+
class="flex-shrink-0 rounded-[3px] px-2 py-1 font-mono text-xs font-semibold text-on-surface underline-offset-2 hover:bg-surface-sunken hover:underline"
|
|
83
83
|
>
|
|
84
84
|
{action.label}
|
|
85
85
|
</button>
|
|
86
86
|
{/if}
|
|
87
87
|
<button
|
|
88
88
|
onclick={() => toast.remove(toastItem.id)}
|
|
89
|
-
class="flex-shrink-0 rounded-
|
|
89
|
+
class="flex-shrink-0 rounded-[3px] p-1 text-on-surface-muted hover:bg-surface-sunken hover:text-on-surface"
|
|
90
90
|
aria-label="Close notification"
|
|
91
91
|
>
|
|
92
92
|
<X class="h-4 w-4" aria-hidden="true" />
|
|
@@ -55,7 +55,6 @@
|
|
|
55
55
|
class="
|
|
56
56
|
relative inline-flex shrink-0 items-center rounded-full
|
|
57
57
|
{sizeConfig.track}
|
|
58
|
-
transition-colors duration-200
|
|
59
58
|
focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
|
|
60
59
|
{checked ? 'bg-primary' : 'bg-outline-hover'}
|
|
61
60
|
{disabled ? 'cursor-not-allowed' : 'cursor-pointer'}
|
|
@@ -65,7 +64,7 @@
|
|
|
65
64
|
class="
|
|
66
65
|
inline-block rounded-full bg-surface-raised shadow-sm
|
|
67
66
|
{sizeConfig.thumb}
|
|
68
|
-
transform transition-transform duration-
|
|
67
|
+
transform transition-transform duration-[120ms]
|
|
69
68
|
{checked ? sizeConfig.translate : 'translate-x-0.5'}
|
|
70
69
|
"
|
|
71
70
|
></span>
|
|
@@ -74,7 +73,7 @@
|
|
|
74
73
|
{#if label || description}
|
|
75
74
|
<div class="flex flex-col gap-0.5">
|
|
76
75
|
{#if label}
|
|
77
|
-
<span class="{sizeConfig.text} font-medium text-on-surface">{label}</span>
|
|
76
|
+
<span class="{sizeConfig.text} font-mono font-medium text-on-surface">{label}</span>
|
|
78
77
|
{/if}
|
|
79
78
|
{#if description}
|
|
80
79
|
<span class="text-sm text-on-surface-muted">{description}</span>
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
const arrowClasses: Record<TooltipPosition, string> = {
|
|
34
|
-
top: "top-full left-1/2 -translate-x-1/2 border-t-
|
|
35
|
-
bottom: "bottom-full left-1/2 -translate-x-1/2 border-b-
|
|
36
|
-
left: "left-full top-1/2 -translate-y-1/2 border-l-
|
|
37
|
-
right: "right-full top-1/2 -translate-y-1/2 border-r-
|
|
34
|
+
top: "top-full left-1/2 -translate-x-1/2 border-t-outline border-x-transparent border-b-transparent",
|
|
35
|
+
bottom: "bottom-full left-1/2 -translate-x-1/2 border-b-outline border-x-transparent border-t-transparent",
|
|
36
|
+
left: "left-full top-1/2 -translate-y-1/2 border-l-outline border-y-transparent border-r-transparent",
|
|
37
|
+
right: "right-full top-1/2 -translate-y-1/2 border-r-outline border-y-transparent border-l-transparent",
|
|
38
38
|
};
|
|
39
39
|
</script>
|
|
40
40
|
|
|
@@ -44,12 +44,11 @@
|
|
|
44
44
|
<div
|
|
45
45
|
class="
|
|
46
46
|
absolute z-50 {positionClasses[position]}
|
|
47
|
-
pointer-events-none invisible rounded-
|
|
48
|
-
bg-
|
|
49
|
-
|
|
47
|
+
pointer-events-none invisible rounded-[3px]
|
|
48
|
+
border border-outline bg-surface-overlay px-2.5 py-1.5 font-sans
|
|
49
|
+
text-xs
|
|
50
50
|
{wide ? 'w-max max-w-xs whitespace-normal' : 'whitespace-nowrap'}
|
|
51
|
-
text-
|
|
52
|
-
duration-150 group-hover:visible
|
|
51
|
+
text-on-surface opacity-0 group-hover:visible
|
|
53
52
|
group-hover:opacity-100
|
|
54
53
|
"
|
|
55
54
|
role="tooltip"
|
|
@@ -7,45 +7,44 @@ export type ButtonSize = "xs" | "sm" | "md" | "lg";
|
|
|
7
7
|
export const BUTTON_BASE = `
|
|
8
8
|
group
|
|
9
9
|
inline-flex items-center justify-center gap-2
|
|
10
|
-
font-
|
|
11
|
-
|
|
12
|
-
focus-visible:outline-none focus-visible:ring-
|
|
10
|
+
font-mono font-medium tracking-normal
|
|
11
|
+
cursor-pointer select-none border
|
|
12
|
+
focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2
|
|
13
13
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
14
|
-
|
|
15
|
-
active:scale-[0.98]
|
|
14
|
+
active:translate-y-px
|
|
16
15
|
`;
|
|
17
16
|
|
|
18
17
|
export const BUTTON_VARIANTS: Record<ButtonVariant, string> = {
|
|
19
18
|
primary: `
|
|
20
|
-
bg-primary text-on-primary
|
|
21
|
-
hover:bg-primary-hover
|
|
19
|
+
bg-primary text-on-primary border-transparent
|
|
20
|
+
hover:bg-primary-hover
|
|
22
21
|
active:bg-primary-active
|
|
23
22
|
`,
|
|
24
23
|
secondary: `
|
|
25
|
-
bg-surface-raised text-on-surface
|
|
26
|
-
hover:
|
|
24
|
+
bg-surface-raised text-on-surface border-outline
|
|
25
|
+
hover:border-outline-hover hover:text-primary
|
|
27
26
|
active:bg-surface-sunken
|
|
28
27
|
`,
|
|
29
28
|
ghost: `
|
|
30
|
-
bg-transparent text-on-surface-muted
|
|
29
|
+
bg-transparent text-on-surface-muted border-transparent
|
|
31
30
|
hover:bg-surface-sunken hover:text-on-surface
|
|
32
31
|
active:bg-surface-sunken
|
|
33
32
|
`,
|
|
34
33
|
danger: `
|
|
35
|
-
bg-danger-surface text-on-danger
|
|
36
|
-
hover:bg-danger-hover
|
|
34
|
+
bg-danger-surface text-on-danger border-transparent
|
|
35
|
+
hover:bg-danger-hover
|
|
37
36
|
active:bg-danger-active
|
|
38
37
|
`,
|
|
39
38
|
success: `
|
|
40
|
-
bg-success-surface text-on-success
|
|
41
|
-
hover:bg-success-hover
|
|
39
|
+
bg-success-surface text-on-success border-transparent
|
|
40
|
+
hover:bg-success-hover
|
|
42
41
|
active:bg-success-surface
|
|
43
42
|
`,
|
|
44
43
|
};
|
|
45
44
|
|
|
46
45
|
export const BUTTON_SIZES: Record<ButtonSize, string> = {
|
|
47
|
-
xs: "text-xs px-2 py-1 rounded-
|
|
48
|
-
sm: "text-sm px-3 py-1.5 rounded-
|
|
49
|
-
md: "text-sm px-4 py-2 rounded-
|
|
50
|
-
lg: "text-base px-6 py-
|
|
46
|
+
xs: "text-xs px-2.5 py-1 rounded-[3px]",
|
|
47
|
+
sm: "text-sm px-3 py-1.5 rounded-[3px]",
|
|
48
|
+
md: "text-sm px-4 py-2 rounded-[3px]",
|
|
49
|
+
lg: "text-base px-6 py-2.5 rounded-[3px]",
|
|
51
50
|
};
|
|
@@ -15,12 +15,13 @@
|
|
|
15
15
|
RotateCw,
|
|
16
16
|
RefreshCcw,
|
|
17
17
|
ChevronDown,
|
|
18
|
-
|
|
18
|
+
RotateCcwClock,
|
|
19
19
|
PanelLeftClose,
|
|
20
20
|
SlidersHorizontal,
|
|
21
21
|
Maximize2,
|
|
22
22
|
Minimize2,
|
|
23
23
|
TextWrap,
|
|
24
|
+
SearchX,
|
|
24
25
|
} from "@lucide/svelte";
|
|
25
26
|
import Button from "../Button.svelte";
|
|
26
27
|
import EmptyState from "../EmptyState.svelte";
|
|
@@ -67,6 +68,7 @@
|
|
|
67
68
|
historyVisible = false,
|
|
68
69
|
highlightLine = null,
|
|
69
70
|
getInstanceCount = () => 1,
|
|
71
|
+
notFound = false,
|
|
70
72
|
}: {
|
|
71
73
|
run: Run | undefined;
|
|
72
74
|
fetchLogs: (
|
|
@@ -112,6 +114,10 @@
|
|
|
112
114
|
// Resolves a task's currently configured instance count so multi-instance
|
|
113
115
|
// services render a 1-based #N suffix. Defaults to single-instance.
|
|
114
116
|
getInstanceCount?: (taskName: string) => number;
|
|
117
|
+
// True when a deep-linked run id resolved to no run (deleted by retention,
|
|
118
|
+
// or never existed). The empty state then says so plainly instead of the
|
|
119
|
+
// generic "Select a run" — the caller must not silently substitute another.
|
|
120
|
+
notFound?: boolean;
|
|
115
121
|
} = $props();
|
|
116
122
|
|
|
117
123
|
let canDelete = $derived.by(() => {
|
|
@@ -356,7 +362,7 @@
|
|
|
356
362
|
<div class="flex items-start gap-4">
|
|
357
363
|
<!-- Verdict tile -->
|
|
358
364
|
<div
|
|
359
|
-
class="flex h-[38px] w-[38px] shrink-0 items-center justify-center rounded-[
|
|
365
|
+
class="flex h-[38px] w-[38px] shrink-0 items-center justify-center rounded-[4px] {config.bg} {config.color} ring-1 ring-current/25 ring-inset"
|
|
360
366
|
>
|
|
361
367
|
<DetailIcon size={20} class={isRunning ? "animate-spin" : ""} />
|
|
362
368
|
</div>
|
|
@@ -382,7 +388,7 @@
|
|
|
382
388
|
outcome, so stopped reads amber, not red. -->
|
|
383
389
|
<Tooltip content={config.description} position="bottom" wide>
|
|
384
390
|
<span
|
|
385
|
-
class="rounded-
|
|
391
|
+
class="rounded-[3px] border px-2.5 py-0.5 font-mono text-2xs font-bold tracking-wider uppercase {config.color} {config.bg} {config.border}"
|
|
386
392
|
>
|
|
387
393
|
{status.toUpperCase()}
|
|
388
394
|
</span>
|
|
@@ -396,7 +402,7 @@
|
|
|
396
402
|
<!-- When the title carries the task name, the run's
|
|
397
403
|
date/time lives here in the sub-line (otherwise it's
|
|
398
404
|
already the title, so don't repeat it). -->
|
|
399
|
-
<span title={formatFullDateTime(startedAt)}>
|
|
405
|
+
<span class="font-mono" title={formatFullDateTime(startedAt)}>
|
|
400
406
|
Run · {formatCalendarDate(startedAt)}
|
|
401
407
|
{formatTimeHM(startedAt)}
|
|
402
408
|
</span>
|
|
@@ -406,7 +412,7 @@
|
|
|
406
412
|
type="button"
|
|
407
413
|
onclick={() => copyRunId(run.id)}
|
|
408
414
|
title="Copy run ID"
|
|
409
|
-
class="inline-flex items-center gap-1.5 rounded-
|
|
415
|
+
class="inline-flex items-center gap-1.5 rounded-[3px] border border-outline-faint bg-surface-sunken px-1.5 py-0.5 font-mono text-2xs text-on-surface-faint hover:border-outline-hover hover:text-primary"
|
|
410
416
|
>
|
|
411
417
|
{#if copiedId}
|
|
412
418
|
<Check size={11} class="text-success-surface" />Copied
|
|
@@ -417,7 +423,7 @@
|
|
|
417
423
|
{#if retry}
|
|
418
424
|
<span class="hidden h-1 w-1 rounded-full bg-outline-faint sm:block"
|
|
419
425
|
></span>
|
|
420
|
-
<span class="inline-flex items-center gap-1.5">
|
|
426
|
+
<span class="inline-flex items-center gap-1.5 font-mono">
|
|
421
427
|
<RotateCw size={14} />
|
|
422
428
|
Retry #{run.retry_attempt}{#if run.retry_of_run_id}
|
|
423
429
|
<span class="text-on-surface-faint"
|
|
@@ -431,7 +437,7 @@
|
|
|
431
437
|
<Popover placement="bottom-start">
|
|
432
438
|
{#snippet trigger()}
|
|
433
439
|
<span
|
|
434
|
-
class="inline-flex cursor-pointer items-center gap-1.5 rounded-
|
|
440
|
+
class="inline-flex cursor-pointer items-center gap-1.5 rounded-[3px] border border-outline-faint bg-surface-sunken px-2.5 py-0.5 font-mono text-xs font-medium text-on-surface-muted hover:border-outline-hover hover:text-primary"
|
|
435
441
|
title="View run parameters"
|
|
436
442
|
>
|
|
437
443
|
<SlidersHorizontal size={12} />
|
|
@@ -441,7 +447,7 @@
|
|
|
441
447
|
{/snippet}
|
|
442
448
|
<div class="max-w-md min-w-48">
|
|
443
449
|
<span
|
|
444
|
-
class="text-xs font-semibold tracking-
|
|
450
|
+
class="font-mono text-xs font-semibold tracking-[0.14em] text-on-surface-faint uppercase"
|
|
445
451
|
>Parameters</span
|
|
446
452
|
>
|
|
447
453
|
<dl
|
|
@@ -471,7 +477,7 @@
|
|
|
471
477
|
<button
|
|
472
478
|
type="button"
|
|
473
479
|
onclick={() => onToggleHistory()}
|
|
474
|
-
class="inline-flex items-center justify-center rounded-
|
|
480
|
+
class="inline-flex items-center justify-center rounded-[3px] border border-outline-faint bg-surface-raised p-2 text-on-surface-muted hover:border-outline-hover hover:bg-surface-sunken hover:text-primary"
|
|
475
481
|
title={historyVisible ? "Hide run history" : "Show run history"}
|
|
476
482
|
aria-label={historyVisible
|
|
477
483
|
? "Hide run history"
|
|
@@ -480,7 +486,7 @@
|
|
|
480
486
|
{#if historyVisible}
|
|
481
487
|
<PanelLeftClose size={15} />
|
|
482
488
|
{:else}
|
|
483
|
-
<
|
|
489
|
+
<RotateCcwClock size={15} />
|
|
484
490
|
{/if}
|
|
485
491
|
</button>
|
|
486
492
|
{/if}
|
|
@@ -499,7 +505,7 @@
|
|
|
499
505
|
title={serviceStopped
|
|
500
506
|
? "Starts the service"
|
|
501
507
|
: "Cancels and respawns every instance"}
|
|
502
|
-
class="inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-
|
|
508
|
+
class="inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-[3px] border border-primary-soft-border bg-surface-raised px-3 font-mono text-sm font-medium text-primary hover:bg-primary-soft active:translate-y-px disabled:cursor-not-allowed disabled:opacity-60"
|
|
503
509
|
>
|
|
504
510
|
{#if serviceStopped}
|
|
505
511
|
<Play size={15} fill="currentColor" stroke="none" />
|
|
@@ -517,7 +523,7 @@
|
|
|
517
523
|
onclick={() => onStopService()}
|
|
518
524
|
disabled={serviceBusy}
|
|
519
525
|
title="Stops the service for the rest of the daemon's lifetime"
|
|
520
|
-
class="inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-
|
|
526
|
+
class="inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-[3px] border border-danger-soft-border bg-surface-raised px-3 font-mono text-sm font-medium text-danger-surface hover:bg-danger-soft active:translate-y-px disabled:cursor-not-allowed disabled:opacity-60"
|
|
521
527
|
>
|
|
522
528
|
<Square size={15} fill="currentColor" stroke="none" />
|
|
523
529
|
<span class="@max-md:hidden">Stop Service</span>
|
|
@@ -528,13 +534,13 @@
|
|
|
528
534
|
<!-- Split button: Run (defaults) + an arrow for the
|
|
529
535
|
reuse-parameters variant, shown only when there is one. -->
|
|
530
536
|
<div
|
|
531
|
-
class="inline-flex overflow-hidden rounded-
|
|
537
|
+
class="inline-flex overflow-hidden rounded-[3px] border border-primary-soft-border"
|
|
532
538
|
>
|
|
533
539
|
<button
|
|
534
540
|
type="button"
|
|
535
541
|
onclick={() => onRun()}
|
|
536
542
|
title="Run this task now with default options"
|
|
537
|
-
class="inline-flex h-9 cursor-pointer items-center gap-1.5 bg-surface-raised px-3 text-sm font-medium text-primary
|
|
543
|
+
class="inline-flex h-9 cursor-pointer items-center gap-1.5 bg-surface-raised px-3 font-mono text-sm font-medium text-primary hover:bg-primary-soft active:translate-y-px"
|
|
538
544
|
>
|
|
539
545
|
<Play size={15} fill="currentColor" stroke="none" />
|
|
540
546
|
<span class="@max-md:hidden">Run</span>
|
|
@@ -543,7 +549,7 @@
|
|
|
543
549
|
<Popover bind:open={runMenuOpen} placement="bottom-end">
|
|
544
550
|
{#snippet trigger()}
|
|
545
551
|
<span
|
|
546
|
-
class="flex h-9 cursor-pointer items-center border-l border-primary-soft bg-surface-raised px-2 text-primary
|
|
552
|
+
class="flex h-9 cursor-pointer items-center border-l border-primary-soft-border bg-surface-raised px-2 text-primary hover:bg-primary-soft"
|
|
547
553
|
title="More run options"
|
|
548
554
|
aria-label="More run options"
|
|
549
555
|
>
|
|
@@ -564,7 +570,7 @@
|
|
|
564
570
|
/>
|
|
565
571
|
<span class="flex flex-col">
|
|
566
572
|
<span
|
|
567
|
-
class="text-sm font-medium text-on-surface"
|
|
573
|
+
class="font-mono text-sm font-medium text-on-surface"
|
|
568
574
|
>Run again</span
|
|
569
575
|
>
|
|
570
576
|
<span class="text-xs text-on-surface-muted"
|
|
@@ -580,7 +586,7 @@
|
|
|
580
586
|
<button
|
|
581
587
|
type="button"
|
|
582
588
|
onclick={() => onStop(run.id)}
|
|
583
|
-
class="inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-
|
|
589
|
+
class="inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-[3px] border border-danger-soft-border bg-surface-raised px-3 font-mono text-sm font-medium text-danger-surface hover:bg-danger-soft active:translate-y-px"
|
|
584
590
|
>
|
|
585
591
|
<Square size={15} fill="currentColor" stroke="none" />
|
|
586
592
|
<span class="@max-md:hidden">Stop</span>
|
|
@@ -592,7 +598,7 @@
|
|
|
592
598
|
run.task_name,
|
|
593
599
|
)}/runs/{encodeURIComponent(run.id)}/log/raw"
|
|
594
600
|
download="{run.task_name}-{run.id}.log"
|
|
595
|
-
class="inline-flex items-center justify-center rounded-
|
|
601
|
+
class="inline-flex items-center justify-center rounded-[3px] border border-outline-faint bg-surface-raised p-2 text-on-surface-muted hover:border-outline-hover hover:bg-surface-sunken hover:text-primary"
|
|
596
602
|
title="Download the full log (rotated and current parts as one file)"
|
|
597
603
|
aria-label="Download log"
|
|
598
604
|
>
|
|
@@ -602,7 +608,7 @@
|
|
|
602
608
|
<Popover bind:open={confirmDeleteOpen} placement="bottom-end">
|
|
603
609
|
{#snippet trigger()}
|
|
604
610
|
<span
|
|
605
|
-
class="flex cursor-pointer items-center justify-center rounded-
|
|
611
|
+
class="flex cursor-pointer items-center justify-center rounded-[3px] border border-outline-faint bg-surface-raised p-2 text-on-surface-muted hover:border-danger-soft-border hover:bg-danger-soft hover:text-danger-surface"
|
|
606
612
|
title="Delete this run"
|
|
607
613
|
aria-label="Delete run"
|
|
608
614
|
>
|
|
@@ -610,7 +616,7 @@
|
|
|
610
616
|
</span>
|
|
611
617
|
{/snippet}
|
|
612
618
|
<div class="w-60">
|
|
613
|
-
<div class="text-sm font-semibold text-on-surface">
|
|
619
|
+
<div class="font-mono text-sm font-semibold text-on-surface">
|
|
614
620
|
Delete this run?
|
|
615
621
|
</div>
|
|
616
622
|
<div class="mt-1 text-xs leading-relaxed text-on-surface-muted">
|
|
@@ -645,13 +651,13 @@
|
|
|
645
651
|
<!-- Instrument cluster: the run's vital readout — value over a one-word
|
|
646
652
|
context line, hairline-divided. -->
|
|
647
653
|
<div
|
|
648
|
-
class="mt-4 flex flex-wrap overflow-hidden rounded-
|
|
654
|
+
class="mt-4 flex flex-wrap overflow-hidden rounded-[4px] border border-outline-faint bg-surface-raised"
|
|
649
655
|
>
|
|
650
656
|
<div
|
|
651
657
|
class="flex min-w-30 flex-1 flex-col gap-0.5 border-l border-outline-faint px-4 py-2.5 first:border-l-0"
|
|
652
658
|
>
|
|
653
659
|
<span
|
|
654
|
-
class="text-2xs font-bold tracking-
|
|
660
|
+
class="font-mono text-2xs font-bold tracking-[0.12em] text-on-surface-faint uppercase"
|
|
655
661
|
>Queued</span
|
|
656
662
|
>
|
|
657
663
|
<span
|
|
@@ -660,7 +666,7 @@
|
|
|
660
666
|
>
|
|
661
667
|
{formatClockTime(run.created_at)}
|
|
662
668
|
</span>
|
|
663
|
-
<span class="text-2xs text-on-surface-muted"
|
|
669
|
+
<span class="font-mono text-2xs text-on-surface-muted"
|
|
664
670
|
>+{startDelay ?? "0s"} queued</span
|
|
665
671
|
>
|
|
666
672
|
</div>
|
|
@@ -669,7 +675,7 @@
|
|
|
669
675
|
class="flex min-w-30 flex-1 flex-col gap-0.5 border-l border-outline-faint px-4 py-2.5 first:border-l-0"
|
|
670
676
|
>
|
|
671
677
|
<span
|
|
672
|
-
class="text-2xs font-bold tracking-
|
|
678
|
+
class="font-mono text-2xs font-bold tracking-[0.12em] text-on-surface-faint uppercase"
|
|
673
679
|
>Started</span
|
|
674
680
|
>
|
|
675
681
|
<span
|
|
@@ -677,7 +683,7 @@
|
|
|
677
683
|
>
|
|
678
684
|
{run.start_at ? formatClockTime(run.start_at) : "—"}
|
|
679
685
|
</span>
|
|
680
|
-
<span class="text-2xs text-on-surface-muted">
|
|
686
|
+
<span class="font-mono text-2xs text-on-surface-muted">
|
|
681
687
|
{run.start_at ? formatCalendarDate(run.start_at) : "not started"}
|
|
682
688
|
</span>
|
|
683
689
|
</div>
|
|
@@ -686,7 +692,7 @@
|
|
|
686
692
|
class="flex min-w-30 flex-1 flex-col gap-0.5 border-l border-outline-faint px-4 py-2.5 first:border-l-0"
|
|
687
693
|
>
|
|
688
694
|
<span
|
|
689
|
-
class="text-2xs font-bold tracking-
|
|
695
|
+
class="font-mono text-2xs font-bold tracking-[0.12em] text-on-surface-faint uppercase"
|
|
690
696
|
>Ran for</span
|
|
691
697
|
>
|
|
692
698
|
<span
|
|
@@ -694,7 +700,7 @@
|
|
|
694
700
|
>
|
|
695
701
|
{duration ?? "—"}
|
|
696
702
|
</span>
|
|
697
|
-
<span class="text-2xs text-on-surface-muted">
|
|
703
|
+
<span class="font-mono text-2xs text-on-surface-muted">
|
|
698
704
|
{isRunning ? "and counting" : run.end_at ? "wall clock" : "—"}
|
|
699
705
|
</span>
|
|
700
706
|
</div>
|
|
@@ -703,7 +709,7 @@
|
|
|
703
709
|
class="flex min-w-30 flex-1 flex-col gap-0.5 border-l border-outline-faint px-4 py-2.5 first:border-l-0"
|
|
704
710
|
>
|
|
705
711
|
<span
|
|
706
|
-
class="text-2xs font-bold tracking-
|
|
712
|
+
class="font-mono text-2xs font-bold tracking-[0.12em] text-on-surface-faint uppercase"
|
|
707
713
|
>Exit</span
|
|
708
714
|
>
|
|
709
715
|
<span
|
|
@@ -716,26 +722,28 @@
|
|
|
716
722
|
<span>{showCode ? run.exit_code : "—"}</span>
|
|
717
723
|
{#if exitFail}
|
|
718
724
|
<span
|
|
719
|
-
class="rounded bg-danger-soft px-1 py-px text-[9px] font-bold tracking-wide text-danger-surface uppercase"
|
|
725
|
+
class="rounded-[3px] bg-danger-soft px-1 py-px font-mono text-[9px] font-bold tracking-wide text-danger-surface uppercase"
|
|
720
726
|
>fail</span
|
|
721
727
|
>
|
|
722
728
|
{/if}
|
|
723
729
|
</span>
|
|
724
|
-
<span class="text-2xs text-on-surface-muted"
|
|
730
|
+
<span class="font-mono text-2xs text-on-surface-muted"
|
|
731
|
+
>{exitSubLabel(status)}</span
|
|
732
|
+
>
|
|
725
733
|
</div>
|
|
726
734
|
|
|
727
735
|
<div
|
|
728
736
|
class="flex min-w-30 flex-1 flex-col gap-0.5 border-l border-outline-faint px-4 py-2.5 first:border-l-0"
|
|
729
737
|
>
|
|
730
738
|
<span
|
|
731
|
-
class="text-2xs font-bold tracking-
|
|
739
|
+
class="font-mono text-2xs font-bold tracking-[0.12em] text-on-surface-faint uppercase"
|
|
732
740
|
>Trigger</span
|
|
733
741
|
>
|
|
734
742
|
<span
|
|
735
743
|
class="font-mono text-base font-medium tracking-tight whitespace-nowrap text-on-surface tabular-nums"
|
|
736
744
|
>{formatTriggeredByLabel(run.triggered_by)}</span
|
|
737
745
|
>
|
|
738
|
-
<span class="text-2xs text-on-surface-muted"
|
|
746
|
+
<span class="font-mono text-2xs text-on-surface-muted"
|
|
739
747
|
>{triggerSub(run.triggered_by)}</span
|
|
740
748
|
>
|
|
741
749
|
</div>
|
|
@@ -755,25 +763,27 @@
|
|
|
755
763
|
<div
|
|
756
764
|
use:maximizePortal={consoleMaximized}
|
|
757
765
|
class={consoleMaximized
|
|
758
|
-
? "console-zoom fixed inset-3 z-50 flex flex-col overflow-hidden rounded-
|
|
759
|
-
: "ml-1 flex min-h-[300px] flex-1 flex-col overflow-hidden border-t border-[
|
|
766
|
+
? "console-zoom fixed inset-3 z-50 flex flex-col overflow-hidden rounded-[4px] bg-[var(--rw-con-bg)] shadow-2xl ring-1 ring-[var(--rw-con-gutter)] sm:inset-6"
|
|
767
|
+
: "ml-1 flex min-h-[300px] flex-1 flex-col overflow-hidden border-t border-[var(--rw-con-gutter)] bg-[var(--rw-con-bg)]"}
|
|
760
768
|
>
|
|
761
769
|
<div
|
|
762
|
-
class="flex shrink-0 items-center justify-between gap-3 border-b border-[
|
|
770
|
+
class="flex shrink-0 items-center justify-between gap-3 border-b border-[var(--rw-con-gutter)] bg-[var(--rw-con-panel)] px-3.5 py-[9px] font-mono text-[11.5px] text-[var(--rw-con-dim)]"
|
|
763
771
|
>
|
|
764
772
|
<div class="flex min-w-0 items-center gap-3">
|
|
765
773
|
{#if consoleMaximized}
|
|
766
774
|
<!-- Focus-mode identity: which run is filling the screen -->
|
|
767
775
|
<span class="flex min-w-0 items-center gap-2">
|
|
768
776
|
<span class="h-2 w-2 shrink-0 rounded-full {spine}"></span>
|
|
769
|
-
<span class="truncate font-medium text-[
|
|
777
|
+
<span class="truncate font-medium text-[var(--rw-con-text)]">
|
|
770
778
|
{run.task_name}{suffix}
|
|
771
779
|
</span>
|
|
772
780
|
<span class="text-[var(--rw-con-gutter)]">·</span>
|
|
773
781
|
<span class="font-semibold capitalize {config.color}">{status}</span>
|
|
774
782
|
</span>
|
|
775
783
|
{:else}
|
|
776
|
-
<span
|
|
784
|
+
<span
|
|
785
|
+
class="flex items-center gap-2 font-semibold text-[var(--rw-con-text)]"
|
|
786
|
+
>
|
|
777
787
|
<TerminalIcon size={14} class="opacity-70" />
|
|
778
788
|
Console output
|
|
779
789
|
</span>
|
|
@@ -786,8 +796,8 @@
|
|
|
786
796
|
<button
|
|
787
797
|
type="button"
|
|
788
798
|
onclick={() => (consoleWrap = !consoleWrap)}
|
|
789
|
-
class="flex cursor-pointer items-center gap-1.5 rounded-
|
|
790
|
-
? 'text-[
|
|
799
|
+
class="flex cursor-pointer items-center gap-1.5 rounded-[3px] px-2 py-1 hover:bg-[var(--rw-con-gutter)]/30 hover:text-[var(--rw-con-text)] {consoleWrap
|
|
800
|
+
? 'text-[var(--rw-con-text)]'
|
|
791
801
|
: 'text-[var(--rw-con-dim)]'}"
|
|
792
802
|
title={consoleWrap ? "Unwrap lines" : "Wrap long lines"}
|
|
793
803
|
aria-pressed={consoleWrap}
|
|
@@ -799,14 +809,14 @@
|
|
|
799
809
|
<button
|
|
800
810
|
type="button"
|
|
801
811
|
onclick={() => (consoleMaximized = !consoleMaximized)}
|
|
802
|
-
class="flex cursor-pointer items-center gap-1.5 rounded-
|
|
812
|
+
class="flex cursor-pointer items-center gap-1.5 rounded-[3px] px-2 py-1 text-[var(--rw-con-dim)] hover:bg-[var(--rw-con-gutter)]/30 hover:text-[var(--rw-con-text)]"
|
|
803
813
|
title={consoleMaximized ? "Restore console (Esc)" : "Maximize console · F"}
|
|
804
814
|
aria-label={consoleMaximized ? "Restore console" : "Maximize console"}
|
|
805
815
|
>
|
|
806
816
|
{#if consoleMaximized}
|
|
807
817
|
<Minimize2 size={13} />
|
|
808
818
|
<span
|
|
809
|
-
class="rounded border border-[var(--rw-con-gutter)] px-1.5 text-[10px] tracking-wide"
|
|
819
|
+
class="rounded-[3px] border border-[var(--rw-con-gutter)] px-1.5 text-[10px] tracking-wide"
|
|
810
820
|
>Esc</span
|
|
811
821
|
>
|
|
812
822
|
{:else}
|
|
@@ -837,17 +847,19 @@
|
|
|
837
847
|
class="flex min-w-0 flex-1 flex-col items-center justify-center gap-4 bg-surface-sunken/30"
|
|
838
848
|
>
|
|
839
849
|
<EmptyState
|
|
840
|
-
title={onRunTask ? "No runs yet" : "Select a run"}
|
|
841
|
-
description={
|
|
842
|
-
? "This
|
|
843
|
-
:
|
|
844
|
-
|
|
850
|
+
title={notFound ? "Run not found" : onRunTask ? "No runs yet" : "Select a run"}
|
|
851
|
+
description={notFound
|
|
852
|
+
? "This run doesn't exist — it may have been deleted by retention, or the link is wrong. Pick a run from the list to continue."
|
|
853
|
+
: onRunTask
|
|
854
|
+
? "This task hasn't run yet. Trigger it to see its output here."
|
|
855
|
+
: "Pick a run from the list to view details and logs."}
|
|
856
|
+
icon={notFound ? SearchX : MousePointerClick}
|
|
845
857
|
/>
|
|
846
|
-
{#if onRunTask}
|
|
858
|
+
{#if onRunTask && !notFound}
|
|
847
859
|
<button
|
|
848
860
|
type="button"
|
|
849
861
|
onclick={() => onRunTask()}
|
|
850
|
-
class="inline-flex cursor-pointer items-center gap-1.5 rounded-
|
|
862
|
+
class="inline-flex cursor-pointer items-center gap-1.5 rounded-[3px] border border-primary-soft-border bg-surface-raised px-3 py-2 font-mono text-sm font-medium text-primary hover:bg-primary-soft active:translate-y-px"
|
|
851
863
|
>
|
|
852
864
|
<Play size={15} fill="currentColor" stroke="none" />
|
|
853
865
|
Run task
|
|
@@ -866,7 +878,7 @@
|
|
|
866
878
|
|
|
867
879
|
/* Gentle fade for the maximize backdrop; disabled under reduced motion. */
|
|
868
880
|
.console-backdrop {
|
|
869
|
-
animation: console-backdrop-in 150ms
|
|
881
|
+
animation: console-backdrop-in 150ms;
|
|
870
882
|
}
|
|
871
883
|
@keyframes console-backdrop-in {
|
|
872
884
|
from {
|