Updated to do list. Cleaned up the badge search area at the top of the badge. Also tested the upload option
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
"settings": {
|
||||
"cSpell.words": [
|
||||
"autofetch",
|
||||
"Axonius",
|
||||
"displayplacer",
|
||||
"filelist",
|
||||
"gsettings",
|
||||
|
||||
@@ -56,10 +56,8 @@ When navigating from the Presenter View to the Launcher, the frontend has to do
|
||||
session lookup to discover the location (magic redirect in launcher base `+page.svelte`).
|
||||
Joining `event_session.event_location_id` into the presenter view/response would let the
|
||||
frontend pass the location directly in the Launcher URL without the extra lookup.
|
||||
- Backend: add `event_location_id` (and `event_location_id_random`) to the `event_presenter`
|
||||
view or API response
|
||||
- Frontend: add `event_location_id` to `ae_EventPresenter` type and `properties_to_save`;
|
||||
pass as `events__launcher_id` in `presenter_page_menu.svelte`
|
||||
- [x] Backend: added `event_location_id` (and `event_location_id_random`) to the `event_presenter` view or API response (2026-04-09)
|
||||
- [x] Frontend: updated `ae_EventPresenter` type and `properties_to_save`; now pass as `events__launcher_id` in `presenter_page_menu.svelte` (2026-04-09)
|
||||
|
||||
|
||||
|
||||
@@ -180,8 +178,7 @@ Full audit: `src/routes/events/[event_id]/(leads)/` and `src/lib/ae_events/ae_ev
|
||||
3 states: paid confirmation (priority=true), admin setup hint / "contact organizer" (no Stripe config),
|
||||
payment form. `client_reference_id=exhibit_id`. TypeScript declaration in `app.d.ts`.
|
||||
Stripe keys verified visible in `$ae_loc.site_cfg_json` on dev/demo site. Keys need validity check in Stripe dashboard.
|
||||
- [ ] **End-to-end smoke test** — sign in with shared passcode, scan/search a badge, add a lead,
|
||||
view detail, add notes/responses, export CSV; verify on mobile (Chrome/Safari PWA)
|
||||
- [x] **End-to-end smoke test (canceled by client)** — sign in with shared passcode, scan/search a badge, add a lead, view detail, add notes/responses, export CSV; canceled 2026-04-09.
|
||||
- [x] **Install prompt** — PWA install nudge implemented (2026-03-16). `pwa_install.svelte.ts`
|
||||
singleton captures `beforeinstallprompt` (Chrome/Android/desktop) and detects iOS Safari
|
||||
for manual "Share → Add to Home Screen" instructions. Reusable `element_pwa_install_prompt.svelte`
|
||||
|
||||
@@ -429,62 +429,64 @@ async function handle_search_refresh(params: any) {
|
||||
></Comp_badge_search>
|
||||
|
||||
{#if $ae_loc.trusted_access && $ae_loc.edit_mode}
|
||||
<div class="flex flex-row items-center justify-center">
|
||||
<div class="flex flex-row gap-1 items-center justify-center">
|
||||
{#if badges_loc.current.enable_add_badge_btn ?? true}
|
||||
<!-- <div class="flex justify-end px-4"> -->
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm preset-tonal-primary border-primary-500 border"
|
||||
class="btn btn-sm preset-tonal-warning border-warning-500 border"
|
||||
onclick={() => {
|
||||
show_create_badge_modal = true;
|
||||
create_badge_dialog?.showModal();
|
||||
}}>
|
||||
}}
|
||||
title="Manually create a badge for an attendee. Required fields: given name, family name, and email. Optional fields: badge type, affiliations, and any other custom fields defined in your event's badge templates."
|
||||
>
|
||||
<UserPlus size="1em" />
|
||||
Create Badge
|
||||
</button>
|
||||
<!-- </div> -->
|
||||
{/if}
|
||||
|
||||
{#if badges_loc.current.enable_upload_badge_li_btn ?? true}
|
||||
<!-- <div class="flex justify-end px-4 mt-2"> -->
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm ml-2"
|
||||
class="btn btn-sm preset-tonal-warning border-warning-500 border"
|
||||
onclick={() => {
|
||||
show_upload_badge_modal = true;
|
||||
upload_badge_dialog?.showModal();
|
||||
}}>
|
||||
}}
|
||||
title="Upload a CSV file to bulk create badges. Required columns: given_name, family_name, email. Optional columns: badge_type_code, affiliations, and any other custom fields defined in your event's badge templates."
|
||||
>
|
||||
<Upload size="1em" /> Upload Badge List
|
||||
</button>
|
||||
<!-- </div> -->
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if badges_loc.current.enable_mass_print ?? true}
|
||||
<div class="flex flex-row gap-1 items-center justify-center">
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/badges/print_list?printed_status=not_printed`}
|
||||
class="btn preset-filled-secondary">
|
||||
<Printer size="1em" /> Print Unprinted
|
||||
</a>
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/badges/print_list`}
|
||||
class="btn preset-filled-secondary">
|
||||
<Printer size="1em" /> Print All
|
||||
</a>
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/templates`}
|
||||
class="btn btn-tertiary">
|
||||
<FileText size="1em" /> Manage Templates
|
||||
</a>
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/badges/stats`}
|
||||
class="btn btn-tertiary">
|
||||
<BarChart2 size="1em" /> Badge Printing Stats
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
{#if $ae_loc.trusted_access && (badges_loc.current.enable_mass_print ?? true)}
|
||||
<div class="mt-2 flex gap-2 px-4">
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/badges/print_list?printed_status=not_printed`}
|
||||
class="btn preset-filled-secondary">
|
||||
<Printer size="1em" /> Print Unprinted
|
||||
</a>
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/badges/print_list`}
|
||||
class="btn preset-filled-secondary">
|
||||
<Printer size="1em" /> Print All
|
||||
</a>
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/templates`}
|
||||
class="btn btn-tertiary">
|
||||
<FileText size="1em" /> Manage Templates
|
||||
</a>
|
||||
<a
|
||||
href={`/events/${$events_slct?.event_id}/badges/stats`}
|
||||
class="btn btn-tertiary">
|
||||
<BarChart2 size="1em" /> Badge Printing Stats
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
|
||||
<!-- Create Badge modal — native <dialog> for focus trap + backdrop.
|
||||
Clicking the backdrop closes it. The form remounts each open so state is fresh. -->
|
||||
|
||||
@@ -169,7 +169,7 @@ function handle_qr_scan_result(event: {
|
||||
$events_sess.badges.show_form__scan = true;
|
||||
$events_sess.badges.qr_scan_start = true;
|
||||
}}
|
||||
class="btn btn-sm preset-tonal-primary border-primary-500 border">
|
||||
class="btn btn-sm preset-tonal-warning border-warning-500 border">
|
||||
<QrCode size="1em" class="mr-1" />
|
||||
QR Scan
|
||||
</button>
|
||||
@@ -181,7 +181,7 @@ function handle_qr_scan_result(event: {
|
||||
onclick={() => document.getElementById('badge_fulltext_search_qry_str')?.focus()}
|
||||
aria-label="Start here — focus search field"
|
||||
data-testid="badge-start-btn"
|
||||
class="btn btn-sm preset-filled-secondary-300-700"
|
||||
class="btn btn-sm preset-filled-secondary-300-700 font-semibold"
|
||||
class:opacity-30={!!badges_loc.current.fulltext_search_qry_str}
|
||||
>
|
||||
<StepForward size="1em" class="mx-1" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { Loader2 } from '@lucide/svelte';
|
||||
import type { key_val } from '$lib/stores/ae_stores';
|
||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
||||
import { ae_api } from '$lib/stores/ae_stores';
|
||||
import { ae_api, ae_loc } from '$lib/stores/ae_stores';
|
||||
import { api } from '$lib/api/api';
|
||||
|
||||
interface Props {
|
||||
@@ -23,7 +23,7 @@ let upload_status: string = $state('idle'); // idle, loading, processing, succes
|
||||
let upload_message: string = $state('');
|
||||
let processed_badges_count: number = $state(0);
|
||||
let total_badges_in_file: number = $state(0);
|
||||
let upload_mode: 'client_csv' | 'axonius_zoom' = $state('client_csv');
|
||||
let upload_mode: 'client_csv' | 'axonius_zoom' = $state('axonius_zoom');
|
||||
let begin_at: number | null = $state(null);
|
||||
let end_at: number | null = $state(null);
|
||||
let return_detail: boolean = $state(false);
|
||||
@@ -194,11 +194,11 @@ function handle_cancel() {
|
||||
|
||||
<form onsubmit={handle_upload} class="space-y-4 p-4">
|
||||
<h3 class="h3">Upload Badge List (CSV)</h3>
|
||||
<p>
|
||||
<!-- <p>
|
||||
Upload a CSV file containing badge data. The first row should be
|
||||
headers.
|
||||
</p>
|
||||
<p>
|
||||
</p> -->
|
||||
<!-- <p>
|
||||
Supported headers (case-sensitive): <code>full_name</code>,
|
||||
<code>name</code>,
|
||||
<code>professional_title</code>, <code>affiliations</code>,
|
||||
@@ -206,22 +206,25 @@ function handle_cancel() {
|
||||
<code>location</code>, <code>email</code>, <code>allow_tracking</code>
|
||||
(true/false or 1/0),
|
||||
<code>badge_type_code</code>.
|
||||
</p> -->
|
||||
<p>
|
||||
Upload the standard Axonius Zoom event tickets CSV export file here. This will trigger server-side processing to import the new and changed badges. This can take a few seconds to a few minutes.
|
||||
</p>
|
||||
|
||||
<fieldset class="space-y-2">
|
||||
<legend class="label"><span>Upload format</span></legend>
|
||||
<div class="flex gap-4 items-center">
|
||||
<label class="label flex items-center gap-2">
|
||||
<!-- <label class="label flex items-center gap-2">
|
||||
<input type="radio" name="upload_mode" value="client_csv" bind:group={upload_mode} />
|
||||
<span>Standard CSV (client-side parse)</span>
|
||||
</label>
|
||||
</label> -->
|
||||
<label class="label flex items-center gap-2">
|
||||
<input type="radio" name="upload_mode" value="axonius_zoom" bind:group={upload_mode} />
|
||||
<span>Axonius Zoom CSV (server import)</span>
|
||||
<span>Axonius Zoom CSV (event tickets)</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{#if upload_mode === 'axonius_zoom'}
|
||||
{#if $ae_loc.administrator_access && upload_mode === 'axonius_zoom'}
|
||||
<div class="grid grid-cols-3 gap-2 items-center">
|
||||
<input type="number" min="0" placeholder="begin_at (0)" bind:value={begin_at} class="input" />
|
||||
<input type="number" min="0" placeholder="end_at (20000)" bind:value={end_at} class="input" />
|
||||
|
||||
Reference in New Issue
Block a user