feat(documents): rebalance list row — summary + archive chips, restored sender/receiver
Refill the columns that went visually empty after the previous dedup commit (`fc0fc57`): - Middle column gains the document `summary` (line-clamp-2, italic, with `summaryOffsets` highlighting — the backend already populates the offsets, the frontend just wasn't rendering them) and a row of thin neutral chips for `archiveBox`, `archiveFolder`, and `location` (~99% of docs in the corpus carry these). Chips are desktop-only and skip empty values. - Right column restores `VON sender` and `AN receivers`, now with `<mark>` highlighting that the previous right-column copy lacked, so search matches stay visible there. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,15 @@ const snippet = $derived(item.matchData?.transcriptionSnippet ?? null);
|
||||
const snippetSegments = $derived(
|
||||
snippet ? applyOffsets(snippet, item.matchData?.snippetOffsets ?? []) : null
|
||||
);
|
||||
const summary = $derived(doc.summary?.trim() ? doc.summary : null);
|
||||
const summarySegments = $derived(
|
||||
summary ? applyOffsets(summary, item.matchData?.summaryOffsets ?? []) : null
|
||||
);
|
||||
const archiveChips = $derived(
|
||||
[doc.archiveBox, doc.archiveFolder, doc.location].filter(
|
||||
(c): c is string => !!c && c.trim().length > 0
|
||||
)
|
||||
);
|
||||
const senderMatched = $derived(item.matchData?.senderMatched ?? false);
|
||||
const matchedReceiverIds = $derived(new Set(item.matchData?.matchedReceiverIds ?? []));
|
||||
const matchedTagIds = $derived(new Set(item.matchData?.matchedTagIds ?? []));
|
||||
@@ -77,46 +86,36 @@ function safeTagColor(color: string | null | undefined): string {
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<!-- Sender / receivers — desktop only, stacked -->
|
||||
<div class="mt-2 mb-2 hidden flex-col gap-1 font-sans text-xs text-ink-2 sm:flex">
|
||||
<div>
|
||||
<span class="font-bold tracking-wide text-ink-3 uppercase">{m.docs_list_from()}</span>
|
||||
<span class="ml-1">
|
||||
{#if doc.sender}
|
||||
{#if senderMatched}
|
||||
<mark
|
||||
class="bg-transparent text-inherit underline decoration-brand-navy decoration-2 underline-offset-2"
|
||||
>{doc.sender.displayName}</mark
|
||||
>
|
||||
{:else}
|
||||
{doc.sender.displayName}
|
||||
{/if}
|
||||
<!-- Summary excerpt — only when populated -->
|
||||
{#if summarySegments}
|
||||
<p
|
||||
data-testid="doc-summary"
|
||||
class="mt-1 mb-2 line-clamp-2 font-serif text-sm text-ink-2 italic"
|
||||
>
|
||||
{#each summarySegments as seg, i (i)}
|
||||
{#if seg.highlight}
|
||||
<mark
|
||||
class="bg-transparent text-inherit underline decoration-brand-navy decoration-2 underline-offset-2"
|
||||
>{seg.text}</mark
|
||||
>
|
||||
{:else}
|
||||
<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
|
||||
{seg.text}
|
||||
{/if}
|
||||
</span>
|
||||
{/each}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
<!-- Archive metadata chips — desktop only -->
|
||||
{#if archiveChips.length > 0}
|
||||
<div class="mt-2 hidden flex-wrap items-center gap-1.5 sm:flex">
|
||||
{#each archiveChips as chip, i (i)}
|
||||
<span
|
||||
class="rounded border border-line px-1.5 py-0.5 font-sans text-[10px] tracking-widest text-ink-3 uppercase"
|
||||
>{chip}</span
|
||||
>
|
||||
{/each}
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-bold tracking-wide text-ink-3 uppercase">{m.docs_list_to()}</span>
|
||||
<span class="ml-1">
|
||||
{#if doc.receivers && doc.receivers.length > 0}
|
||||
{#each doc.receivers as receiver, i (receiver.id)}
|
||||
{#if i > 0}<span>, </span>{/if}
|
||||
{#if matchedReceiverIds.has(receiver.id)}
|
||||
<mark
|
||||
class="bg-transparent text-inherit underline decoration-brand-navy decoration-2 underline-offset-2"
|
||||
>{receiver.displayName}</mark
|
||||
>
|
||||
{:else}
|
||||
{receiver.displayName}
|
||||
{/if}
|
||||
{/each}
|
||||
{:else}
|
||||
<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Tags -->
|
||||
{#if doc.tags && doc.tags.length > 0}
|
||||
@@ -158,6 +157,43 @@ function safeTagColor(color: string | null | undefined): string {
|
||||
<div>
|
||||
{doc.documentDate ? formatDate(doc.documentDate) : '—'}
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-bold tracking-wide text-ink-3 uppercase">{m.docs_list_from()}</span>
|
||||
<span class="ml-1">
|
||||
{#if doc.sender}
|
||||
{#if senderMatched}
|
||||
<mark
|
||||
class="bg-transparent text-inherit underline decoration-brand-navy decoration-2 underline-offset-2"
|
||||
>{doc.sender.displayName}</mark
|
||||
>
|
||||
{:else}
|
||||
{doc.sender.displayName}
|
||||
{/if}
|
||||
{:else}
|
||||
<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-bold tracking-wide text-ink-3 uppercase">{m.docs_list_to()}</span>
|
||||
<span class="ml-1">
|
||||
{#if doc.receivers && doc.receivers.length > 0}
|
||||
{#each doc.receivers as receiver, i (receiver.id)}
|
||||
{#if i > 0}<span>, </span>{/if}
|
||||
{#if matchedReceiverIds.has(receiver.id)}
|
||||
<mark
|
||||
class="bg-transparent text-inherit underline decoration-brand-navy decoration-2 underline-offset-2"
|
||||
>{receiver.displayName}</mark
|
||||
>
|
||||
{:else}
|
||||
{receiver.displayName}
|
||||
{/if}
|
||||
{/each}
|
||||
{:else}
|
||||
<span class="text-ink-3 italic">{m.docs_list_unknown()}</span>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-start gap-2">
|
||||
<ProgressRing percentage={item.completionPercentage} />
|
||||
<div class="flex h-9 items-center">
|
||||
|
||||
Reference in New Issue
Block a user