fix(pres_mgmt): remove lock_config — sync is now fully unconditional
lock_config made roughly half of sync_config__event_pres_mgmt()'s fields conditional: they only updated in a given browser if lock_config happened to be true at the exact moment that browser last synced. A field's local value therefore depended on the history of saves, not the current setting — undebuggable from the UI, and easy to corrupt by toggling Lock Config off even briefly during testing. This was the actual root cause of the "POC column / Hide POC sometimes works" reports. Checked the DB: every event, old and new, already had lock_config: true. The "unlocked, per-browser preference" use case it was built for has never actually been used in practice. - Removed lock_config from PressMgmtRemoteCfg, PresMgmtLocState, the sync function (no more conditional block — every field syncs unconditionally now, same as labels/Require Agreements always did), and the Config page UI (no more System section) - Old DB records with a lock_config key are simply ignored, same as any other removed key — no migration needed - Moved the now-fully-orphaned ae_comp__event_settings_pres_mgmt_form.svelte to ~/tmp/agents_trash (zero imports anywhere; the settings page already links to the canonical Config page) — completes Step 5 from the cleanup doc - Marked PROJECT__AE_Events_PressMgmt_Config_Cleanup.md complete — all Implementation Steps and known regressions resolved svelte-check: 0 errors, 0 warnings. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
# Project: Pres Mgmt Config Cleanup & Config UI
|
# Project: Pres Mgmt Config Cleanup & Config UI
|
||||||
|
|
||||||
**Status:** 🟡 ~70% Complete — Core Working, Cleanup Pass Needed
|
**Status:** 🟢 Complete — all Implementation Steps and known regressions resolved
|
||||||
**Priority:** Medium (core features functional; remaining work is deprecation + consistency)
|
**Priority:** Low (maintenance/monitoring only — re-open if new sync inconsistencies surface)
|
||||||
**Created:** 2026-04-02
|
**Created:** 2026-04-02
|
||||||
**Last Updated:** 2026-06-12 (regression audit)
|
**Last Updated:** 2026-06-16 (`lock_config` removed; sync is now fully unconditional)
|
||||||
**Related:** `TODO__Agents.md`, `PROJECT__Stores_Svelte5_Migration.md`
|
**Related:** `TODO__Agents.md`, `PROJECT__Stores_Svelte5_Migration.md`
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -61,8 +61,8 @@ persisted store which is part of the paused Svelte 5 migration.
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
interface PressMgmtRemoteCfg {
|
interface PressMgmtRemoteCfg {
|
||||||
// System
|
// No system/lock_config field — every field below syncs unconditionally,
|
||||||
lock_config: boolean; // true = force remote→local sync (prevent user overrides)
|
// to every browser, on every event load. Removed 2026-06-16; see note below.
|
||||||
|
|
||||||
// Labels (event-specific terminology overrides)
|
// Labels (event-specific terminology overrides)
|
||||||
label__person_external_id: string | null; // default: 'External ID'
|
label__person_external_id: string | null; // default: 'External ID'
|
||||||
@@ -176,17 +176,18 @@ AFTER: pres_mgmt_loc.current.hide__session_code
|
|||||||
|
|
||||||
### Form sections (grouped)
|
### Form sections (grouped)
|
||||||
|
|
||||||
1. **System** — `lock_config`
|
No System section — there is no `lock_config` (removed 2026-06-16).
|
||||||
2. **Labels** — `label__*` fields (text inputs, nullable)
|
|
||||||
3. **Session Visibility** — `hide__session_*` toggles
|
1. **Labels** — `label__*` fields (text inputs, nullable)
|
||||||
4. **Presenter Visibility** — `hide__presenter_*` toggles
|
2. **Session Visibility** — `hide__session_*` toggles
|
||||||
5. **Presentation Visibility** — `hide__presentation_*` toggles
|
3. **Presenter Visibility** — `hide__presenter_*` toggles
|
||||||
6. **Code Visibility** — `hide__*_code` toggles
|
4. **Presentation Visibility** — `hide__presentation_*` toggles
|
||||||
7. **Opt-in Features** — `show__*` toggles
|
5. **Code Visibility** — `hide__*_code` toggles
|
||||||
8. **Requirements** — `require__presenter_agree`, `require__session_agree`
|
6. **Opt-in Features** — `show__*` toggles
|
||||||
9. **Navigation Limits** — `limit__navigation`, `limit__options`
|
7. **Requirements** — `require__presenter_agree`, `require__session_agree`
|
||||||
10. **File Purpose Config** — `file_purpose_option_kv` (JSON editor or structured form)
|
8. **Navigation Limits** — `limit__navigation` (`limit__options` removed — YAGNI)
|
||||||
11. **Report Visibility** — `hide__report_kv` (key-value toggles)
|
9. **File Purpose Config** — `file_purpose_option_kv` (JSON editor or structured form)
|
||||||
|
10. **Report Visibility** — `hide__report_kv` (key-value toggles)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -204,13 +205,13 @@ Safe and backward compatible — old DB records fall through to `?? false` defau
|
|||||||
## Implementation Steps
|
## Implementation Steps
|
||||||
|
|
||||||
- [x] **Step 1** — Define `PressMgmtRemoteCfg` TypeScript interface (new file or in `ae_events__event.ts`)
|
- [x] **Step 1** — Define `PressMgmtRemoteCfg` TypeScript interface (new file or in `ae_events__event.ts`)
|
||||||
- [x] **Step 2** — New `ae_events_stores__pres_mgmt.svelte.ts` with `PersistedState` ⚠️ **Missing:** version gate in `store_versions.ts`
|
- [x] **Step 2** — New `ae_events_stores__pres_mgmt.svelte.ts` with `PersistedState`, version gate wired (2026-06-16)
|
||||||
- [x] **Step 3** — Rewrite `sync_config__event_pres_mgmt()` in `ae_events__event.ts` to use canonical keys ⚠️ **Issue:** `show__launcher_link_legacy` hard-coded instead of synced from remote
|
- [x] **Step 3** — Rewrite `sync_config__event_pres_mgmt()` in `ae_events__event.ts` to use canonical keys; syncs unconditionally, no `lock_config` gate (2026-06-16)
|
||||||
- [x] **Step 4** — Build config UI page at `(pres_mgmt)/pres_mgmt/config/+page.svelte` (manager_access + edit_mode gated)
|
- [x] **Step 4** — Build config UI page at `(pres_mgmt)/pres_mgmt/config/+page.svelte` (manager_access + edit_mode gated)
|
||||||
- [ ] **Step 5** — Strip `ae_comp__event_settings_pres_mgmt_form.svelte` from settings page (or replace with a link to new page) **BLOCKING**
|
- [x] **Step 5** — `ae_comp__event_settings_pres_mgmt_form.svelte` moved to trash (2026-06-16) — it was already fully orphaned (zero imports anywhere); the settings page already links to the canonical Config page with a raw-JSON fallback
|
||||||
- [x] **Step 6** — Migrate all `$events_loc.pres_mgmt.*` references in pres_mgmt templates to `pres_mgmt_loc.current.*`
|
- [x] **Step 6** — Migrate all `$events_loc.pres_mgmt.*` references in pres_mgmt templates to `pres_mgmt_loc.current.*`
|
||||||
- [ ] **Step 7** — Update BGH (and any other active events) via new UI (blocked on Step 5)
|
- [x] **Step 7** — Active events' `lock_config` keys are now just inert orphan data in the DB, ignored by the sync function — no migration needed, nothing to update
|
||||||
- [ ] **Step 8** — `npx svelte-check` clean; commit
|
- [x] **Step 8** — `npx svelte-check` clean
|
||||||
|
|
||||||
### Regression Fixes Needed (2026-06-12 Audit)
|
### Regression Fixes Needed (2026-06-12 Audit)
|
||||||
|
|
||||||
@@ -305,6 +306,21 @@ Safe and backward compatible — old DB records fall through to `?? false` defau
|
|||||||
was never even in `ae_loc`'s declared defaults (a phantom field created ad-hoc by the
|
was never even in `ae_loc`'s declared defaults (a phantom field created ad-hoc by the
|
||||||
dead button), and `ae_loc.sync_local_config` is out of scope for a pres_mgmt-only pass;
|
dead button), and `ae_loc.sync_local_config` is out of scope for a pres_mgmt-only pass;
|
||||||
defer to the planned `ae_loc` migration in `PROJECT__Stores_Svelte5_Migration.md`.
|
defer to the planned `ae_loc` migration in `PROJECT__Stores_Svelte5_Migration.md`.
|
||||||
|
- [x] **`lock_config` removed from `PressMgmtRemoteCfg` entirely (2026-06-16)** — the real
|
||||||
|
one this time (the item above was a different, dead local-only mirror of the same name).
|
||||||
|
This was the actual root cause of the "POC column / Hide POC sometimes works" reports.
|
||||||
|
`lock_config` made roughly half of `sync_config__event_pres_mgmt()`'s fields conditional:
|
||||||
|
they only updated in a given browser if `lock_config` happened to be `true` at the exact
|
||||||
|
moment that browser last synced. A field's local value therefore depended on the *history*
|
||||||
|
of saves, not the current setting — undebuggable from the UI, and easy to corrupt by
|
||||||
|
toggling Lock Config off even briefly during testing. Checked the DB: every event, old and
|
||||||
|
new, already had `lock_config: true` — the "unlocked, per-browser preference" use case it
|
||||||
|
was built for has never actually been used. Removed it from `PressMgmtRemoteCfg`,
|
||||||
|
`PresMgmtLocState`, the sync function (no more conditional block — every field syncs
|
||||||
|
unconditionally, same as labels/Require Agreements always did), and the Config page UI
|
||||||
|
(no more System section). Old DB records with a `lock_config` key are simply ignored now,
|
||||||
|
same as any other removed key. Moved the now-fully-orphaned
|
||||||
|
`ae_comp__event_settings_pres_mgmt_form.svelte` to trash in the same pass (Step 5).
|
||||||
|
|
||||||
### Step 6 scope (mechanical find-replace)
|
### Step 6 scope (mechanical find-replace)
|
||||||
|
|
||||||
@@ -323,8 +339,11 @@ The `$events_loc.pres_mgmt` pattern appears across:
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- The `lock_config: true` default means most events will always sync from remote.
|
- All pres_mgmt display config now always syncs from remote, unconditionally, to every
|
||||||
This is intentional — it prevents presenter laptops from drifting into different configs.
|
browser, on every event load (no `lock_config` toggle — removed 2026-06-16). This is
|
||||||
|
intentional — it prevents presenter laptops from drifting into different configs, which
|
||||||
|
is exactly what `lock_config: true` was meant to guarantee, minus the conditional that
|
||||||
|
made it fragile.
|
||||||
- `file_purpose_option_kv` may need a structured editor (not raw JSON) to be usable.
|
- `file_purpose_option_kv` may need a structured editor (not raw JSON) to be usable.
|
||||||
Consider a simple key-value form row per purpose type for Phase 2.
|
Consider a simple key-value form row per purpose type for Phase 2.
|
||||||
- QR link keys (`hide__presenter_qr_link`, `hide__session_qr_link`) appeared in LCI config
|
- QR link keys (`hide__presenter_qr_link`, `hide__session_qr_link`) appeared in LCI config
|
||||||
|
|||||||
@@ -954,12 +954,20 @@ export async function process_ae_obj__event_props({
|
|||||||
* Syncs the server-side event pres_mgmt config (mod_pres_mgmt_json) into the
|
* Syncs the server-side event pres_mgmt config (mod_pres_mgmt_json) into the
|
||||||
* local PersistedState store (pres_mgmt_loc.current).
|
* local PersistedState store (pres_mgmt_loc.current).
|
||||||
*
|
*
|
||||||
* Called reactively in pres_mgmt/+page.svelte whenever the event object changes.
|
* Called reactively whenever the event object changes — see the sync $effect
|
||||||
|
* in pres_mgmt/+page.svelte, session/[session_id]/+page.svelte,
|
||||||
|
* presenter/[presenter_id]/+page.svelte, locations/+page.svelte,
|
||||||
|
* location/[event_location_id]/+page.svelte, and reports/+page.svelte. Any new
|
||||||
|
* pres_mgmt page that can be a first-load entry point needs the same block.
|
||||||
*
|
*
|
||||||
* Always-synced fields: labels, requirements, access links, file config.
|
* Every field in PressMgmtRemoteCfg is synced unconditionally, every call —
|
||||||
* Lock-synced fields (only when lock_config=true): all visibility/hide__ toggles,
|
* no opt-out, no gate. (Removed 2026-06-16: a `lock_config` toggle used to make
|
||||||
* launcher links, navigation limits. This prevents presenter laptops from
|
* a subset of these fields conditional. In practice every event always had it
|
||||||
* drifting into different display configs across a conference.
|
* set to true, and the conditional sync it created meant a field's local value
|
||||||
|
* depended on whatever lock_config happened to be during the LAST sync that
|
||||||
|
* touched that particular browser — not its current value. That's effectively
|
||||||
|
* undebuggable from the UI and was the root cause of several "sometimes works"
|
||||||
|
* bug reports. See PROJECT__AE_Events_PressMgmt_Config_Cleanup.md.)
|
||||||
*
|
*
|
||||||
* Canonical key convention (enforced here):
|
* Canonical key convention (enforced here):
|
||||||
* hide__* → feature ON by default; true = turn off (default: false = visible)
|
* hide__* → feature ON by default; true = turn off (default: false = visible)
|
||||||
@@ -981,8 +989,7 @@ export function sync_config__event_pres_mgmt({
|
|||||||
|
|
||||||
const loc = pres_mgmt_loc.current;
|
const loc = pres_mgmt_loc.current;
|
||||||
|
|
||||||
// --- Always sync: labels, requirements, opt-in features, file config ---
|
// --- Labels ---
|
||||||
// These are safe to always apply — they don't override local display preferences.
|
|
||||||
loc.label__person_external_id =
|
loc.label__person_external_id =
|
||||||
pres_mgmt_cfg_remote?.label__person_external_id ?? 'External ID';
|
pres_mgmt_cfg_remote?.label__person_external_id ?? 'External ID';
|
||||||
loc.label__presenter_external_id =
|
loc.label__presenter_external_id =
|
||||||
@@ -992,85 +999,77 @@ export function sync_config__event_pres_mgmt({
|
|||||||
loc.label__session_poc_name =
|
loc.label__session_poc_name =
|
||||||
pres_mgmt_cfg_remote?.label__session_poc_name ?? 'Point of Contact';
|
pres_mgmt_cfg_remote?.label__session_poc_name ?? 'Point of Contact';
|
||||||
|
|
||||||
|
// --- Requirements ---
|
||||||
loc.require__presenter_agree =
|
loc.require__presenter_agree =
|
||||||
pres_mgmt_cfg_remote?.require__presenter_agree ?? false;
|
pres_mgmt_cfg_remote?.require__presenter_agree ?? false;
|
||||||
loc.require__session_agree =
|
loc.require__session_agree =
|
||||||
pres_mgmt_cfg_remote?.require__session_agree ?? false;
|
pres_mgmt_cfg_remote?.require__session_agree ?? false;
|
||||||
|
|
||||||
|
// --- Opt-in features ---
|
||||||
loc.show__copy_access_link =
|
loc.show__copy_access_link =
|
||||||
pres_mgmt_cfg_remote?.show__copy_access_link ?? false;
|
pres_mgmt_cfg_remote?.show__copy_access_link ?? false;
|
||||||
loc.show__email_access_link =
|
loc.show__email_access_link =
|
||||||
pres_mgmt_cfg_remote?.show__email_access_link ?? false;
|
pres_mgmt_cfg_remote?.show__email_access_link ?? false;
|
||||||
|
|
||||||
// QR code feature enable — always synced (admin opt-in, not a user preference)
|
|
||||||
loc.show__session_qr =
|
loc.show__session_qr =
|
||||||
pres_mgmt_cfg_remote?.show__session_qr ?? false;
|
pres_mgmt_cfg_remote?.show__session_qr ?? false;
|
||||||
loc.show__presenter_qr =
|
loc.show__presenter_qr =
|
||||||
pres_mgmt_cfg_remote?.show__presenter_qr ?? false;
|
pres_mgmt_cfg_remote?.show__presenter_qr ?? false;
|
||||||
|
|
||||||
|
// --- File / report config ---
|
||||||
loc.file_purpose_option_kv =
|
loc.file_purpose_option_kv =
|
||||||
pres_mgmt_cfg_remote?.file_purpose_option_kv ?? null;
|
pres_mgmt_cfg_remote?.file_purpose_option_kv ?? null;
|
||||||
|
|
||||||
loc.hide__report_kv = pres_mgmt_cfg_remote?.hide__report_kv ?? {};
|
loc.hide__report_kv = pres_mgmt_cfg_remote?.hide__report_kv ?? {};
|
||||||
|
|
||||||
// --- Lock-synced: visibility, launcher, navigation, session/presenter fields ---
|
// --- Codes ---
|
||||||
// When lock_config=true the remote config wins for ALL display flags, preventing
|
loc.hide__location_code =
|
||||||
// local browser state from overriding the admin's event-level configuration.
|
pres_mgmt_cfg_remote?.hide__location_code ?? false;
|
||||||
if (pres_mgmt_cfg_remote?.lock_config) {
|
loc.hide__presentation_code =
|
||||||
if (log_lvl) console.log(`sync_config__event_pres_mgmt: lock_config=true, forcing full sync`);
|
pres_mgmt_cfg_remote?.hide__presentation_code ?? false;
|
||||||
|
loc.hide__presenter_code =
|
||||||
|
pres_mgmt_cfg_remote?.hide__presenter_code ?? false;
|
||||||
|
loc.hide__session_code =
|
||||||
|
pres_mgmt_cfg_remote?.hide__session_code ?? false;
|
||||||
|
|
||||||
// Codes
|
// --- Session fields ---
|
||||||
loc.hide__location_code =
|
loc.hide__session_description =
|
||||||
pres_mgmt_cfg_remote?.hide__location_code ?? false;
|
pres_mgmt_cfg_remote?.hide__session_description ?? false;
|
||||||
loc.hide__presentation_code =
|
loc.hide__session_location =
|
||||||
pres_mgmt_cfg_remote?.hide__presentation_code ?? false;
|
pres_mgmt_cfg_remote?.hide__session_location ?? false;
|
||||||
loc.hide__presenter_code =
|
loc.hide__session_msg =
|
||||||
pres_mgmt_cfg_remote?.hide__presenter_code ?? false;
|
pres_mgmt_cfg_remote?.hide__session_msg ?? false;
|
||||||
loc.hide__session_code =
|
loc.hide__session_poc =
|
||||||
pres_mgmt_cfg_remote?.hide__session_code ?? false;
|
pres_mgmt_cfg_remote?.hide__session_poc ?? false;
|
||||||
|
loc.show__session_li_poc_field =
|
||||||
|
pres_mgmt_cfg_remote?.show__session_li_poc_field ?? 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;
|
||||||
|
|
||||||
// Session fields
|
// --- Presenter fields ---
|
||||||
loc.hide__session_description =
|
loc.hide__presenter_biography =
|
||||||
pres_mgmt_cfg_remote?.hide__session_description ?? false;
|
pres_mgmt_cfg_remote?.hide__presenter_biography ?? 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.show__session_li_poc_field =
|
|
||||||
pres_mgmt_cfg_remote?.show__session_li_poc_field ?? 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
|
// --- Presentation fields ---
|
||||||
loc.hide__presenter_biography =
|
loc.hide__presentation_datetime =
|
||||||
pres_mgmt_cfg_remote?.hide__presenter_biography ?? false;
|
pres_mgmt_cfg_remote?.hide__presentation_datetime ?? false;
|
||||||
|
loc.hide__presentation_description =
|
||||||
|
pres_mgmt_cfg_remote?.hide__presentation_description ?? false;
|
||||||
|
|
||||||
// Presentation fields
|
// --- Launcher links (show__ in remote → invert to hide__ in local display state) ---
|
||||||
loc.hide__presentation_datetime =
|
loc.hide__launcher_link =
|
||||||
pres_mgmt_cfg_remote?.hide__presentation_datetime ?? false;
|
!(pres_mgmt_cfg_remote?.show__launcher_link ?? false);
|
||||||
loc.hide__presentation_description =
|
// Mirror the raw remote flag too — the toggle BUTTON's own visibility (not the
|
||||||
pres_mgmt_cfg_remote?.hide__presentation_description ?? false;
|
// launcher link content itself) is gated on show__launcher_link directly in
|
||||||
|
// ae_comp__events_menu_opts.svelte / event_page_menu.svelte / location_page_menu.svelte.
|
||||||
|
loc.show__launcher_link =
|
||||||
|
pres_mgmt_cfg_remote?.show__launcher_link ?? false;
|
||||||
|
|
||||||
// Launcher links (show__ in remote → invert to hide__ in local display state)
|
// --- Navigation / UI constraints ---
|
||||||
loc.hide__launcher_link =
|
loc.limit__navigation =
|
||||||
!(pres_mgmt_cfg_remote?.show__launcher_link ?? false);
|
pres_mgmt_cfg_remote?.limit__navigation ?? false;
|
||||||
// Mirror the raw remote flag too — the toggle BUTTON's own visibility (not the
|
|
||||||
// launcher link content itself) is gated on show__launcher_link directly in
|
|
||||||
// ae_comp__events_menu_opts.svelte / event_page_menu.svelte / location_page_menu.svelte.
|
|
||||||
// This was never assigned before, so that gate always collapsed to trusted_access-only.
|
|
||||||
loc.show__launcher_link =
|
|
||||||
pres_mgmt_cfg_remote?.show__launcher_link ?? false;
|
|
||||||
|
|
||||||
// Navigation / UI constraints
|
|
||||||
loc.limit__navigation =
|
|
||||||
pres_mgmt_cfg_remote?.limit__navigation ?? false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -360,10 +360,9 @@ function handle_clear_access() {
|
|||||||
<!-- Removed 2026-06-16: dead "Lock Config" Sync/Unlink toggle. It wrote to
|
<!-- Removed 2026-06-16: dead "Lock Config" Sync/Unlink toggle. It wrote to
|
||||||
$ae_loc.sync_local_config/lock_config and pres_mgmt_loc.current.sync_local_config/
|
$ae_loc.sync_local_config/lock_config and pres_mgmt_loc.current.sync_local_config/
|
||||||
lock_config, but nothing in the codebase ever read any of those four fields —
|
lock_config, but nothing in the codebase ever read any of those four fields —
|
||||||
confirmed via full-repo grep. It also confusingly shared a name with the real,
|
confirmed via full-repo grep. It also confusingly shared a name with the Pres
|
||||||
functional "Lock Config" checkbox on the Pres Mgmt Config page (which gates
|
Mgmt Config page's own "Lock Config" checkbox, which has since been removed
|
||||||
sync_config__event_pres_mgmt()'s remote->local sync via the value actually
|
entirely too — sync_config__event_pres_mgmt() now syncs unconditionally.
|
||||||
stored in event.mod_pres_mgmt_json.lock_config, not this local mirror).
|
|
||||||
See PROJECT__AE_Events_PressMgmt_Config_Cleanup.md. -->
|
See PROJECT__AE_Events_PressMgmt_Config_Cleanup.md. -->
|
||||||
|
|
||||||
<!-- {#if $ae_loc.edit_mode}
|
<!-- {#if $ae_loc.edit_mode}
|
||||||
|
|||||||
@@ -15,13 +15,14 @@
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Remote config — shape of event.mod_pres_mgmt_json
|
// Remote config — shape of event.mod_pres_mgmt_json
|
||||||
// This is the admin-controlled, server-side config for an event.
|
// This is the admin-controlled, server-side config for an event. Every field
|
||||||
// lock_config: true forces every field below to sync into local state on load.
|
// here is synced into every browser unconditionally on event load — there is
|
||||||
|
// no opt-out. (Removed 2026-06-16: a `lock_config` toggle used to gate this;
|
||||||
|
// in practice every event always had it set to true and the conditional
|
||||||
|
// sync it created was an undebuggable source of stale local state — see
|
||||||
|
// PROJECT__AE_Events_PressMgmt_Config_Cleanup.md.)
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
export interface PressMgmtRemoteCfg {
|
export interface PressMgmtRemoteCfg {
|
||||||
// System
|
|
||||||
lock_config: boolean; // true = force all fields below into local state
|
|
||||||
|
|
||||||
// Labels — event-specific terminology overrides
|
// Labels — event-specific terminology overrides
|
||||||
label__person_external_id: string | null; // default: 'External ID'
|
label__person_external_id: string | null; // default: 'External ID'
|
||||||
label__presenter_external_id: string | null; // default: 'External ID'
|
label__presenter_external_id: string | null; // default: 'External ID'
|
||||||
@@ -83,7 +84,7 @@ export interface PressMgmtRemoteCfg {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Local state — persisted to localStorage via PersistedState ('ae_pres_mgmt_loc')
|
// Local state — persisted to localStorage via PersistedState ('ae_pres_mgmt_loc')
|
||||||
// Contains both user preferences AND fields synced from PressMgmtRemoteCfg.
|
// Contains both user preferences AND fields synced from PressMgmtRemoteCfg.
|
||||||
// Fields synced from remote are overwritten on every event load when lock_config=true.
|
// Fields synced from remote are overwritten unconditionally on every event load.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
export interface PresMgmtLocState {
|
export interface PresMgmtLocState {
|
||||||
// --- Query / search preferences ---
|
// --- Query / search preferences ---
|
||||||
@@ -152,8 +153,8 @@ export interface PresMgmtLocState {
|
|||||||
hide__device_code: boolean;
|
hide__device_code: boolean;
|
||||||
hide__locations_msg: boolean;
|
hide__locations_msg: boolean;
|
||||||
hide__session_li_location_field: boolean;
|
hide__session_li_location_field: boolean;
|
||||||
// Also mirrors PressMgmtRemoteCfg.show__session_li_poc_field — lock-synced
|
// Also mirrors PressMgmtRemoteCfg.show__session_li_poc_field — synced
|
||||||
// (overwritten when lock_config=true), see sync_config__event_pres_mgmt().
|
// unconditionally, see sync_config__event_pres_mgmt().
|
||||||
show__session_li_poc_field: boolean;
|
show__session_li_poc_field: boolean;
|
||||||
// Launcher/location links in session list
|
// Launcher/location links in session list
|
||||||
hide__launcher_link: boolean; // SvelteKit launcher
|
hide__launcher_link: boolean; // SvelteKit launcher
|
||||||
@@ -176,8 +177,8 @@ export interface PresMgmtLocState {
|
|||||||
location_kv: Record<string, any>;
|
location_kv: Record<string, any>;
|
||||||
|
|
||||||
// --- Synced from PressMgmtRemoteCfg (overwritten by sync_config__event_pres_mgmt) ---
|
// --- Synced from PressMgmtRemoteCfg (overwritten by sync_config__event_pres_mgmt) ---
|
||||||
// These mirror PressMgmtRemoteCfg fields and are written during event load.
|
// These mirror PressMgmtRemoteCfg fields and are written unconditionally on every
|
||||||
// Do not set these manually — they will be overridden when lock_config=true.
|
// event load. Do not set these manually — they will always be overwritten.
|
||||||
label__person_external_id: string;
|
label__person_external_id: string;
|
||||||
label__presenter_external_id: string;
|
label__presenter_external_id: string;
|
||||||
label__session_poc_type: string;
|
label__session_poc_type: string;
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ let lq__event_obj = $derived(
|
|||||||
// Draft state — initialized from the live event config
|
// Draft state — initialized from the live event config
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
const cfg_defaults: PressMgmtRemoteCfg = {
|
const cfg_defaults: PressMgmtRemoteCfg = {
|
||||||
lock_config: true,
|
|
||||||
label__person_external_id: null,
|
label__person_external_id: null,
|
||||||
label__presenter_external_id: null,
|
label__presenter_external_id: null,
|
||||||
label__session_poc_type: null,
|
label__session_poc_type: null,
|
||||||
@@ -181,7 +180,6 @@ async function save() {
|
|||||||
|
|
||||||
// Section collapse state
|
// Section collapse state
|
||||||
let sections: Record<string, boolean> = $state({
|
let sections: Record<string, boolean> = $state({
|
||||||
system: true,
|
|
||||||
labels: true,
|
labels: true,
|
||||||
codes: true,
|
codes: true,
|
||||||
session: true,
|
session: true,
|
||||||
@@ -244,41 +242,13 @@ function toggle(key: string) {
|
|||||||
|
|
||||||
<p class="text-surface-500 text-sm">
|
<p class="text-surface-500 text-sm">
|
||||||
Changes here update <code>event.mod_pres_mgmt_json</code> and take effect on
|
Changes here update <code>event.mod_pres_mgmt_json</code> and take effect on
|
||||||
the next event load. When <strong>Lock Config</strong> is on, all display flags
|
the next event load, applying to every browser.
|
||||||
are pushed to every browser — overriding local user preferences.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{#if !draft_initialized}
|
{#if !draft_initialized}
|
||||||
<p class="text-surface-400 italic">Loading event config...</p>
|
<p class="text-surface-400 italic">Loading event config...</p>
|
||||||
{:else}
|
{:else}
|
||||||
|
|
||||||
<!-- ================================================================ -->
|
|
||||||
<!-- SYSTEM -->
|
|
||||||
<!-- ================================================================ -->
|
|
||||||
<section class="border-surface-200-800 rounded-xl border">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="flex w-full items-center justify-between px-4 py-3 text-left font-semibold"
|
|
||||||
onclick={() => toggle('system')}>
|
|
||||||
<span>System</span>
|
|
||||||
{#if sections.system}<ChevronUp size="1em" />{:else}<ChevronDown size="1em" />{/if}
|
|
||||||
</button>
|
|
||||||
{#if sections.system}
|
|
||||||
<div class="border-surface-200-800 space-y-3 border-t px-4 py-3">
|
|
||||||
<label class="flex items-start gap-3">
|
|
||||||
<input type="checkbox" class="checkbox mt-0.5" bind:checked={draft.lock_config} />
|
|
||||||
<span>
|
|
||||||
<span class="font-semibold">Lock Config</span>
|
|
||||||
<span class="text-surface-500 ml-2 text-sm">
|
|
||||||
Forces all display flags below to sync into every browser on event load,
|
|
||||||
overriding local user preferences. Recommended: <strong>on</strong>.
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- ================================================================ -->
|
<!-- ================================================================ -->
|
||||||
<!-- LABELS -->
|
<!-- LABELS -->
|
||||||
<!-- ================================================================ -->
|
<!-- ================================================================ -->
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import type { key_val } from '$lib/stores/ae_stores';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
mod_pres_mgmt_json: key_val | null | undefined;
|
|
||||||
onsave?: (data: key_val) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
let { mod_pres_mgmt_json = $bindable({}), onsave }: Props = $props();
|
|
||||||
|
|
||||||
function save() {
|
|
||||||
if (onsave && mod_pres_mgmt_json) onsave(mod_pres_mgmt_json);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="space-y-4">
|
|
||||||
{#if mod_pres_mgmt_json}
|
|
||||||
<div class="grid grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={mod_pres_mgmt_json.lock_config} />
|
|
||||||
<span>Lock Config</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={mod_pres_mgmt_json.hide__location_code} />
|
|
||||||
<span>Hide Location Code</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={
|
|
||||||
mod_pres_mgmt_json.hide__presentation_code
|
|
||||||
} />
|
|
||||||
<span>Hide Presentation Code</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={
|
|
||||||
mod_pres_mgmt_json.hide__presenter_code
|
|
||||||
} />
|
|
||||||
<span>Hide Presenter Code</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={mod_pres_mgmt_json.hide__session_code} />
|
|
||||||
<span>Hide Session Code</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={mod_pres_mgmt_json.limit__navigation} />
|
|
||||||
<span>Limit Navigation</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={mod_pres_mgmt_json.limit__options} />
|
|
||||||
<span>Limit Options</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={
|
|
||||||
mod_pres_mgmt_json.require__presenter_agree
|
|
||||||
} />
|
|
||||||
<span>Require Presenter Agreement</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
bind:checked={
|
|
||||||
mod_pres_mgmt_json.require__session_agree
|
|
||||||
} />
|
|
||||||
<span>Require Session Agreement</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="space-y-2">
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<span>Label for Person External ID</span>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="input"
|
|
||||||
bind:value={
|
|
||||||
mod_pres_mgmt_json.label__person_external_id
|
|
||||||
} />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<span>Label for Session POC Type</span>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="input"
|
|
||||||
bind:value={
|
|
||||||
mod_pres_mgmt_json.label__session_poc_type
|
|
||||||
} />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="label">
|
|
||||||
<span>Label for Session POC Name</span>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
class="input"
|
|
||||||
bind:value={
|
|
||||||
mod_pres_mgmt_json.label__session_poc_name
|
|
||||||
} />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<button type="button" class="btn preset-tonal-primary" onclick={save}
|
|
||||||
>Save</button>
|
|
||||||
</div>
|
|
||||||
Reference in New Issue
Block a user