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
|
||||
},
|
||||
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_presenter: 1,
|
||||
event_badge: 1,
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
idaa_slct,
|
||||
idaa_trig
|
||||
} 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 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.
|
||||
$effect(() => {
|
||||
// 1. Reactive Dependencies
|
||||
const account_id = $ae_loc.account_id;
|
||||
if (!account_id) return; // Wait for account context
|
||||
// Use $slct (non-persisted, set only by bootstrap Sync Effect) not $ae_loc
|
||||
// (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.
|
||||
// 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;
|
||||
|
||||
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;
|
||||
|
||||
if (!account_id) return;
|
||||
@@ -253,11 +255,11 @@ async function handle_search_refresh(qry_key: string) {
|
||||
(b.name ?? '').localeCompare(a.name ?? '')
|
||||
);
|
||||
} else {
|
||||
// Robust Chronological Sort using pre-computed tmp_sort_1
|
||||
// Handles Priority, Manual Sort, and the updated_on/created_on fallback
|
||||
// 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),
|
||||
// NOT build_tmp_sort's inverted encoding. priority=true→'1' > priority=false→'0',
|
||||
// so DESCENDING sort puts priority items first.
|
||||
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 ?? '')
|
||||
);
|
||||
} 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) =>
|
||||
(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
|
||||
{event_id_li}
|
||||
link_to_type={'account'}
|
||||
link_to_id={$ae_loc.account_id}
|
||||
link_to_id={$slct.account_id}
|
||||
limit={$idaa_loc.recovery_meetings.qry__limit}
|
||||
{log_lvl} />
|
||||
{:else}
|
||||
@@ -508,14 +511,25 @@ if (browser) {
|
||||
type="button"
|
||||
class="btn btn-sm preset-tonal-surface preset-outlined-warning-100-900 hover:preset-filled-warning-200-800 transition-all"
|
||||
onclick={async () => {
|
||||
localStorage.removeItem('ae_loc');
|
||||
localStorage.removeItem('ae_idaa_loc');
|
||||
try { await db_events.event.clear(); } catch { /* ignore */ }
|
||||
// Save the iframe reload URL first — it carries the Novi UUID + key
|
||||
// params needed to re-authenticate after the cache wipe.
|
||||
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 {
|
||||
const saved_url = sessionStorage.getItem('idaa_iframe_reload_url');
|
||||
if (saved_url) { location.href = saved_url; return; }
|
||||
const db_list = await indexedDB.databases();
|
||||
for (const db of db_list) {
|
||||
if (db.name) indexedDB.deleteDatabase(db.name);
|
||||
}
|
||||
} 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>
|
||||
Clear Cache & Reload
|
||||
|
||||
@@ -93,12 +93,11 @@ let lq__event_obj_li = $derived.by(() => {
|
||||
(b.name ?? '').localeCompare(a.name ?? '')
|
||||
);
|
||||
} else {
|
||||
// Robust Chronological Sort using pre-computed tmp_sort_1 (Refactored 2026-02-16)
|
||||
// This handles Group > Priority > Manual Sort > Date (with updated_on fallback)
|
||||
// tmp_sort_1 is built by build_tmp_sort() for ascending comparison:
|
||||
// priority=true encodes as '0', priority=false as '1', so ASC puts priority first.
|
||||
// Events use legacy tmp_sort_1 encoding (ae_events__event.ts: priority ? 1 : 0),
|
||||
// NOT build_tmp_sort's inverted encoding. priority=true→'1' > priority=false→'0',
|
||||
// so DESCENDING sort puts priority items first.
|
||||
results.sort((a, b) =>
|
||||
(a.tmp_sort_1 ?? '').localeCompare(b.tmp_sort_1 ?? '')
|
||||
(b.tmp_sort_1 ?? '').localeCompare(a.tmp_sort_1 ?? '')
|
||||
);
|
||||
}
|
||||
return results;
|
||||
|
||||
Reference in New Issue
Block a user