feat(timeline): render letter buckets in TimelineView/YearBand
Thread groupingMode through TimelineView → YearBand. TimelineView resolves the event lookup once over the filtered view (so Ereignis clusters never reference a filtered-out event). In non-Datum modes YearBand keeps its event pills/world-bands identical (REQ-001) and replaces the loose letters with per-year LetterBuckets (REQ-002/003/004); Datum keeps the original card/strip path. The undated bucket is unchanged in every mode. Refs #827 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -165,3 +165,60 @@ describe('YearBand', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('YearBand — grouping modes (#827)', () => {
|
||||
it('keeps individual letter cards and no buckets in Datum mode (default)', () => {
|
||||
render(YearBand, { year: makeYear(1915, manyLetters(1915, 3)) });
|
||||
expect(document.querySelector('[data-testid="letter-bucket"]')).toBeNull();
|
||||
expect(document.querySelectorAll('a')).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('clusters loose letters under their linked event in Ereignis mode (REQ-002/003)', () => {
|
||||
const a = makeEntry({ documentId: 'a', linkedEventId: 'e1', eventDate: '1915-03-01' });
|
||||
const b = makeEntry({ documentId: 'b', linkedEventId: 'e1', eventDate: '1915-04-01' });
|
||||
render(YearBand, {
|
||||
year: makeYear(1915, [a, b]),
|
||||
groupingMode: 'event',
|
||||
eventLookup: new Map([['e1', 'Briefe von der Front']])
|
||||
});
|
||||
expect(document.querySelectorAll('[data-testid="letter-bucket"]')).toHaveLength(1);
|
||||
expect(document.body.textContent).toContain('Briefe von der Front');
|
||||
// no alternating individual letter rows in grouped mode
|
||||
expect(document.querySelector('.letter-row')).toBeNull();
|
||||
});
|
||||
|
||||
it('still renders the event world-band in Ereignis mode (REQ-001)', () => {
|
||||
const band = makeEntry({
|
||||
kind: 'EVENT',
|
||||
type: 'HISTORICAL',
|
||||
precision: 'RANGE',
|
||||
eventDate: '1914-01-01',
|
||||
eventDateEnd: '1918-12-31',
|
||||
title: 'Erster Weltkrieg',
|
||||
senderName: '',
|
||||
receiverName: '',
|
||||
documentId: undefined
|
||||
});
|
||||
const letter = makeEntry({ documentId: 'a', linkedEventId: 'e1', eventDate: '1914-05-01' });
|
||||
render(YearBand, {
|
||||
year: makeYear(1914, [band, letter]),
|
||||
groupingMode: 'event',
|
||||
eventLookup: new Map([['e1', 'Front']])
|
||||
});
|
||||
expect(document.querySelector('[data-testid="world-range"]')).not.toBeNull();
|
||||
expect(document.querySelector('[data-testid="letter-bucket"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('buckets loose letters under their root tag in Thema mode (REQ-004)', () => {
|
||||
const a = makeEntry({
|
||||
documentId: 'a',
|
||||
rootTagId: 't1',
|
||||
rootTagName: 'Krieg',
|
||||
rootTagColor: 'sienna',
|
||||
eventDate: '1915-03-01'
|
||||
});
|
||||
render(YearBand, { year: makeYear(1915, [a]), groupingMode: 'thema', eventLookup: new Map() });
|
||||
const chip = document.querySelector('[data-testid="bucket-header-chip"]');
|
||||
expect(chip?.textContent).toContain('Krieg');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user