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

@@ -21,6 +21,7 @@ import {
events_trigger,
events_trig_kv
} from '$lib/stores/ae_events_stores';
import { pres_mgmt_loc } from '$lib/stores/ae_events_stores__pres_mgmt.svelte';
import {
Ban,
Barcode,
@@ -53,17 +54,17 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.expand__menu_opts =
!$events_loc.pres_mgmt.expand__menu_opts;
pres_mgmt_loc.current.expand__menu_opts =
!pres_mgmt_loc.current.expand__menu_opts;
}}
class="btn btn-sm preset-tonal-info border-info-500 border">
{#if !$events_loc.pres_mgmt.expand__menu_opts}
{#if !pres_mgmt_loc.current.expand__menu_opts}
<ChevronUp size="1em" class="m-1" />
{:else}
<ChevronDown size="1em" class="m-1" />
{/if}
Æ Pres Mgmt Menu Options
{#if !$events_loc.pres_mgmt.expand__menu_opts}
{#if !pres_mgmt_loc.current.expand__menu_opts}
<ChevronUp size="1em" class="m-1" />
{:else}
<ChevronDown size="1em" class="m-1" />
@@ -73,7 +74,7 @@ import {
<div
class="flex flex-row flex-wrap items-center justify-between gap-1"
class:hidden={!$events_loc.pres_mgmt.expand__menu_opts}>
class:hidden={!pres_mgmt_loc.current.expand__menu_opts}>
{#if $ae_loc.authenticated_access}
<div class="flex flex-col items-end justify-center gap-1">
<span class="flex flex-col items-end justify-center gap-1">
@@ -85,7 +86,7 @@ import {
for="qry_limit__people">
Max people:
</label>
<!-- Not using: $events_loc.pres_mgmt.qry_limit__people -->
<!-- Not using: pres_mgmt_loc.current.qry_limit__people -->
<select
id="qry_limit__people"
bind:value={$ae_loc.person.qry_limit__people}
@@ -115,7 +116,7 @@ import {
<select
id="qry_limit__presenters"
bind:value={
$events_loc.pres_mgmt.qry_limit__presenters
pres_mgmt_loc.current.qry_limit__presenters
}
class="select preset-tonal-surface w-20 px-1 text-sm">
<option value="">-- not set --</option>
@@ -144,7 +145,7 @@ import {
<select
id="qry_limit__sessions"
bind:value={
$events_loc.pres_mgmt.qry_limit__sessions
pres_mgmt_loc.current.qry_limit__sessions
}
class="select preset-tonal-surface w-20 px-1 text-sm">
<option value="">-- not set --</option>
@@ -167,7 +168,7 @@ import {
</label>
<select
id="qry_limit__files"
bind:value={$events_loc.pres_mgmt.qry_limit__files}
bind:value={pres_mgmt_loc.current.qry_limit__files}
class="select preset-tonal-surface w-20 px-1 text-sm">
<option value="">-- not set --</option>
<option value={25}>25</option>
@@ -186,20 +187,20 @@ import {
<button
type="button"
onclick={() => {
if ($events_loc.pres_mgmt.qry_hidden == 'all') {
$events_loc.pres_mgmt.qry_hidden = 'not_hidden';
if (pres_mgmt_loc.current.qry_hidden == 'all') {
pres_mgmt_loc.current.qry_hidden = 'not_hidden';
} else {
$events_loc.pres_mgmt.qry_hidden = 'all';
pres_mgmt_loc.current.qry_hidden = 'all';
}
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle between showing hidden sessions">
{#if $events_loc.pres_mgmt.qry_hidden == 'all'}<ToggleRight
{#if pres_mgmt_loc.current.qry_hidden == 'all'}<ToggleRight
size="1em"
class="m-1" />{:else}<ToggleLeft
size="1em"
class="m-1" />{/if}
{#if $events_loc.pres_mgmt.qry_hidden == 'all'}
{#if pres_mgmt_loc.current.qry_hidden == 'all'}
<span class="grow">
<EyeOff size="1em" class="m-1" />
Hide Hidden Sessions
@@ -219,22 +220,22 @@ import {
type="button"
onclick={() => {
if (
$events_loc.pres_mgmt.qry_enabled == 'all'
pres_mgmt_loc.current.qry_enabled == 'all'
) {
$events_loc.pres_mgmt.qry_enabled =
pres_mgmt_loc.current.qry_enabled =
'enabled';
} else {
$events_loc.pres_mgmt.qry_enabled = 'all';
pres_mgmt_loc.current.qry_enabled = 'all';
}
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle between showing disabled sessions">
{#if $events_loc.pres_mgmt.qry_enabled == 'all'}<ToggleRight
{#if pres_mgmt_loc.current.qry_enabled == 'all'}<ToggleRight
size="1em"
class="m-1" />{:else}<ToggleLeft
size="1em"
class="m-1" />{/if}
{#if $events_loc.pres_mgmt.qry_enabled == 'all'}
{#if pres_mgmt_loc.current.qry_enabled == 'all'}
<span class="grow">
<Ban size="1em" class="m-1" />
Hide Disabled Sessions
@@ -255,15 +256,14 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.save_search_text =
!$events_loc.pres_mgmt.save_search_text;
pres_mgmt_loc.current.save_search_text =
!pres_mgmt_loc.current.save_search_text;
}}
class="btn btn-sm w-full justify-between text-center"
class:ae_btn_surface={$events_loc.pres_mgmt.save_search_text}
class:ae_btn_surface_outlined={!$events_loc.pres_mgmt
.save_search_text}
class:ae_btn_surface={pres_mgmt_loc.current.save_search_text}
class:ae_btn_surface_outlined={!pres_mgmt_loc.current.save_search_text}
title="Save the search text for this session search?">
{#if $events_loc.pres_mgmt.save_search_text}
{#if pres_mgmt_loc.current.save_search_text}
<ToggleRight size="1em" class="m-1" />
<span class="grow">
<Save size="1em" class="m-1" />
@@ -279,11 +279,11 @@ import {
</button>
{#if $ae_loc.authenticated_access}
{#if !$events_loc.pres_mgmt.hide__session_msg}
{#if !pres_mgmt_loc.current.hide__session_msg}
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__session_msg = true;
pres_mgmt_loc.current.hide__session_msg = true;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center">
<ToggleRight size="1em" class="m-1" />
@@ -296,7 +296,7 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__session_msg = false;
pres_mgmt_loc.current.hide__session_msg = false;
}}
class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
<ToggleLeft size="1em" class="m-1" />
@@ -310,11 +310,11 @@ import {
{#if $ae_loc.authenticated_access}
<!-- Show or hide the session code -->
{#if !$events_loc.pres_mgmt.hide__session_code}
{#if !pres_mgmt_loc.current.hide__session_code}
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__session_code = true;
pres_mgmt_loc.current.hide__session_code = true;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center">
<ToggleRight size="1em" class="m-1" />
@@ -327,7 +327,7 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__session_code = false;
pres_mgmt_loc.current.hide__session_code = false;
}}
class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
<ToggleLeft size="1em" class="m-1" />
@@ -343,11 +343,11 @@ import {
<div class="flex flex-col items-center justify-center gap-1">
{#if $ae_loc.trusted_access}
<div class="flex flex-col items-center justify-center gap-1">
{#if $events_loc.pres_mgmt.show__copy_access_link}
{#if pres_mgmt_loc.current.show__copy_access_link}
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show__copy_access_link = false;
pres_mgmt_loc.current.show__copy_access_link = false;
}}
class="btn btn-sm ae_btn_surface w-full">
<ToggleRight size="1em" class="m-1" />
@@ -357,7 +357,7 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show__copy_access_link = true;
pres_mgmt_loc.current.show__copy_access_link = true;
}}
class="btn btn-sm ae_btn_surface_outlined w-full">
<ToggleLeft size="1em" class="m-1" />
@@ -365,11 +365,11 @@ import {
</button>
{/if}
{#if $events_loc.pres_mgmt.show__email_access_link}
{#if pres_mgmt_loc.current.show__email_access_link}
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show__email_access_link = false;
pres_mgmt_loc.current.show__email_access_link = false;
}}
class="btn btn-sm ae_btn_surface w-full">
<ToggleRight size="1em" class="m-1" />
@@ -379,7 +379,7 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show__email_access_link = true;
pres_mgmt_loc.current.show__email_access_link = true;
}}
class="btn btn-sm ae_btn_surface_outlined w-full">
<ToggleLeft size="1em" class="m-1" />
@@ -391,11 +391,11 @@ import {
{#if $ae_loc.authenticated_access}
<div class="flex flex-col items-end justify-center gap-1">
{#if $events_loc.pres_mgmt.show_content__session_qr}
{#if pres_mgmt_loc.current.show_content__session_qr}
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show_content__session_qr = false;
pres_mgmt_loc.current.show_content__session_qr = false;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Showing Session QR Code">
@@ -409,7 +409,7 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show_content__session_qr = true;
pres_mgmt_loc.current.show_content__session_qr = true;
}}
class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center"
title="Show Session QR Code">
@@ -421,11 +421,11 @@ import {
</button>
{/if}
{#if $events_loc.pres_mgmt.show_content__presenter_qr}
{#if pres_mgmt_loc.current.show_content__presenter_qr}
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show_content__presenter_qr = false;
pres_mgmt_loc.current.show_content__presenter_qr = false;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Showing Presenter QR Code">
@@ -439,7 +439,7 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show_content__presenter_qr = true;
pres_mgmt_loc.current.show_content__presenter_qr = true;
}}
class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center"
title="Show Presenter QR Code">
@@ -460,18 +460,18 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__launcher_link =
!$events_loc.pres_mgmt.hide__launcher_link;
pres_mgmt_loc.current.hide__launcher_link =
!pres_mgmt_loc.current.hide__launcher_link;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center">
{#if $events_loc.pres_mgmt.hide__launcher_link}<ToggleLeft
{#if pres_mgmt_loc.current.hide__launcher_link}<ToggleLeft
size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow">
<Plane size="1em" class="m-1" />
{$events_loc.pres_mgmt.hide__launcher_link
{pres_mgmt_loc.current.hide__launcher_link
? 'Show Launcher Links'
: 'Hide Launcher Links?'}
</span>
@@ -481,18 +481,18 @@ import {
<!-- <button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__launcher_link_legacy =
!$events_loc.pres_mgmt.hide__launcher_link_legacy;
pres_mgmt_loc.current.hide__launcher_link_legacy =
!pres_mgmt_loc.current.hide__launcher_link_legacy;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center">
{#if $events_loc.pres_mgmt.hide__launcher_link_legacy}<ToggleLeft
{#if pres_mgmt_loc.current.hide__launcher_link_legacy}<ToggleLeft
size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow">
<Send size="1em" class="m-1" />
{$events_loc.pres_mgmt.hide__launcher_link_legacy
{pres_mgmt_loc.current.hide__launcher_link_legacy
? 'Show Legacy Launcher Links'
: 'Hide Legacy Launcher Links?'}
</span>
@@ -502,18 +502,18 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__location_link =
!$events_loc.pres_mgmt.hide__location_link;
pres_mgmt_loc.current.hide__location_link =
!pres_mgmt_loc.current.hide__location_link;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center">
{#if $events_loc.pres_mgmt.hide__location_link}<ToggleLeft
{#if pres_mgmt_loc.current.hide__location_link}<ToggleLeft
size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow">
<MapPin size="1em" class="m-1" />
{$events_loc.pres_mgmt.hide__location_link
{pres_mgmt_loc.current.hide__location_link
? 'Show Location Links'
: 'Hide Location Links?'}
</span>
@@ -523,20 +523,19 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.hide__session_li_location_field =
!$events_loc.pres_mgmt
.hide__session_li_location_field;
pres_mgmt_loc.current.hide__session_li_location_field =
!pres_mgmt_loc.current.hide__session_li_location_field;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle showing the Location column in session lists and tables">
{#if $events_loc.pres_mgmt.hide__session_li_location_field}<ToggleLeft
{#if pres_mgmt_loc.current.hide__session_li_location_field}<ToggleLeft
size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow">
<!-- <span class="fas fa-door-open m-1"></span> -->
{$events_loc.pres_mgmt.hide__session_li_location_field
{pres_mgmt_loc.current.hide__session_li_location_field
? 'Show Location Column'
: 'Hide Location Column?'}
</span>
@@ -546,19 +545,19 @@ import {
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show__session_li_poc_field =
!$events_loc.pres_mgmt.show__session_li_poc_field;
pres_mgmt_loc.current.show__session_li_poc_field =
!pres_mgmt_loc.current.show__session_li_poc_field;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle showing the POC column in session lists and tables">
{#if !$events_loc.pres_mgmt.show__session_li_poc_field}<ToggleLeft
{#if !pres_mgmt_loc.current.show__session_li_poc_field}<ToggleLeft
size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow">
<!-- <span class="fas fa-user-tie m-1"></span> -->
{!$events_loc.pres_mgmt.show__session_li_poc_field
{!pres_mgmt_loc.current.show__session_li_poc_field
? 'Show POC Column'
: 'Hide POC Column?'}
</span>
@@ -567,12 +566,12 @@ import {
<!-- These are related to more content showing in lists. -->
<span
class="flex flex-col flex-wrap items-center justify-evenly gap-1">
{#if $events_loc.pres_mgmt.show_content__session_files}
{#if pres_mgmt_loc.current.show_content__session_files}
<button
type="button"
disabled={!$ae_loc.manager_access}
onclick={() => {
$events_loc.pres_mgmt.show_content__session_files = false;
pres_mgmt_loc.current.show_content__session_files = false;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center">
<ToggleRight size="1em" class="m-1" />
@@ -586,7 +585,7 @@ import {
type="button"
disabled={!$ae_loc.manager_access}
onclick={() => {
$events_loc.pres_mgmt.show_content__session_files = true;
pres_mgmt_loc.current.show_content__session_files = true;
}}
class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
<ToggleLeft size="1em" class="m-1" />
@@ -597,12 +596,12 @@ import {
</button>
{/if}
{#if $events_loc.pres_mgmt.show_content__session_presentations}
{#if pres_mgmt_loc.current.show_content__session_presentations}
<button
type="button"
disabled={!$ae_loc.manager_access}
onclick={() => {
$events_loc.pres_mgmt.show_content__session_presentations = false;
pres_mgmt_loc.current.show_content__session_presentations = false;
}}
class="btn btn-sm ae_btn_surface w-full justify-between text-center">
<ToggleRight size="1em" class="m-1" />
@@ -616,7 +615,7 @@ import {
type="button"
disabled={!$ae_loc.manager_access}
onclick={() => {
$events_loc.pres_mgmt.show_content__session_presentations = true;
pres_mgmt_loc.current.show_content__session_presentations = true;
}}
class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
<ToggleLeft size="1em" class="m-1" />