Enhance sorting functionality for additional fields in SQLiteFileRepository and update emission_date to be sortable in the frontend

This commit is contained in:
2026-10-20 23:20:02 +02:00
parent 6a47e6ad56
commit 58404ac8dc
2 changed files with 18 additions and 6 deletions
+6
View File
@@ -337,9 +337,15 @@ class SQLiteFileRepository:
"emitting_company": "emitting_company", "emitting_company": "emitting_company",
"document_type": "document_type", "document_type": "document_type",
"period": "period", "period": "period",
"emission_date": "emission_date",
"confidence": "confidence", "confidence": "confidence",
"updated_at": "updated_at", "updated_at": "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_column = sortable_columns.get(sort_by, "updated_at")
order_direction = "ASC" if sort_order.lower() == "asc" else "DESC" order_direction = "ASC" if sort_order.lower() == "asc" else "DESC"
query += f" ORDER BY {order_column} {order_direction} LIMIT ? OFFSET ?" query += f" ORDER BY {order_column} {order_direction} LIMIT ? OFFSET ?"
+11 -5
View File
@@ -20,7 +20,7 @@ const columnDefinitions = {
period: { label: 'Period', filter: 'period', sortable: true }, period: { label: 'Period', filter: 'period', sortable: true },
updated_at: { label: 'Last modified', filter: 'updated_at', sortable: true }, updated_at: { label: 'Last modified', filter: 'updated_at', sortable: true },
template_name: { label: 'Template', filter: 'template', 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 }, confidence: { label: 'Confidence', filter: 'confidence', sortable: true },
}; };
let visibleColumns = (() => { let visibleColumns = (() => {
@@ -57,7 +57,7 @@ const renderColumnPicker = () => {
}; };
const renderTableHead = () => { const renderTableHead = () => {
const header = (key) => { 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 `<th scope="col" ${def.sortable ? `data-sort-column="${key}"` : ''}>${def.sortable ? `<button class="sort-button" data-sort="${key}">${escapeHtml(def.label)} <span></span></button>` : escapeHtml(def.label)}</th>`; return `<th scope="col" ${def.sortable ? `data-sort-column="${key}"` : ''}>${def.sortable ? `<button class="sort-button" data-sort="${key}">${escapeHtml(def.label)} <span></span></button>` : escapeHtml(def.label)}</th>`;
}; };
const previousFilterValues = Object.fromEntries(columnFilters.map((filter) => [filter.dataset.filter, filter.value])); const previousFilterValues = Object.fromEntries(columnFilters.map((filter) => [filter.dataset.filter, filter.value]));
@@ -73,8 +73,11 @@ const renderTableHead = () => {
columnFilters = [...tableHead.querySelectorAll('[data-filter]')]; columnFilters = [...tableHead.querySelectorAll('[data-filter]')];
columnFilters.forEach((filter) => filter.addEventListener('input', () => { selectedIds.clear(); allFilteredSelection = false; updateSelectionUi(); loadDocuments(); })); columnFilters.forEach((filter) => filter.addEventListener('input', () => { selectedIds.clear(); allFilteredSelection = false; updateSelectionUi(); loadDocuments(); }));
tableHead.querySelectorAll('[data-sort]').forEach((button) => button.addEventListener('click', () => { tableHead.querySelectorAll('[data-sort]').forEach((button) => button.addEventListener('click', () => {
if (sortBy === button.dataset.sort) sortOrder = sortOrder === 'asc' ? 'desc' : 'asc'; const selectedSort = button.dataset.sort.startsWith('additional:')
else { sortBy = button.dataset.sort; sortOrder = 'asc'; } ? `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(); updateSortIndicators(); loadDocuments();
})); }));
const selectHead = tableHead.querySelector('#select-page-head'); const selectHead = tableHead.querySelector('#select-page-head');
@@ -250,7 +253,10 @@ const loadDocuments = async ({ append = false } = {}) => {
const updateSortIndicators = () => { const updateSortIndicators = () => {
sortButtons = [...document.querySelectorAll('[data-sort]')]; sortButtons = [...document.querySelectorAll('[data-sort]')];
document.querySelectorAll('[data-sort-column]').forEach((header) => { 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'); header.setAttribute('aria-sort', active ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none');
const indicator = header.querySelector('.sort-button span'); const indicator = header.querySelector('.sort-button span');
indicator.textContent = active ? (sortOrder === 'asc' ? '↑' : '↓') : ''; indicator.textContent = active ? (sortOrder === 'asc' ? '↑' : '↓') : '';