- QR scanner (single + multi): detect previously-removed leads via IDB enable flag;
route to 'reenable' state instead of duplicate error; offer Re-activate button
- API fallback: if create fails and no IDB record, search API for disabled tracking
record by event_exhibit_id + event_badge_id (adds qry_badge_id param to
search__exhibit_tracking)
- Lead detail page: Replace raw enable checkbox with Remove Lead (two-click confirm,
navigates back after) and Restore Lead card (shown when enable is falsy)
- Fix flash of disabled records in leads list: filter !enable in both filtered_lead_li
derived and local IDB fast-path in handle_search_refresh
- eslint.config.js: disable svelte/no-navigation-without-resolve (no base path configured)
- Also includes _random field annotation cleanup (db_events, ae_types), iframe layout
fixes, badge view tweaks, test updates, and doc updates from prior session
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
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>
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.
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
Svelte 5 does not support <style> or conditional {#if} blocks wrapping
<style> tags inside <svelte:head>. The parser treats them as raw-text
elements and reports '<script> was left open' at EOF.
Fix:
- Print media CSS moved to static/ae-print-badge.css (plain static file,
no framework magic needed — all selectors target global elements).
- svelte:head now uses a simple <link> to that file.
- $effect injects the @page size dynamically per template layout field,
avoiding the Svelte 5 parser limitation for conditional style injection.
- Badge_template interface in db_events.ts: added cfg_json / data_json
(standard Aether object fields that were missing from the type).
- Defaults to true (authenticated_access required) — no change to existing consumers
- Launcher file buttons set require_auth=false to allow unauthenticated downloads
Replaces all alert() calls in the user/pass auth flow with reactive state.
Button shows: Verifying… (disabled) → Failed — retry? (red) →
Enter credentials first (amber) → Username/User ID Sign In (default).
Error messages (wrong password, no person record, no server response)
appear as small text below the button on failure.
Clicking the button resets to default so retry is clean.
Also removes dead commented-out alert and cleans up the promise chains.
No type="button" issues found — all non-submit buttons were already typed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removes the debug alert() calls from the email magic-link flow.
Button now shows live feedback inline:
- 'Sending…' while the lookup is in flight (disabled + cursor-wait)
- 'Email sent ✓' on success (green fill)
- 'No account found' if no user matches the email
- 'Error — retry?' on network/API failure
- 'Enter an email first' if submitted empty
Clicking the button while showing a result resets it to the default label.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign In/Out (e_app_sign_in_out.svelte):
- Remove redundant internal header (sr-only was broken by :global CSS override)
- Full-width form inputs and buttons with 'or' divider between the two methods
- Signed-in state shows centered username and full-width action buttons
Access/Passcode (e_app_access_type.svelte):
- Fix 'Locked' button: was running trigger=true (no-op permission reprocess);
now correctly toggles show_passcode_input so the input shows/hides on click
System bar (e_app_sys_bar.svelte):
- Dynamic section headers: Sign In/Out shows username when signed in;
Access/Passcode shows ShieldEllipsis/ShieldMinus/ShieldUser based on state
- Fix passcode input not showing on re-open via menu button:
onDestroy resets show_element__passcode_input=false; toggle_expand now
restores it to true for anonymous/no-access state (matches handle_shield_click)
- Broaden anonymous check from === 'anonymous' to !access_type || === 'anonymous'
- Remove dead getElementById focus call (DOM not ready at that point;
focus_input binding in Element_access_type handles it correctly)
- Appearance section: mode/font buttons at top, dark mode gets amber tint
in light mode for visual context, theme select uses text-sm
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hover info strip is always in DOM (opacity-only toggle, no {#if} mount)
so first hover no longer triggers a layout recalc/flash
- Bar strip gets fixed h-9 height so inline label text appearing on
group-hover can never shift the bar vertically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hover info strip is now absolute-positioned above the bar (opacity fade
with delay-500) so it never shifts the bar layout — fixes the bounce
- Panel widened to w-80 with overflow-x-hidden — fixes horizontal scroll
caused by sub-components hardcoding w-72 inside the padded panel
- All panel sections are now collapsible (Access open by default, others
closed) — reduces vertical crowding; matches launcher_cfg pattern
- Section headers show current state inline (access level, theme name/mode)
- Admin section groups cfg + debug trigger together cleanly
- Bar transitions use duration-200 for snappier feel without bounce
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New compact bar + expandable panel design:
- Compact strip (bottom-right): auth shield, font cycler, dark/light toggle,
edit mode toggle (authenticated+), menu expand — icon-only by default,
labels reveal on hover
- Hover info strip shows person name + access level when logged in
- Expanded panel: sign in/out, access/passcode, appearance (theme), admin
(config + URL builder + debug trigger) — all gated same as before
- Debug overlay trigger moved into admin section (edit mode only)
- All business logic preserved via existing sub-components (unchanged)
- e_app_sys_menu.svelte retained but no longer mounted (import commented out)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New e_app_url_builder.svelte component lets admins construct and copy
shareable URLs with any combination of core global params (iframe, theme,
theme_mode, key). Outputs full URL by default; toggleable to params-only
string for pasting onto existing links. Integrated into e_app_cfg Utilities
section (visible in edit mode).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds binary-search font auto-scaling for badge text fields, replacing
the character-count heuristic in v1. New files:
- action_fit_text.ts: Svelte action using binary search + MutationObserver
+ ResizeObserver. Pass null to disable (manual override mode).
- element_fit_text.svelte: Component wrapper with min/max/manual_size/
height/width props. height prop required for overflow detection to work.
- ae_comp__badge_obj_view_v2.svelte: Badge render using Element_fit_text
for name/title/affiliations/location in display mode. font_size_* props
default to undefined (auto-scale) instead of numeric defaults.
fit_heights derived object provides layout-aware section heights for
badge_3.5x5.5_pvc, badge_4x5_fanfold, and badge_4x6_fanfold layouts.
flex_justify() maps shorthand ('around','between','even') to CSS values.
Edit mode uses plain divs — inputs are never auto-scaled.
print/+page.svelte: Added v1/v2 toggle button in header. V1 preserved
as fallback. font_size_* passed as null (not ?? undefined) to v2 so
auto-scaling is active by default; manual override from print controls
still disables it per-field.
Docs: PROJECT__AE_Events_Badges_Review_Print.md updated with kiosk
workflow design intent, email address rule (always event_badge.email),
permission model alignment gap (TASK 4.0), and v2 implementation status.
TODO__Agents.md: completed items removed, badge polish tasks updated.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ae_auth_error writable store to ae_stores.ts
- Wire api_get_object, api_post_object, api_patch_object to set
ae_auth_error on 401/403 (browser-only guard, never fires SSR)
- Root layout watches ae_auth_error; only raises flag_expired when
a JWT is present (prevents false trigger on unauthenticated loads)
- Dismissible amber banner added to root layout (non-blocking, above content)
- Tested via debug menu trigger; banner fires and clears correctly
- Remove vestigial try_cache param from generate_qr_code (never used in body)
- Remove vestigial try_cache from ae_core_functions: load_ae_obj_id__site_domain,
update_ae_obj_id_crud, update_ae_obj_id_crud_v2 (none referenced it in body)
- Add proper SWR pattern to load_ae_obj_id__sponsorship_cfg and
load_ae_obj_id__sponsorship; change defaults from false to true
- Change load_ae_obj_id__event_file default try_cache from false to true
(consistent with load_ae_obj_li__event_file)
- Change load_ae_obj_id__hosted_file default try_cache from false to true
(consistent with load_ae_obj_li__hosted_file)
- Remove stale try_cache arg from element_ae_crud.svelte caller
element_manage_event_file_li_all.svelte — also derives context_session_type_code
via Dexie chain (event_presentation → session, or event_presenter → presentation →
session) and passes it to element_manage_event_file_li. Fixes the button not showing
when viewing a presenter's files from the session view.
element_manage_event_file_li_direct.svelte — extends the Dexie chain to also handle
event_session (direct lookup) and event_presentation, not just event_presenter.
Both: correct API URL to /v3/hosted_file/ per backend agent's examples.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>