pres_mgmt: migrate to typed PersistedState store, canonical config schema

Replaces untyped $events_loc.pres_mgmt (svelte-persisted-store) with a
dedicated pres_mgmt_loc (runed PersistedState) backed by a fully typed
PresMgmtLocState interface and PressMgmtRemoteCfg for the server-side JSON.

Key changes:
- ae_events_stores__pres_mgmt_defaults.ts: canonical interfaces + defaults
  covering all hide__/show__ fields, labels, report prefs, query filters,
  and lock_config sync fields; qry_enabled uses 'not_enabled' (matches API)
- ae_events_stores__pres_mgmt.svelte.ts: new PersistedState store
- ae_events__event.ts: sync_config__event_pres_mgmt() rewired to write
  directly to pres_mgmt_loc.current; launcher link inversion preserved
- All 26+ pres_mgmt templates migrated from $events_loc.pres_mgmt.* to
  pres_mgmt_loc.current.*
- New config UI at (pres_mgmt)/pres_mgmt/config/ — manager + edit mode only
- Event settings page: removed embedded pres_mgmt form, links to config page
- event_page_menu: Config button visible only when manager_access + edit_mode

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-04-02 15:27:12 -04:00
parent 21f0fe69af
commit fd9e5f6dc0
31 changed files with 1426 additions and 661 deletions

View File

@@ -1,5 +1,7 @@
import type { key_val } from '$lib/stores/ae_stores';
import { api } from '$lib/api/api';
import { pres_mgmt_loc } from '$lib/stores/ae_events_stores__pres_mgmt.svelte';
import type { PressMgmtRemoteCfg } from '$lib/stores/ae_events_stores__pres_mgmt_defaults';
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
import { db_events } from '$lib/ae_events/db_events';
@@ -944,83 +946,117 @@ export async function process_ae_obj__event_props({
});
}
/**
* sync_config__event_pres_mgmt
*
* Syncs the server-side event pres_mgmt config (mod_pres_mgmt_json) into the
* local PersistedState store (pres_mgmt_loc.current).
*
* Called reactively in pres_mgmt/+page.svelte whenever the event object changes.
*
* Always-synced fields: labels, requirements, access links, file config.
* Lock-synced fields (only when lock_config=true): all visibility/hide__ toggles,
* launcher links, navigation limits. This prevents presenter laptops from
* drifting into different display configs across a conference.
*
* Canonical key convention (enforced here):
* hide__* → feature ON by default; true = turn off (default: false = visible)
* show__* → feature OFF by default; true = turn on (default: false = hidden)
*/
export function sync_config__event_pres_mgmt({
pres_mgmt_cfg_remote,
pres_mgmt_cfg_local,
log_lvl = 0
}: {
pres_mgmt_cfg_remote: key_val;
pres_mgmt_cfg_local: key_val;
pres_mgmt_cfg_remote: Partial<PressMgmtRemoteCfg>;
log_lvl?: number;
}) {
if (log_lvl) {
console.log(
`*** sync_config__event_pres_mgmt() *** pres_mgmt_cfg_remote:`,
`*** sync_config__event_pres_mgmt() *** remote:`,
pres_mgmt_cfg_remote
);
}
pres_mgmt_cfg_local.label__person_external_id =
const loc = pres_mgmt_loc.current;
// --- Always sync: labels, requirements, opt-in features, file config ---
// These are safe to always apply — they don't override local display preferences.
loc.label__person_external_id =
pres_mgmt_cfg_remote?.label__person_external_id ?? 'External ID';
pres_mgmt_cfg_local.label__presenter_external_id =
loc.label__presenter_external_id =
pres_mgmt_cfg_remote?.label__presenter_external_id ?? 'External ID';
pres_mgmt_cfg_local.label__session_poc_type =
loc.label__session_poc_type =
pres_mgmt_cfg_remote?.label__session_poc_type ?? 'poc';
pres_mgmt_cfg_local.label__session_poc_name =
pres_mgmt_cfg_remote?.label__session_poc_name_short ?? 'POC';
pres_mgmt_cfg_local.label__session_poc_name =
loc.label__session_poc_name =
pres_mgmt_cfg_remote?.label__session_poc_name ?? 'Point of Contact';
pres_mgmt_cfg_local.hide__session_poc =
pres_mgmt_cfg_remote?.hide__session_poc ?? false;
pres_mgmt_cfg_local.require__presenter_agree =
loc.require__presenter_agree =
pres_mgmt_cfg_remote?.require__presenter_agree ?? false;
pres_mgmt_cfg_local.require__session_agree =
loc.require__session_agree =
pres_mgmt_cfg_remote?.require__session_agree ?? false;
pres_mgmt_cfg_local.show__copy_access_link =
loc.show__copy_access_link =
pres_mgmt_cfg_remote?.show__copy_access_link ?? false;
pres_mgmt_cfg_local.show__email_access_link =
loc.show__email_access_link =
pres_mgmt_cfg_remote?.show__email_access_link ?? false;
pres_mgmt_cfg_local.file_purpose_option_kv =
loc.file_purpose_option_kv =
pres_mgmt_cfg_remote?.file_purpose_option_kv ?? null;
if (pres_mgmt_cfg_local.lock_config) {
console.log(`The config should be locked! Forcing the sync!`);
pres_mgmt_cfg_local.sync_local_config = true;
}
loc.hide__report_kv = pres_mgmt_cfg_remote?.hide__report_kv ?? {};
if (pres_mgmt_cfg_local?.sync_local_config) {
pres_mgmt_cfg_local.hide__location_code =
// --- Lock-synced: visibility, launcher, navigation, session/presenter fields ---
// When lock_config=true the remote config wins for ALL display flags, preventing
// local browser state from overriding the admin's event-level configuration.
if (pres_mgmt_cfg_remote?.lock_config) {
if (log_lvl) console.log(`sync_config__event_pres_mgmt: lock_config=true, forcing full sync`);
// Codes
loc.hide__location_code =
pres_mgmt_cfg_remote?.hide__location_code ?? false;
pres_mgmt_cfg_local.hide__presentation_code =
loc.hide__presentation_code =
pres_mgmt_cfg_remote?.hide__presentation_code ?? false;
pres_mgmt_cfg_local.hide__presentation_datetime =
pres_mgmt_cfg_remote?.hide__presentation_datetime ?? false;
pres_mgmt_cfg_local.show_content__presentation_description =
pres_mgmt_cfg_remote?.show_content__presentation_description ??
false;
pres_mgmt_cfg_local.hide__presenter_code =
loc.hide__presenter_code =
pres_mgmt_cfg_remote?.hide__presenter_code ?? false;
pres_mgmt_cfg_local.hide__presenter_biography =
pres_mgmt_cfg_remote?.hide__presenter_biography ?? false;
pres_mgmt_cfg_local.hide__session_code =
loc.hide__session_code =
pres_mgmt_cfg_remote?.hide__session_code ?? false;
pres_mgmt_cfg_local.hide__session_description =
pres_mgmt_cfg_remote?.hide__session_description ?? false;
pres_mgmt_cfg_local.hide__session_location =
pres_mgmt_cfg_remote?.hide__session_location ?? false;
pres_mgmt_cfg_local.hide__session_msg =
pres_mgmt_cfg_remote?.hide__session_msg ?? false;
pres_mgmt_cfg_local.hide__session_poc_profile =
pres_mgmt_cfg_remote?.hide__session_poc_profile ?? false;
pres_mgmt_cfg_local.hide__session_poc_biography =
pres_mgmt_cfg_remote?.hide__session_poc_biography ?? false;
pres_mgmt_cfg_local.hide__session_poc_profile_pic =
pres_mgmt_cfg_remote?.hide__session_poc_profile_pic ?? false;
pres_mgmt_cfg_local.hide_launcher_link =
pres_mgmt_cfg_remote?.hide_launcher_link ?? false;
pres_mgmt_cfg_local.hide_launcher_link_legacy =
pres_mgmt_cfg_remote?.hide_launcher_link_legacy ?? false;
}
return pres_mgmt_cfg_local;
// Session fields
loc.hide__session_description =
pres_mgmt_cfg_remote?.hide__session_description ?? false;
loc.hide__session_location =
pres_mgmt_cfg_remote?.hide__session_location ?? false;
loc.hide__session_msg =
pres_mgmt_cfg_remote?.hide__session_msg ?? false;
loc.hide__session_poc =
pres_mgmt_cfg_remote?.hide__session_poc ?? false;
loc.hide__session_poc_biography =
pres_mgmt_cfg_remote?.hide__session_poc_biography ?? false;
loc.hide__session_poc_profile =
pres_mgmt_cfg_remote?.hide__session_poc_profile ?? false;
loc.hide__session_poc_profile_pic =
pres_mgmt_cfg_remote?.hide__session_poc_profile_pic ?? false;
// Presenter fields
loc.hide__presenter_biography =
pres_mgmt_cfg_remote?.hide__presenter_biography ?? false;
// Presentation fields
loc.hide__presentation_datetime =
pres_mgmt_cfg_remote?.hide__presentation_datetime ?? false;
loc.hide__presentation_description =
pres_mgmt_cfg_remote?.hide__presentation_description ?? false;
// Launcher links (show__ in remote → invert to hide__ in local display state)
loc.hide__launcher_link =
!(pres_mgmt_cfg_remote?.show__launcher_link ?? false);
loc.hide__launcher_link_legacy =
!(pres_mgmt_cfg_remote?.show__launcher_link_legacy ?? false);
// Navigation / UI constraints
loc.limit__navigation =
pres_mgmt_cfg_remote?.limit__navigation ?? false;
loc.limit__options =
pres_mgmt_cfg_remote?.limit__options ?? false;
}
}