From b1e059fe05f1dfe109f4a0eb46ad6b8a784f967f Mon Sep 17 00:00:00 2001 From: McElwain Date: Tue, 28 Apr 2026 22:25:53 -0500 Subject: [PATCH] feat: improve document detail UI and disable deprecated PDF save routes --- app/routes/documents.py | 69 ++----------- app/static/app.css | 68 ++++++++++++ app/templates/base.html | 4 +- app/templates/documents/detail.html | 154 +++++++++++++++++++++++----- 4 files changed, 202 insertions(+), 93 deletions(-) diff --git a/app/routes/documents.py b/app/routes/documents.py index 9492019..af0fdc3 100644 --- a/app/routes/documents.py +++ b/app/routes/documents.py @@ -959,38 +959,10 @@ def rerun_ocr(document_id: str, db: Session = Depends(get_db)): @router.post("/{document_id}/save-ocr-corrected-pdf", response_class=RedirectResponse) def save_ocr_corrected_pdf(document_id: str, db: Session = Depends(get_db)): - document = ( - db.query(Document) - .options( - selectinload(Document.text_versions), - selectinload(Document.naming_fields), - selectinload(Document.extracted_fields), - selectinload(Document.additional_fields), - ) - .filter(Document.document_id == document_id) - .first() + return RedirectResponse( + url=f"/documents/{document_id}?error=deprecated_pdf_route_disabled&tab=ocr-review", + status_code=303, ) - if document is None: - return RedirectResponse(url="/documents/", status_code=303) - - save_root = get_default_save_root() - naming_row = document.naming_fields[0] if getattr(document, "naming_fields", None) else None - output_path = Path( - build_proposed_storage_path( - document=document, - save_root=save_root, - naming_row=naming_row, - ) - ) - output_path.parent.mkdir(parents=True, exist_ok=True) - - try: - create_ocr_corrected_pdf_version(db, document, output_path=output_path_obj) - except Exception: - return RedirectResponse(url=f"/documents/{document.document_id}?error=save_ocr_corrected_failed", status_code=303) - - return RedirectResponse(url=f"/documents/{document.document_id}?tab=ocr-review", status_code=303) - @router.post("/{document_id}/save-review-flags", response_class=RedirectResponse) @@ -1109,39 +1081,10 @@ def save_pdf(document_id: str, output_path: str = Form(""), db: Session = Depend @router.post("/{document_id}/save-field-enriched-pdf", response_class=RedirectResponse) def save_field_enriched_pdf(document_id: str, db: Session = Depends(get_db)): - document = ( - db.query(Document) - .options( - selectinload(Document.naming_fields), - selectinload(Document.extracted_fields), - selectinload(Document.additional_fields), - ) - .filter(Document.document_id == document_id) - .first() + return RedirectResponse( + url=f"/documents/{document_id}?error=deprecated_pdf_route_disabled&tab=extracted-fields", + status_code=303, ) - if document is None: - return RedirectResponse(url="/documents/", status_code=303) - - save_root = get_default_save_root() - naming_row = document.naming_fields[0] if getattr(document, "naming_fields", None) else None - output_path = Path( - build_proposed_storage_path( - document=document, - save_root=save_root, - naming_row=naming_row, - ) - ) - output_path = output_path.with_name( - re.sub(r"_v\d+(?=\.[^.]+$)", "", output_path.name) - ) - output_path.parent.mkdir(parents=True, exist_ok=True) - - try: - create_field_enriched_pdf_version(db, document, output_path=output_path_obj) - except Exception as e: - return RedirectResponse(url=f"/documents/{document.document_id}?error=save_field_enriched_failed", status_code=303) - - return RedirectResponse(url=f"/documents/{document.document_id}?tab=extracted-fields", status_code=303) @router.post("/{document_id}/review-text", response_class=RedirectResponse) diff --git a/app/static/app.css b/app/static/app.css index 7d12064..dcca5b5 100644 --- a/app/static/app.css +++ b/app/static/app.css @@ -5695,3 +5695,71 @@ table { } /* ===== end polished login page ===== */ + +/* ===== mobile split mode wide canvas ===== */ +@media (max-width: 900px) { + body.detail-mode-split .document-detail-grid, + body.detail-mode-split .detail-layout-grid, + body.detail-mode-split .detail-main-grid { + display: grid !important; + grid-template-columns: 1.2fr 0.8fr !important; + gap: 0.75rem !important; + width: 300vw !important; + min-width: 300vw !important; + max-width: 300vw !important; + align-items: start !important; + } + + body.detail-mode-split .preview-card, + body.detail-mode-split .tabbed-review-card, + body.detail-mode-split .review-card, + body.detail-mode-split .document-preview-card, + body.detail-mode-split .document-review-card { + width: 100% !important; + max-width: none !important; + min-width: 0 !important; + } + + body.detail-mode-split .main, + body.detail-mode-split .main-content { + overflow-x: auto !important; + } +} +/* ===== end mobile split mode wide canvas ===== */ + +.line-item-delete-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 2.25rem; + height: 2.25rem; + padding: 0; + border: 1px solid #e7bcbc; + border-radius: 0.75rem; + background: #fff; + cursor: pointer; +} + +.line-item-delete-btn:hover { + background: #fff5f5; +} + +.line-item-delete-btn svg { + width: 1.25rem; + height: 1.25rem; + display: block; +} + +.line-item-delete-btn .trash-tile { + fill: #fff; + stroke: #cf2e2e; + stroke-width: 1.6; +} + +.line-item-delete-btn .trash-can { + fill: none; + stroke: #cf2e2e; + stroke-width: 1.9; + stroke-linecap: round; + stroke-linejoin: round; +} diff --git a/app/templates/base.html b/app/templates/base.html index a57f6b2..f728337 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -4,8 +4,8 @@ {% block title %}Document Processor{% endblock %} - - + + + @@ -227,7 +229,7 @@ document.addEventListener("DOMContentLoaded", () => { -
+

Reviewed OCR

@@ -458,7 +460,7 @@ document.addEventListener("DOMContentLoaded", () => { {% set base_count = line_items|length %} - {% set row_count = base_count + 3 if base_count > 0 else 12 %} + {% set row_count = base_count if base_count > 0 else 0 %}
@@ -479,13 +481,26 @@ document.addEventListener("DOMContentLoaded", () => { Tax Category Notes - + {% for i in range(row_count) %} {% set item = line_items[i] if i < line_items|length else None %} - - {{ i + 1 }} + + + {{ i + 1 }} + + @@ -506,17 +521,64 @@ document.addEventListener("DOMContentLoaded", () => {
@@ -585,40 +658,65 @@ function addRow() {
-

Data Reset

+

Restore from version history

- - + + + {% for tv in (document.text_versions | sort(attribute='version_number', reverse=True)) %} + + {% endfor %}
+
- - + + + {% for v in (document.extracted_field_versions | sort(attribute='version_number', reverse=True)) %} + + {% endfor %}
+
- - + + + {% for v in (document.additional_field_versions | sort(attribute='version_number', reverse=True)) %} + + {% endfor %}
+
- - + + + {% if document.line_item_set_versions is defined %} + {% for v in (document.line_item_set_versions | sort(attribute='version_number', reverse=True)) %} + + {% endfor %} + {% endif %}