fix(idaa-recovery-meetings): fix priority sort, stale account_id gate, and cache clear
Three fixes for the IDAA Recovery Meetings load/display issues:
1. Sort direction: events use legacy encoding (priority ? 1 : 0), not build_tmp_sort.
priority=true→'1' requires DESCENDING sort to put priority items first. The prior
commit (ee79e33a2) incorrectly applied the build_tmp_sort-compatible ASC comparator
to the events module, which does not use that encoding. Reverted in +page.svelte
(both fast-path and API-results sort) and ae_idaa_comp__event_obj_li_wrapper.svelte.
2. Stale account_id gate: search $effect and handle_search_refresh now read
$slct.account_id (set only by the bootstrap Sync Effect, reliable) instead of
$ae_loc.account_id (persisted localStorage, may be stale from a prior session).
Follows the mistake #14 pattern from BOOTSTRAP__AI_Agent_Quickstart.md.
3. Clear Cache & Reload: now enumerates and deletes ALL IDB databases via
indexedDB.databases() (not just db_events.event), clears all localStorage and
sessionStorage (not just two keys), and preserves the iframe reload URL for
Novi re-authentication — matching the Full Reset pattern in e_app_help_tech.svelte.
4. IDB version bump: events.event → v3 (precautionary; flushes any stale cached
event records on next user load in case prior deploys missed a bump).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -86,7 +86,7 @@ export const IDB_CONTENT_VERSIONS = {
|
|||||||
journal_entry: 3 // 2026-05-14: removed content_md_html + history_md_html from properties_to_save
|
journal_entry: 3 // 2026-05-14: removed content_md_html + history_md_html from properties_to_save
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
event: 2, // Bumped 2026-05-16: force-clear stale IDB data causing "no meetings found" on IDAA
|
event: 3, // Bumped 2026-06-03: precautionary clear after sort-direction and account_id gate fixes
|
||||||
event_session: 1,
|
event_session: 1,
|
||||||
event_presenter: 1,
|
event_presenter: 1,
|
||||||
event_badge: 1,
|
event_badge: 1,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
idaa_slct,
|
idaa_slct,
|
||||||
idaa_trig
|
idaa_trig
|
||||||
} from '$lib/stores/ae_idaa_stores';
|
} from '$lib/stores/ae_idaa_stores';
|
||||||
import { ae_loc, ae_api } from '$lib/stores/ae_stores';
|
import { ae_loc, ae_api, slct } from '$lib/stores/ae_stores';
|
||||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||||
|
|
||||||
import Element_data_store from '$lib/elements/element_data_store.svelte';
|
import Element_data_store from '$lib/elements/element_data_store.svelte';
|
||||||
@@ -135,8 +135,10 @@ function clear_filters() {
|
|||||||
// This effect manages the orchestration between UI state and data fetching.
|
// This effect manages the orchestration between UI state and data fetching.
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
// 1. Reactive Dependencies
|
// 1. Reactive Dependencies
|
||||||
const account_id = $ae_loc.account_id;
|
// Use $slct (non-persisted, set only by bootstrap Sync Effect) not $ae_loc
|
||||||
if (!account_id) return; // Wait for account context
|
// (persisted, may hold stale account_id from a previous session in localStorage).
|
||||||
|
const account_id = $slct.account_id;
|
||||||
|
if (!account_id) return; // Wait for bootstrap to set account context
|
||||||
|
|
||||||
// Auth gate: do not fetch IDAA events for unauthenticated users.
|
// Auth gate: do not fetch IDAA events for unauthenticated users.
|
||||||
// WHY $effect and not +layout.ts: layout load functions fire on SvelteKit link prefetch,
|
// WHY $effect and not +layout.ts: layout load functions fire on SvelteKit link prefetch,
|
||||||
@@ -180,7 +182,7 @@ async function handle_search_refresh(qry_key: string) {
|
|||||||
last_executed_key = qry_key;
|
last_executed_key = qry_key;
|
||||||
|
|
||||||
const current_search_id = ++last_search_id;
|
const current_search_id = ++last_search_id;
|
||||||
const account_id = $ae_loc.account_id;
|
const account_id = $slct.account_id;
|
||||||
const remote_first = $idaa_loc.recovery_meetings.qry__remote_first;
|
const remote_first = $idaa_loc.recovery_meetings.qry__remote_first;
|
||||||
|
|
||||||
if (!account_id) return;
|
if (!account_id) return;
|
||||||
@@ -253,11 +255,11 @@ async function handle_search_refresh(qry_key: string) {
|
|||||||
(b.name ?? '').localeCompare(a.name ?? '')
|
(b.name ?? '').localeCompare(a.name ?? '')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Robust Chronological Sort using pre-computed tmp_sort_1
|
// Events use legacy tmp_sort_1 encoding (ae_events__event.ts: priority ? 1 : 0),
|
||||||
// Handles Priority, Manual Sort, and the updated_on/created_on fallback
|
// NOT build_tmp_sort's inverted encoding. priority=true→'1' > priority=false→'0',
|
||||||
// tmp_sort_1 built by build_tmp_sort(): priority=true→'0', so ASC puts priority first.
|
// so DESCENDING sort puts priority items first.
|
||||||
local_results.sort((a, b) =>
|
local_results.sort((a, b) =>
|
||||||
(a.tmp_sort_1 ?? '').localeCompare(b.tmp_sort_1 ?? '')
|
(b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,9 +338,10 @@ async function handle_search_refresh(qry_key: string) {
|
|||||||
(b.name ?? '').localeCompare(a.name ?? '')
|
(b.name ?? '').localeCompare(a.name ?? '')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// tmp_sort_1 built by build_tmp_sort(): priority=true→'0', so ASC puts priority first.
|
// Events use legacy tmp_sort_1 encoding (ae_events__event.ts: priority ? 1 : 0).
|
||||||
|
// DESCENDING sort puts priority=true ('1') items first.
|
||||||
api_results.sort((a, b) =>
|
api_results.sort((a, b) =>
|
||||||
(a.tmp_sort_1 ?? '').localeCompare(b.tmp_sort_1 ?? '')
|
(b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,7 +468,7 @@ if (browser) {
|
|||||||
<Comp__event_obj_li_wrapper
|
<Comp__event_obj_li_wrapper
|
||||||
{event_id_li}
|
{event_id_li}
|
||||||
link_to_type={'account'}
|
link_to_type={'account'}
|
||||||
link_to_id={$ae_loc.account_id}
|
link_to_id={$slct.account_id}
|
||||||
limit={$idaa_loc.recovery_meetings.qry__limit}
|
limit={$idaa_loc.recovery_meetings.qry__limit}
|
||||||
{log_lvl} />
|
{log_lvl} />
|
||||||
{:else}
|
{:else}
|
||||||
@@ -508,14 +511,25 @@ if (browser) {
|
|||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm preset-tonal-surface preset-outlined-warning-100-900 hover:preset-filled-warning-200-800 transition-all"
|
class="btn btn-sm preset-tonal-surface preset-outlined-warning-100-900 hover:preset-filled-warning-200-800 transition-all"
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
localStorage.removeItem('ae_loc');
|
// Save the iframe reload URL first — it carries the Novi UUID + key
|
||||||
localStorage.removeItem('ae_idaa_loc');
|
// params needed to re-authenticate after the cache wipe.
|
||||||
try { await db_events.event.clear(); } catch { /* ignore */ }
|
let reload_url: string | null = null;
|
||||||
|
try { reload_url = sessionStorage.getItem('idaa_iframe_reload_url'); } catch { /* ignore */ }
|
||||||
|
|
||||||
|
// Delete every IDB database on this origin (not just db_events.event).
|
||||||
try {
|
try {
|
||||||
const saved_url = sessionStorage.getItem('idaa_iframe_reload_url');
|
const db_list = await indexedDB.databases();
|
||||||
if (saved_url) { location.href = saved_url; return; }
|
for (const db of db_list) {
|
||||||
|
if (db.name) indexedDB.deleteDatabase(db.name);
|
||||||
|
}
|
||||||
} catch { /* ignore */ }
|
} catch { /* ignore */ }
|
||||||
location.reload();
|
|
||||||
|
// Clear all localStorage and sessionStorage. IDAA auth comes from
|
||||||
|
// the Novi UUID in the URL, not localStorage, so a full clear is safe.
|
||||||
|
localStorage.clear();
|
||||||
|
sessionStorage.clear();
|
||||||
|
|
||||||
|
if (reload_url) { location.href = reload_url; } else { location.reload(); }
|
||||||
}}>
|
}}>
|
||||||
<span class="fas fa-sync-alt m-1"></span>
|
<span class="fas fa-sync-alt m-1"></span>
|
||||||
Clear Cache & Reload
|
Clear Cache & Reload
|
||||||
|
|||||||
@@ -93,12 +93,11 @@ let lq__event_obj_li = $derived.by(() => {
|
|||||||
(b.name ?? '').localeCompare(a.name ?? '')
|
(b.name ?? '').localeCompare(a.name ?? '')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Robust Chronological Sort using pre-computed tmp_sort_1 (Refactored 2026-02-16)
|
// Events use legacy tmp_sort_1 encoding (ae_events__event.ts: priority ? 1 : 0),
|
||||||
// This handles Group > Priority > Manual Sort > Date (with updated_on fallback)
|
// NOT build_tmp_sort's inverted encoding. priority=true→'1' > priority=false→'0',
|
||||||
// tmp_sort_1 is built by build_tmp_sort() for ascending comparison:
|
// so DESCENDING sort puts priority items first.
|
||||||
// priority=true encodes as '0', priority=false as '1', so ASC puts priority first.
|
|
||||||
results.sort((a, b) =>
|
results.sort((a, b) =>
|
||||||
(a.tmp_sort_1 ?? '').localeCompare(b.tmp_sort_1 ?? '')
|
(b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? '')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
|
|||||||
Reference in New Issue
Block a user