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]; +}