Making custom changes just for Axonius badge printing next week

This commit is contained in:
Scott Idem
2026-04-07 14:59:23 -04:00
parent 988ba75df3
commit 93fea0d165
3 changed files with 106 additions and 12 deletions

View File

@@ -17,6 +17,7 @@
/* --- Badge front --- */
[data-layout='badge_3.5x5.5_pvc'] .badge_front {
min-width: 3.5in;
width: 3.5in;
min-height: 5.5in;
max-height: 5.5in;
@@ -32,6 +33,7 @@
padding: 0;
gap: 0;
min-height: 0;
min-width: 3.5in;
width: 3.5in;
max-width: 3.5in;
}

View File

@@ -29,8 +29,9 @@ import { events_func } from '$lib/ae_events/ae_events_functions';
import Comp_badge_search from './ae_comp__badge_search.svelte';
import Comp_badge_obj_li from './ae_comp__badge_obj_li.svelte';
import Comp_badge_create_form from './ae_comp__badge_create_form.svelte';
import Comp_badge_upload_form from './ae_comp__badge_upload_form.svelte';
import { LoaderCircle, UserPlus } from '@lucide/svelte';
import { LoaderCircle, UserPlus, Printer, Upload, FileText, BarChart2 } from '@lucide/svelte';
// Load templates for this event so the create form can show the selector and
// derive badge_type_code_li from whichever template the user picks.
@@ -61,6 +62,7 @@ let lq__badge_template_li = $derived(
let show_create_badge_modal: boolean = $state(false);
let show_upload_badge_modal: boolean = $state(false);
let create_badge_dialog: HTMLDialogElement | undefined = $state();
let upload_badge_dialog: HTMLDialogElement | undefined = $state();
let event_badge_id_li: Array<string> = $state([]);
let search_debounce_timer: any = null;
@@ -400,6 +402,45 @@ async function handle_search_refresh(params: any) {
</div>
{/if}
{#if $ae_loc.trusted_access && (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"
onclick={() => {
show_upload_badge_modal = true;
upload_badge_dialog?.showModal();
}}>
<Upload size="1em" /> Upload Badge List
</button>
</div>
{/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. -->
<dialog
@@ -428,6 +469,38 @@ async function handle_search_refresh(params: any) {
{/if}
</dialog>
<!-- Upload Badge List modal -->
<dialog
bind:this={upload_badge_dialog}
class="w-full max-w-lg rounded-xl border border-gray-200 bg-white p-0 shadow-2xl dark:border-gray-700 dark:bg-gray-900"
onclick={(e) => {
if (e.target === upload_badge_dialog) {
upload_badge_dialog?.close();
show_upload_badge_modal = false;
}
}}
onclose={() => {
show_upload_badge_modal = false;
}}>
<div class="border-surface-200-800 border-b px-5 py-3">
<h2 class="text-surface-900-50 text-base font-semibold">Upload Badge List</h2>
</div>
{#if show_upload_badge_modal}
<Comp_badge_upload_form
event_id={$events_slct?.event_id ?? ''}
onsuccess={() => {
upload_badge_dialog?.close();
show_upload_badge_modal = false;
badges_loc.current.search_version = (badges_loc.current.search_version ?? 0) + 1;
badges_loc.current.qry__remote_first = true;
}}
oncancel={() => {
upload_badge_dialog?.close();
show_upload_badge_modal = false;
}} />
{/if}
</dialog>
{#if $events_sess?.badges?.search_status === 'loading' && event_badge_id_li.length === 0}
<div
class="flex flex-col items-center justify-center p-10 text-center opacity-50">

View File

@@ -321,16 +321,30 @@ let fit_heights = $derived.by(() => {
let base: Record<string, string>;
if (layout === 'badge_3.5x5.5_pvc') {
// 3.5" × 5.5" PVC card — single-sided, compact
// Modified for Axonius 2026
base = {
grp_name_title: '1.6in',
grp_name_title_flex: 'around',
name: '1.4in',
title: '0.55in',
grp_aff_loc: '1.5in',
grp_aff_loc_flex: 'around',
affiliations: '0.75in',
location: '0.75in'
title: '0.4in',
grp_aff_loc: '.4in',
grp_aff_loc_flex: 'end',
affiliations: '0.4in',
location: '0.0in'
};
// Looks pretty good if all the common fields are showing
// base = {
// grp_name_title: '1.6in',
// grp_name_title_flex: 'around',
// name: '1.4in',
// title: '0.55in',
// grp_aff_loc: '1.5in',
// grp_aff_loc_flex: 'around',
// affiliations: '0.75in',
// location: '0.75in'
// };
} else if (layout === 'badge_4x5_fanfold') {
// 4" × 5" fanfold — slightly taller, duplex
base = {
@@ -576,6 +590,7 @@ const code_to_icon: {
group relative m-0
flex max-h-[6.0in]
min-h-[6.0in]
min-w-3.5
w-[4in]
max-w-fit
flex-col
@@ -644,7 +659,9 @@ const code_to_icon: {
flex-col
items-center
justify-end overflow-clip
p-0 px-1
p-0 px-8 pb-1
text-white
gap-0
">
<!--
person_name container: explicit height from fit_heights so Element_fit_text
@@ -655,6 +672,7 @@ const code_to_icon: {
class="person_name
m-0 flex
flex-col
gap-2
overflow-hidden p-0
hover:outline-2 hover:outline-gray-500/75 hover:outline-dashed
"
@@ -674,11 +692,12 @@ const code_to_icon: {
manual_size={font_size_name ?? null}
height={fit_heights.name}
class="full_name_override_all leading-none hover:bg-pink-100/50">
<!-- class:name_pad_short
class:name_pad_mid
class:name_pad_long -->
<div
class="full_name_override"
class:name_pad_short
class:name_pad_mid
class:name_pad_long
style="text-align: {align_name};">
{#if display_name}
{display_name.trim()}
@@ -698,7 +717,7 @@ const code_to_icon: {
max={38}
manual_size={font_size_title ?? null}
height={fit_heights.title}
class="professional_title leading-none italic hover:bg-pink-100/50">
class="professional_title leading-none hover:bg-pink-100/50">
<div style="text-align: {align_title};">{@html display_title}</div>
</Element_fit_text>
{/if}
@@ -730,7 +749,7 @@ const code_to_icon: {
max={40}
manual_size={font_size_affiliations ?? null}
height={fit_heights.affiliations}
class="affiliations leading-none hover:bg-pink-100/50">
class="affiliations leading-none italic hover:bg-pink-100/50">
<div style="text-align: {align_affiliations};">{@html display_affiliations}</div>
</Element_fit_text>
{/if}