V4.11 Added tags + lots of little changes to the UI
Quality Gate / gate (push) Failing after 12s

This commit is contained in:
Jim Lancaster
2026-08-22 18:32:52 -05:00
parent 63c21d4a14
commit 0d554c0648
36 changed files with 932 additions and 116 deletions
+29 -22
View File
@@ -79,29 +79,36 @@ Small, low-risk structural-parity fixes across Person/Job/Document detail pages:
---
## V4.11 — Bigger UI Features
## V4.11 — Approved Scope
- **Tags** (supersedes "collections"): many-to-many tagging for documents,
reusing the Settings registry pattern (autocomplete against existing tags,
managed like Document Types/Person Roles). Since you want dedicated UI to
browse/filter by tag, include a tag-filter view (e.g. a "Tags" entry point
showing documents grouped/filterable by tag) as part of this version, not
deferred — that's the UI surface that makes tags actually replace collections
day-to-day, not just a data field.
- **UI theme selection**: kept simple, per your confirmation — 24 curated
themes (e.g. Archival/Sepia, Light, Dark, High-contrast), a single stored
preference, swapped via existing CSS variables/Tailwind tokens in
`theme.py`. No open-ended theme builder.
- **Edit Transcription sub-page**: source image + transcription text +
editable revision side-by-side, keeping the existing Save Revision/Reset
buttons. You noted the exact interaction/layout needs to be clarified when
this is scoped — treat this as a design-first item: confirm the two/three
column breakpoint behavior and what happens on narrow windows before
building.
- **Source detail page reflow** (move Candidate Machine Transcriptions to the
bottom of the image column; align Source Metadata's top edge with
Transcription Text): do this *after* the Edit Transcription sub-page above,
since that page will reuse/rearrange the same boxes — avoids reflowing twice.
- **Tags** (supersedes "collections"): many-to-many tagging for Documents with
Settings-style management (same pattern as Document Types and Person Roles),
autocomplete-capable assignment, and a dedicated **Tags** entry point for
browse/filter-by-tag workflows.
- **Source Detail simplification**: remove the separate **Transcription Text**
card; show Source image + Editable Revision + Source/SourceJob metadata in a
3-column top layout, then keep Candidate Machine Transcriptions below the
image/revision area.
- **Integrity reconciliation checks in tests**:
- document folder count under `UPLOAD_DIR/documents` must equal `document`
row count.
- source file count under each `UPLOAD_DIR/documents/{document_id}` folder
must equal `source` row count for that Document.
- failures should include actionable mismatch details (missing row/folder or
file/source mapping).
- **UI table updates**:
- Archival Documents: remove **Archive Ref**, add **# Sources**.
- Archival Entities: People: remove **Display Name** and **Maiden Name**
columns, add **FamilySearch ID**.
- Transcription Pipeline Jobs: add **# Sources**.
- **Create Processing Job page**: Provider and Model must be selectable for new
job creation.
Deferred out of this release:
- UI theme selection.
- Settings-based `.env` editing and runtime controls.
- Person table structural redesign (removing/splitting name fields).
---
+32 -4
View File
@@ -6,10 +6,11 @@ This document is the field-accurate Version 4 schema contract aligned to `src/tr
- `src/transcription/db/models.py:60-78` (status and purpose enums)
- `src/transcription/db/models.py:80-120` (`DocumentType`, `PersonRole`)
- `src/transcription/db/models.py:122-207` (`Document`, `Person`, `DocumentPerson`)
- `src/transcription/db/models.py:208-255` (`Job`)
- `src/transcription/db/models.py:273-386` (`Source`, `JobSource`)
- `src/transcription/db/models.py:387-445` (`ExecutionAttempt`)
- `src/transcription/db/models.py:122-148` (`Tag`, `Document`)
- `src/transcription/db/models.py:149-255` (`Person`, `DocumentPerson`, `DocumentTag`)
- `src/transcription/db/models.py:256-303` (`Job`)
- `src/transcription/db/models.py:304-417` (`Source`, `JobSource`)
- `src/transcription/db/models.py:418-476` (`ExecutionAttempt`)
## Entity Relationship Overview
@@ -19,8 +20,10 @@ erDiagram
Document ||--o{ Job : has
Document ||--o{ Source : has
Document ||--o{ DocumentPerson : links
Document ||--o{ DocumentTag : tagged
Person ||--o{ DocumentPerson : links
PersonRole ||--o{ DocumentPerson : labels
Tag ||--o{ DocumentTag : labels
Job ||--o{ JobSource : includes
Source ||--o{ JobSource : participates
JobSource ||--o{ ExecutionAttempt : attempts
@@ -74,6 +77,18 @@ erDiagram
| `created_at` | `datetime` | default now |
| `updated_at` | `datetime` | default now, onupdate |
### `Tag`
| Field | Type | Notes |
| :--- | :--- | :--- |
| `id` | `UUID` | PK |
| `semantic_key` | `str \| None` | nullable unique, indexed |
| `label` | `str` | required |
| `normalized_label` | `str` | unique, indexed |
| `is_active` | `bool` | default `True` |
| `created_at` | `datetime` | default now |
| `updated_at` | `datetime` | default now, onupdate |
### `Document`
| Field | Type | Notes |
@@ -124,6 +139,19 @@ erDiagram
Constraint:
- `UniqueConstraint(document_id, person_id)` named `uq_document_person`
### `DocumentTag`
| Field | Type | Notes |
| :--- | :--- | :--- |
| `id` | `UUID` | PK |
| `document_id` | `UUID` | FK -> `document.id`, indexed |
| `tag_id` | `UUID` | FK -> `tag.id`, indexed |
| `created_at` | `datetime` | default now |
| `updated_at` | `datetime` | default now, onupdate |
Constraint:
- `UniqueConstraint(document_id, tag_id)` named `uq_document_tag`
### `Job`
| Field | Type | Notes |
+5 -2
View File
@@ -22,9 +22,10 @@ Documents manages the archival record for each historical artifact independently
- The title is **Archival Documents**.
- **Create new document** opens the create route.
- The table defaults to Document Title order and supports search and column sorting.
- Columns are Document Title, Type, Author, Document Date, and Archive Ref.
- Columns are Document Title, Type, Author, Document Date, and # Sources.
- Document Title is left-aligned; the remaining columns are centered.
- Author lists all linked people in the `author` role.
- # Sources reflects the count of linked Source rows for each Document.
- Date display prefers exact date, then approximate date, then `Unknown`.
- Selecting a row opens Document Detail.
- No records displays `No documents found in repository.`
@@ -43,12 +44,14 @@ Optional:
- Document location.
- Archive identifier.
- Notes.
- Tags.
- Linked People, with exactly one Person Role per linked Person.
Rules:
- Exact date must parse as `YYYY-MM-DD`; browser presentation may follow locale.
- Existing people appear with disambiguating labels.
- Tag assignment supports selecting existing tags and adding new labels inline.
- **Create new person** opens Person creation.
- `person_id` may preselect that Person in the author role on Document creation.
- An invalid requested Person produces a warning rather than a broken form.
@@ -65,7 +68,7 @@ Rules:
- The heading shows name, type, and internal ID.
- The first Source, when present, appears in the dark-room viewer.
- Archival Metadata shows authors, Document Type, compact Document date, location, and archive identifier. Notes appear in a separate archival-notes block within the same card.
- Archival Metadata shows authors, Document Type, tags, compact Document date, location, and archive identifier. Notes appear in a separate archival-notes block within the same card.
- System Logistics shows created and updated timestamps.
- Related People are grouped by role and link to Person Detail.
- **Sources & Pipeline Jobs** shows counts and actions for filtered Sources, Document Jobs, and adding a Job.
+2 -2
View File
@@ -19,7 +19,7 @@ Jobs manages transcription processing runs. A Job belongs to one Document, links
- The title is **Transcription Pipeline Jobs**.
- **Create job** opens Job creation and **Refresh** reloads the table.
- Columns are Job ID, Status, Document Name, Retries, and Updated.
- Columns are Job ID, Status, Document Name, # Sources, Retries, and Updated.
- Updated is the primary date/sort field.
- Search covers Job ID, document name, and status.
- Status is displayed as a semantic status chip.
@@ -31,7 +31,7 @@ Jobs manages transcription processing runs. A Job belongs to one Document, links
- A Target Document and at least one source file are required.
- `document_id` may preselect a Target Document.
- If no Documents exist, the page explains the prerequisite and links to Document creation with a return path.
- Provider and Model are optional request overrides.
- Provider and Model are selectable when creating a new Job.
- Upload accepts JPEG, PNG, TIFF, and PDF files and supports multiple/folder selection.
- The visible upload queue is sorted alphabetically by original filename.
- Files can be removed individually or cleared before submission.
+3 -2
View File
@@ -19,8 +19,9 @@ People manages reusable historical-person records. A Person may appear in many D
- The title is **Archival Entities: People**.
- **Create new person** opens the create route.
- The table defaults to Full Name order and supports search and column sorting.
- Columns are Full Name, Display Name, Maiden Name, Birth Date, and Death Date.
- Full Name is left-aligned; Display Name, Maiden Name, and date columns are centered.
- Columns are Full Name, FamilySearch ID, Birth Date, Death Date, and # Documents.
- Full Name is left-aligned; FamilySearch ID, date columns, and # Documents are centered.
- # Documents reflects how many linked Documents each Person is connected to.
- Birth and death values independently prefer exact date, then approximate date, then `Unknown`.
- Selecting a row opens Person Detail.
- No records displays `No person records found in repository.`
+4 -3
View File
@@ -8,7 +8,7 @@ Settings manages installation-local registries and editable text assets from one
| Route | Purpose |
| --- | --- |
| `/settings` | Manage Document Types, Person Roles, Prompts, and Home Page Text. |
| `/settings` | Manage Document Types, Person Roles, Tags, Prompts, and Home Page Text. |
## Behavior
@@ -16,15 +16,16 @@ Settings manages installation-local registries and editable text assets from one
- Configuration surfaces are grouped as tabs:
- **Document Types**
- **Person Roles**
- **Tags**
- **Prompts**
- **Home Page Text**
- Document Types and Person Roles support Add/Edit/Delete with existing guardrails.
- Document Types, Person Roles, and Tags support Add/Edit/Delete with existing guardrails.
- Prompts exposes only `transcribe_document.md` for editing and restore-from-backup.
- Home Page Text edits the same Markdown content rendered on `/homepage`.
## Acceptance Checklist
- `/ui/settings` renders all four tabs.
- `/ui/settings` renders all five tabs.
- Registry and prompt workflows keep existing validation and error handling.
- Saving Home Page Text persists content for the homepage view.
+3 -4
View File
@@ -34,13 +34,12 @@ The list accepts optional `document_id` and `job_id` query parameters. Document
- **Delete Source** opens the guarded delete route.
- Previous and Next navigate only among Sources belonging to the same Document in page order; unavailable boundary actions are disabled.
- The media viewer resolves the stored Source path through the configured upload root.
- Transcription Text is read-only and displays the preferred machine projection, with a legacy latest-JobSource
fallback only when no Source projection exists.
- Editable Revision is seeded from an existing revision or the machine transcription.
- The top layout is three columns: Source image, Editable Revision, and Source/SourceJob metadata.
- Editable Revision is seeded from an existing revision or the preferred machine transcription.
- Source Metadata shows upload name, stored filename, page number, Document Name, Document ID, and stored path. Source ID appears in the page-header subtitle.
- SourceJob Metadata shows latest status, Job ID, execution time, provider, model, prompt, and failure detail.
- Revision Logistics shows revised state, last-revised time, and upload time.
- Candidate Machine Transcriptions remains compact until a candidate is expanded, then compares it with the preferred
- Candidate Machine Transcriptions appears below the image/revision area, remains compact until expanded, then compares it with the preferred
machine result and requires confirmation before **Use this transcription**.
- Candidate promotion does not alter a human revision. Empty states distinguish no machine result from no candidates.
- An orientation-normalized artifact appears in evidence only when recognized metadata required a physical rotation.
+31
View File
@@ -0,0 +1,31 @@
# Tags Page Contract
## Purpose
Tags provides a dedicated browse/filter entry point for document tagging workflows.
## Route
| Route | Purpose |
| --- | --- |
| `/tags` | Browse Documents grouped by Tag and filter to one Tag. |
## Behavior
- The page title is **Tags**.
- When no tags exist, the page shows `No tags are configured yet.`
- A Tag filter select allows narrowing to one tag.
- Each rendered group header includes the tag label and document count.
- Document names are clickable and open Document Detail.
## Acceptance Checklist
- `/ui/tags` renders successfully from the main navigation.
- Group counts match the number of linked Documents per Tag.
- Filtering hides non-matching tag groups.
## Implementation Anchors
- `src/transcription/ui/pages/tags_page.py`
- `src/transcription/services/documents.py`
- `tests/ui/test_tags_page.py`