feat(tags): split flat tag taxonomy into documentType + event + freeform dimensions #325
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
/admin/tagsalready informally groups tags into sections (Dokumententyp, Ereignisse, Alltag, …). All live in a singleTagtable, but they serve at least three distinct semantic roles:Telegramm(2),Schulrechnung(1),Kaufvertrag(1),Briefumschlag(2),Sterbeurkunde & Traueranzeige(1),Adressenliste(2). Should be a controlled vocabulary, single-valued per document.Brautbriefe(129),Kondolenz(60),Tod Walter & Geburtstag Clara(1),Danksagung(1),Fest(1).Alltag(31),Erbauseinandersetzung(12),Alltag in Ruhrort,Briefwechsel Religionszugehörigkeit Lilli.Currently all three live as rows in
Tag, loosely grouped only by a spec file (docs/specs/admin-tag-overhaul.html). Consequences:Telegramm— a document type)./documentsfilter can't narrow by type alone (typing filter and topic filter compete in one UI).Marcel already has a design spec at
docs/specs/admin-tag-overhaul.html— reuse it for the admin UI.Non-goals
Proposed model
Layer 1: introduce
DocumentTypeenum onDocumentDocumentType { LETTER, TELEGRAM, RECEIPT, CONTRACT, DEATH_CERTIFICATE, ADDRESS_LIST, ENVELOPE, POSTCARD, OTHER }.Document.documentType: DocumentType NOT NULL DEFAULT LETTER.LETTER).Layer 2: extend
Tagwith a subtype columnTag.tagType: TagType NOT NULL DEFAULT 'FREEFORM'— enum{ FREEFORM, EVENT, DOCUMENT_TYPE_LEGACY }.DOCUMENT_TYPE_LEGACYmarks the migrated document-type tags so they can be displayed but not re-used during new uploads.Migration (one-time, scripted)
A Flyway
V<next>__document_type_and_tag_type.sql:documents.document_typecolumn.tag.tag_typecolumn.docs/specs/admin-tag-overhaul.html):document_typeto the matching enum.tag_type = DOCUMENT_TYPE_LEGACY.INSERT INTO migration_reports …or a console log) so the operator can review.tag_type = EVENT.FREEFORM.The migration must be idempotent and reversible in spirit (running twice does nothing; dropping the columns restores current state).
Implementation plan
Backend
DocumentType(new).TagType(new).Document.documentTypefield +@Schema(requiredMode = REQUIRED).Tag.tagTypefield +@Schema(requiredMode = REQUIRED).DocumentService+TagServicemethods to filter by type.DocumentController.searchaccepts?type=<DocumentType>filter.TagController.searchaccepts?tagType=<TagType>filter (used by typeahead).Frontend
/documents/new): new dropdown for DocumentType (required, default LETTER)./documents/[id]/edit): same dropdown.TagInput.svelte: when opened in "event"-context, narrow the typeahead totagType=EVENT OR FREEFORM. When in "freeform"-context, onlyFREEFORM. Do not surfaceDOCUMENT_TYPE_LEGACYtags at all in typeahead./documentsfilter bar: new "Typ" facet driven byDocumentTypeenum./admin/tags: three tabs or filter chips —Freeform/Event/Dokumententyp (Legacy). Followdocs/specs/admin-tag-overhaul.html.i18n
10–12 new keys for the UI (dropdown labels, tab names, filter facet).
Translations for each
DocumentTypeenum value in de/en/es (exposed via a utilitydocumentTypeLabel(type, locale)).Tests
/api/documents/search?type=TELEGRAMreturns only telegrams;/api/tags/search?tagType=EVENTreturns only events./documentsfilter chip works.?type=LETTER; confirm visible; search with?type=TELEGRAM; confirm hidden.Verification
Post-migration sanity checks:
SELECT document_type, COUNT(*) FROM documents GROUP BY document_type;— distribution matches the pre-migration tag counts.SELECT tag_type, COUNT(*) FROM tag GROUP BY tag_type;— Freeform > Event > Legacy.Acceptance criteria
DocumentTypeenum exists on Document with non-null defaultTag.tagTypecolumn exists with non-null default/documentsfilter supports typeTagInputnarrows suggestions by context/admin/tagsseparates Freeform / Event / LegacyCritical files
Related
docs/specs/admin-tag-overhaul.html/persons/[id](#306 Korrespondenz-Überblick) must be updated to respect tagType after this merges.