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 { api } from '$lib/api/api';
|
||||||
|
|
||||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
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 { db_events } from '$lib/ae_events/db_events';
|
||||||
import type { ae_EventPresentation } from '$lib/types/ae_types';
|
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)
|
if (obj.event_session_id_random)
|
||||||
obj.event_session_id = 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;
|
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;
|
return obj;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { key_val } from '$lib/stores/ae_stores';
|
|||||||
import { api } from '$lib/api/api';
|
import { api } from '$lib/api/api';
|
||||||
|
|
||||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
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 { db_journals } from '$lib/ae_journals/db_journals';
|
||||||
import type { ae_Journal } from '$lib/types/ae_types';
|
import type { ae_Journal } from '$lib/types/ae_types';
|
||||||
|
|
||||||
@@ -885,9 +886,16 @@ export async function process_ae_obj__journal_props({
|
|||||||
|
|
||||||
const updated =
|
const updated =
|
||||||
obj.updated_on ?? obj.created_on ?? new Date(0).toISOString();
|
obj.updated_on ?? obj.created_on ?? new Date(0).toISOString();
|
||||||
obj.tmp_sort_3 = `${obj.group ?? '0'}_${obj.priority ? 1 : 0}_${obj.sort ?? '0'}_${
|
const { tmp_sort_1, tmp_sort_2, tmp_sort_3 } = build_tmp_sort({
|
||||||
obj.name
|
prefix: [obj.group ?? '0'],
|
||||||
}_${updated}`;
|
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 ?? ''}`;
|
obj.combined_passcode = `${obj.passcode ?? ''}:${obj.private_passcode ?? ''}`;
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { key_val } from '$lib/stores/ae_stores';
|
|||||||
import { api } from '$lib/api/api';
|
import { api } from '$lib/api/api';
|
||||||
|
|
||||||
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
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 { db_journals } from '$lib/ae_journals/db_journals';
|
||||||
import type { ae_JournalEntry } from '$lib/types/ae_types';
|
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 = history;
|
||||||
obj.history_md_html = history_md_html;
|
obj.history_md_html = history_md_html;
|
||||||
|
|
||||||
// Journal entry-specific computed sort fields, overriding generic ones if needed
|
// Journal entry-specific computed sort fields via build_tmp_sort.
|
||||||
const sort_val = (obj.sort ?? 0).toString().padStart(3, '0');
|
// Order: priority DESC → sort ASC → name ASC → updated ASC (all ascending, no .reverse())
|
||||||
const updated =
|
const updated =
|
||||||
obj.updated_on ?? obj.created_on ?? new Date(0).toISOString();
|
obj.updated_on ?? obj.created_on ?? new Date(0).toISOString();
|
||||||
obj.tmp_sort_1 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
const { tmp_sort_1, tmp_sort_2, tmp_sort_3 } = build_tmp_sort({
|
||||||
sort_val
|
prefix: [obj.group ?? ''],
|
||||||
}_${updated}`;
|
priority: obj.priority,
|
||||||
obj.tmp_sort_2 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
sort: obj.sort,
|
||||||
sort_val
|
fields_2: [obj.name],
|
||||||
}_${obj.name ?? ''}_${updated}`;
|
fields_3: [updated]
|
||||||
obj.tmp_sort_3 = `${obj.group ?? ''}_${obj.priority ? '1' : '0'}_${
|
});
|
||||||
sort_val
|
obj.tmp_sort_1 = tmp_sort_1;
|
||||||
}_${obj.name ?? ''}_${updated}`;
|
obj.tmp_sort_2 = tmp_sort_2;
|
||||||
|
obj.tmp_sort_3 = tmp_sort_3;
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,11 +90,11 @@ let lq__event_file_obj_li = $derived.by(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Event Presentation
|
// Event Presentation
|
||||||
// WHY: $derived.by — same reason as above. Captures both id and sort_by in the outer
|
// WHY: $derived.by — captures id in the outer closure so a new Observable is
|
||||||
// closure so a new Observable is created whenever the session or its type changes.
|
// 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(() => {
|
let lq__event_presentation_obj_li = $derived.by(() => {
|
||||||
const id = slct__event_session_id;
|
const id = slct__event_session_id;
|
||||||
const sort_by = type_code == 'poster' ? 'name' : 'start_datetime';
|
|
||||||
return liveQuery(async () => {
|
return liveQuery(async () => {
|
||||||
if (!id) return [];
|
if (!id) return [];
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ let lq__event_presentation_obj_li = $derived.by(() => {
|
|||||||
return await db_events.presentation
|
return await db_events.presentation
|
||||||
.where('event_session_id')
|
.where('event_session_id')
|
||||||
.equals(id)
|
.equals(id)
|
||||||
.sortBy(sort_by);
|
.sortBy('tmp_sort_2');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -67,40 +67,18 @@ let lq__event_session_obj = $derived(
|
|||||||
);
|
);
|
||||||
|
|
||||||
// 2. Presentation List Observable
|
// 2. Presentation List Observable
|
||||||
// WHY: Dexie sortBy() is single-field only. Multi-field sort requires toArray() + JS comparator.
|
// WHY: tmp_sort_2 encodes priority DESC → sort ASC → start_datetime ASC → code ASC → name ASC
|
||||||
// Desired order: 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(
|
let lq__event_presentation_obj_li = $derived(
|
||||||
liveQuery(async () => {
|
liveQuery(async () => {
|
||||||
if (log_lvl)
|
if (log_lvl)
|
||||||
console.log(
|
console.log(
|
||||||
`[LQ] Querying Presentations for Session: ${url_session_id}`
|
`[LQ] Querying Presentations for Session: ${url_session_id}`
|
||||||
);
|
);
|
||||||
const results = await db_events.presentation
|
return await db_events.presentation
|
||||||
.where('event_session_id')
|
.where('event_session_id')
|
||||||
.equals(url_session_id)
|
.equals(url_session_id)
|
||||||
.toArray();
|
.sortBy('tmp_sort_2');
|
||||||
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;
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ let lq__journal_obj_li = $derived(
|
|||||||
return await db_journals.journal
|
return await db_journals.journal
|
||||||
.where('person_id')
|
.where('person_id')
|
||||||
.equals($ae_loc.person_id)
|
.equals($ae_loc.person_id)
|
||||||
.reverse()
|
|
||||||
.sortBy('tmp_sort_3');
|
.sortBy('tmp_sort_3');
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ let lq__journal_obj_li = $derived(
|
|||||||
let results = await db_journals.journal
|
let results = await db_journals.journal
|
||||||
.where('person_id')
|
.where('person_id')
|
||||||
.equals($ae_loc.person_id)
|
.equals($ae_loc.person_id)
|
||||||
.reverse()
|
|
||||||
.sortBy('tmp_sort_2');
|
.sortBy('tmp_sort_2');
|
||||||
|
|
||||||
// Check if results are different than the current session version stored under $journals_slct
|
// Check if results are different than the current session version stored under $journals_slct
|
||||||
|
|||||||
Reference in New Issue
Block a user