fix(timeline): track the meta-line counts to the filtered view
All checks were successful
CI / fail2ban Regex (push) Successful in 46s
CI / Unit & Component Tests (push) Successful in 5m21s
CI / OCR Service Tests (push) Successful in 25s
CI / Backend Unit Tests (push) Successful in 5m48s
CI / Semgrep Security Scan (push) Successful in 22s
CI / Compose Bucket Idempotency (push) Successful in 1m7s
All checks were successful
CI / fail2ban Regex (push) Successful in 46s
CI / Unit & Component Tests (push) Successful in 5m21s
CI / OCR Service Tests (push) Successful in 25s
CI / Backend Unit Tests (push) Successful in 5m48s
CI / Semgrep Security Scan (push) Successful in 22s
CI / Compose Bucket Idempotency (push) Successful in 1m7s
The /zeitstrahl header sub-line counted the unfiltered timeline, so a
hidden layer (e.g. Letters off) still showed its entries in the totals
("1 Brief" with no letters on screen) — the documented D1 limitation.
Derive the meta from filteredTimeline so the range and letter/event
counts always match what is actually rendered. hasContent stays on the
full timeline so the filter bar and meta line still appear whenever the
archive has content.
Refs #780
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #843.
This commit is contained in:
@@ -8,14 +8,11 @@ import type { PageData } from './$types';
|
|||||||
|
|
||||||
let { data }: { data: PageData } = $props();
|
let { data }: { data: PageData } = $props();
|
||||||
|
|
||||||
const meta = $derived(timelineMeta(data.timeline));
|
|
||||||
const hasContent = $derived(data.timeline.years.length > 0 || data.timeline.undated.length > 0);
|
const hasContent = $derived(data.timeline.years.length > 0 || data.timeline.undated.length > 0);
|
||||||
|
|
||||||
// Layer-filter state (#780). Layer hiding is client-side only — the whole
|
// Layer-filter state (#780). Layer hiding is client-side only — the whole
|
||||||
// timeline is loaded once by #779's SSR load and we derive a filtered view of
|
// timeline is loaded once by #779's SSR load and we derive a filtered view of
|
||||||
// it here; there is no goto, no URL param, and no extra fetch. Known limitation
|
// it here; there is no goto, no URL param, and no extra fetch.
|
||||||
// (D1): the meta-line counts above stay on the unfiltered timeline, so they
|
|
||||||
// include entries the active toggles hide.
|
|
||||||
let personalOn = $state(true);
|
let personalOn = $state(true);
|
||||||
let historicalOn = $state(true);
|
let historicalOn = $state(true);
|
||||||
let lettersOn = $state(true);
|
let lettersOn = $state(true);
|
||||||
@@ -27,6 +24,11 @@ const filteredEmpty = $derived(
|
|||||||
filteredTimeline.years.length === 0 && filteredTimeline.undated.length === 0
|
filteredTimeline.years.length === 0 && filteredTimeline.undated.length === 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Meta-line figures track the *filtered* view, so the header counts always
|
||||||
|
// match what is actually on screen once layers are toggled off (#780 — this
|
||||||
|
// closes the prior D1 limitation, where the counts stayed on the full timeline).
|
||||||
|
const meta = $derived(timelineMeta(filteredTimeline));
|
||||||
|
|
||||||
function resetFilters() {
|
function resetFilters() {
|
||||||
personalOn = true;
|
personalOn = true;
|
||||||
historicalOn = true;
|
historicalOn = true;
|
||||||
|
|||||||
@@ -196,4 +196,20 @@ describe('/zeitstrahl layer filter (#780)', () => {
|
|||||||
await page.getByTestId('timeline-filter-empty-reset').click();
|
await page.getByTestId('timeline-filter-empty-reset').click();
|
||||||
await expect.element(page.getByText('Brief Eins')).toBeVisible();
|
await expect.element(page.getByText('Brief Eins')).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('recomputes the meta-line counts from the filtered view, so a hidden layer drops out of the totals (#780, resolves D1)', async () => {
|
||||||
|
render(Page, { data: pageData(mixed()) });
|
||||||
|
const meta = page.getByTestId('timeline-meta');
|
||||||
|
// all layers on → the one letter and the two events are counted
|
||||||
|
await expect.element(meta).toHaveTextContent(m.timeline_letters_count_singular());
|
||||||
|
await expect.element(meta).toHaveTextContent(m.timeline_events_count({ count: 2 }));
|
||||||
|
|
||||||
|
await openBar();
|
||||||
|
await page.getByTestId('timeline-filter-letters').click();
|
||||||
|
|
||||||
|
// the hidden letter leaves the count instead of lingering as "1 Brief";
|
||||||
|
// the event total is untouched
|
||||||
|
await expect.element(meta).not.toHaveTextContent(m.timeline_letters_count_singular());
|
||||||
|
await expect.element(meta).toHaveTextContent(m.timeline_events_count({ count: 2 }));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user