refactor(stores): phase 1 cleanup — ae_stores.ts and ae_events_stores.ts

- Remove ~200 lines of dead commented-out code (old test blocks, stale
  import alternatives, unused console.log lines)
- Remove ver_idb fields — superseded by store_versions.ts __version mechanism
- Remove Stripe button IDs / publishable key from events_sess (no consumers)
- Remove stale event-specific comments (CHOW 2024 sponsor tiers, ISHLT note)
- Remove example: true test field from session leads struct
- Improve comments: ver stamp rationale, auth__kv expiry intent, api_*_kv
  shape doc, slct/events_slct tab-isolation rationale, level_guest_max_li
  fallback note, events_trig_kv purpose
- Keep all active business logic and exports unchanged; zero consumer impact
This commit is contained in:
Scott Idem
2026-03-16 14:50:53 -04:00
parent 04aee814e1
commit 65291aa5b9
3 changed files with 108 additions and 306 deletions

View File

@@ -32,7 +32,7 @@ frontend pass the location directly in the Launcher URL without the extra lookup
- [x] **Minor Svelte warning:** `slct_event_location_id` in `menu_location_list.svelte` — prop already has `$bindable(null)`; stale comment in file updated. (2026-03-11) - [x] **Minor Svelte warning:** `slct_event_location_id` in `menu_location_list.svelte` — prop already has `$bindable(null)`; stale comment in file updated. (2026-03-11)
### [Svelte] State reference warnings ### [Svelte] State reference warnings
- [x] **`state_referenced_locally` warnings resolved** — all 42 warnings fixed. v1 edit form retired; v2 renamed to canonical name. Remaining 23 warnings in `ae_idaa_comp__event_obj_id_edit.svelte` are CSS `@apply`/`@reference` warnings from the svelte-check CSS language service not understanding Tailwind v4 at-rules — harmless, build works fine, not fixable without a full `<style>` block refactor. (2026-03-11) - [x] **`svelte-check` fully clean — 0 errors, 0 warnings.** All 42 `state_referenced_locally` warnings fixed (2026-03-11). CSS `@apply`/`@reference` warnings in `ae_idaa_comp__event_obj_id_edit.svelte` also resolved — Tailwind utilities inlined, `<style>` block removed. (2026-03-16)
### [Badges] Remaining badge work before first live event ### [Badges] Remaining badge work before first live event
- **Badge print controls UX polish:** Scott has improvements in mind — TBD next session. - **Badge print controls UX polish:** Scott has improvements in mind — TBD next session.
@@ -75,6 +75,10 @@ lead record look like in the DB?
- **Input Field Audit:** Several input fields are missing `name`/`id` attributes or `data-testid`. Known examples: badge override fields in `ae_comp__badge_obj_view.svelte`; template name input in `ae_comp__badge_template_form.svelte`. Matters for: accessibility, autofill, label associations, and test targeting. (For tests, use `getByLabel()` rather than `input[value*=...]` which only checks the HTML attribute, not the Svelte-bound DOM property.) - **Input Field Audit:** Several input fields are missing `name`/`id` attributes or `data-testid`. Known examples: badge override fields in `ae_comp__badge_obj_view.svelte`; template name input in `ae_comp__badge_template_form.svelte`. Matters for: accessibility, autofill, label associations, and test targeting. (For tests, use `getByLabel()` rather than `input[value*=...]` which only checks the HTML attribute, not the Svelte-bound DOM property.)
## ✅ Completed (2026-03) ## ✅ Completed (2026-03)
- [x] **[UI]** Pres Mgmt Phase 3 — FA→Lucide icon migration across all 24 pres_mgmt files. (2026-03-16)
- [x] **[IDAA]** `ae_idaa_comp__event_obj_id_edit.svelte` — inlined Tailwind utilities, removed `<style>` block; eliminated all 23 `@apply`/`@reference` svelte-check warnings. (2026-03-16)
- [x] **[Badges]** Badge print page svelte-check fix: extracted print CSS to `static/ae-print-badge.css`; fixed unclosed `<script>` tag in `print/+page.svelte`. (2026-03-16)
- [x] **[Svelte/Tests]** svelte-check cleanup: fixed `select_ref_badge_type` `$state()` declaration; two `<svelte:component>` deprecations in launcher components; `page.evaluate()` two-arg pattern in `badge_print_layout.test.ts`. (2026-03-16)
- [x] **[Launcher]** Hosted file download button `require_auth` prop — added `require_auth?: boolean` (default `true`) to `ae_comp__hosted_files_download_button.svelte`; all existing consumers unchanged. Launcher `launcher_file_cont.svelte` passes `require_auth={false}` so unauthenticated kiosk users can open/download files without being blocked. (2026-03-16) - [x] **[Launcher]** Hosted file download button `require_auth` prop — added `require_auth?: boolean` (default `true`) to `ae_comp__hosted_files_download_button.svelte`; all existing consumers unchanged. Launcher `launcher_file_cont.svelte` passes `require_auth={false}` so unauthenticated kiosk users can open/download files without being blocked. (2026-03-16)
- [x] **[Security]** `PUBLIC_AE_API_SECRET_KEY` audit complete. Key is `PUBLIC_*` by design (always in client bundle). Highest-risk anonymous path uses limited-permission `PUBLIC_AE_BOOTSTRAP_KEY`. Full server-side migration not justified given JWT + account_id auth layers. Current state acceptable. (2026-03-11) - [x] **[Security]** `PUBLIC_AE_API_SECRET_KEY` audit complete. Key is `PUBLIC_*` by design (always in client bundle). Highest-risk anonymous path uses limited-permission `PUBLIC_AE_BOOTSTRAP_KEY`. Full server-side migration not justified given JWT + account_id auth layers. Current state acceptable. (2026-03-11)
- [x] **[UX]** Session Expired banner — `ae_auth_error` store wired to API helpers; root layout sets `flag_expired` on 401/403; non-blocking dismissible banner rendered. (2026-03-12) - [x] **[UX]** Session Expired banner — `ae_auth_error` store wired to API helpers; root layout sets `flag_expired` on 401/403; non-blocking dismissible banner rendered. (2026-03-12)

View File

@@ -8,21 +8,20 @@ import type { Writable } from 'svelte/store';
import type { key_val } from '$lib/stores/ae_stores'; import type { key_val } from '$lib/stores/ae_stores';
// Set the version for the app data. Changing this should force a notification and ask the user to clear and reload the page. // Deployment version stamp. Compared against events_sess.ver in events/+layout.svelte
// to detect stale persisted data after a deploy (triggers a reload). Bump this alongside
// events_session_data_struct.ver. See store_versions.ts for the schema-level wipe mechanism.
const ver = '2025-10-16_2139'; const ver = '2025-10-16_2139';
const ver_idb = '2025-10-16_2139';
/* *** BEGIN *** Initialize events_local_data_struct */ /* *** BEGIN *** Initialize events_local_data_struct */
// Longer-term app data. This should be stored to *local* storage. // Persisted to localStorage. Retains user preferences and event-specific config across
// Updated 2024-03-06 // browser sessions. See store_versions.ts for the schema-level invalidation mechanism.
const events_local_data_struct: key_val = { const events_local_data_struct: key_val = {
__version: AE_EVENTS_LOC_VERSION, // Schema version gate — see store_versions.ts __version: AE_EVENTS_LOC_VERSION, // Schema version gate — see store_versions.ts
ver: ver, ver: ver, // Deployment stamp — compared against events_sess.ver to trigger reloads.
ver_idb: ver_idb,
// Shared name: 'Aether - Events',
name: 'Aether - Events (SvelteKit 2.x Svelte 4.x)', title: `OSIT's Æ Events`,
title: `OSIT's Æ Events`, // - Dev SvelteKit`, // &AElig;
ds: {}, ds: {},
@@ -44,41 +43,19 @@ const events_local_data_struct: key_val = {
// The auth__entered_key (usually email or person_id) and auth__entered_passcode is found under events_sess.entered_key and events_sess.entered_passcode because it should be temporary. // The auth__entered_key (usually email or person_id) and auth__entered_passcode is found under events_sess.entered_key and events_sess.entered_passcode because it should be temporary.
// auth__entered_passcode: null, // auth__entered_passcode: null,
// The auth__kv (key value pairs) is used to store the xyz IDs that the browser client can access. This is a key value list of xyz ID and created datetime stamp (or just true). These should not be more than X days old. // auth__kv tracks which IDs the browser client is permitted to access.
// Each entry is an ID mapped to true, false, 'read', or 'write'.
// Keys should be no older than a configurable max age (checked on read).
auth__kv: { auth__kv: {
event: { event: {},
// 'LNDF-67-89-92': true exhibit: {},
}, location: {},
exhibit: { session: {},
// 'LNDF-67-89-92': true presentation: {},
}, presenter: {},
location: { person: {}
// 'LNDF-67-89-92': true
},
session: {
// 'LNDF-67-89-92': true, false, 'read', 'write'
},
presentation: {
// 'LNDF-67-89-92': true
},
presenter: {
// 'LNDF-67-89-92': true
},
person: {
// 'LNDF-67-89-92': true
}
}, },
// auth__session_kv: {
// // {'LNDF-67-89-92': true}
// },
// auth__presentation_kv: {
// // {'LNDF-67-89-92': true}
// },
// auth__presenter_kv: {
// // {'LNDF-67-89-92': true}
// },
// Badge Printing // Badge Printing
badges: { badges: {
auto_view: true, auto_view: true,
@@ -91,8 +68,6 @@ const events_local_data_struct: key_val = {
show_element__cfg: true, show_element__cfg: true,
show_element__cfg_detail: false, show_element__cfg_detail: false,
// 'theme_mode': 'dark',
// 'theme_name': 'wintry',
fulltext_search_qry_str: null, fulltext_search_qry_str: null,
search_badge_type_code: null, search_badge_type_code: null,
@@ -114,10 +89,6 @@ const events_local_data_struct: key_val = {
classes__form: 'border border-surface-200 p-4 space-y-4 rounded-container' classes__form: 'border border-surface-200 p-4 space-y-4 rounded-container'
}, },
// Event Files - uploads for sessions, presenters, etc
// 'files': {
// },
// Event Presentation Launcher (and native Electron app) // Event Presentation Launcher (and native Electron app)
launcher: { launcher: {
// default - browser, onsite - browser onsite, native - Electron app onsite // default - browser, onsite - browser onsite, native - Electron app onsite
@@ -192,8 +163,6 @@ const events_local_data_struct: key_val = {
}, },
native: { native: {
// 'local_file_cache_path': aether_cfg_data.app.local_file_cache_path,
// 'host_file_temp_path': aether_cfg_data.app.host_file_temp_path,
host_file_config_path: 'device_configs/ae_native_app_config.default.json' host_file_config_path: 'device_configs/ae_native_app_config.default.json'
}, },
@@ -223,8 +192,8 @@ const events_local_data_struct: key_val = {
show_content__email_link_warning: true, show_content__email_link_warning: true,
default_to_scan: true, default_to_scan: true,
// Fallback external registration ID used when building lead export data.
// For ISHLT 2024 Annual Meeting only! // Should be overridden by the active event's external_event_id in cfg_json.
default__external_registration_id: '2024_Annual Meeting', default__external_registration_id: '2024_Annual Meeting',
auto_view: true, // Show the new lead after added by scan or search auto_view: true, // Show the new lead after added by scan or search
@@ -251,15 +220,11 @@ const events_local_data_struct: key_val = {
// The entered_passcode is the exhibit booths shared passcode for staff. This is used to initially access the lead retrieval service. // The entered_passcode is the exhibit booths shared passcode for staff. This is used to initially access the lead retrieval service.
entered_passcode: null, entered_passcode: null,
// The auth_exhibit_kv (key value pairs) is used to store the exhibit IDs that the browser client can access. This is a key value list of exhibit ID and created datetime stamp. These should not be more than X days old. The entered_passcode for events_sess.leads is what they are entering to log in. // auth_exhibit_kv: key-value of exhibit IDs this browser client
auth_exhibit_kv: { // is authorized for, mapped to { key, updated_on }. Entries expire
// {'LNDF-67-89-92': {key: 'example@oneskyit.com', updated_on: '2024-03-13T08:05:29Z}} // after a configurable max age and must be re-authenticated.
}, auth_exhibit_kv: {},
// The auth_exhibit_license_li is used to store the exhibit license(s) being used on the browser client. There can be multiple exhibit IDs, but only one license per exhibit ID for the browser client. This is used to determine who can actually access and use the lead retrieval service. This is a key value list of key (email address) and created datetime stamp. These should not be more than X days old.
// auth_exhibit_license_li: {
// // 'LNDF-67-89-92': { 'key': 'example@oneskyit.com', 'updated_on': '2024-03-13T08:05:29Z'}
// },
edit_license_li: false, edit_license_li: false,
// The "tab" is a key value list of exhibit ID and tab name. This is intentionally using local storage to store the current tab for each exhibit. // The "tab" is a key value list of exhibit ID and tab name. This is intentionally using local storage to store the current tab for each exhibit.
@@ -298,10 +263,7 @@ const events_local_data_struct: key_val = {
require__presenter_agree: false, require__presenter_agree: false,
require__session_agree: false, require__session_agree: false,
// show_content__agree_text: false,
show_content__event_view: null, show_content__event_view: null,
// show__launcher_link: false,
// show__location_link: false,
show_content__location_qr: false, show_content__location_qr: false,
show_content__presentation_description: false, // Note that this is for *all* presentations in the user interface. It is a global setting. show_content__presentation_description: false, // Note that this is for *all* presentations in the user interface. It is a global setting.
show_content__presenter_page_help: true, show_content__presenter_page_help: true,
@@ -348,10 +310,6 @@ const events_local_data_struct: key_val = {
show_menu__event_reports: null, show_menu__event_reports: null,
show_report: null, show_report: null,
// show_report__presenters_agree: false,
// show_report__recent_files: false,
// time_format: 'time_12_short', // 'time_short', 'time_12_short'
disable_submit__opt_out: true, disable_submit__opt_out: true,
submit_status__opt_out: null, submit_status__opt_out: null,
@@ -364,27 +322,15 @@ const events_local_data_struct: key_val = {
} }
} }
// Speakers Management (Collection)
// 'speakers': {
// },
// other
}; };
// console.log(`AE Stores - App Events Local Storage Data:`, events_local_data_struct);
// This works, but does not uses local storage:
// export let ae_loc = writable(events_local_data_struct);
// This works and uses *local* storage:
export const events_loc: Writable<key_val> = persisted('ae_events_loc', events_local_data_struct); export const events_loc: Writable<key_val> = persisted('ae_events_loc', events_local_data_struct);
// console.log(`AE Stores - App Local Storage Data:`, get(ae_loc));
/* *** BEGIN *** Initialize events_session_data_struct */ /* *** BEGIN *** Initialize events_session_data_struct */
// Temporary app data. This should be stored to session storage. // In-memory only (writable, not persisted). Resets on page load.
// Updated 2024-03-06
const events_session_data_struct: key_val = { const events_session_data_struct: key_val = {
// Deployment stamp — compared against events_loc.ver in events/+layout.svelte.
ver: ver, ver: ver,
ver_idb: ver_idb,
log_lvl: 1, log_lvl: 1,
// Shared // Shared
@@ -477,8 +423,6 @@ const events_session_data_struct: key_val = {
// Lead Retrievals (Exhibit) // Lead Retrievals (Exhibit)
leads: { leads: {
example: true,
show_form__license: false, show_form__license: false,
show_form__search: false, show_form__search: false,
show_form__scan: false, show_form__scan: false,
@@ -496,7 +440,6 @@ const events_session_data_struct: key_val = {
last_refresh_time: null as string | null, last_refresh_time: null as string | null,
next_refresh_countdown: 0, next_refresh_countdown: 0,
// The entered_passcode is the exhibit booths shared passcode for staff. This is used to initially access the lead retrieval service.
entered_passcode: null, entered_passcode: null,
tmp_license: { tmp_license: {
@@ -517,24 +460,6 @@ const events_session_data_struct: key_val = {
qr_scan_result: null qr_scan_result: null
}, },
stripe: {
license_qty: 1,
rental_qty: 0,
rental_option: true,
api_use: false,
client_reference_id: null,
publishable_key: 'pk_live_zqaWNDfak2eDHeqnRiyaJcFi',
btn_payment_id: null,
btn_1_license: 'buy_btn_1OvqWJ2gJkNsDuiNqMCWz5nG',
btn_1_license_rental: 'buy_btn_1OvqVA2gJkNsDuiNhk9r8Io2',
btn_3_license: 'buy_btn_1OvrI22gJkNsDuiNXjBg3c4Y',
btn_3_license_rental: 'buy_btn_1OvrKa2gJkNsDuiNhSBCkNau',
btn_6_license: 'buy_btn_1OvrWc2gJkNsDuiN7mnwvZNL',
btn_6_license_rental: 'buy_btn_1OvrXP2gJkNsDuiNZpWZs3Uy',
btn_10_license: 'buy_btn_1OvrPM2gJkNsDuiNRCMHfSuz',
btn_10_license_rental: 'buy_btn_1OvrPs2gJkNsDuiN1nPkjPOM'
},
// Presentation Management // Presentation Management
pres_mgmt: { pres_mgmt: {
// link: { // link: {
@@ -616,11 +541,10 @@ const events_session_data_struct: key_val = {
// other // other
}; };
// console.log(`AE Stores - App Events Session Storage Data:`, events_session_data_struct);
export const events_sess = writable(events_session_data_struct); export const events_sess = writable(events_session_data_struct);
/* *** BEGIN *** Initialize events_slct and events_trigger */ /* *** BEGIN *** Initialize events_slct and events_trigger */
/* The slct and slct_trigger variable should not be stored in local storage. Only use session storage because browser tabs can be open to different events, badges, exhibits, etc. */ // In-memory only — tabs can have different event/session/presenter selections.
// Intended for temporary session storage. // Intended for temporary session storage.
// Updated 2024-03-06 // Updated 2024-03-06
@@ -692,20 +616,14 @@ const events_slct_obj_template: key_val = {
auth__event_presenter_id: null, auth__event_presenter_id: null,
auth__event_presentation_id: null auth__event_presentation_id: null
}; };
// console.log(`AE Stores - Selected Events Objects:`, events_slct_obj_template); // In-memory only (not persisted) — separate tabs can select different events/sessions/presenters.
// This works, and uses *session* (not local) storage:
export const events_slct = writable(events_slct_obj_template); export const events_slct = writable(events_slct_obj_template);
// This works and uses *local* storage: // Broadcast trigger — increment or set truthy to signal subscribers to re-query.
// export let events_slct: Writable<key_val> = persisted('ae_events_slct', events_slct_obj_template);
/* *** BEGIN *** Initialize events_trigger */
// Intended for temporary session storage.
// Updated 2024-03-06
export const events_trigger: any = writable(null); export const events_trigger: any = writable(null);
// console.log(`AE Events Stores - Events Trigger:`, events_trigger);
// events_trig: fine-grained triggers per object type.
// Set an ID to signal that specific object needs to be re-fetched.
const tmp__events_trig: key_val = { const tmp__events_trig: key_val = {
event_id: null, event_id: null,
event_id_li: [], event_id_li: [],
@@ -721,22 +639,7 @@ const tmp__events_trig: key_val = {
// console.log(`AE Stores - Events Trigger:`, events_trig); // console.log(`AE Stores - Events Trigger:`, events_trig);
export const events_trig: Writable<key_val> = writable(tmp__events_trig); export const events_trig: Writable<key_val> = writable(tmp__events_trig);
/* *** BEGIN *** TESTING Initialize trig_resp */ // events_trig_kv: response/status map — keys are request IDs, values are
// The idea behind this is for a shared (Svelte app (within Events for now)) trigger and response. In theory this could be used to monitor multiple downloads or have a universal status area. Intended for temporary session storage. // completion status or Promise results. Used for tracking parallel downloads.
// Updated 2024-06-25
const tmp__events_trig_kv: key_val = {}; const tmp__events_trig_kv: key_val = {};
// {
// 'example-1':
// {
// 'a-rand-id-1': true,
// 'a-rand-id-2': false,
// 'a-rand-id-3': Promise.resolve('This is a test promise.'),
// },
// 'example-2':
// {
// 'a-rand-id-4': true,
// 'a-rand-id-5': false,
// 'a-rand-id-6': Promise.resolve('This is a test promise.'),
// },
// };
export const events_trig_kv = writable(tmp__events_trig_kv); export const events_trig_kv = writable(tmp__events_trig_kv);

View File

@@ -36,69 +36,49 @@ const ae_no_account_id_token = PUBLIC_AE_NO_ACCOUNT_ID_TOKEN;
const ae_event_id = PUBLIC_AE_EVENT_ID; const ae_event_id = PUBLIC_AE_EVENT_ID;
const ae_sponsorship_cfg_id = PUBLIC_AE_SPONSORSHIP_CFG_ID; const ae_sponsorship_cfg_id = PUBLIC_AE_SPONSORSHIP_CFG_ID;
// import { getStores, navigating, page, updated } from '$app/stores'; // Loose bag-of-anything type used throughout the store. Once stores are broken into
// import { assets, base, resolveRoute } from '$app/paths'; // typed domain files, individual structs will have proper interfaces instead.
// console.log(page.path); // Everything after the domain name
// console.log(import.meta.env.MODE);
// console.log(import.meta.env.BASE_URL);
// Export the key_val type for use in other files.
export type key_val = { export type key_val = {
[key: string]: any; // variable key [key: string]: any;
// name: string;
}; };
// export type key_val = key_val;
// import { html__not_set, classes__events_pres_mgmt_menu } from './ae_string_snippets';
import { string_snippets } from '$lib/utils/ae_string_snippets'; import { string_snippets } from '$lib/utils/ae_string_snippets';
export const ae_snip = string_snippets; export const ae_snip = string_snippets;
// export let ae_snip = // Deployment version stamp. Compared against ae_sess.ver in +layout.svelte to detect
// { // stale persisted data after a deploy (triggers a reload). Bump this alongside
// 'not_set': html__not_set, // ae_app_session_data_defaults.ver whenever a deploy changes expected stored shape.
// 'classes__events_pres_mgmt_menu': classes__events_pres_mgmt_menu // See store_versions.ts for the schema-level localStorage wipe mechanism (separate concern).
// }; const ver = '2025-05-01_1445';
// Set the version for the app data. Changing this should force a notification and ask the user to clear and reload the page.
const ver = '2025-05-01_1445'; // KEEP: 2025-05-01_1445
const ver_idb = '2025-05-01_1445'; // Not currently used
// *** BEGIN *** Longer-term app data. This should be stored to local storage. // *** BEGIN *** Longer-term app data. This should be stored to local storage.
const ae_app_local_data_defaults: key_val = { const ae_app_local_data_defaults: key_val = {
__version: AE_LOC_VERSION, // Schema version gate — see store_versions.ts __version: AE_LOC_VERSION, // Schema version gate — see store_versions.ts
last_page_reload: null, last_page_reload: null,
// last_idb_reload: null,
// last_cache_refresh: null, // Date.now()
last_cache_refresh: Date.now(), last_cache_refresh: Date.now(),
cache_expired: false, cache_expired: false,
ver: ver, // ver, // '2025-04-18_1100', // Deployment stamp — compared against ae_sess.ver in +layout.svelte to trigger
ver_idb: ver_idb, // '2025-04-18_1100', // a reload when the persisted local data predates the current deploy.
ver: ver,
name: 'Aether - App Hub (SvelteKit 2.x Svelte 4.x)', name: 'Aether - App Hub',
theme: 'light', theme: 'light',
theme_mode: 'light', theme_mode: 'light',
theme_name: 'AE_Firefly', // "Shiny serenity, like a firefly." — OSIT default 2026 theme_name: 'AE_Firefly', // OSIT default theme
font_size_mode: 'default', // 'default' | 'larger' | 'smaller' font_size_mode: 'default', // 'default' | 'larger' | 'smaller'
iframe: false, iframe: false,
// disable_sys_header: false, browser_type: null, // Safari needs special handling for scrolling in iframes.
// disable_sys_nav: false,
// disable_sys_footer: false,
browser_type: null, // Safari needs help with scrolling correctly in iframes. title: `OSIT's Æ`,
title: `OSIT's Æ`, // - Dev SvelteKit`, // &AElig; debug_mode: false,
edit_mode: false,
adv_mode: false,
sync_local_config: true, // When true, pulls site config from the remote API on load.
// debug_menu: false, // Flag show debug menu. account_id: ae_account_id,
debug_mode: false, // Flag to know if we should be in debug mode and show show debug options.
edit_mode: false, // Flag to know if we should be in edit mode and show edit options.
adv_mode: false, // Flag to know if we should be in advanced mode and show advanced options.
// sys_menu: true, // Flag show system menu.
sync_local_config: true, // Flag to know if we should sync local config with the remote API server.
account_id: ae_account_id, // OSIT Demo _XY7DXtc9MY
account_code: 'not_set', account_code: 'not_set',
account_name: 'Account Name Not Set', account_name: 'Account Name Not Set',
allow_access: true, // Set to key site key was used, otherwise set to true. allow_access: true, // Set to key site key was used, otherwise set to true.
@@ -112,18 +92,14 @@ const ae_app_local_data_defaults: key_val = {
header_image_path: null header_image_path: null
}, },
// The site access codes can be pulled from the site records for an account. // Per-permission-level passcodes loaded from the site record on login.
// null = no passcode required for that tier. Overwritten by the site API response.
site_access_code_kv: { site_access_code_kv: {
// 'manager': '10240',
administrator: null, administrator: null,
trusted: null, trusted: null,
public: 'public1980', public: 'public1980',
authenticated: 'auth1980' authenticated: 'auth1980'
}, },
// 'manager_passcode': '10240',
// 'administrator_passcode': '11500',
// 'trusted_passcode': '19111',
// 'authenticated_passcode': 'auth2024',
access_type: 'anonymous', access_type: 'anonymous',
administrator_access: false, administrator_access: false,
@@ -132,49 +108,40 @@ const ae_app_local_data_defaults: key_val = {
authenticated_access: false, authenticated_access: false,
anonymous_access: true, anonymous_access: true,
user_email: null, // Currently used with Sponsorships only? user_email: null,
user_access_type: null, // Used to revert back to the user's access type after quick access (temporarily escalate permissions) turned off. // Stored on sign-in so the original permission level can be restored if temporarily escalated.
user_access_type: null,
jwt: null, // JSON Web Token for authenticated API requests jwt: null, // JSON Web Token for authenticated API requests.
// Added 2025-04-04 person_id: null,
person_id: null, // The current person_id of the logged-in user (if any)
person: { person: {
// WARNING: We need to add some logic on sign in to only include needed fields. 2025-08-12 id: null,
id: null, // The current person_id of the logged-in user
// profile_id: null, // The current person_profile_id of the logged-in user
// pronouns: null,
// informal_name: null,
given_name: null, given_name: null,
// family_name: null, full_name: null,
// professional_title: null, full_name_override: null, // Previously called display_name.
full_name: null, // convenience primary_email: null,
full_name_override: null, // was called display_name user_id: null,
// affiliations: null,
primary_email: null, // The primary email of the logged-in person/user
user_id: null, // The user ID of the logged-in user
qry_limit__people: 150, qry_limit__people: 150,
show_content__person_page_help: false show_content__person_page_help: false
}, },
// Added 2025-04-04 user_id: null,
user_id: null, // The current user_id of the logged-in user (if any)
user: { user: {
id: null, // The current user_id of the logged-in user id: null,
username: null, username: null,
name: null, name: null,
email: null, // The email of the logged-in user email: null,
allow_auth_key: null, // For sign in without password allow_auth_key: null, // Magic-link token — allows sign-in without password.
super: false, // Is the user a super user super: false,
manager: false, // Is the user a global manager (can manage accounts and users) manager: false, // Can manage accounts and users globally.
administrator: false, // Is the user an account administrator administrator: false, // Account-level administrator.
verified: false, // Is the user verified verified: false,
public: false, // Is the user a public user (can view public content) public: false,
person_id: null, // The person ID of the logged-in user person_id: null,
access_type: null, // The access type of the logged-in user access_type: null,
qry_limit__users: 100 qry_limit__users: 100
}, },
@@ -208,7 +175,6 @@ const ae_app_local_data_defaults: key_val = {
debug_menu: { debug_menu: {
hide: false, hide: false,
expand: false expand: false
// hide_quick_info: true
}, },
app_cfg: { app_cfg: {
@@ -259,18 +225,10 @@ const ae_app_local_data_defaults: key_val = {
show_list__event_presenter_obj_li: true, show_list__event_presenter_obj_li: true,
show_view__event_presenter_obj: false, show_view__event_presenter_obj: false,
submit_status: null, // 'saving', 'created', 'updated' submit_status: null,
// Badge Printing // When set, new presenters are automatically assigned to this session.
default_session_id: null
// Lead Retrievals
// Presentation Management
// Speakers Management
default_session_id: null // Assign to presenters by default
// other
}, },
journals: {}, journals: {},
@@ -283,15 +241,17 @@ const ae_app_local_data_defaults: key_val = {
for_type: null, for_type: null,
for_id: null, for_id: null,
// Max complimentary guests per sponsorship tier (0 = no tier).
// These are fallback defaults; the active event config should override via events_cfg_json.
level_guest_max_li: { level_guest_max_li: {
0: 0, 0: 0,
1: 4, // CHOW 2024 - Friend 1: 4,
2: 8, // CHOW 2024 - Supporter 2: 8,
3: 8, // CHOW 2024 - Advocate 3: 8,
4: 8, // CHOW 2024 - Champion 4: 8,
5: 8, // CHOW 2024 - Presenting Partner 5: 8,
6: 16, // CHOW 2024 - Signature Partner 6: 16,
7: 16 // CHOW 2024 - Premier Partner 7: 16
}, },
show_edit__sponsorship_obj: false, show_edit__sponsorship_obj: false,
@@ -305,57 +265,15 @@ const ae_app_local_data_defaults: key_val = {
// testing: {}, // testing: {},
} }
// testing: true,
// ver_testing: true,
}; };
// let ae_app_local_data_struct: key_val = {
// ...ae_app_local_data_defaults,
// };
// // {
// // // ...ae_app_local_data_defaults,
// // };
// // console.log(`AE Stores - App Local Storage Data:`, ae_app_local_data_struct);
// if (!ae_app_local_data_defaults?.ver_testing) {
// console.log(`TEST: AE Stores - ver_testing missing:`, ae_app_local_data_defaults);
// // ae_app_local_data_struct = {
// // ...ae_app_local_data_defaults,
// // ...ae_app_local_data_struct,
// // };
// } else {
// console.log(`TEST: AE Stores - ver_testing found`);
// }
// if (ae_app_local_data_struct?.ver !== ae_app_local_data_defaults?.ver) {
// console.log(`TEST: AE Stores - ver not match:`, ae_app_local_data_struct);
// ae_app_local_data_struct = {
// ...ae_app_local_data_defaults,
// };
// } else {
// console.log(`TEST: AE Stores - ver match: ${ae_app_local_data_struct.ver} === ${ae_app_local_data_defaults.ver}`);
// }
// if (!ae_app_local_data_struct?.app_cfg) {
// console.log(`TEST: AE Stores - app_cfg missing:`, ae_app_local_data_struct);
// ae_app_local_data_struct = {
// ...ae_app_local_data_defaults,
// ...ae_app_local_data_struct,
// };
// }
// This works, but does not uses local storage:
// export let ae_loc = writable(ae_app_local_data_struct);
// This works and uses local storage:
export const ae_loc: Writable<key_val> = persisted('ae_loc', ae_app_local_data_defaults); export const ae_loc: Writable<key_val> = persisted('ae_loc', ae_app_local_data_defaults);
// console.log(`AE Stores - App Local Storage Data:`, get(ae_loc));
// *** BEGIN *** Temporary app data. This should be stored to session storage. // *** BEGIN *** Temporary app data. This should be stored to session storage.
const ae_app_session_data_defaults: key_val = { const ae_app_session_data_defaults: key_val = {
// ver: '2025-04-18_1335', // ver, // '2025-04-18_1100', // Deployment stamp — compared against ae_loc.ver in +layout.svelte.
// When these differ, the app reloads to flush stale persisted data.
ver: ver, ver: ver,
ver_idb: ver_idb,
log_lvl: 0, log_lvl: 0,
disable_sys_header: false, disable_sys_header: false,
@@ -391,9 +309,8 @@ const ae_app_session_data_defaults: key_val = {
video_clip_file_kv: {}, video_clip_file_kv: {},
processed_file_list: [], processed_file_list: [],
status__file_list: null, status__file_list: null,
// uploaded_file_list: [],
video_clip_file_list: [], video_clip_file_list: [],
submit_status: null, // 'saving', 'created', 'updated', 'saved' submit_status: null,
clip_complete: null clip_complete: null
}, },
@@ -410,13 +327,7 @@ const ae_app_session_data_defaults: key_val = {
}, },
mod: { mod: {
archives: {}, archives: {},
events: { events: {},
// Badge Printing
// Lead Retrievals
// Presentation Management
// Speakers Management
// other
},
journals: {}, journals: {},
posts: {}, posts: {},
sponsorships: { sponsorships: {
@@ -437,25 +348,23 @@ const ae_app_session_data_defaults: key_val = {
show__modal_change_password: false, show__modal_change_password: false,
download: {}, download: {},
// For API download and upload progress status per file. // Per-file progress keyed by file_id (downloads) or temp_id (uploads).
// Shape: { status, endpoint, filename, size_total, size_loaded, percent_completed }
api_download_kv: {}, api_download_kv: {},
// Example: {example_file_id: {status: 'downloading', endpoint: '/event/file/abc123/download', filename: 'example_file_name.ext', size_total: 0, size_loaded: 0, percent_completed: 0}} api_upload_kv: {},
api_upload_kv: {}, // {example_temp_id: {status: 'uploading', endpoint: '/event/file/abc123/upload', filename: 'example_file_name.ext', size_total: 0, size_loaded: 0, percent_completed: 0}}
test: true test: true
}; };
// console.log(`AE Stores - App Session Storage Data:`, ae_app_session_data_defaults);
export const ae_sess = writable(ae_app_session_data_defaults); export const ae_sess = writable(ae_app_session_data_defaults);
// *** BEGIN *** Temporary API data. This should be stored to session storage.
export const ae_api_data_struct: key_val = { export const ae_api_data_struct: key_val = {
ver: '2024-08-11_11', ver: '2024-08-11_11',
fqdn: api_server_fqdn, fqdn: api_server_fqdn,
base_url: api_base_url, base_url: api_base_url,
base_url_bak: api_base_url_bak, base_url_bak: api_base_url_bak,
api_secret_key: api_secret_key, // 'YOUR_API_SECRET_KEY', api_secret_key: api_secret_key,
api_secret_key_bak: api_secret_key, // 'YOUR_API_SECRET_KEY', api_secret_key_bak: api_secret_key,
api_crud_super_key: api_crud_super_key, // 'YOUR_SUPER_KEY' 'zp5PtX4zUsI' api_crud_super_key: api_crud_super_key, // Used for operations that bypass normal account-scoped CRUD limits.
headers: {}, headers: {},
account_id: ae_account_id account_id: ae_account_id
}; };
@@ -465,18 +374,15 @@ ae_api_headers['Content-Type'] = 'application/json';
ae_api_headers['x-aether-api-key'] = ae_api_data_struct.api_secret_key; ae_api_headers['x-aether-api-key'] = ae_api_data_struct.api_secret_key;
if (ae_account_id) { if (ae_account_id) {
ae_api_headers['x-account-id'] = ae_account_id; ae_api_headers['x-account-id'] = ae_account_id;
} else {
// ae_api_headers['x-account-id'] = ;
} }
if (ae_no_account_id) { if (ae_no_account_id) {
ae_api_headers['x-no-account-id'] = ae_no_account_id; ae_api_headers['x-no-account-id'] = ae_no_account_id;
} }
ae_api_data_struct['headers'] = ae_api_headers; ae_api_data_struct['headers'] = ae_api_headers;
// console.log(`AE Stores - API Data:`, ae_api_data_struct);
export const ae_api = writable(ae_api_data_struct); export const ae_api = writable(ae_api_data_struct);
// *** BEGIN *** Trigger to update the slct variables and other things. // General-purpose reactive trigger. Set any truthy value to signal consumers to re-query.
const ae_trig_template: key_val = {}; const ae_trig_template: key_val = {};
export const ae_trig = writable(ae_trig_template); export const ae_trig = writable(ae_trig_template);
@@ -491,9 +397,6 @@ const slct_obj_template: key_val = {
event_id: null, event_id: null,
event_obj: {}, event_obj: {},
event_obj_li: [], event_obj_li: [],
// 'event_exhibit_id': null,
// 'event_exhibit_obj': {},
// 'event_exhibit_obj_li': [],
event_presentation_id: null, event_presentation_id: null,
event_presentation_obj: {}, event_presentation_obj: {},
event_presentation_obj_li: [], event_presentation_obj_li: [],
@@ -516,26 +419,18 @@ const slct_obj_template: key_val = {
post_comment_obj: {}, post_comment_obj: {},
post_comment_obj_li: [] post_comment_obj_li: []
}; };
// console.log(`AE Stores - Selected Objects:`, slct_obj_template); // In-memory only (not persisted) — separate browser tabs can have different selections.
// This works, and uses *session* (not local) storage:
export const slct = writable(slct_obj_template); export const slct = writable(slct_obj_template);
// This works and uses *local* storage: // Increment (or set any truthy value) to tell subscribers that the selection changed
// export let slct: Writable<key_val> = persisted('ae_slct', slct_obj_template); // and they should re-query their data.
/* *** BEGIN *** Initialize slct_trigger */
// Intended for temporary session storage.
// Updated 2024-02-27
export const slct_trigger: any = writable(null); export const slct_trigger: any = writable(null);
// console.log(`AE Stores - Selected Trigger:`, slct_trigger);
// Auth error signal — set by API helpers on 401/403 to trigger the session-expired banner in the root layout. // Auth error signal — set by API helpers on 401/403 to trigger the session-expired banner in the root layout.
// Only set from browser context (never SSR). 'expired' covers both 401 and 403 responses. // Only set from browser context (never SSR). 'expired' covers both 401 and 403 responses.
export const ae_auth_error = writable<{ type: 'expired' | null; ts: number | null }>({ type: null, ts: null }); export const ae_auth_error = writable<{ type: 'expired' | null; ts: number | null }>({ type: null, ts: null });
/* *** BEGIN *** Create time variable */ // Reactive clock — updates every second. Used for live countdown and elapsed-time displays.
// Updated 2020
export const time = readable(new Date(), function start(set) { export const time = readable(new Date(), function start(set) {
const interval = setInterval(() => { const interval = setInterval(() => {
set(new Date()); set(new Date());