The browser fires beforeinstallprompt very early (~1s after page load),
before Svelte's $effects run. Moving the event listener registration to
module level ensures we never miss the event regardless of when init()
is called from the root layout.
init() now only handles dismiss state (localStorage) and standalone
detection (DOM) — both safe to defer until after component mount.
Platforms:
- Chrome / Chromium / Android: native install button via captured prompt
- iOS Safari: manual Share → Add to Home Screen instructions (unchanged)
- Firefox desktop: no beforeinstallprompt support (browser-level limitation);
Firefox shows its own install button in the address bar automatically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Eye/EyeOff toggle to exhibit tracking search bar; wired to
existing $events_loc.leads.show_hidden store field
- Guard + init the show_hidden field in +page.svelte
- Add show_hidden to search_params so toggling triggers a refresh
- Apply hide filter in local IDB search path (skip hidden unless toggled)
- Pass hidden: 'not_hidden' | 'all' to API search__exhibit_tracking call
- Apply hide filter in filtered_lead_li for the broad liveQuery fallback path
- README: remove stale allow_tracking/PWA/export gaps; add Implemented section;
fix ae_events_functions import path (moved to ae_events/ subdir)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
element_ae_crud.svelte and element_ae_crud_v2.svelte had zero active
importers; only a commented-out reference remained. Moved both to trash
and removed the dead comment from ae_comp__event_presentation_obj_li.svelte.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Relocates the functions file from lib root into its module directory,
matching the pattern used by all other modules (ae_journals, ae_archives, etc.).
Updated all 85 import paths from \$lib/ae_events_functions → \$lib/ae_events/ae_events_functions.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add justify-center + h-6 to the debug info row above the badge so it stays centered
and doesn't cause vertical shift when conditional elements show/hide on edit mode toggle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add field_shown() and field_editable() functions driven by event_badge_template.other_json:
controls_cfg: { shown?: string[], auth_editable?: string[] }
Access rules:
- No authenticated_access → display-only, no edit buttons shown
- authenticated only → can edit fields in auth_editable (default: title/affiliations/location/allow_tracking/pronouns)
- trusted + edit_mode → always sees and edits all fields, ignores config
Each attendee field card (name, title, affiliations, location, allow_tracking, pronouns)
is now wrapped in {#if field_shown()} and its edit button/accordion gated by field_editable().
No backend changes needed — other_json is an existing longtext JSON column.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add name_two_lines toggle (default: true) — uses CSS horizontal padding scaled by
character count to coax short names (e.g. "Scott Idem") into a natural two-line wrap
without a hard <br>; three tiers: ≤12 chars (18%), ≤20 (8%), ≤28 (2%), >28 no pad
- Inner <div> (block element) used inside Element_fit_text for class: directives —
Svelte scoped CSS requires static class names in the template; dynamic strings and
class: on component elements both fail to match scoped CSS rules
- Add leading-none to all four Element_fit_text fields (name, title, affiliations,
location) — line-height must be set at the wrapper div level where fit_text measures
scrollHeight, otherwise the binary-search scaler returns inflated sizes
- name_two_lines state persisted to localStorage (ae_badge_print_tweaks key) alongside
existing print_offset, hide_chrome, and banner_full_width tweaks
- Rewrite badge_header_calibration.svg as a precise SVG ruler with labeled tick marks
(major at 1in intervals, minor at 0.25in) for accurate physical print calibration
- Gate debug outline CSS on html.debug_outlines class (set by controls panel) so
outlines never appear in normal print mode
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
iframe=true now hides the sys bar for all users (previously trusted_access
users still saw it). Admins can pass show_menu=true to re-enable it while
testing an embedded page like video_conferences.
hide_menu=true remains for non-iframe hide use cases (kiosk, etc).
Updated URL builder: hide_menu checkbox → show_menu checkbox.
Updated GUIDE__Development.md URL params table.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ae_ prefix belongs on Svelte component/variable names, not URL params.
Updated both the consumer (+layout.svelte) and the builder (jitsi_url_builder).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The URL builder generates ae_hide_menu=true but nothing consumed it.
Now layout.svelte reads the param on mount and sets $ae_loc.sys_menu.hide,
which flows through bind:hide into E_app_sys_bar's class:hidden.
Applies even for trusted_access users who bypass the iframe guard.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds ae_hide_menu=true query param option to suppress the AE navigation
chrome when embedding the Jitsi video conference page in Novi or other
host pages that provide their own navigation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New component ae_idaa_comp__jitsi_url_builder.svelte builds and previews
Jitsi iframe URLs for testing and Novi page configuration. Features:
- Environment selector (prod / dev / local / custom)
- Room name, Novi UUID, site key inputs
- Moderator toggle (explains JWT + logging implication)
- Advanced: domain, start muted/hidden, all 5 sound settings
- Output in URL or iframe HTML snippet mode with copy button
- "Open in new tab" for quick testing
Embedded on jitsi_reports page as a collapsible panel, gated to
trusted_access users only.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jitsi_reports was previously at src/routes/idaa/jitsi_reports/ and
was not protected by the (idaa) layout auth gate. Moved to
src/routes/idaa/(idaa)/jitsi_reports/ — same URL, now requires
trusted_access or Novi-verified authenticated access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a passcode matched, entered_passcode was cleared and the trigger
was set, but show_passcode_input was never set to false. This left the
input visible so users could keep typing after access was granted.
Set show_passcode_input = false immediately after clearing entered_passcode
on a successful match, consistent with the intent described in the
handle_clear_access() function which resets it to true on clear.
Export button now only renders when event_exhibit.leads_api_access === true,
preventing a 403 that would always fire otherwise. Endpoint confirmed live on
backend. TODO updated to reflect export + allow_tracking gate both resolved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updated download_export__event_exhibit_tracking to call
/v3/action/event_exhibit/{exhibit_id}/tracking_export instead of the
legacy /event/exhibit/{exhibit_id}/tracking/export (V1 path).
Added doc comment listing the expected export columns so the backend
agent has the full field spec when implementing the endpoint.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- QR scanner: after badge loads, blocks add with 'Tracking Opt-Out' warning
card if allow_tracking !== true; replaced deprecated CheckCircle → CircleCheck
- Manual search: shows ShieldOff 'Opt-Out' label per row for blocked badges;
add_as_lead() also guards against programmatic bypass
- Fix: ae_comp__exhibit_tracking_obj_li — Loader2 from wrong package
@lucide/svelte → LoaderCircle from lucide-svelte
- ae_types.ts: added allow_tracking and agree_to_tc to ae_EventBadge interface
- README.md (leads): full rewrite reflecting actual current state and known gaps
- TODO__Agents.md: updated Leads entry from stale 'NEXT MAJOR FEATURE' to
accurate in-progress status with remaining checklist
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ae_stores.ts
- Extract auth/identity section (~80 lines) into ae_stores__auth_loc_defaults.ts
- Spread auth_loc_defaults into ae_app_local_data_defaults (zero consumer changes)
ae_events_stores.ts (both loc and sess structs)
- badges → ae_events_stores__badges_defaults.ts
- launcher → ae_events_stores__launcher_defaults.ts
- leads → ae_events_stores__leads_defaults.ts
- pres_mgmt → ae_events_stores__pres_mgmt_defaults.ts
Each new file exports *_loc_defaults and *_sess_defaults. The store files
now reference these by name instead of embedding inline objects. All
$ae_loc.* and $events_loc.* consumer paths are unchanged.
svelte-check: 0 errors, 0 warnings
- Remove unused `import { offset } from '@floating-ui/dom'`
- Remove ver_idb constant and field (same as ae_stores / ae_events_stores)
- Remove commented-out personal Novi UUIDs (security hygiene — these belong
in site_cfg_json on the server, not in source; idaa layout already reads
them from $ae_loc.site_cfg_json and writes to idaa_loc at mount)
- Add comment explaining novi_admin/trusted/jitsi_mod_li are server-driven
- Remove dead writable/persisted alternatives and console.log lines
- Remove stale 'Updated 20xx-xx-xx' date comments
- Condense redundant tracking comments to single-line form
Lucide renders <svg> elements which default to inline-block in browsers,
causing icons to break onto their own line when mixed with text — unlike
FA spans which were display:inline.
Added svg.lucide { display: inline; vertical-align: middle; } to app.css
so all Lucide icons flow inline with adjacent text globally, matching the
FA icon behavior without needing class="inline" on every icon instance.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move the FA 5.15.4 CDN <link> from app.html (global) into
src/routes/idaa/+layout.svelte <svelte:head> so it only loads
on /idaa/* routes. All other modules now use Lucide exclusively.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert 6 template-level FA spans to Lucide components (Star, Biohazard,
Asterisk, Wifi). The code_to_html JS string dict (dietary symbols used
with {@html}) retains FA spans since they are raw HTML strings, not
Svelte template markup — FontAwesome CSS (app.html CDN) renders them.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>