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": {
|
"settings": {
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"autofetch",
|
"autofetch",
|
||||||
|
"Axonius",
|
||||||
"displayplacer",
|
"displayplacer",
|
||||||
"filelist",
|
"filelist",
|
||||||
"gsettings",
|
"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`).
|
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
|
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.
|
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`
|
- [x] Backend: added `event_location_id` (and `event_location_id_random`) to the `event_presenter` view or API response (2026-04-09)
|
||||||
view or API response
|
- [x] Frontend: updated `ae_EventPresenter` type and `properties_to_save`; now pass as `events__launcher_id` in `presenter_page_menu.svelte` (2026-04-09)
|
||||||
- Frontend: add `event_location_id` to `ae_EventPresenter` type and `properties_to_save`;
|
|
||||||
pass as `events__launcher_id` in `presenter_page_menu.svelte`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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),
|
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`.
|
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.
|
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,
|
- [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.
|
||||||
view detail, add notes/responses, export CSV; verify on mobile (Chrome/Safari PWA)
|
|
||||||
- [x] **Install prompt** — PWA install nudge implemented (2026-03-16). `pwa_install.svelte.ts`
|
- [x] **Install prompt** — PWA install nudge implemented (2026-03-16). `pwa_install.svelte.ts`
|
||||||
singleton captures `beforeinstallprompt` (Chrome/Android/desktop) and detects iOS Safari
|
singleton captures `beforeinstallprompt` (Chrome/Android/desktop) and detects iOS Safari
|
||||||
for manual "Share → Add to Home Screen" instructions. Reusable `element_pwa_install_prompt.svelte`
|
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>
|
></Comp_badge_search>
|
||||||
|
|
||||||
{#if $ae_loc.trusted_access && $ae_loc.edit_mode}
|
{#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}
|
{#if badges_loc.current.enable_add_badge_btn ?? true}
|
||||||
<!-- <div class="flex justify-end px-4"> -->
|
|
||||||
<button
|
<button
|
||||||
type="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={() => {
|
onclick={() => {
|
||||||
show_create_badge_modal = true;
|
show_create_badge_modal = true;
|
||||||
create_badge_dialog?.showModal();
|
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" />
|
<UserPlus size="1em" />
|
||||||
Create Badge
|
Create Badge
|
||||||
</button>
|
</button>
|
||||||
<!-- </div> -->
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if badges_loc.current.enable_upload_badge_li_btn ?? true}
|
{#if badges_loc.current.enable_upload_badge_li_btn ?? true}
|
||||||
<!-- <div class="flex justify-end px-4 mt-2"> -->
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm ml-2"
|
class="btn btn-sm preset-tonal-warning border-warning-500 border"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
show_upload_badge_modal = true;
|
show_upload_badge_modal = true;
|
||||||
upload_badge_dialog?.showModal();
|
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
|
<Upload size="1em" /> Upload Badge List
|
||||||
</button>
|
</button>
|
||||||
<!-- </div> -->
|
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</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}
|
||||||
|
|
||||||
{#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.
|
<!-- Create Badge modal — native <dialog> for focus trap + backdrop.
|
||||||
Clicking the backdrop closes it. The form remounts each open so state is fresh. -->
|
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.show_form__scan = true;
|
||||||
$events_sess.badges.qr_scan_start = 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" />
|
<QrCode size="1em" class="mr-1" />
|
||||||
QR Scan
|
QR Scan
|
||||||
</button>
|
</button>
|
||||||
@@ -181,7 +181,7 @@ function handle_qr_scan_result(event: {
|
|||||||
onclick={() => document.getElementById('badge_fulltext_search_qry_str')?.focus()}
|
onclick={() => document.getElementById('badge_fulltext_search_qry_str')?.focus()}
|
||||||
aria-label="Start here — focus search field"
|
aria-label="Start here — focus search field"
|
||||||
data-testid="badge-start-btn"
|
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}
|
class:opacity-30={!!badges_loc.current.fulltext_search_qry_str}
|
||||||
>
|
>
|
||||||
<StepForward size="1em" class="mx-1" />
|
<StepForward size="1em" class="mx-1" />
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import { Loader2 } from '@lucide/svelte';
|
import { Loader2 } from '@lucide/svelte';
|
||||||
import type { key_val } from '$lib/stores/ae_stores';
|
import type { key_val } from '$lib/stores/ae_stores';
|
||||||
import { events_func } from '$lib/ae_events/ae_events_functions';
|
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';
|
import { api } from '$lib/api/api';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -23,7 +23,7 @@ let upload_status: string = $state('idle'); // idle, loading, processing, succes
|
|||||||
let upload_message: string = $state('');
|
let upload_message: string = $state('');
|
||||||
let processed_badges_count: number = $state(0);
|
let processed_badges_count: number = $state(0);
|
||||||
let total_badges_in_file: 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 begin_at: number | null = $state(null);
|
||||||
let end_at: number | null = $state(null);
|
let end_at: number | null = $state(null);
|
||||||
let return_detail: boolean = $state(false);
|
let return_detail: boolean = $state(false);
|
||||||
@@ -194,11 +194,11 @@ function handle_cancel() {
|
|||||||
|
|
||||||
<form onsubmit={handle_upload} class="space-y-4 p-4">
|
<form onsubmit={handle_upload} class="space-y-4 p-4">
|
||||||
<h3 class="h3">Upload Badge List (CSV)</h3>
|
<h3 class="h3">Upload Badge List (CSV)</h3>
|
||||||
<p>
|
<!-- <p>
|
||||||
Upload a CSV file containing badge data. The first row should be
|
Upload a CSV file containing badge data. The first row should be
|
||||||
headers.
|
headers.
|
||||||
</p>
|
</p> -->
|
||||||
<p>
|
<!-- <p>
|
||||||
Supported headers (case-sensitive): <code>full_name</code>,
|
Supported headers (case-sensitive): <code>full_name</code>,
|
||||||
<code>name</code>,
|
<code>name</code>,
|
||||||
<code>professional_title</code>, <code>affiliations</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>
|
<code>location</code>, <code>email</code>, <code>allow_tracking</code>
|
||||||
(true/false or 1/0),
|
(true/false or 1/0),
|
||||||
<code>badge_type_code</code>.
|
<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>
|
</p>
|
||||||
|
|
||||||
<fieldset class="space-y-2">
|
<fieldset class="space-y-2">
|
||||||
<legend class="label"><span>Upload format</span></legend>
|
<legend class="label"><span>Upload format</span></legend>
|
||||||
<div class="flex gap-4 items-center">
|
<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} />
|
<input type="radio" name="upload_mode" value="client_csv" bind:group={upload_mode} />
|
||||||
<span>Standard CSV (client-side parse)</span>
|
<span>Standard CSV (client-side parse)</span>
|
||||||
</label>
|
</label> -->
|
||||||
<label class="label flex items-center gap-2">
|
<label class="label flex items-center gap-2">
|
||||||
<input type="radio" name="upload_mode" value="axonius_zoom" bind:group={upload_mode} />
|
<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>
|
</label>
|
||||||
</div>
|
</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">
|
<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="begin_at (0)" bind:value={begin_at} class="input" />
|
||||||
<input type="number" min="0" placeholder="end_at (20000)" bind:value={end_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