# Documents Page Contract ## Purpose Documents manages the archival record for each historical artifact independently of its source files and transcription jobs. A Document can be created first, linked to people in one or more roles, and used later as the parent for Sources and Jobs. ## Routes | Route | Purpose | | --- | --- | | `/documents` | Searchable archival Document list. | | `/documents/new` | Create a Document. | | `/documents/{document_id}` | View one Document and its related records. | | `/documents/{document_id}/info` | View archival metadata and system logistics for one Document. | | `/documents/{document_id}/edit` | Edit metadata and the complete Linked People set. | | `/documents/{document_id}/delete` | Confirm or block deletion. | | `/documents/{document_id}/jobs` | Show Jobs belonging to the Document. | | `/documents/{document_id}/sources` | Source-image gallery for the Document. | | `/documents/{document_id}/print` | Preview and browser-print the persisted Document. | ## List Behavior - 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, Author, Tags, Document Date, Type, # Sources, and Transcription Status. - 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. - Transcription Status reflects the most recent Job status for that Document; documents with no Jobs show a blank marker. - Date display prefers exact date, then approximate date, then `Unknown`. - Selecting a row opens Document Detail. - Row navigation includes list context so Document Detail provides **Back to Documents**. - No records displays `No documents found in repository.` ## Create and Edit Behavior Required: - Document name. - Document type selected from the Document Type registry. Optional: - Exact date. - Approximate date. - 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. - The exact-date input is labeled **Document date**. - 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. - `return_to=jobs_new` returns a successful create to Job creation with the new Document selected. - Edit includes active and inactive Document Types so historical values remain maintainable. - One Linked People table contains Select, Person, and Role columns. - Add and Edit use an inline Person/Role editor; Save, Cancel, and Delete change staged UI state only. - A Person may appear once per Document regardless of role. - Existing inactive-role links remain visible; only active roles may be newly assigned. - Document fields and the complete staged link set commit atomically on the main save. - Save success returns to Document Detail. ## Detail Behavior - The heading shows name, type, and internal ID. - The header includes a contextual back action: **Back to Documents** by default, **Back to Person** when opened from Person Detail, and **Back to Job** when opened from Job Detail. - The detail workspace shows a Source-style pan/zoom media viewer with **Previous Page** / **Next Page** navigation for document source pages. - The center column is **Editable Revision** for the active source page. - Related People are grouped by role and link to Person Detail. - **Source Pages & Transcriptions** shows source/job counts and actions for source-image gallery, document jobs, and adding a Job. - **Edit Document**, **Print**, **Document Details**, **View Source Detail**, and **Delete** are available from the header. - Invalid IDs and missing Documents produce explicit states without rendering a partial page. ## Document Source Images Behavior - `/documents/{document_id}/sources` shows the current Document's source pages in a thumbnail gallery. - Each card shows the page number, stored filename, and an **Open Source Detail** action. - The page includes a **Back to Document** action. - No source pages displays an explicit empty state. ## Document Info Behavior - `/documents/{document_id}/info` contains **Archival Metadata** and **System Logistics**. - It includes a **Back to Document** action. - Archival metadata includes authors, document type, tags, document date, location (linked when present), archive identifier, and notes. ## Print Behavior - Print opens a dedicated preview for persisted Document data. - **Facsimile** places each Source image beside its current transcription and starts every Source on a new printed sheet. - **Text only** omits images, joins single line breaks inside paragraphs, and preserves blank-line paragraph boundaries. - Non-null revised text takes precedence over raw transcription, including an intentionally empty revision. - Archival metadata resolves Author through the hidden built-in semantic identity, not its mutable label. - Archival metadata includes the Document Type label. - Metadata tables use a narrow non-wrapping label column and wider wrapping data columns rather than stretching across the page. - Job metadata uses one oldest-to-newest column per Job and ends with Status. - Stored text is escaped and Source media uses record-validated application URLs rather than local file paths. - Printing uses the browser print dialog; server-generated PDFs are not provided. ## Document Jobs Behavior - The page lists the Document's Jobs newest first with status and Job ID. - **Open Job** navigates to Job Detail. - **Create Job** opens Job creation with the Document selected. - No jobs displays an explicit empty state. ## Delete Behavior - Deletion is blocked while any Source or Job belongs to the Document. - The blocked state names the dependency categories and provides navigation back and to Jobs. - An unlinked Document requires an explicit permanent-delete action. - Success returns to the Documents list. ## Acceptance Checklist - List columns, alignment, search, sorting, date fallback, and row navigation match this contract. - Create/edit enforce name, registered type, and valid exact-date input. - Linked People staging enforces one role and one row per Person. - Document and Linked People writes never partially commit. - Person-first Document creation preselects the requested Person as author. - Detail links people, Sources, and Jobs to the correct records. - Delete never removes a Document with Source or Job dependencies. - Both print formats preserve the frozen content, ordering, text-precedence, and safety contracts. - Service failures use the shared error presenter and never report false success. ## Implementation Anchors - `src/transcription/ui/pages/documents_page.py` - `src/transcription/ui/components/table/documents.py` - `src/transcription/services/documents.py` - `src/transcription/services/people.py` - `src/transcription/services/workflows.py` - `src/transcription/ui/components/linked_people.py` - `src/transcription/ui/pages/print_preview_page.py` - `src/transcription/api/print_api.py` - `tests/ui/test_documents_page.py` - `tests/services/test_document_service.py` ## Known Limitations and Deferred Work - Source page ordering remains read-only. - Printing other entities, batch printing, and server-side export formats are deferred.