Compare commits
3 Commits
322abc2691
...
4a39ca1468
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a39ca1468 | ||
|
|
182a066d38 | ||
|
|
35fed53e2a |
54
src/lib/ae_core/core__idb_sort.ts
Normal file
54
src/lib/ae_core/core__idb_sort.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* src/lib/ae_core/core__idb_sort.ts
|
||||
*
|
||||
* Shared utility for computing tmp_sort_* fields stored in Dexie.
|
||||
* All fields are designed for ascending .sortBy() — no .reverse() needed.
|
||||
*
|
||||
* Encoding rules:
|
||||
* priority — inverted boolean: true→'0', false→'1' so priority=true sorts first (ASC)
|
||||
* sort — zero-padded integer string so "00000010" < "00000020" (correct numeric order)
|
||||
* all other fields — appended as-is; ISO 8601 datetimes already sort correctly
|
||||
*
|
||||
* Usage:
|
||||
* const { tmp_sort_1, tmp_sort_2, tmp_sort_3 } = build_tmp_sort({
|
||||
* prefix: [obj.group ?? '0'], // fields before priority (optional)
|
||||
* priority: obj.priority,
|
||||
* sort: obj.sort,
|
||||
* fields_1: [obj.start_datetime], // appended to base for tmp_sort_1
|
||||
* fields_2: [obj.name], // appended after fields_1 for tmp_sort_2
|
||||
* fields_3: [obj.updated_on], // appended after fields_2 for tmp_sort_3
|
||||
* });
|
||||
*/
|
||||
export function build_tmp_sort({
|
||||
prefix = [],
|
||||
priority,
|
||||
sort,
|
||||
fields_1 = [],
|
||||
fields_2 = [],
|
||||
fields_3 = [],
|
||||
pad_width = 8
|
||||
}: {
|
||||
prefix?: (string | null | undefined)[];
|
||||
priority?: boolean | null;
|
||||
sort?: number | string | null;
|
||||
fields_1?: (string | null | undefined)[];
|
||||
fields_2?: (string | null | undefined)[];
|
||||
fields_3?: (string | null | undefined)[];
|
||||
pad_width?: number;
|
||||
}): { tmp_sort_1: string; tmp_sort_2: string; tmp_sort_3: string } {
|
||||
const clean = (v: string | null | undefined): string => v ?? '';
|
||||
|
||||
const p = priority ? '0' : '1';
|
||||
const s = String(Number(sort ?? 0)).padStart(pad_width, '0');
|
||||
|
||||
const parts_base = [...prefix.map(clean), p, s].join('_');
|
||||
const parts_1 = fields_1.map(clean).filter(Boolean).join('_');
|
||||
const parts_2 = fields_2.map(clean).filter(Boolean).join('_');
|
||||
const parts_3 = fields_3.map(clean).filter(Boolean).join('_');
|
||||
|
||||
const tmp_sort_1 = [parts_base, parts_1].filter(Boolean).join('_');
|
||||
const tmp_sort_2 = [tmp_sort_1, parts_2].filter(Boolean).join('_');
|
||||
const tmp_sort_3 = [tmp_sort_2, parts_3].filter(Boolean).join('_');
|
||||
|
||||
return { tmp_sort_1, tmp_sort_2, tmp_sort_3 };
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { build_tmp_sort } from '$lib/ae_core/core__idb_sort';
|
||||
import { db_events } from '$lib/ae_events/db_events';
|
||||
import type { ae_EventPresentation } from '$lib/types/ae_types';
|
||||
|
||||
@@ -680,6 +681,17 @@ export async function process_ae_obj__event_presentation_props({
|
||||
if (obj.event_session_id_random)
|
||||
obj.event_session_id = obj.event_session_id_random;
|
||||
if (obj.event_id_random) obj.event_id = obj.event_id_random;
|
||||
|
||||
// Override generic tmp_sort_* with presentation-specific encoding via
|
||||
// build_tmp_sort. Order: priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC
|
||||
const { tmp_sort_1, tmp_sort_2 } = build_tmp_sort({
|
||||
priority: obj.priority,
|
||||
sort: obj.sort,
|
||||
fields_1: [obj.start_datetime, obj.code],
|
||||
fields_2: [obj.name]
|
||||
});
|
||||
obj.tmp_sort_1 = tmp_sort_1;
|
||||
obj.tmp_sort_2 = tmp_sort_2;
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { build_tmp_sort } from '$lib/ae_core/core__idb_sort';
|
||||
import { db_journals } from '$lib/ae_journals/db_journals';
|
||||
import type { ae_Journal } from '$lib/types/ae_types';
|
||||
|
||||
@@ -885,9 +886,16 @@ export async function process_ae_obj__journal_props({
|
||||
|
||||
const updated =
|
||||
obj.updated_on ?? obj.created_on ?? new Date(0).toISOString();
|
||||
obj.tmp_sort_3 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${obj.sort ?? '0'}_${
|
||||
obj.name
|
||||
}_${updated}`;
|
||||
const { tmp_sort_1, tmp_sort_2, tmp_sort_3 } = build_tmp_sort({
|
||||
prefix: [obj.group ?? '0'],
|
||||
priority: obj.priority,
|
||||
sort: obj.sort,
|
||||
fields_2: [obj.name],
|
||||
fields_3: [updated]
|
||||
});
|
||||
obj.tmp_sort_1 = tmp_sort_1;
|
||||
obj.tmp_sort_2 = tmp_sort_2;
|
||||
obj.tmp_sort_3 = tmp_sort_3;
|
||||
obj.combined_passcode = `${obj.passcode ?? ''}:${obj.private_passcode ?? ''}`;
|
||||
|
||||
return obj;
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||
import { build_tmp_sort } from '$lib/ae_core/core__idb_sort';
|
||||
import { db_journals } from '$lib/ae_journals/db_journals';
|
||||
import type { ae_JournalEntry } from '$lib/types/ae_types';
|
||||
|
||||
@@ -1050,19 +1051,20 @@ export async function process_ae_obj__journal_entry_props({
|
||||
obj.history = history;
|
||||
obj.history_md_html = history_md_html;
|
||||
|
||||
// Journal entry-specific computed sort fields, overriding generic ones if needed
|
||||
const sort_val = (obj.sort ?? 0).toString().padStart(3, '0');
|
||||
// Journal entry-specific computed sort fields via build_tmp_sort.
|
||||
// Order: priority DESC → sort ASC → name ASC → updated ASC (all ascending, no .reverse())
|
||||
const updated =
|
||||
obj.updated_on ?? obj.created_on ?? new Date(0).toISOString();
|
||||
obj.tmp_sort_1 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
||||
sort_val
|
||||
}_${updated}`;
|
||||
obj.tmp_sort_2 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
||||
sort_val
|
||||
}_${obj.name ?? ''}_${updated}`;
|
||||
obj.tmp_sort_3 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
||||
sort_val
|
||||
}_${obj.name ?? ''}_${updated}`;
|
||||
const { tmp_sort_1, tmp_sort_2, tmp_sort_3 } = build_tmp_sort({
|
||||
prefix: [obj.group ?? ''],
|
||||
priority: obj.priority,
|
||||
sort: obj.sort,
|
||||
fields_2: [obj.name],
|
||||
fields_3: [updated]
|
||||
});
|
||||
obj.tmp_sort_1 = tmp_sort_1;
|
||||
obj.tmp_sort_2 = tmp_sort_2;
|
||||
obj.tmp_sort_3 = tmp_sort_3;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -90,11 +90,11 @@ let lq__event_file_obj_li = $derived.by(() => {
|
||||
});
|
||||
|
||||
// Event Presentation
|
||||
// WHY: $derived.by — same reason as above. Captures both id and sort_by in the outer
|
||||
// closure so a new Observable is created whenever the session or its type changes.
|
||||
// WHY: $derived.by — captures id in the outer closure so a new Observable is
|
||||
// created whenever the session changes. tmp_sort_2 encodes the full sort chain:
|
||||
// priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC
|
||||
let lq__event_presentation_obj_li = $derived.by(() => {
|
||||
const id = slct__event_session_id;
|
||||
const sort_by = type_code == 'poster' ? 'name' : 'start_datetime';
|
||||
return liveQuery(async () => {
|
||||
if (!id) return [];
|
||||
|
||||
@@ -105,7 +105,7 @@ let lq__event_presentation_obj_li = $derived.by(() => {
|
||||
return await db_events.presentation
|
||||
.where('event_session_id')
|
||||
.equals(id)
|
||||
.sortBy(sort_by);
|
||||
.sortBy('tmp_sort_2');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -67,40 +67,18 @@ let lq__event_session_obj = $derived(
|
||||
);
|
||||
|
||||
// 2. Presentation List Observable
|
||||
// WHY: Dexie sortBy() is single-field only. Multi-field sort requires toArray() + JS comparator.
|
||||
// Desired order: priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC
|
||||
// WHY: tmp_sort_2 encodes priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC
|
||||
// as a lexicographically correct string. See process_ae_obj__event_presentation_props.
|
||||
let lq__event_presentation_obj_li = $derived(
|
||||
liveQuery(async () => {
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
`[LQ] Querying Presentations for Session: ${url_session_id}`
|
||||
);
|
||||
const results = await db_events.presentation
|
||||
return await db_events.presentation
|
||||
.where('event_session_id')
|
||||
.equals(url_session_id)
|
||||
.toArray();
|
||||
return results.sort((a, b) => {
|
||||
// priority DESC (true first)
|
||||
const pa = a.priority ? 1 : 0;
|
||||
const pb = b.priority ? 1 : 0;
|
||||
if (pb !== pa) return pb - pa;
|
||||
// sort ASC
|
||||
const sa = a.sort ?? 0;
|
||||
const sb = b.sort ?? 0;
|
||||
if (sa !== sb) return sa - sb;
|
||||
// start_datetime ASC
|
||||
const da = a.start_datetime ?? '';
|
||||
const db_val = b.start_datetime ?? '';
|
||||
if (da !== db_val) return da < db_val ? -1 : 1;
|
||||
// code ASC
|
||||
const ca = a.code ?? '';
|
||||
const cb = b.code ?? '';
|
||||
if (ca !== cb) return ca < cb ? -1 : 1;
|
||||
// name ASC
|
||||
const na = a.name ?? '';
|
||||
const nb = b.name ?? '';
|
||||
return na < nb ? -1 : na > nb ? 1 : 0;
|
||||
});
|
||||
.sortBy('tmp_sort_2');
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@ let lq__journal_obj_li = $derived(
|
||||
return await db_journals.journal
|
||||
.where('person_id')
|
||||
.equals($ae_loc.person_id)
|
||||
.reverse()
|
||||
.sortBy('tmp_sort_3');
|
||||
})
|
||||
);
|
||||
|
||||
@@ -105,7 +105,6 @@ let lq__journal_obj_li = $derived(
|
||||
let results = await db_journals.journal
|
||||
.where('person_id')
|
||||
.equals($ae_loc.person_id)
|
||||
.reverse()
|
||||
.sortBy('tmp_sort_2');
|
||||
|
||||
// Check if results are different than the current session version stored under $journals_slct
|
||||
|
||||
Reference in New Issue
Block a user