From d05420d9c174d2478979aa5d0d895d41ccddb205 Mon Sep 17 00:00:00 2001
From: Scott Idem
Date: Thu, 9 Apr 2026 15:10:03 -0400
Subject: [PATCH] Badges: persist template controls_cfg; fix onchange syntax in
template form
---
.../ae_comp__badge_print_controls.svelte | 31 ++++---
.../ae_comp__badge_template_form.svelte | 89 ++++++++++++++++++-
2 files changed, 106 insertions(+), 14 deletions(-)
diff --git a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte
index d7f101ea..7bb57251 100644
--- a/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte
+++ b/src/routes/events/[event_id]/(badges)/badges/[badge_id]/ae_comp__badge_print_controls.svelte
@@ -121,18 +121,27 @@ interface ControlsCfg {
shown?: string[];
auth_editable?: string[];
}
-let template_controls_cfg = $derived(
- (() => {
- try {
- const parsed = JSON.parse(
- $lq__event_badge_template_obj?.other_json ?? '{}'
- );
- return (parsed?.controls_cfg ?? null) as ControlsCfg | null;
- } catch {
- return null;
+let template_controls_cfg = $derived.by((): ControlsCfg | null => {
+ try {
+ const raw = $lq__event_badge_template_obj?.cfg_json ?? null;
+ if (raw) {
+ const parsed = typeof raw === 'string' ? JSON.parse(raw) : raw;
+ if (parsed?.controls_cfg) return parsed.controls_cfg as ControlsCfg;
}
- })()
-);
+ } catch {
+ // fall through to other_json fallback
+ }
+ try {
+ const raw2 = $lq__event_badge_template_obj?.other_json ?? null;
+ if (raw2) {
+ const parsed2 = typeof raw2 === 'string' ? JSON.parse(raw2) : raw2;
+ return (parsed2?.controls_cfg ?? null) as ControlsCfg | null;
+ }
+ } catch {
+ return null;
+ }
+ return null;
+});
// Default auth-editable fields when the template has no explicit config.
// Covers the fields an attendee most commonly needs to fix at the badge table.
diff --git a/src/routes/events/[event_id]/(badges)/templates/ae_comp__badge_template_form.svelte b/src/routes/events/[event_id]/(badges)/templates/ae_comp__badge_template_form.svelte
index 08a94444..e286b1c2 100644
--- a/src/routes/events/[event_id]/(badges)/templates/ae_comp__badge_template_form.svelte
+++ b/src/routes/events/[event_id]/(badges)/templates/ae_comp__badge_template_form.svelte
@@ -57,6 +57,10 @@ let cfg_show_qr_back = $state(true);
let cfg_hide_title = $state(false);
let cfg_hide_affiliations = $state(false);
let cfg_hide_location = $state(false);
+// Controls menu config (per-template) — which fields the controls panel shows
+// and which fields authenticated users may edit. Stored under cfg_json.controls_cfg
+let cfg_controls_shown: string[] = $state([]);
+let cfg_controls_auth_editable: string[] = $state([]);
// Body text color (hex)
let cfg_body_text_color = $state('#000000');
// Alignment overrides: 'left' | 'center' | 'right' | 'justify'
@@ -128,6 +132,13 @@ async function load_template(id: string) {
cfg_hide_affiliations = parsed_cfg.hasOwnProperty('hide_affiliations') ? !!parsed_cfg.hide_affiliations : false;
cfg_hide_location = parsed_cfg.hasOwnProperty('hide_location') ? !!parsed_cfg.hide_location : false;
+ // Controls menu cfg (preferred location: cfg_json.controls_cfg)
+ const parsed_controls = parsed_cfg?.controls_cfg ?? parsed_cfg?.controlsCfg ?? parsed_cfg?.controls ?? null;
+ cfg_controls_shown = Array.isArray(parsed_controls?.shown) ? [...parsed_controls.shown] : [];
+ cfg_controls_auth_editable = Array.isArray(parsed_controls?.auth_editable)
+ ? [...parsed_controls.auth_editable]
+ : [];
+
// Body text color (hex-only). Prefer explicit hex keys.
const _hex_candidate = parsed_cfg.body_text_color_hex ?? parsed_cfg.body_text_color ?? parsed_cfg.text_color ?? '';
if (typeof _hex_candidate === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(_hex_candidate.trim())) {
@@ -195,6 +206,12 @@ async function handle_submit() {
cfg_obj.qr_alignment.front = cfg_qr_alignment_front;
cfg_obj.qr_alignment.back = cfg_qr_alignment_back;
+ // Controls menu config: which fields the controls panel shows and which
+ // fields authenticated users may edit. Stored under cfg_json.controls_cfg
+ cfg_obj.controls_cfg = cfg_obj.controls_cfg || {};
+ if (cfg_controls_shown && cfg_controls_shown.length > 0) cfg_obj.controls_cfg.shown = [...cfg_controls_shown];
+ if (cfg_controls_auth_editable && cfg_controls_auth_editable.length > 0) cfg_obj.controls_cfg.auth_editable = [...cfg_controls_auth_editable];
+
// Body text color (hex-only)
if (typeof cfg_body_text_color === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(cfg_body_text_color.trim())) {
cfg_obj.body_text_color = cfg_body_text_color.trim();
@@ -258,6 +275,17 @@ async function handle_submit() {
function handle_cancel() {
if (oncancel) oncancel();
}
+
+// Toggle helpers for controls_cfg arrays
+function toggle_cfg_controls_shown(key: string) {
+ if (cfg_controls_shown.includes(key)) cfg_controls_shown = cfg_controls_shown.filter((k) => k !== key);
+ else cfg_controls_shown = [...cfg_controls_shown, key];
+}
+
+function toggle_cfg_controls_auth_editable(key: string) {
+ if (cfg_controls_auth_editable.includes(key)) cfg_controls_auth_editable = cfg_controls_auth_editable.filter((k) => k !== key);
+ else cfg_controls_auth_editable = [...cfg_controls_auth_editable, key];
+}
-
- These values are saved into cfg_json. Existing cfg_json keys are preserved.
-
+
{/if}