V5.0 Minor change to UI
Quality Gate / gate (push) Failing after 11s

This commit is contained in:
Jim Lancaster
2026-08-23 10:49:40 -05:00
parent 0f30d902b9
commit 141ee1fa85
4 changed files with 55 additions and 14 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ Documents manages the archival record for each historical artifact independently
- The title is **Archival Documents**. - The title is **Archival Documents**.
- **Create new document** opens the create route. - **Create new document** opens the create route.
- The table defaults to Document Title order and supports search and column sorting. - The table defaults to Document Title order and supports search and column sorting.
- Columns are Document Title, Type, Author, Document Date, and # Sources. - Columns are Document Title, Author, Tags, Document Date, Type, and # Sources.
- Document Title is left-aligned; the remaining columns are centered. - Document Title is left-aligned; the remaining columns are centered.
- Author lists all linked people in the `author` role. - Author lists all linked people in the `author` role.
- # Sources reflects the count of linked Source rows for each Document. - # Sources reflects the count of linked Source rows for each Document.
@@ -22,6 +22,7 @@ class DocumentTableRow:
name: str name: str
document_type: str document_type: str
authors: str authors: str
tags: str
document_date: str document_date: str
source_count: int source_count: int
@@ -33,6 +34,7 @@ def _serialize_rows(rows: Sequence[DocumentTableRow]) -> list[dict[str, Any]]:
"name": row.name, "name": row.name,
"document_type": row.document_type or "Unspecified", "document_type": row.document_type or "Unspecified",
"authors": row.authors or "Not set", "authors": row.authors or "Not set",
"tags": row.tags or "Not tagged",
"document_date": row.document_date, "document_date": row.document_date,
"source_count": row.source_count, "source_count": row.source_count,
} }
@@ -59,15 +61,6 @@ def render_documents_table(rows: Sequence[DocumentTableRow]) -> None:
"align": "left", "align": "left",
"style": "width: 30%;", "style": "width: 30%;",
}, },
{
"name": "document_type",
"label": "Type",
"field": "document_type",
"sortable": True,
"classes": "ui-table-cell-wrap",
"align": "center",
"style": "width: 14%;",
},
{ {
"name": "authors", "name": "authors",
"label": "Author", "label": "Author",
@@ -75,7 +68,16 @@ def render_documents_table(rows: Sequence[DocumentTableRow]) -> None:
"sortable": True, "sortable": True,
"classes": "ui-table-cell-wrap", "classes": "ui-table-cell-wrap",
"align": "center", "align": "center",
"style": "width: 22%;", "style": "width: 18%;",
},
{
"name": "tags",
"label": "Tags",
"field": "tags",
"sortable": True,
"classes": "ui-table-cell-wrap",
"align": "center",
"style": "width: 16%;",
}, },
{ {
"name": "document_date", "name": "document_date",
@@ -86,6 +88,15 @@ def render_documents_table(rows: Sequence[DocumentTableRow]) -> None:
"align": "center", "align": "center",
"style": "width: 14%;", "style": "width: 14%;",
}, },
{
"name": "document_type",
"label": "Type",
"field": "document_type",
"sortable": True,
"classes": "ui-table-cell-wrap",
"align": "center",
"style": "width: 12%;",
},
{ {
"name": "source_count", "name": "source_count",
"label": "# Sources", "label": "# Sources",
@@ -93,7 +104,7 @@ def render_documents_table(rows: Sequence[DocumentTableRow]) -> None:
"sortable": True, "sortable": True,
"classes": "font-mono", "classes": "font-mono",
"align": "center", "align": "center",
"style": "width: 20%;", "style": "width: 10%;",
}, },
], ],
default_sort_by="name", default_sort_by="name",
+13 -1
View File
@@ -193,9 +193,10 @@ def register_page() -> None: # noqa: PLR0915
DocumentTableRow( DocumentTableRow(
id=doc.id, id=doc.id,
name=doc.name, name=doc.name,
document_type=(doc.document_type_ref.label if doc.document_type_ref is not None else ""),
authors=", ".join(_author_names(doc)), authors=", ".join(_author_names(doc)),
tags=", ".join(_tag_labels(doc)),
document_date=compact_date(doc.document_date, doc.document_date_raw), document_date=compact_date(doc.document_date, doc.document_date_raw),
document_type=(doc.document_type_ref.label if doc.document_type_ref is not None else ""),
source_count=len(doc.sources), source_count=len(doc.sources),
) )
for doc in documents for doc in documents
@@ -628,6 +629,17 @@ def _author_names(document: Document) -> list[str]:
) )
def _tag_labels(document: Document) -> list[str]:
return sorted(
(
link.tag_ref.label
for link in document.document_tags
if link.tag_ref is not None and link.tag_ref.label.strip()
),
key=str.casefold,
)
def _resolve_selected_tag_labels(value: object) -> list[str]: def _resolve_selected_tag_labels(value: object) -> list[str]:
def flatten(item: object) -> list[str]: def flatten(item: object) -> list[str]:
if item is None: if item is None:
+19 -1
View File
@@ -1,6 +1,7 @@
"""Tests for the documents page routes and action handlers.""" """Tests for the documents page routes and action handlers."""
from datetime import date from datetime import date
import re
import pytest import pytest
import pytest_asyncio import pytest_asyncio
@@ -13,6 +14,8 @@ from transcription.db.models import DocumentType
from transcription.db.models import Job from transcription.db.models import Job
from transcription.db.models import Person from transcription.db.models import Person
from transcription.db.models import PersonRole from transcription.db.models import PersonRole
from transcription.db.models import Tag
from transcription.db.models import DocumentTag
from transcription.db.models import Source from transcription.db.models import Source
from transcription.ui.pages.documents_page import _resolve_selected_tag_labels from transcription.ui.pages.documents_page import _resolve_selected_tag_labels
@@ -69,12 +72,15 @@ class TestDocumentsPageRendering:
async with session_scope() as session: async with session_scope() as session:
postcard_type = (await session.exec(select(DocumentType).where(DocumentType.label == "Postcard"))).one() postcard_type = (await session.exec(select(DocumentType).where(DocumentType.label == "Postcard"))).one()
family_tag = Tag(label="Family", normalized_label="family")
doc = Document( doc = Document(
name="1924 Postcard", name="1924 Postcard",
document_type_id=postcard_type.id, document_type_id=postcard_type.id,
archive_identifier="PC-001", archive_identifier="PC-001",
) )
session.add(doc) session.add_all([doc, family_tag])
await session.flush()
session.add(DocumentTag(document_id=doc.id, tag_id=family_tag.id))
await session.commit() await session.commit()
response = client.get("/ui/documents") response = client.get("/ui/documents")
@@ -84,8 +90,20 @@ class TestDocumentsPageRendering:
assert "Postcard" in response.text assert "Postcard" in response.text
assert "Document Date" in response.text assert "Document Date" in response.text
assert "Author" in response.text assert "Author" in response.text
assert "Tags" in response.text
assert "Family" in response.text
assert "# Sources" in response.text assert "# Sources" in response.text
assert "Archive Ref" not in response.text assert "Archive Ref" not in response.text
assert re.search(
r'"name":"name","label":"Document Title".*'
r'"name":"authors","label":"Author".*'
r'"name":"tags","label":"Tags".*'
r'"name":"document_date","label":"Document Date".*'
r'"name":"document_type","label":"Type".*'
r'"name":"source_count","label":"# Sources"',
response.text,
re.DOTALL,
)
def test_document_create_page_renders_form(self, app_client): def test_document_create_page_renders_form(self, app_client):
_, client = app_client _, client = app_client