Standardized robust chronological sorting across modules.

Updated '_process_generic_props' in multiple libraries to ensure 'updated' timestamp always falls back to 'created_on' or epoch start, preventing null values from breaking newest-first ordering in IndexedDB.

Aligned Recovery Meetings and Archives list views to use these pre-computed sort keys for consistent UI behavior even when 'updated_on' is null.
This commit is contained in:
Scott Idem
2026-02-16 15:40:00 -05:00
parent fdfba0f752
commit f34e24aa02
8 changed files with 32 additions and 27 deletions

View File

@@ -388,7 +388,7 @@ async function _process_generic_props<T extends Record<string, any>>({ obj_li, o
const group = processed_obj.group ?? '0'; const group = processed_obj.group ?? '0';
const priority = processed_obj.priority ? 1 : 0; const priority = processed_obj.priority ? 1 : 0;
const sort = processed_obj.sort ?? '0'; const sort = processed_obj.sort ?? '0';
const updated = processed_obj.updated_on ?? processed_obj.created_on; const updated = processed_obj.updated_on ?? processed_obj.created_on ?? new Date(0).toISOString();
const name = processed_obj.name ?? ''; const name = processed_obj.name ?? '';
(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`; (processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;
(processed_obj as any).tmp_sort_2 = `${group}_${priority}_${sort}_${name}_${updated}`; (processed_obj as any).tmp_sort_2 = `${group}_${priority}_${sort}_${name}_${updated}`;

View File

@@ -814,7 +814,7 @@ async function _process_generic_props<T extends Record<string, any>>({
const group = processed_obj.group ?? '0'; const group = processed_obj.group ?? '0';
const priority = processed_obj.priority ? 1 : 0; const priority = processed_obj.priority ? 1 : 0;
const sort = processed_obj.sort ?? '0'; const sort = processed_obj.sort ?? '0';
const updated = processed_obj.updated_on ?? processed_obj.created_on; const updated = processed_obj.updated_on ?? processed_obj.created_on ?? new Date(0).toISOString();
const name = processed_obj.name ?? ''; const name = processed_obj.name ?? '';
(processed_obj as any).tmp_sort_1 = (processed_obj as any).tmp_sort_1 =

View File

@@ -943,7 +943,7 @@ async function _process_generic_props<T extends Record<string, any>>({
const group = processed_obj.group ?? '0'; const group = processed_obj.group ?? '0';
const priority = processed_obj.priority ? 1 : 0; const priority = processed_obj.priority ? 1 : 0;
const sort = processed_obj.sort ?? '0'; const sort = processed_obj.sort ?? '0';
const updated = processed_obj.updated_on ?? processed_obj.created_on; const updated = processed_obj.updated_on ?? processed_obj.created_on ?? new Date(0).toISOString();
const name = processed_obj.name ?? ''; const name = processed_obj.name ?? '';
(processed_obj as any).tmp_sort_1 = (processed_obj as any).tmp_sort_1 =

View File

@@ -512,7 +512,7 @@ async function _process_generic_props<T extends Record<string, any>>({
const group = processed_obj.group ?? '0'; const group = processed_obj.group ?? '0';
const priority = processed_obj.priority ? 1 : 0; const priority = processed_obj.priority ? 1 : 0;
const sort = processed_obj.sort ?? '0'; const sort = processed_obj.sort ?? '0';
const updated = processed_obj.updated_on ?? processed_obj.created_on; const updated = processed_obj.updated_on ?? processed_obj.created_on ?? new Date(0).toISOString();
const name = processed_obj.username ?? processed_obj.name ?? ''; const name = processed_obj.username ?? processed_obj.name ?? '';
(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`; (processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;

View File

@@ -336,7 +336,7 @@ async function _process_generic_props<T extends Record<string, any>>({
const group = processed_obj.group ?? '0'; const group = processed_obj.group ?? '0';
const priority = processed_obj.priority ? 1 : 0; const priority = processed_obj.priority ? 1 : 0;
const sort = processed_obj.sort ?? '0'; const sort = processed_obj.sort ?? '0';
const updated = processed_obj.updated_on ?? processed_obj.created_on; const updated = processed_obj.updated_on ?? processed_obj.created_on ?? new Date(0).toISOString();
const name = processed_obj.name ?? ''; const name = processed_obj.name ?? '';
(processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`; (processed_obj as any).tmp_sort_1 = `${group}_${priority}_${sort}_${updated}`;

View File

@@ -43,9 +43,11 @@
const sortB = b.sort ?? 0; const sortB = b.sort ?? 0;
if (sortA !== sortB) return sortB - sortA; if (sortA !== sortB) return sortB - sortA;
} else if (qry_sort_mode === 'updated_desc') { } else if (qry_sort_mode === 'updated_desc') {
const dateA = new Date(a.updated_on || a.created_on).getTime(); // SORT: Most recently updated or created at the top (Refactored 2026-02-16)
const dateB = new Date(b.updated_on || b.created_on).getTime(); // ROBUSTNESS: Ensure fallback to created_on then to 0 to prevent NaN comparison issues
return dateB - dateA; const date_a = new Date(a.updated_on ?? a.created_on ?? 0).getTime() || 0;
const date_b = new Date(b.updated_on ?? b.created_on ?? 0).getTime() || 0;
return date_b - date_a;
} }
// Default fallback: Name // Default fallback: Name

View File

@@ -143,21 +143,15 @@
}) })
.toArray(); .toArray();
// Sort local results matching UI selection // Sort local results matching UI selection (Refactored 2026-02-16)
if ($idaa_loc.recovery_meetings.qry__order_by === 'name') { if ($idaa_loc.recovery_meetings.qry__order_by === 'name') {
local_results.sort((a, b) => local_results.sort((a, b) =>
(a.name ?? '').localeCompare(b.name ?? '') (a.name ?? '').localeCompare(b.name ?? '')
); );
} else { } else {
local_results.sort((a, b) => { // Robust Chronological Sort using pre-computed tmp_sort_1
const dateA = a.updated_on // Handles Priority, Manual Sort, and the updated_on/created_on fallback
? new Date(a.updated_on).getTime() local_results.sort((a, b) => (b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? ''));
: 0;
const dateB = b.updated_on
? new Date(b.updated_on).getTime()
: 0;
return dateB - dateA;
});
} }
local_ids = local_results local_ids = local_results
@@ -226,6 +220,13 @@
return true; return true;
}); });
// RE-SORT: Ensure perfect chronological order even if API puts NULLs last (Refactored 2026-02-16)
if ($idaa_loc.recovery_meetings.qry__order_by === 'name') {
api_results.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''));
} else {
api_results.sort((a, b) => (b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? ''));
}
const api_ids = api_results const api_ids = api_results
.map((e: any) => String(e.id)) .map((e: any) => String(e.id))
.filter(Boolean); .filter(Boolean);

View File

@@ -78,17 +78,19 @@
.where(dq__where_type_id_val) .where(dq__where_type_id_val)
.equals(link_to_id); .equals(link_to_id);
if (order_by == 'name') { const results = await base_query
return await base_query .and((ev) => !ev.hide && !!ev.enable)
.and((ev) => !ev.hide && !!ev.enable) .limit(limit > 0 ? limit : 500)
.limit(limit > 0 ? limit : 500) .toArray();
.sortBy('name');
if (order_by === 'name') {
results.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''));
} else { } else {
return await base_query // Robust Chronological Sort using pre-computed tmp_sort_1 (Refactored 2026-02-16)
.and((ev) => !ev.hide && !!ev.enable) // This handles Group > Priority > Manual Sort > Date (with updated_on fallback)
.limit(limit > 0 ? limit : 500) results.sort((a, b) => (b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? ''));
.sortBy('updated_on');
} }
return results;
} }
return null; return null;
}); });