From 58404ac8dccee73457126c70de0458fd933c96fa Mon Sep 17 00:00:00 2001 From: thomas Date: Tue, 20 Oct 2026 23:20:02 +0200 Subject: [PATCH] Enhance sorting functionality for additional fields in SQLiteFileRepository and update emission_date to be sortable in the frontend --- automatic-pdf-renamer/app/db.py | 8 +++++++- automatic-pdf-renamer/web/app.js | 16 +++++++++++----- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/automatic-pdf-renamer/app/db.py b/automatic-pdf-renamer/app/db.py index 748bd64..c2ae3e3 100644 --- a/automatic-pdf-renamer/app/db.py +++ b/automatic-pdf-renamer/app/db.py @@ -337,10 +337,16 @@ class SQLiteFileRepository: "emitting_company": "emitting_company", "document_type": "document_type", "period": "period", + "emission_date": "emission_date", "confidence": "confidence", "updated_at": "updated_at", } - order_column = sortable_columns.get(sort_by, "updated_at") + if sort_by.startswith("additional_field__"): + field_name = sort_by.removeprefix("additional_field__") + order_column = "json_extract(optional_fields, ?)" + params.append('$.' + '"' + field_name.replace('"', '\\"') + '"') + else: + order_column = sortable_columns.get(sort_by, "updated_at") order_direction = "ASC" if sort_order.lower() == "asc" else "DESC" query += f" ORDER BY {order_column} {order_direction} LIMIT ? OFFSET ?" params.extend([page_size, (page - 1) * page_size]) diff --git a/automatic-pdf-renamer/web/app.js b/automatic-pdf-renamer/web/app.js index e09c4f4..eb929fb 100644 --- a/automatic-pdf-renamer/web/app.js +++ b/automatic-pdf-renamer/web/app.js @@ -20,7 +20,7 @@ const columnDefinitions = { period: { label: 'Period', filter: 'period', sortable: true }, updated_at: { label: 'Last modified', filter: 'updated_at', sortable: true }, template_name: { label: 'Template', filter: 'template', sortable: true }, - emission_date: { label: 'Emission date', filter: 'emission_date', sortable: false, inputType: 'date' }, + emission_date: { label: 'Emission date', filter: 'emission_date', sortable: true, inputType: 'date' }, confidence: { label: 'Confidence', filter: 'confidence', sortable: true }, }; let visibleColumns = (() => { @@ -57,7 +57,7 @@ const renderColumnPicker = () => { }; const renderTableHead = () => { const header = (key) => { - const def = columnDefinitions[key] || { label: key.replace(/^additional:/, ''), filter: `additional_field__${key.slice(11)}`, sortable: false }; + const def = columnDefinitions[key] || { label: key.replace(/^additional:/, ''), filter: `additional_field__${key.slice(11)}`, sortable: true }; return `${def.sortable ? `` : escapeHtml(def.label)}`; }; const previousFilterValues = Object.fromEntries(columnFilters.map((filter) => [filter.dataset.filter, filter.value])); @@ -73,8 +73,11 @@ const renderTableHead = () => { columnFilters = [...tableHead.querySelectorAll('[data-filter]')]; columnFilters.forEach((filter) => filter.addEventListener('input', () => { selectedIds.clear(); allFilteredSelection = false; updateSelectionUi(); loadDocuments(); })); tableHead.querySelectorAll('[data-sort]').forEach((button) => button.addEventListener('click', () => { - if (sortBy === button.dataset.sort) sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; - else { sortBy = button.dataset.sort; sortOrder = 'asc'; } + const selectedSort = button.dataset.sort.startsWith('additional:') + ? `additional_field__${button.dataset.sort.slice(11)}` + : button.dataset.sort; + if (sortBy === selectedSort) sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; + else { sortBy = selectedSort; sortOrder = 'asc'; } updateSortIndicators(); loadDocuments(); })); const selectHead = tableHead.querySelector('#select-page-head'); @@ -250,7 +253,10 @@ const loadDocuments = async ({ append = false } = {}) => { const updateSortIndicators = () => { sortButtons = [...document.querySelectorAll('[data-sort]')]; document.querySelectorAll('[data-sort-column]').forEach((header) => { - const active = header.dataset.sortColumn === sortBy; + const columnSort = header.dataset.sortColumn.startsWith('additional:') + ? `additional_field__${header.dataset.sortColumn.slice(11)}` + : header.dataset.sortColumn; + const active = columnSort === sortBy; header.setAttribute('aria-sort', active ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'); const indicator = header.querySelector('.sort-button span'); indicator.textContent = active ? (sortOrder === 'asc' ? '↑' : '↓') : '';