feat(documents): rebalance list row — summary + archive chips, restored sender/receiver
Some checks failed
CI / Unit & Component Tests (push) Failing after 2m43s
CI / OCR Service Tests (push) Successful in 33s
CI / Backend Unit Tests (push) Failing after 2m57s

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:
Marcel
2026-04-23 08:44:49 +02:00
parent fc0fc57409
commit a7efb0044c
2 changed files with 150 additions and 43 deletions

View File

@@ -118,28 +118,99 @@ describe('DocumentRow sender', () => {
await expect.element(unknownElements.first()).toBeInTheDocument();
});
it('renders the sender display name only once across the row', async () => {
it('highlights the sender when senderMatched is true', async () => {
const item = makeItem({
document: {
...makeItem().document,
sender: { id: 's1', displayName: 'Großmutter Maria' }
},
matchData: {
...makeItem().matchData,
senderMatched: true
}
});
render(DocumentRow, { item });
const matches = await page.getByText('Großmutter Maria').all();
expect(matches.length).toBe(1);
const mark = page.getByRole('mark').first();
await expect.element(mark).toHaveTextContent('Großmutter Maria');
});
it('renders each receiver display name only once across the row', async () => {
it('highlights a receiver when matchedReceiverIds includes its id', async () => {
const item = makeItem({
document: {
...makeItem().document,
receivers: [{ id: 'r1', displayName: 'Onkel Karl' }]
},
matchData: {
...makeItem().matchData,
matchedReceiverIds: ['r1']
}
});
render(DocumentRow, { item });
const matches = await page.getByText('Onkel Karl').all();
expect(matches.length).toBe(1);
const mark = page.getByRole('mark').first();
await expect.element(mark).toHaveTextContent('Onkel Karl');
});
});
// ─── Summary ─────────────────────────────────────────────────────────────────
describe('DocumentRow summary', () => {
it('renders the document summary when present', async () => {
const item = makeItem({
document: {
...makeItem().document,
summary: 'Brief von Eugenie über die Heimreise aus dem Süden.'
}
});
render(DocumentRow, { item });
await expect
.element(page.getByTestId('doc-summary'))
.toHaveTextContent('Brief von Eugenie über die Heimreise aus dem Süden.');
});
it('does not render the summary block when summary is empty', async () => {
render(DocumentRow, { item: makeItem() });
await expect.element(page.getByTestId('doc-summary')).not.toBeInTheDocument();
});
it('applies summary search-match highlight via summaryOffsets', async () => {
const item = makeItem({
document: { ...makeItem().document, summary: 'Brief über Menton' },
matchData: {
...makeItem().matchData,
summaryOffsets: [{ start: 11, length: 6 }]
}
});
render(DocumentRow, { item });
const mark = page.getByRole('mark').first();
await expect.element(mark).toHaveTextContent('Menton');
});
});
// ─── Archive chips ───────────────────────────────────────────────────────────
describe('DocumentRow archive chips', () => {
it('renders the archive box chip when set', async () => {
const item = makeItem({
document: { ...makeItem().document, archiveBox: 'K3' }
});
render(DocumentRow, { item });
await expect.element(page.getByText('K3')).toBeInTheDocument();
});
it('renders the archive folder chip when set', async () => {
const item = makeItem({
document: { ...makeItem().document, archiveFolder: 'Mappe A' }
});
render(DocumentRow, { item });
await expect.element(page.getByText('Mappe A')).toBeInTheDocument();
});
it('renders the location chip when meta_location is set', async () => {
const item = makeItem({
document: { ...makeItem().document, location: 'Berlin' }
});
render(DocumentRow, { item });
await expect.element(page.getByText('Berlin')).toBeInTheDocument();
});
});