M9 diagnostics follow-ups: playback relabel, sort, connected fix, per-skip + track-identity #105

Merged
bvandeusen merged 4 commits from dev into main 2026-06-30 19:19:15 -04:00
Showing only changes of commit 96b15b75e6 - Show all commits
+57 -18
View File
@@ -36,13 +36,26 @@
} }
} }
// Default view = the most recent N events, no time window. The
// start/end window is an Advanced affordance.
const DEFAULT_LIMIT = 500;
// Filter state. // Filter state.
let accountId = $state(''); let accountId = $state('');
let clientId = $state(''); let clientId = $state('');
let kind = $state(''); let kind = $state('');
let fromLocal = $state(''); let fromLocal = $state('');
let toLocal = $state(''); let toLocal = $state('');
let limit = $state(500); let limit = $state(DEFAULT_LIMIT);
// True when an explicit time window is set (drives the caption wording).
const hasWindow = $derived(Boolean(fromLocal || toLocal));
function resetWindow() {
fromLocal = '';
toLocal = '';
limit = DEFAULT_LIMIT;
}
// datetime-local (browser-local, no tz) → RFC3339 UTC the API accepts. // datetime-local (browser-local, no tz) → RFC3339 UTC the API accepts.
function toRfc(v: string): string | undefined { function toRfc(v: string): string | undefined {
@@ -191,8 +204,10 @@
</div> </div>
</section> </section>
<!-- Filters --> <!-- Filters. Default view = most recent {DEFAULT_LIMIT} events, no time
<section class="flex flex-wrap items-end gap-3"> window; the start/end window lives under Advanced. -->
<section class="space-y-3">
<div class="flex flex-wrap items-end gap-3">
<label class="block text-xs text-text-secondary"> <label class="block text-xs text-text-secondary">
Device Device
<select <select
@@ -217,6 +232,34 @@
{/each} {/each}
</select> </select>
</label> </label>
<div class="ml-auto flex gap-2">
<button
type="button"
onclick={onCopyJson}
disabled={rows.length === 0}
class="inline-flex items-center gap-1.5 rounded border border-border px-3 py-2 text-sm text-text-primary hover:bg-surface-hover disabled:opacity-50"
>
<Copy size={15} /> Copy JSON
</button>
<button
type="button"
onclick={onDownloadNdjson}
disabled={rows.length === 0}
class="inline-flex items-center gap-1.5 rounded border border-border px-3 py-2 text-sm text-text-primary hover:bg-surface-hover disabled:opacity-50"
>
<Download size={15} /> Download
</button>
</div>
</div>
<!-- Advanced: explicit start/end window + row cap. Collapsed by
default so the common case (recent N) needs no interaction. -->
<details class="rounded-md border border-border" open={hasWindow}>
<summary class="cursor-pointer px-3 py-2 text-xs text-text-secondary">
Advanced filters{hasWindow ? ' · window active' : ''}
</summary>
<div class="flex flex-wrap items-end gap-3 border-t border-border px-3 py-3">
<label class="block text-xs text-text-secondary"> <label class="block text-xs text-text-secondary">
From From
<input <input
@@ -243,25 +286,15 @@
class="mt-1 block w-24 rounded border border-border bg-surface px-2 py-1.5 text-sm text-text-primary" class="mt-1 block w-24 rounded border border-border bg-surface px-2 py-1.5 text-sm text-text-primary"
/> />
</label> </label>
<div class="ml-auto flex gap-2">
<button <button
type="button" type="button"
onclick={onCopyJson} onclick={resetWindow}
disabled={rows.length === 0} class="rounded border border-border px-3 py-2 text-sm text-text-secondary hover:bg-surface-hover"
class="inline-flex items-center gap-1.5 rounded border border-border px-3 py-2 text-sm text-text-primary hover:bg-surface-hover disabled:opacity-50"
> >
<Copy size={15} /> Copy JSON Reset to recent {DEFAULT_LIMIT}
</button>
<button
type="button"
onclick={onDownloadNdjson}
disabled={rows.length === 0}
class="inline-flex items-center gap-1.5 rounded border border-border px-3 py-2 text-sm text-text-primary hover:bg-surface-hover disabled:opacity-50"
>
<Download size={15} /> Download
</button> </button>
</div> </div>
</details>
</section> </section>
<!-- Timeline --> <!-- Timeline -->
@@ -276,7 +309,13 @@
</p> </p>
{:else} {:else}
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<span class="text-xs text-text-muted">{rows.length} events (oldest first)</span> <span class="text-xs text-text-muted">
{#if hasWindow}
{rows.length} events in window (oldest first)
{:else}
Most recent {rows.length} events (oldest first) · set a time window under Advanced
{/if}
</span>
</div> </div>
<ul class="divide-y divide-border rounded-md border border-border font-mono text-xs"> <ul class="divide-y divide-border rounded-md border border-border font-mono text-xs">
{#each rows as r (r.id)} {#each rows as r (r.id)}