feat(ui): interactive graph, strip context menus, days by activity, message times, limit status words
This commit is contained in:
+60
-20
@@ -14,7 +14,7 @@
|
||||
import type { ConversationIndex } from "$lib/panel/index.svelte";
|
||||
import Strip from "$lib/shell/strip.svelte";
|
||||
import { cn } from "$lib/utils";
|
||||
import { type DayGroup, groupByDay } from "./days";
|
||||
import { type DayGroup, daySummary, groupByDay } from "./days";
|
||||
import NewConversation from "./new-conversation.svelte";
|
||||
|
||||
let {
|
||||
@@ -64,10 +64,9 @@
|
||||
}
|
||||
return index.conversations.filter(
|
||||
(row) =>
|
||||
row.kind !== "job" &&
|
||||
((row.title ?? "").toLowerCase().includes(needle) ||
|
||||
row.id.startsWith(needle) ||
|
||||
(row.last_item?.text ?? "").toLowerCase().includes(needle))
|
||||
(row.title ?? "").toLowerCase().includes(needle) ||
|
||||
row.id.startsWith(needle) ||
|
||||
(row.last_item?.text ?? "").toLowerCase().includes(needle)
|
||||
);
|
||||
});
|
||||
|
||||
@@ -120,22 +119,20 @@
|
||||
expanded = next;
|
||||
}
|
||||
|
||||
function summary(group: DayGroup): string {
|
||||
const parts: string[] = [];
|
||||
if (group.branches.length) {
|
||||
parts.push(
|
||||
`${group.branches.length} ${group.branches.length === 1 ? "branch" : "branches"}`
|
||||
);
|
||||
let jobsOpen = $state<Set<string>>(new Set());
|
||||
|
||||
function toggleJobs(day: string) {
|
||||
const next = new Set(jobsOpen);
|
||||
if (next.has(day)) {
|
||||
next.delete(day);
|
||||
} else {
|
||||
next.add(day);
|
||||
}
|
||||
if (group.deep.length) {
|
||||
parts.push(`${group.deep.length} deep`);
|
||||
}
|
||||
if (group.others.length) {
|
||||
parts.push(`${group.others.length} more`);
|
||||
}
|
||||
return parts.join(" · ");
|
||||
jobsOpen = next;
|
||||
}
|
||||
|
||||
const refresh = () => index.load().catch(() => undefined);
|
||||
|
||||
const linkOf = (id: string) => href?.(id);
|
||||
</script>
|
||||
|
||||
@@ -188,10 +185,12 @@
|
||||
<div class="bay-rack">
|
||||
{#each found as row (row.id)}
|
||||
<Strip
|
||||
{client}
|
||||
current={row.id === selected}
|
||||
detail={row.last_item?.text ?? ""}
|
||||
href={linkOf(row.id)}
|
||||
{now}
|
||||
onChanged={refresh}
|
||||
onclick={onOpen}
|
||||
{row}
|
||||
/>
|
||||
@@ -254,17 +253,19 @@
|
||||
></span>
|
||||
{/if}
|
||||
<span class="truncate text-muted-foreground text-xs">
|
||||
{summary(group)}
|
||||
{daySummary(group, position === 0)}
|
||||
</span>
|
||||
</button>
|
||||
{#if shown}
|
||||
<div class="bay-rack">
|
||||
{#if group.master}
|
||||
<Strip
|
||||
{client}
|
||||
current={group.master.id === selected}
|
||||
detail={group.master.last_item?.text ?? ""}
|
||||
href={linkOf(group.master.id)}
|
||||
{now}
|
||||
onChanged={refresh}
|
||||
onclick={onOpen}
|
||||
row={group.master}
|
||||
/>
|
||||
@@ -272,34 +273,73 @@
|
||||
{#each group.branches as row (row.id)}
|
||||
<Strip
|
||||
class="strip-child"
|
||||
{client}
|
||||
current={row.id === selected}
|
||||
detail={row.last_item?.text ?? ""}
|
||||
href={linkOf(row.id)}
|
||||
{now}
|
||||
onChanged={refresh}
|
||||
onclick={onOpen}
|
||||
{row}
|
||||
/>
|
||||
{/each}
|
||||
{#each group.deep as row (row.id)}
|
||||
<Strip
|
||||
{client}
|
||||
current={row.id === selected}
|
||||
detail={row.last_item?.text ?? ""}
|
||||
href={linkOf(row.id)}
|
||||
{now}
|
||||
onChanged={refresh}
|
||||
onclick={onOpen}
|
||||
{row}
|
||||
/>
|
||||
{/each}
|
||||
{#each group.others as row (row.id)}
|
||||
{#each [...group.forks, ...group.others] as row (row.id)}
|
||||
<Strip
|
||||
class="strip-child"
|
||||
{client}
|
||||
current={row.id === selected}
|
||||
detail="{row.kind} · {row.status}"
|
||||
href={linkOf(row.id)}
|
||||
{now}
|
||||
onChanged={refresh}
|
||||
onclick={onOpen}
|
||||
{row}
|
||||
/>
|
||||
{/each}
|
||||
{#if group.jobs.length > 0}
|
||||
{@const shownJobs = jobsOpen.has(group.day)}
|
||||
<button
|
||||
aria-expanded={shownJobs}
|
||||
class="strip w-full text-left text-muted-foreground text-xs"
|
||||
onclick={() => toggleJobs(group.day)}
|
||||
type="button"
|
||||
>
|
||||
<span class="size-5"></span>
|
||||
<span>
|
||||
{group.jobs.length}
|
||||
{group.jobs.length === 1 ? "job run" : "job runs"}
|
||||
· {shownJobs ? "hide" : "show"}
|
||||
</span>
|
||||
<span></span>
|
||||
</button>
|
||||
{#if shownJobs}
|
||||
{#each group.jobs as row (row.id)}
|
||||
<Strip
|
||||
class="strip-child"
|
||||
{client}
|
||||
current={row.id === selected}
|
||||
detail={row.last_item?.text ?? ""}
|
||||
href={linkOf(row.id)}
|
||||
{now}
|
||||
onChanged={refresh}
|
||||
onclick={onOpen}
|
||||
{row}
|
||||
/>
|
||||
{/each}
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user