ui: enable pagination on Activity page and fix table reactivity

- add showPagination to Activity route's ActivityTable
- fix pagination reactivity: reassign pagination object in
  onPaginationChange so TanStack's effect.pre detects the change, and
  reset to first page only when pageSize changes
- move data-change page reset into untrack to avoid clobbering
  navigation
- render Cached/Prompt/Drafted headers with a dotted underline trigger
  instead of a separate info icon
This commit is contained in:
Benson Wong
2026-06-28 03:43:55 +00:00
parent 040ee1e284
commit d207a059a4
3 changed files with 25 additions and 13 deletions
+18 -11
View File
@@ -1,4 +1,5 @@
<script lang="ts">
import { untrack } from "svelte";
import type { ActivityLogEntry, ReqRespCapture } from "../lib/types";
import { getCapture } from "../stores/api";
import { persistentStore } from "../stores/persistent";
@@ -135,23 +136,21 @@
// svelte-ignore state_referenced_locally
const storedPageSize = persistentStore<number>(`${storagePrefix}-page-size`, 10);
// When not paginating, use a large page size so all rows render in one page.
// svelte-ignore state_referenced_locally
let pagination = $state<PaginationState>({
pageIndex: 0,
pageSize: showPagination ? $storedPageSize : 1,
});
// When not paginating, show every row; reset page on data/pageSize change.
$effect(() => {
if (!showPagination) {
pagination.pageSize = metrics.length || 1;
}
pageSize: showPagination ? $storedPageSize : Number.MAX_SAFE_INTEGER,
});
// Reset to the first page when the data source changes. We deliberately do
// NOT track pagination here — page-size changes reset pageIndex inside
// onPaginationChange instead, to avoid clobbering page navigation.
$effect(() => {
metrics;
pagination.pageSize;
pagination.pageIndex = 0;
untrack(() => {
pagination = { ...pagination, pageIndex: 0 };
});
});
let selectedCapture = $state<ReqRespCapture | null>(null);
@@ -286,8 +285,16 @@
},
},
onPaginationChange: (updater) => {
const prev = pagination;
const next =
typeof updater === "function" ? updater(prev) : updater;
// Reassign so the table's $effect.pre (which reads state.pagination)
// picks up the new value. Reset to first page when the page size
// changes so we don't land on an empty page.
pagination =
typeof updater === "function" ? updater(pagination) : updater;
next.pageSize !== prev.pageSize
? { pageIndex: 0, pageSize: next.pageSize }
: next;
if (showPagination) storedPageSize.set(pagination.pageSize);
},
onColumnVisibilityChange: (updater) => {
@@ -9,9 +9,13 @@
let { label, tooltip }: Props = $props();
</script>
{label}{#if tooltip}
{#if tooltip}
<Tooltip.Root>
<Tooltip.Trigger class="cursor-help align-middle normal-case">&#9432;</Tooltip.Trigger>
<Tooltip.Trigger class="cursor-help border-b border-dotted border-current align-middle">
{label}
</Tooltip.Trigger>
<Tooltip.Content>{tooltip}</Tooltip.Content>
</Tooltip.Root>
{:else}
{label}
{/if}
+1
View File
@@ -15,6 +15,7 @@
metrics={sortedMetrics}
storagePrefix="activity"
showModelColumn={true}
showPagination={true}
cardClass="min-h-[30rem] overflow-auto"
emptyMessage="No activity recorded"
/>