Prettier for Events as a whole. Everything else under that primary directory.

This commit is contained in:
Scott Idem
2026-03-24 12:16:44 -04:00
parent 6e67534454
commit 6018a94499
11 changed files with 1459 additions and 1465 deletions

View File

@@ -1,34 +1,34 @@
<script lang="ts"> <script lang="ts">
// console.log(`ae_events_pres_mgmt +page data:`, data); // console.log(`ae_events_pres_mgmt +page data:`, data);
// console.log(`ae_events_pres_mgmt Data Params:`, data.url.searchParams.get('event_id')); // console.log(`ae_events_pres_mgmt Data Params:`, data.url.searchParams.get('event_id'));
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { db_events } from '$lib/ae_events/db_events'; import { db_events } from '$lib/ae_events/db_events';
import { import {
ae_loc, ae_loc,
ae_sess, ae_sess,
ae_api, ae_api,
slct, slct,
slct_trigger slct_trigger
} from '$lib/stores/ae_stores'; } from '$lib/stores/ae_stores';
// import { // import {
// events_loc, // events_loc,
// events_slct, // events_slct,
// events_trigger // events_trigger
// } from '$lib/stores/ae_events_stores'; // } from '$lib/stores/ae_events_stores';
import { ae_util } from '$lib/ae_utils/ae_utils'; import { ae_util } from '$lib/ae_utils/ae_utils';
import { CalendarDays, LoaderCircle, TriangleAlert } from '@lucide/svelte'; import { CalendarDays, LoaderCircle, TriangleAlert } from '@lucide/svelte';
import { page } from '$app/stores'; import { page } from '$app/stores';
interface Props { interface Props {
data: any; data: any;
} }
let { data }: Props = $props(); let { data }: Props = $props();
let lq__event_obj_li = $derived( let lq__event_obj_li = $derived(
liveQuery(async () => { liveQuery(async () => {
const account_id = $page.data.account_id; const account_id = $page.data.account_id;
if (!account_id) return []; if (!account_id) return [];
@@ -39,35 +39,35 @@
.sortBy('start_datetime'); .sortBy('start_datetime');
return results; return results;
}) })
); );
let items_per_page = 10; let items_per_page = 10;
let current_page = $state(1); let current_page = $state(1);
let paginated_events = $derived(() => { let paginated_events = $derived(() => {
const start = (current_page - 1) * items_per_page; const start = (current_page - 1) * items_per_page;
const end = start + items_per_page; const end = start + items_per_page;
return $lq__event_obj_li?.slice(start, end) ?? []; return $lq__event_obj_li?.slice(start, end) ?? [];
}); });
let total_events = $derived($lq__event_obj_li?.length ?? 0); let total_events = $derived($lq__event_obj_li?.length ?? 0);
let total_pages = $derived(Math.ceil(total_events / items_per_page)); let total_pages = $derived(Math.ceil(total_events / items_per_page));
function next_page() { function next_page() {
if (current_page < total_pages) { if (current_page < total_pages) {
current_page++; current_page++;
} }
} }
function prev_page() { function prev_page() {
if (current_page > 1) { if (current_page > 1) {
current_page--; current_page--;
} }
} }
onMount(() => { onMount(() => {
// console.log('Events - Presentation Management: +page.svelte'); // console.log('Events - Presentation Management: +page.svelte');
}); });
</script> </script>
<h2 class="h3"> <h2 class="h3">
@@ -119,12 +119,11 @@
{#each $lq__event_obj_li as event_obj (event_obj.event_id)} {#each $lq__event_obj_li as event_obj (event_obj.event_id)}
<li class:dim={event_obj?.hide}> <li class:dim={event_obj?.hide}>
<span <span
class="w-full flex flex-row gap-1 items-center justify-between" class="flex w-full flex-row items-center justify-between gap-1">
>
<!-- We do not want to show events more than 8 months old. --> <!-- We do not want to show events more than 8 months old. -->
{#if new Date(event_obj.start_datetime ?? '').getTime() > new Date().getTime() - 1000 * 60 * 60 * 24 * 30 * 8 || $ae_loc.trusted_access} {#if new Date(event_obj.start_datetime ?? '').getTime() > new Date().getTime() - 1000 * 60 * 60 * 24 * 30 * 8 || $ae_loc.trusted_access}
<span> <span>
<CalendarDays size="1em" class="inline mx-1" /> <CalendarDays size="1em" class="mx-1 inline" />
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
event_obj.start_datetime, event_obj.start_datetime,
'date_long' 'date_long'
@@ -135,7 +134,7 @@
</strong> </strong>
{:else} {:else}
<span> <span>
<CalendarDays size="1em" class="inline mx-1" /> <CalendarDays size="1em" class="mx-1 inline" />
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
event_obj.start_datetime, event_obj.start_datetime,
'date_long' 'date_long'
@@ -148,36 +147,31 @@
</span> </span>
<span <span
class="w-full flex flex-row gap-1 items-center justify-evenly" class="flex w-full flex-row items-center justify-evenly gap-1">
>
{#if $ae_loc.authenticated_access} {#if $ae_loc.authenticated_access}
<a <a
data-sveltekit-reload data-sveltekit-reload
href="/events/{event_obj.event_id}" href="/events/{event_obj.event_id}"
class="btn btn-sm preset-tonal-secondary border border-secondary-500 hover:preset-filled-secondary-500" class="btn btn-sm preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 border"
title="Presentation Management for {event_obj.name}" title="Presentation Management for {event_obj.name}">
>
Pres Mgmt Pres Mgmt
</a> </a>
<a <a
href="/events/{event_obj.event_id}/badges" href="/events/{event_obj.event_id}/badges"
class="btn btn-sm preset-tonal-secondary border border-secondary-500 hover:preset-filled-secondary-500" class="btn btn-sm preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 border"
title="Badge Management for {event_obj.name}" title="Badge Management for {event_obj.name}">
>
Badges Badges
</a> </a>
<a <a
href="/events/{event_obj.event_id}/leads" href="/events/{event_obj.event_id}/leads"
class="btn btn-sm preset-tonal-secondary border border-secondary-500 hover:preset-filled-secondary-500" class="btn btn-sm preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 border"
title="Exhibitor Leads for {event_obj.name}" title="Exhibitor Leads for {event_obj.name}">
>
Leads Leads
</a> </a>
<a <a
href="/events/{event_obj.event_id}/launcher" href="/events/{event_obj.event_id}/launcher"
class="btn btn-sm preset-tonal-secondary border border-secondary-500 hover:preset-filled-secondary-500" class="btn btn-sm preset-tonal-secondary border-secondary-500 hover:preset-filled-secondary-500 border"
title="Event Launcher for {event_obj.name}" title="Event Launcher for {event_obj.name}">
>
Launcher Launcher
</a> </a>
{/if} {/if}
@@ -185,9 +179,8 @@
<a <a
data-sveltekit-reload data-sveltekit-reload
href="/event/{event_obj.event_id}" href="/event/{event_obj.event_id}"
class="btn btn-sm preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500" class="btn btn-sm preset-tonal-warning border-warning-500 hover:preset-filled-warning-500 border"
title="Legacy Presentation Management System (Flask/Svelte) for {event_obj.name}" title="Legacy Presentation Management System (Flask/Svelte) for {event_obj.name}">
>
Legacy Pres Mgmt Legacy Pres Mgmt
</a> </a>
{/if} {/if}
@@ -195,31 +188,29 @@
</li> </li>
{/each} {/each}
</ul> </ul>
<div class="flex justify-center items-center space-x-4 mt-4"> <div class="mt-4 flex items-center justify-center space-x-4">
<button <button
type="button" type="button"
class="btn btn-sm" class="btn btn-sm"
onclick={prev_page} onclick={prev_page}
disabled={current_page === 1}>Previous</button disabled={current_page === 1}>Previous</button>
>
<span>Page {current_page} of {total_pages}</span> <span>Page {current_page} of {total_pages}</span>
<button <button
type="button" type="button"
class="btn btn-sm" class="btn btn-sm"
onclick={next_page} onclick={next_page}
disabled={current_page === total_pages}>Next</button disabled={current_page === total_pages}>Next</button>
>
</div> </div>
{:else} {:else}
<div class="flex flex-row items-center justify-center"> <div class="flex flex-row items-center justify-center">
<TriangleAlert size="1em" class="inline text-error-500 mx-1" /> <TriangleAlert size="1em" class="text-error-500 mx-1 inline" />
<span>No events available to display.</span> <span>No events available to display.</span>
<TriangleAlert size="1em" class="inline text-error-500 mx-1" /> <TriangleAlert size="1em" class="text-error-500 mx-1 inline" />
</div> </div>
{/if} {/if}
{:else} {:else}
<div class="flex flex-row items-center justify-center"> <div class="flex flex-row items-center justify-center">
<LoaderCircle size="1em" class="inline animate-spin mx-1" /> <LoaderCircle size="1em" class="mx-1 inline animate-spin" />
<span>Loading...</span> <span>Loading...</span>
</div> </div>
{/if} {/if}

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
// Exports // Exports
container_class_li?: string | Array<string>; container_class_li?: string | Array<string>;
event_file_id_random_li?: Array<string>; event_file_id_random_li?: Array<string>;
@@ -14,9 +14,9 @@
show_session_fields?: boolean; show_session_fields?: boolean;
hide_session_code?: boolean; hide_session_code?: boolean;
log_lvl?: number; log_lvl?: number;
} }
let { let {
container_class_li = [], container_class_li = [],
event_file_id_random_li = [], event_file_id_random_li = [],
lq__event_file_obj_li, lq__event_file_obj_li,
@@ -28,17 +28,17 @@
show_session_fields = false, show_session_fields = false,
hide_session_code = false, hide_session_code = false,
log_lvl = $bindable(0) log_lvl = $bindable(0)
}: Props = $props(); }: Props = $props();
// Imports // Imports
// import { liveQuery } from 'dexie'; // import { liveQuery } from 'dexie';
import type { key_val } from '$lib/stores/ae_stores'; import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils'; import { ae_util } from '$lib/ae_utils/ae_utils';
// import { api } from '$lib/api/api'; // import { api } from '$lib/api/api';
// import { db_events } from '$lib/ae_events/db_events'; // import { db_events } from '$lib/ae_events/db_events';
import { import {
ae_snip, ae_snip,
ae_loc, ae_loc,
ae_sess, ae_sess,
@@ -46,52 +46,70 @@
ae_trig, ae_trig,
slct, slct,
slct_trigger slct_trigger
} from '$lib/stores/ae_stores'; } from '$lib/stores/ae_stores';
// import { events_loc, events_sess, events_slct, events_trigger, events_trig_kv } from '$lib/stores/ae_events_stores'; // import { events_loc, events_sess, events_slct, events_trigger, events_trig_kv } from '$lib/stores/ae_events_stores';
// import { events_func } from '$lib/ae_events/ae_events_functions'; // import { events_func } from '$lib/ae_events/ae_events_functions';
import MyClipboard from '$lib/app_components/e_app_clipboard.svelte'; import MyClipboard from '$lib/app_components/e_app_clipboard.svelte';
import AE_Comp_Hosted_Files_Download_Button from '$lib/ae_core/ae_comp__hosted_files_download_button.svelte'; import AE_Comp_Hosted_Files_Download_Button from '$lib/ae_core/ae_comp__hosted_files_download_button.svelte';
import { Check, Download, FileImage, FileSpreadsheet, ListOrdered, LoaderCircle, Presentation, ToggleLeft, ToggleRight, TriangleAlert, User } from '@lucide/svelte'; import {
// export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher' Check,
Download,
FileImage,
FileSpreadsheet,
ListOrdered,
LoaderCircle,
Presentation,
ToggleLeft,
ToggleRight,
TriangleAlert,
User
} from '@lucide/svelte';
// export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher'
// Variables // Variables
let ae_promises: key_val = $state({}); let ae_promises: key_val = $state({});
// *** Functions and Logic // *** Functions and Logic
// Define the list of unacceptable characters if not using the default. // Define the list of unacceptable characters if not using the default.
// const unacceptable_chars = /[ <>:"/\\|?*]/g; // const unacceptable_chars = /[ <>:"/\\|?*]/g;
let horiz_scroll_warning: boolean = $state(false); let horiz_scroll_warning: boolean = $state(false);
let horiz_check_element: HTMLElement | null = $state(null); let horiz_check_element: HTMLElement | null = $state(null);
// PDF → Image conversion state (keyed by event_file_id) // PDF → Image conversion state (keyed by event_file_id)
// WHY: Poster sessions display files in the Launcher modal via <img> tag — PDFs can't render there. // WHY: Poster sessions display files in the Launcher modal via <img> tag — PDFs can't render there.
// Presenters upload PDFs which must be converted server-side to high-res webp images. // Presenters upload PDFs which must be converted server-side to high-res webp images.
// Button is only shown in edit_mode for PDF files linked to a poster-type session. // Button is only shown in edit_mode for PDF files linked to a poster-type session.
// Backend: /v3/action/hosted_file/{id}/convert_file runs pdf2image (3840px wide, first page only) // Backend: /v3/action/hosted_file/{id}/convert_file runs pdf2image (3840px wide, first page only)
// and saves the result as a new hosted_file record linked to the same parent object. // and saves the result as a new hosted_file record linked to the same parent object.
type ConvertStatus = 'idle' | 'converting' | 'done' | 'error'; type ConvertStatus = 'idle' | 'converting' | 'done' | 'error';
let convert_status_kv: Record<string, ConvertStatus> = $state({}); let convert_status_kv: Record<string, ConvertStatus> = $state({});
let convert_result_kv: Record<string, any> = $state({}); let convert_result_kv: Record<string, any> = $state({});
async function handle_convert_pdf_to_image(event_file_obj: any) { async function handle_convert_pdf_to_image(event_file_obj: any) {
const file_id = event_file_obj.event_file_id; const file_id = event_file_obj.event_file_id;
convert_status_kv[file_id] = 'converting'; convert_status_kv[file_id] = 'converting';
try { try {
// Link the new image to the most specific parent available // Link the new image to the most specific parent available
const link_to_type = event_file_obj.event_session_id ? 'event_session' const link_to_type = event_file_obj.event_session_id
: event_file_obj.event_presentation_id ? 'event_presentation' ? 'event_session'
: event_file_obj.event_presentation_id
? 'event_presentation'
: 'event'; : 'event';
const link_to_id = event_file_obj.event_session_id const link_to_id =
|| event_file_obj.event_presentation_id event_file_obj.event_session_id ||
|| event_file_obj.event_id; event_file_obj.event_presentation_id ||
const filename_no_ext = (event_file_obj.filename ?? 'poster_image').replace(/\.pdf$/i, ''); event_file_obj.event_id;
const url = `${$ae_api.base_url}/v3/hosted_file/${event_file_obj.hosted_file_id}/convert_file` const filename_no_ext = (
+ `?link_to_type=${encodeURIComponent(link_to_type)}` event_file_obj.filename ?? 'poster_image'
+ `&link_to_id=${encodeURIComponent(link_to_id)}` ).replace(/\.pdf$/i, '');
+ `&filename_no_ext=${encodeURIComponent(filename_no_ext)}` const url =
+ `&to_type=webp`; `${$ae_api.base_url}/v3/hosted_file/${event_file_obj.hosted_file_id}/convert_file` +
`?link_to_type=${encodeURIComponent(link_to_type)}` +
`&link_to_id=${encodeURIComponent(link_to_id)}` +
`&filename_no_ext=${encodeURIComponent(filename_no_ext)}` +
`&to_type=webp`;
const resp = await fetch(url, { const resp = await fetch(url, {
headers: { headers: {
'x-aether-api-key': $ae_api.api_secret_key, 'x-aether-api-key': $ae_api.api_secret_key,
@@ -110,10 +128,10 @@
console.error('[convert_pdf] Fetch failed:', err); console.error('[convert_pdf] Fetch failed:', err);
convert_status_kv[file_id] = 'error'; convert_status_kv[file_id] = 'error';
} }
} }
// Check if element is scrolling horizontally // Check if element is scrolling horizontally
$effect(() => { $effect(() => {
if ( if (
horiz_check_element && horiz_check_element &&
horiz_check_element.scrollWidth > horiz_check_element.offsetWidth horiz_check_element.scrollWidth > horiz_check_element.offsetWidth
@@ -124,9 +142,9 @@
horiz_scroll_warning = false; horiz_scroll_warning = false;
// console.log('Element fits within the container. No horizontal scrolling.', horiz_check_element); // console.log('Element fits within the container. No horizontal scrolling.', horiz_check_element);
} }
}); });
function generate_file_export_csv(ae_obj_li: any[]) { function generate_file_export_csv(ae_obj_li: any[]) {
console.log(`*** generate_file_export_csv() ***`, ae_obj_li); console.log(`*** generate_file_export_csv() ***`, ae_obj_li);
// We need to create a list with the column names and then a list of lists with the data. // We need to create a list with the column names and then a list of lists with the data.
@@ -165,7 +183,9 @@
csv_row.push(ae_obj_li[i].extension ? ae_obj_li[i].extension : ''); csv_row.push(ae_obj_li[i].extension ? ae_obj_li[i].extension : '');
csv_row.push( csv_row.push(
ae_obj_li[i].file_size || ae_obj_li[i].hosted_file_size ae_obj_li[i].file_size || ae_obj_li[i].hosted_file_size
? ae_util.format_bytes(ae_obj_li[i].file_size || ae_obj_li[i].hosted_file_size) ? ae_util.format_bytes(
ae_obj_li[i].file_size || ae_obj_li[i].hosted_file_size
)
: '' : ''
); );
csv_row.push(ae_obj_li[i].hash_sha256?.slice(0, 10) ?? 'N/A'); csv_row.push(ae_obj_li[i].hash_sha256?.slice(0, 10) ?? 'N/A');
@@ -187,9 +207,7 @@
); );
csv_row.push( csv_row.push(
ae_obj_li[i].event_session_id ae_obj_li[i].event_session_id ? ae_obj_li[i].event_session_id : ''
? ae_obj_li[i].event_session_id
: ''
); );
csv_row.push( csv_row.push(
ae_obj_li[i].event_session_code ae_obj_li[i].event_session_code
@@ -281,34 +299,30 @@
download_link.click(); download_link.click();
return csv_data; return csv_data;
} }
</script> </script>
<section <section
class:border-r-2={horiz_scroll_warning} class:border-r-2={horiz_scroll_warning}
class:border-dashed={horiz_scroll_warning} class:border-dashed={horiz_scroll_warning}
class:border-warning-900-100={horiz_scroll_warning} class:border-warning-900-100={horiz_scroll_warning}
class="ae_comp event_file_obj_tbl {container_class_li} container overflow-auto max-w-screen" class="ae_comp event_file_obj_tbl {container_class_li} container max-w-screen overflow-auto">
>
<!-- {#if event_file_id_random_li && $lq_kv__event_file_obj_li && $lq_kv__event_file_obj_li?.length > 0 && $lq_kv__event_file_obj_li?.length == event_file_id_random_li?.length} --> <!-- {#if event_file_id_random_li && $lq_kv__event_file_obj_li && $lq_kv__event_file_obj_li?.length > 0 && $lq_kv__event_file_obj_li?.length == event_file_id_random_li?.length} -->
{#if $lq__event_file_obj_li && $lq__event_file_obj_li?.length} {#if $lq__event_file_obj_li && $lq__event_file_obj_li?.length}
<div <div
bind:this={horiz_check_element} bind:this={horiz_check_element}
id="tbl_container" id="tbl_container"
class="space-y-2 pb-8" class="space-y-2 pb-8">
>
<header <header
class="flex flex-row flex-wrap gap-1 items-center justify-between" class="flex flex-row flex-wrap items-center justify-between gap-1">
>
<h2 class="h3"> <h2 class="h3">
<span class="text-base"> Results: </span> <span class="text-base"> Results: </span>
{#if $lq__event_file_obj_li.length} {#if $lq__event_file_obj_li.length}
<span <span
class="text-3xl font-bold preset-filled-success-100-900 px-4 rounded-lg" class="preset-filled-success-100-900 rounded-lg px-4 text-3xl font-bold"
title="Count {$lq__event_file_obj_li.length ?? title="Count {$lq__event_file_obj_li.length ??
'None'}" 'None'}">
>
<ListOrdered size="1em" class="mx-4" /> <ListOrdered size="1em" class="mx-4" />
{$lq__event_file_obj_li.length ?? 'None'}&times; {$lq__event_file_obj_li.length ?? 'None'}&times;
</span> </span>
@@ -316,12 +330,11 @@
</h2> </h2>
<div <div
class="flex flex-row flex-wrap gap-1 items-center justify-end" class="flex flex-row flex-wrap items-center justify-end gap-1"
class:hidden={!$ae_loc.edit_mode} class:hidden={!$ae_loc.edit_mode}>
>
<button <button
type="button" type="button"
class="btn btn-sm preset-tonal-warning border border-warning-500 mb-1 generate_csv_btn" class="btn btn-sm preset-tonal-warning border-warning-500 generate_csv_btn mb-1 border"
onclick={() => { onclick={() => {
if ( if (
!confirm( !confirm(
@@ -335,8 +348,7 @@
$lq__event_file_obj_li $lq__event_file_obj_li
); );
console.log('CSV Data:', csv_data); console.log('CSV Data:', csv_data);
}} }}>
>
<FileSpreadsheet size="1em" class="mx-1" /> <FileSpreadsheet size="1em" class="mx-1" />
Export Files CSV Export Files CSV
</button> </button>
@@ -351,8 +363,7 @@
class="btn btn-sm {show_session_fields class="btn btn-sm {show_session_fields
? 'ae_btn_surface' ? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}" : 'ae_btn_surface_outlined'}"
title="Show or hide the session-related column fields." title="Show or hide the session-related column fields.">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
Showing Session Fields Showing Session Fields
</button> </button>
@@ -365,8 +376,7 @@
class="btn btn-sm {show_session_fields class="btn btn-sm {show_session_fields
? 'ae_btn_surface' ? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}" : 'ae_btn_surface_outlined'}"
title="Show or hide the session-related column fields." title="Show or hide the session-related column fields.">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
Show Session Fields Show Session Fields
</button> </button>
@@ -380,8 +390,7 @@
hide_session_code = true; hide_session_code = true;
}} }}
class="btn btn-sm ae_btn_surface" class="btn btn-sm ae_btn_surface"
title="Hide the session code column from view. Currently showing the Session Code column." title="Hide the session code column from view. Currently showing the Session Code column.">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
Showing Session Code Showing Session Code
</button> </button>
@@ -392,8 +401,7 @@
hide_session_code = false; hide_session_code = false;
}} }}
class="btn btn-sm ae_btn_surface_outlined" class="btn btn-sm ae_btn_surface_outlined"
title="Show the session code column. Currently hiding the Session Code column from view." title="Show the session code column. Currently hiding the Session Code column from view.">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
Show Session Code Show Session Code
</button> </button>
@@ -409,8 +417,7 @@
class="btn btn-sm {show_presentation_fields class="btn btn-sm {show_presentation_fields
? 'ae_btn_surface' ? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}" : 'ae_btn_surface_outlined'}"
title="Show or hide the extra presentation-related column fields." title="Show or hide the extra presentation-related column fields.">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
Showing Presentation Fields Showing Presentation Fields
</button> </button>
@@ -424,8 +431,7 @@
class="btn btn-sm {show_presentation_fields class="btn btn-sm {show_presentation_fields
? 'ae_btn_surface' ? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}" : 'ae_btn_surface_outlined'}"
title="Show or hide the extra presentation-related column fields." title="Show or hide the extra presentation-related column fields.">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
Show Presentation Fields Show Presentation Fields
</button> </button>
@@ -434,8 +440,7 @@
</header> </header>
<table <table
class="table table-auto table-striped w-full text-xs lg:text-sm" class="table-striped table w-full table-auto text-xs lg:text-sm">
>
<thead class=""> <thead class="">
<tr> <tr>
<th class="px-4 py-2"> <th class="px-4 py-2">
@@ -444,8 +449,7 @@
</th> </th>
<th <th
class="px-4 py-2" class="px-4 py-2"
class:hidden={!show_direct_download} class:hidden={!show_direct_download}>
>
Link Link
</th> </th>
<th class="px-4 py-2">Size</th> <th class="px-4 py-2">Size</th>
@@ -456,8 +460,7 @@
{#if show_session_fields} {#if show_session_fields}
<th <th
class="px-4 py-2" class="px-4 py-2"
class:hidden={hide_session_code} class:hidden={hide_session_code}>
>
Code Code
</th> </th>
<th class="px-4 py-2"> Session </th> <th class="px-4 py-2"> Session </th>
@@ -482,41 +485,58 @@
show_divider={true} show_divider={true}
{show_direct_download} {show_direct_download}
max_filename={50} max_filename={50}
classes="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500 min-w-72" classes="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500 min-w-72" />
/>
<!-- PDF → webp convert button: only for poster sessions in edit mode --> <!-- PDF → webp convert button: only for poster sessions in edit mode -->
{#if $ae_loc.edit_mode && event_file_obj?.extension === 'pdf' && event_file_obj?.event_session_type_code === 'poster'} {#if $ae_loc.edit_mode && event_file_obj?.extension === 'pdf' && event_file_obj?.event_session_type_code === 'poster'}
<div class="mt-1"> <div class="mt-1">
{#if !convert_status_kv[event_file_obj.event_file_id] || convert_status_kv[event_file_obj.event_file_id] === 'idle'} {#if !convert_status_kv[event_file_obj.event_file_id] || convert_status_kv[event_file_obj.event_file_id] === 'idle'}
<button <button
type="button" type="button"
class="btn btn-sm preset-tonal-warning border border-warning-500" class="btn btn-sm preset-tonal-warning border-warning-500 border"
title="Convert this PDF to a high-res webp image for use in the Launcher poster display." title="Convert this PDF to a high-res webp image for use in the Launcher poster display."
onclick={() => handle_convert_pdf_to_image(event_file_obj)} onclick={() =>
> handle_convert_pdf_to_image(
<FileImage size="1em" class="mx-1" /> event_file_obj
)}>
<FileImage
size="1em"
class="mx-1" />
Convert PDF → Image Convert PDF → Image
</button> </button>
{:else if convert_status_kv[event_file_obj.event_file_id] === 'converting'} {:else if convert_status_kv[event_file_obj.event_file_id] === 'converting'}
<span class="btn btn-sm preset-tonal-surface opacity-60 cursor-wait"> <span
<LoaderCircle size="1em" class="mx-1 animate-spin" /> class="btn btn-sm preset-tonal-surface cursor-wait opacity-60">
<LoaderCircle
size="1em"
class="mx-1 animate-spin" />
Converting… Converting…
</span> </span>
{:else if convert_status_kv[event_file_obj.event_file_id] === 'done'} {:else if convert_status_kv[event_file_obj.event_file_id] === 'done'}
<span class="btn btn-sm preset-tonal-success" title="Conversion complete. New webp hosted_file created: {convert_result_kv[event_file_obj.event_file_id]?.filename ?? ''}"> <span
<Check size="1em" class="mx-1" /> class="btn btn-sm preset-tonal-success"
Done — {convert_result_kv[event_file_obj.event_file_id]?.filename ?? 'image created'} title="Conversion complete. New webp hosted_file created: {convert_result_kv[
event_file_obj.event_file_id
]?.filename ?? ''}">
<Check
size="1em"
class="mx-1" />
Done — {convert_result_kv[
event_file_obj.event_file_id
]?.filename ?? 'image created'}
</span> </span>
{:else if convert_status_kv[event_file_obj.event_file_id] === 'error'} {:else if convert_status_kv[event_file_obj.event_file_id] === 'error'}
<button <button
type="button" type="button"
class="btn btn-sm preset-tonal-error border border-error-500" class="btn btn-sm preset-tonal-error border-error-500 border"
title="Conversion failed. Click to retry." title="Conversion failed. Click to retry."
onclick={() => { onclick={() => {
convert_status_kv[event_file_obj.event_file_id] = 'idle'; convert_status_kv[
}} event_file_obj.event_file_id
> ] = 'idle';
<TriangleAlert size="1em" class="mx-1" /> }}>
<TriangleAlert
size="1em"
class="mx-1" />
Failed — Retry? Failed — Retry?
</button> </button>
{/if} {/if}
@@ -524,23 +544,20 @@
{/if} {/if}
</td> </td>
<td <td
class="px-4 py-2 flex flex-col gap-0.5" class="flex flex-col gap-0.5 px-4 py-2"
class:hidden={!show_direct_download} class:hidden={!show_direct_download}>
>
<div <div
class:hidden={!show_direct_download} class:hidden={!show_direct_download}
class="flex flex-row gap-0.5" class="flex flex-row gap-0.5">
> <span class="w-32 text-xs text-gray-500">
<span class="text-xs text-gray-500 w-32">
Original: Original:
</span> </span>
<a <a
href="{$ae_api.base_url}/event/file/{event_file_obj?.event_file_id}/download?filename={ae_util.clean_filename( href="{$ae_api.base_url}/event/file/{event_file_obj?.event_file_id}/download?filename={ae_util.clean_filename(
event_file_obj?.filename event_file_obj?.filename
)}&key={$ae_api.account_id}" )}&key={$ae_api.account_id}"
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline" class="btn btn-sm preset-tonal-secondary p-1 underline *:hover:inline lg:text-xs"
title={`Download this file:\n${ae_util.clean_filename(event_file_obj?.filename)}\n[API] SHA256: ${event_file_obj?.hash_sha256?.slice(0, 10) ?? 'N/A'}\nHosted ID: ${event_file_obj?.hosted_file_id} Event File ID: ${event_file_obj?.event_file_id}`} title={`Download this file:\n${ae_util.clean_filename(event_file_obj?.filename)}\n[API] SHA256: ${event_file_obj?.hash_sha256?.slice(0, 10) ?? 'N/A'}\nHosted ID: ${event_file_obj?.hosted_file_id} Event File ID: ${event_file_obj?.event_file_id}`}>
>
<Download size="1em" class="mx-1" /> <Download size="1em" class="mx-1" />
<span class="hidden"> Download </span> <span class="hidden"> Download </span>
</a> </a>
@@ -560,9 +577,8 @@
<div <div
class="flex flex-row gap-0.5" class="flex flex-row gap-0.5"
class:hidden={!show_direct_download} class:hidden={!show_direct_download}>
> <span class="w-32 text-xs text-gray-500">
<span class="text-xs text-gray-500 w-32">
Session Name: Session Name:
</span> </span>
<a <a
@@ -576,9 +592,8 @@
)}-{ae_util.clean_filename( )}-{ae_util.clean_filename(
event_file_obj?.event_presenter_full_name event_file_obj?.event_presenter_full_name
)}.{event_file_obj?.extension}&key={$ae_api.account_id}" )}.{event_file_obj?.extension}&key={$ae_api.account_id}"
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline" class="btn btn-sm preset-tonal-secondary p-1 underline *:hover:inline lg:text-xs"
title={`Download renamed with session name to: ${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}`} title={`Download renamed with session name to: ${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_session_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}`}>
>
<Download size="1em" class="mx-1" /> <Download size="1em" class="mx-1" />
<span class="hidden"> Renamed </span> <span class="hidden"> Renamed </span>
</a> </a>
@@ -595,9 +610,8 @@
<div <div
class:hidden={!show_direct_download} class:hidden={!show_direct_download}
class="flex flex-row gap-0.5" class="flex flex-row gap-0.5">
> <span class="w-32 text-xs text-gray-500">
<span class="text-xs text-gray-500 w-32">
Presentation Name: Presentation Name:
</span> </span>
<a <a
@@ -611,9 +625,8 @@
)}-{ae_util.clean_filename( )}-{ae_util.clean_filename(
event_file_obj?.event_presenter_full_name event_file_obj?.event_presenter_full_name
)}.{event_file_obj?.extension}&key=${$ae_api.account_id}" )}.{event_file_obj?.extension}&key=${$ae_api.account_id}"
class="btn btn-sm p-1 preset-tonal-secondary *:hover:inline lg:text-xs underline" class="btn btn-sm preset-tonal-secondary p-1 underline *:hover:inline lg:text-xs"
title={`Download renamed with presentation name to: ${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_presentation_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}`} title={`Download renamed with presentation name to: ${event_file_obj?.event_session_code}-${ae_util.clean_filename(event_file_obj?.event_presentation_name).substring(0, 20)}-${ae_util.clean_filename(event_file_obj?.event_presenter_full_name)}.${event_file_obj?.extension}`}>
>
<Download size="1em" class="mx-1" /> <Download size="1em" class="mx-1" />
<span class="hidden"> Renamed </span> <span class="hidden"> Renamed </span>
</a> </a>
@@ -630,9 +643,9 @@
</td> </td>
<td class="px-4 py-2" <td class="px-4 py-2"
>{ae_util.format_bytes( >{ae_util.format_bytes(
event_file_obj?.file_size || event_file_obj?.hosted_file_size event_file_obj?.file_size ||
)}</td event_file_obj?.hosted_file_size
> )}</td>
<td class="px-4 py-2"> <td class="px-4 py-2">
<div> <div>
<span> <span>
@@ -669,8 +682,7 @@
event_file_obj?.created_on, event_file_obj?.created_on,
minutes: 2880 minutes: 2880
} }
)} )}>
>
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
event_file_obj?.created_on, event_file_obj?.created_on,
'time_12_short' 'time_12_short'
@@ -691,8 +703,7 @@
{#if show_session_fields} {#if show_session_fields}
<td <td
class="px-4 py-2 lg:text-xs" class="px-4 py-2 lg:text-xs"
class:hidden={hide_session_code} class:hidden={hide_session_code}>
>
{event_file_obj?.event_session_code ?? {event_file_obj?.event_session_code ??
'-- not set --'} '-- not set --'}
</td> </td>
@@ -700,8 +711,7 @@
<Presentation size="1em" /> <Presentation size="1em" />
<a <a
href="/events/{event_file_obj?.event_id}/session/{event_file_obj?.event_session_id}" href="/events/{event_file_obj?.event_id}/session/{event_file_obj?.event_session_id}"
class="text-blue-500 underline hover:text-blue-800" class="text-blue-500 underline hover:text-blue-800">
>
{event_file_obj?.event_session_name} {event_file_obj?.event_session_name}
</a> </a>
</td> </td>
@@ -709,8 +719,7 @@
>{ae_util.iso_datetime_formatter( >{ae_util.iso_datetime_formatter(
event_file_obj?.event_session_start_datetime, event_file_obj?.event_session_start_datetime,
'datetime_iso_12_no_seconds' 'datetime_iso_12_no_seconds'
)}</td )}</td>
>
{/if} {/if}
{#if show_presentation_fields} {#if show_presentation_fields}
<td class="px-4 py-2 lg:text-xs"> <td class="px-4 py-2 lg:text-xs">
@@ -736,8 +745,7 @@
<User size="1em" /> <User size="1em" />
<a <a
href="/events/{event_file_obj?.event_id}/presenter/{event_file_obj?.event_presenter_id}" href="/events/{event_file_obj?.event_id}/presenter/{event_file_obj?.event_presenter_id}"
class="text-blue-500 underline hover:text-blue-800" class="text-blue-500 underline hover:text-blue-800">
>
{event_file_obj?.event_presenter_full_name} {event_file_obj?.event_presenter_full_name}
</a> </a>
{:else} {:else}
@@ -745,7 +753,6 @@
{@html ae_snip.html__not_set} {@html ae_snip.html__not_set}
{/if} {/if}
</td> </td>
</tr> </tr>
{/each} {/each}
</tbody> </tbody>
@@ -757,8 +764,8 @@
</section> </section>
<style> <style>
.dim { .dim {
opacity: 0.5; opacity: 0.5;
color: #999; color: #999;
} }
</style> </style>

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
// Exports // Exports
container_class_li?: string | Array<string>; container_class_li?: string | Array<string>;
event_file_obj_li?: Array<any>; event_file_obj_li?: Array<any>;
@@ -13,9 +13,9 @@
show_session_fields?: boolean; show_session_fields?: boolean;
hide_session_code?: boolean; hide_session_code?: boolean;
log_lvl?: number; log_lvl?: number;
} }
let { let {
container_class_li = [], container_class_li = [],
// display_mode = 'default', // display_mode = 'default',
// event_file_id_random_li = $bindable(), // event_file_id_random_li = $bindable(),
@@ -30,43 +30,43 @@
show_session_fields = true, show_session_fields = true,
hide_session_code = false, hide_session_code = false,
log_lvl = $bindable(0) log_lvl = $bindable(0)
}: Props = $props(); }: Props = $props();
// Imports // Imports
import Comp_event_file_obj_tbl from './ae_comp__event_file_obj_tbl.svelte'; import Comp_event_file_obj_tbl from './ae_comp__event_file_obj_tbl.svelte';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { import {
events_loc, events_loc,
events_sess, events_sess,
events_slct, events_slct,
events_trigger events_trigger
} from '$lib/stores/ae_events_stores'; } from '$lib/stores/ae_events_stores';
import { db_events } from '$lib/ae_events/db_events'; import { db_events } from '$lib/ae_events/db_events';
$effect(() => { $effect(() => {
if (log_lvl) { if (log_lvl) {
console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`); console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`);
} }
}); });
// Variables // Variables
// let ae_promises: key_val = {}; // let ae_promises: key_val = {};
// let ae_tmp: key_val = {}; // let ae_tmp: key_val = {};
// let ae_triggers: key_val = {}; // let ae_triggers: key_val = {};
let event_file_id_random_li: Array<string> = $state([]); let event_file_id_random_li: Array<string> = $state([]);
let dq__where_type_id_val = $derived(`${link_to_type}_id_random`); let dq__where_type_id_val = $derived(`${link_to_type}_id_random`);
let dq__where_eq_id_val = $derived(link_to_id ?? ''); let dq__where_eq_id_val = $derived(link_to_id ?? '');
// *** Functions and Logic // *** Functions and Logic
// OPTIMIZATION: If event_file_obj_li is provided (from API/reports), // OPTIMIZATION: If event_file_obj_li is provided (from API/reports),
// use it directly instead of fetching from IDB. The API returns fully // use it directly instead of fetching from IDB. The API returns fully
// enriched data with all joined fields (session names, presentation names, etc.) // enriched data with all joined fields (session names, presentation names, etc.)
// that aren't available in the base IDB file table. // that aren't available in the base IDB file table.
let lq__event_file_obj_li = $derived( let lq__event_file_obj_li = $derived(
liveQuery(async () => { liveQuery(async () => {
let results: any; let results: any;
@@ -118,7 +118,7 @@
return results; return results;
}) })
); );
</script> </script>
{#if event_file_obj_li && event_file_obj_li?.length} {#if event_file_obj_li && event_file_obj_li?.length}
@@ -132,10 +132,9 @@
{show_presentation_fields} {show_presentation_fields}
{show_session_fields} {show_session_fields}
{hide_session_code} {hide_session_code}
{log_lvl} {log_lvl}></Comp_event_file_obj_tbl>
></Comp_event_file_obj_tbl>
{:else} {:else}
<section class="grow px-1 md:px-2 pb-28 flex flex-col gap-1 items-center"> <section class="flex grow flex-col items-center gap-1 px-1 pb-28 md:px-2">
<p>No files available to show in table.</p> <p>No files available to show in table.</p>
</section> </section>
{/if} {/if}

View File

@@ -1,32 +1,32 @@
<script lang="ts"> <script lang="ts">
/** /**
* src/routes/events/ae_comp__event_files_upload.svelte * src/routes/events/ae_comp__event_files_upload.svelte
* Specialized component for uploading files and automatically linking them to Event objects. * Specialized component for uploading files and automatically linking them to Event objects.
*/ */
import { LoaderCircle, Upload, UploadCloud } from '@lucide/svelte'; import { LoaderCircle, Upload, UploadCloud } from '@lucide/svelte';
import Element_input_files_tbl from '$lib/elements/element_input_files_tbl.svelte'; import Element_input_files_tbl from '$lib/elements/element_input_files_tbl.svelte';
// Import storage, functions, and libraries // Import storage, functions, and libraries
import type { key_val } from '$lib/stores/ae_stores'; import type { key_val } from '$lib/stores/ae_stores';
import { api } from '$lib/api/api'; import { api } from '$lib/api/api';
import { import {
ae_loc, ae_loc,
ae_sess, ae_sess,
ae_api, ae_api,
ae_trig, ae_trig,
slct, slct,
slct_trigger slct_trigger
} from '$lib/stores/ae_stores'; } from '$lib/stores/ae_stores';
import { import {
events_loc, events_loc,
events_sess, events_sess,
events_slct, events_slct,
events_trig events_trig
} from '$lib/stores/ae_events_stores'; } from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events/ae_events_functions'; import { events_func } from '$lib/ae_events/ae_events_functions';
import { db_events } from '$lib/ae_events/db_events'; import { db_events } from '$lib/ae_events/db_events';
interface Props { interface Props {
log_lvl?: number; log_lvl?: number;
// Expecting these for link_to_type: 'event', 'event_location', 'event_presentation', 'event_presenter', 'event_session' // Expecting these for link_to_type: 'event', 'event_location', 'event_presentation', 'event_presenter', 'event_session'
link_to_type: string; link_to_type: string;
@@ -42,9 +42,9 @@
upload_complete?: boolean; upload_complete?: boolean;
submit_status?: null | string; submit_status?: null | string;
label?: import('svelte').Snippet; label?: import('svelte').Snippet;
} }
let { let {
log_lvl = $bindable(0), log_lvl = $bindable(0),
link_to_type, link_to_type,
link_to_id, link_to_id,
@@ -59,29 +59,29 @@
upload_complete = $bindable(false), upload_complete = $bindable(false),
submit_status = $bindable(null), submit_status = $bindable(null),
label label
}: Props = $props(); }: Props = $props();
// Local Variables // Local Variables
let task_id: string = $state(''); let task_id: string = $state('');
let input_file_list: any = $state(null); let input_file_list: any = $state(null);
let ae_promises: key_val = $state({}); let ae_promises: key_val = $state({});
let input_element_id = 'ae_comp__event_files_upload__input'; let input_element_id = 'ae_comp__event_files_upload__input';
// WHY: Keep task_id in sync with prop if it hasn't been set by an upload cycle yet // WHY: Keep task_id in sync with prop if it hasn't been set by an upload cycle yet
$effect(() => { $effect(() => {
if (!ae_promises.upload__hosted_file_obj) { if (!ae_promises.upload__hosted_file_obj) {
task_id = link_to_id; task_id = link_to_id;
} }
}); });
function prevent_default<T extends Event>(fn: (event: T) => void) { function prevent_default<T extends Event>(fn: (event: T) => void) {
return function (event: T) { return function (event: T) {
event.preventDefault(); event.preventDefault();
fn(event); fn(event);
}; };
} }
async function handle_submit_form_files(event: SubmitEvent) { async function handle_submit_form_files(event: SubmitEvent) {
if (log_lvl) console.log('*** handle_submit_form() ***'); if (log_lvl) console.log('*** handle_submit_form() ***');
$events_sess.files.disable_submit__event_file_obj = true; $events_sess.files.disable_submit__event_file_obj = true;
@@ -126,19 +126,17 @@
$events_sess.files.submit_status = 'saved'; $events_sess.files.submit_status = 'saved';
submit_status = 'saved'; submit_status = 'saved';
upload_complete = true; upload_complete = true;
} }
async function handle_input_upload_files({ async function handle_input_upload_files({
input_upload_files, input_upload_files,
task_id task_id
}: { }: {
input_upload_files: any[]; input_upload_files: any[];
task_id: string; task_id: string;
}) { }) {
if (log_lvl) if (log_lvl)
console.log( console.log(`*** handle_input_upload_files() *** task_id = ${task_id}`);
`*** handle_input_upload_files() *** task_id = ${task_id}`
);
const form_data = new FormData(); const form_data = new FormData();
form_data.append('account_id', $ae_loc.account_id); form_data.append('account_id', $ae_loc.account_id);
@@ -191,16 +189,15 @@
}); });
return ae_promises.upload__hosted_file_obj; return ae_promises.upload__hosted_file_obj;
} }
</script> </script>
<form <form
onsubmit={prevent_default(handle_submit_form_files)} onsubmit={prevent_default(handle_submit_form_files)}
class="{class_li_default} {class_li}" class="{class_li_default} {class_li}">
>
{#await ae_promises.upload__hosted_file_obj} {#await ae_promises.upload__hosted_file_obj}
<div class="text-lg flex flex-row gap-1 items-center justify-center"> <div class="flex flex-row items-center justify-center gap-1 text-lg">
<LoaderCircle class="animate-spin m-1" /> <LoaderCircle class="m-1 animate-spin" />
<span class=""> <span class="">
Uploading Uploading
{#if $ae_sess.api_upload_kv[task_id]} {#if $ae_sess.api_upload_kv[task_id]}
@@ -212,31 +209,27 @@
<div <div
class=" class="
border-2 hover:border-2 border-dashed border-primary-500 border-primary-500 preset-filled-primary-50-950 hover:border-primary-800 w-full
p-1 w-full rounded-lg cursor-pointer rounded-lg border-2
preset-filled-primary-50-950 hover:border-primary-800 border-dashed p-1
cursor-pointer transition-colors transition-colors hover:border-2
" ">
>
<label <label
for={input_element_id} for={input_element_id}
class=" class="
svelte_input_file_label svelte_input_file_label
text-center
cursor-pointer cursor-pointer
text-center
" "
class:hidden={$events_sess.files.disable_submit__event_file_obj} class:hidden={$events_sess.files.disable_submit__event_file_obj}>
>
{#if label}{@render label()}{:else} {#if label}{@render label()}{:else}
<div class="flex items-center justify-center gap-2 mb-2 pt-2"> <div class="mb-2 flex items-center justify-center gap-2 pt-2">
<Upload class="text-primary-500" /> <Upload class="text-primary-500" />
<strong class="preset-tonal-primary px-3 py-1 rounded-full" <strong class="preset-tonal-primary rounded-full px-3 py-1"
>Select Files</strong >Select Files</strong>
>
</div> </div>
<div <div
class="text-sm text-gray-600 dark:text-gray-400 italic pb-2" class="pb-2 text-sm text-gray-600 italic dark:text-gray-400">
>
<strong>Presentation materials only</strong><br /> <strong>Presentation materials only</strong><br />
(PPTX, Keynote, PDF, MP4, etc) (PPTX, Keynote, PDF, MP4, etc)
</div> </div>
@@ -254,39 +247,36 @@
class:hidden={$events_sess.files.disable_submit__event_file_obj} class:hidden={$events_sess.files.disable_submit__event_file_obj}
class=" class="
svelte_input_file_element file-dropzone-input svelte_input_file_element file-dropzone-input
block w-full text-lg text-center preset-tonal-primary preset-outlined-primary-200-800 hover:preset-filled-success-200-800 block
rounded-lg w-full
cursor-pointer cursor-pointer
p-1 rounded-lg
preset-tonal-primary preset-outlined-primary-200-800 hover:preset-filled-success-200-800 p-1 text-center text-lg
transition-all transition-all
{input_class_li.join(' ')} {input_class_li.join(' ')}
" " />
/>
</div> </div>
<Element_input_files_tbl <Element_input_files_tbl
bind:input_file_list bind:input_file_list
bind:file_list_status={$events_sess.files.status__file_list} bind:file_list_status={$events_sess.files.status__file_list}
bind:processed_file_list={$events_sess.files.processed_file_list} bind:processed_file_list={$events_sess.files.processed_file_list}
{table_class_li} {table_class_li} />
/>
<button <button
type="submit" type="submit"
class=" class="
btn btn-lg btn btn-lg
preset-tonal-primary
border-primary-500 hover:preset-tonal-success hover:border-success-500 flex w-54
items-center justify-center border
text-lg text-lg
preset-tonal-primary border border-primary-500 hover:preset-tonal-success hover:border-success-500
flex items-center justify-center
w-54
transition-all transition-all
" "
disabled={$events_sess.files.disable_submit__event_file_obj || disabled={$events_sess.files.disable_submit__event_file_obj ||
$events_sess.files.status__file_list != 'ready'} $events_sess.files.status__file_list != 'ready'}>
>
{#await ae_promises.upload__hosted_file_obj} {#await ae_promises.upload__hosted_file_obj}
<LoaderCircle class="animate-spin m-1" /> <LoaderCircle class="m-1 animate-spin" />
<span class=""> <span class="">
{#if $ae_sess.api_upload_kv[task_id]} {#if $ae_sess.api_upload_kv[task_id]}
{$ae_sess.api_upload_kv[task_id].percent_completed}% {$ae_sess.api_upload_kv[task_id].percent_completed}%
@@ -297,7 +287,7 @@
{:then} {:then}
<UploadCloud class="m-1" size={20} /> <UploadCloud class="m-1" size={20} />
<span class="text-sm"> Upload </span> <span class="text-sm"> Upload </span>
<span class="grow font-bold ml-2"> <span class="ml-2 grow font-bold">
{#if $events_sess.files.processed_file_list?.length > 0} {#if $events_sess.files.processed_file_list?.length > 0}
{$events_sess.files.processed_file_list.length} {$events_sess.files.processed_file_list.length}
{$events_sess.files.processed_file_list.length === 1 {$events_sess.files.processed_file_list.length === 1

View File

@@ -1,23 +1,23 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
// Exports // Exports
container_class_li?: string | Array<string>; container_class_li?: string | Array<string>;
display_mode?: string; // 'default', 'compact', 'minimal', 'launcher' display_mode?: string; // 'default', 'compact', 'minimal', 'launcher'
// export let link_to_id: string; // export let link_to_id: string;
lq__event_presentation_obj_li: any; lq__event_presentation_obj_li: any;
log_lvl?: number; // Variables log_lvl?: number; // Variables
} }
let { let {
container_class_li = [], container_class_li = [],
display_mode = 'default', display_mode = 'default',
lq__event_presentation_obj_li, lq__event_presentation_obj_li,
log_lvl = 0 log_lvl = 0
}: Props = $props(); }: Props = $props();
// Imports // Imports
import { ae_util } from '$lib/ae_utils/ae_utils'; import { ae_util } from '$lib/ae_utils/ae_utils';
import { import {
ae_snip, ae_snip,
ae_loc, ae_loc,
ae_sess, ae_sess,
@@ -25,31 +25,37 @@
ae_trig, ae_trig,
slct, slct,
slct_trigger slct_trigger
} from '$lib/stores/ae_stores'; } 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 { import {
events_loc, events_loc,
events_sess, events_sess,
events_slct, events_slct,
events_trigger, events_trigger,
events_trig_kv events_trig_kv
} from '$lib/stores/ae_events_stores'; } from '$lib/stores/ae_events_stores';
import Element_ae_obj_field_editor from '$lib/elements/element_ae_obj_field_editor.svelte'; import Element_ae_obj_field_editor from '$lib/elements/element_ae_obj_field_editor.svelte';
import Comp_event_presenter_obj_li from '../events/[event_id]/(pres_mgmt)/presenter/ae_comp__event_presenter_obj_li_wrapper.svelte'; import Comp_event_presenter_obj_li from '../events/[event_id]/(pres_mgmt)/presenter/ae_comp__event_presenter_obj_li_wrapper.svelte';
import Element_manage_event_file_li_wrap from '$lib/elements/element_manage_event_file_li_all.svelte'; import Element_manage_event_file_li_wrap from '$lib/elements/element_manage_event_file_li_all.svelte';
import { Barcode, CalendarDays, Eye, EyeOff, ListOrdered, Plus } from '@lucide/svelte'; import {
// export let link_to_type: string; Barcode,
CalendarDays,
Eye,
EyeOff,
ListOrdered,
Plus
} from '@lucide/svelte';
// export let link_to_type: string;
// let ae_promises: key_val = {}; // let ae_promises: key_val = {};
// let ae_tmp: key_val = {}; // let ae_tmp: key_val = {};
// let ae_triggers: key_val = {}; // let ae_triggers: key_val = {};
// *** Functions and Logic // *** Functions and Logic
</script> </script>
<section <section
class="ae_comp event_presentation_obj_li px-0.5 py-2 space-y-2 min-w-full w-full container overflow-x-auto {container_class_li}" class="ae_comp event_presentation_obj_li container w-full min-w-full space-y-2 overflow-x-auto px-0.5 py-2 {container_class_li}">
>
<div class="float-right flex flex-row items-center"> <div class="float-right flex flex-row items-center">
{#if $ae_loc.trusted_access && $ae_loc.edit_mode} {#if $ae_loc.trusted_access && $ae_loc.edit_mode}
<button <button
@@ -77,8 +83,7 @@
log_lvl: 1 log_lvl: 1
}); });
}} }}
class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500" class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500">
>
<Plus size="1em" class="mx-1" /> <Plus size="1em" class="mx-1" />
Add Presentation Add Presentation
</button> </button>
@@ -93,10 +98,9 @@
{#if lq__event_presentation_obj_li?.length} {#if lq__event_presentation_obj_li?.length}
<span <span
class="text-3xl font-bold preset-filled-success-100-900 px-4 rounded-lg" class="preset-filled-success-100-900 rounded-lg px-4 text-3xl font-bold"
title="Count {lq__event_presentation_obj_li.length ?? title="Count {lq__event_presentation_obj_li.length ??
'None'}" 'None'}">
>
<ListOrdered size="1em" class="mx-4" /> <ListOrdered size="1em" class="mx-4" />
{lq__event_presentation_obj_li.length ?? 'None'}&times; {lq__event_presentation_obj_li.length ?? 'None'}&times;
</span> </span>
@@ -114,8 +118,9 @@
<!-- Show presentations for this LiveQuery --> <!-- Show presentations for this LiveQuery -->
<ul class="space-y-4"> <ul class="space-y-4">
{#each lq__event_presentation_obj_li ?? [] as event_presentation_obj (event_presentation_obj.event_presentation_id)} {#each lq__event_presentation_obj_li ?? [] as event_presentation_obj (event_presentation_obj.event_presentation_id)}
<li class="space-y-3 border border-surface-200-800 bg-surface-50-900 p-4 rounded-xl shadow-sm transition-colors duration-200"> <li
<div class="float-right space-2 flex flex-row items-center"> class="border-surface-200-800 bg-surface-50-900 space-y-3 rounded-xl border p-4 shadow-sm transition-colors duration-200">
<div class="space-2 float-right flex flex-row items-center">
{#if $ae_loc.trusted_access && $ae_loc.edit_mode} {#if $ae_loc.trusted_access && $ae_loc.edit_mode}
<button <button
type="button" type="button"
@@ -147,21 +152,19 @@
log_lvl: 1 log_lvl: 1
}); });
}} }}
class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500" class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500">
>
<Plus size="1em" class="mx-1" /> <Plus size="1em" class="mx-1" />
Add Presenter Add Presenter
</button> </button>
{/if} {/if}
</div> </div>
<h4 class="text-lg font-bold rounded-lg px-3 py-2 bg-surface-100-900 flex flex-wrap items-center gap-2"> <h4
class="bg-surface-100-900 flex flex-wrap items-center gap-2 rounded-lg px-3 py-2 text-lg font-bold">
<span <span
class:hidden={!event_presentation_obj.start_datetime || class:hidden={!event_presentation_obj.start_datetime ||
$events_loc.pres_mgmt $events_loc.pres_mgmt.hide__presentation_datetime}
.hide__presentation_datetime} class="border-r-2 border-gray-800/50 px-1 text-base">
class="text-base border-r-2 border-gray-800/50 px-1"
>
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
event_presentation_obj.start_datetime, event_presentation_obj.start_datetime,
'dddd' 'dddd'
@@ -182,8 +185,13 @@
field_type={'text'} field_type={'text'}
current_value={event_presentation_obj?.name} current_value={event_presentation_obj?.name}
display_block={true} display_block={true}
on_success={() => events_func.load_ae_obj_id__event_presentation({ api_cfg: $ae_api, event_presentation_id: event_presentation_obj.event_presentation_id, log_lvl: 1 })} on_success={() =>
> events_func.load_ae_obj_id__event_presentation({
api_cfg: $ae_api,
event_presentation_id:
event_presentation_obj.event_presentation_id,
log_lvl: 1
})}>
<span class="italic"> <span class="italic">
{event_presentation_obj?.name} {event_presentation_obj?.name}
</span> </span>
@@ -197,28 +205,29 @@
field_type={'text'} field_type={'text'}
current_value={event_presentation_obj?.code} current_value={event_presentation_obj?.code}
display_block={true} display_block={true}
on_success={() => events_func.load_ae_obj_id__event_presentation({ api_cfg: $ae_api, event_presentation_id: event_presentation_obj.event_presentation_id, log_lvl: 1 })} on_success={() =>
> events_func.load_ae_obj_id__event_presentation({
api_cfg: $ae_api,
event_presentation_id:
event_presentation_obj.event_presentation_id,
log_lvl: 1
})}>
{#if (event_presentation_obj?.code || event_presentation_obj?.abstract_code) && !$events_loc.pres_mgmt.hide__presentation_code} {#if (event_presentation_obj?.code || event_presentation_obj?.abstract_code) && !$events_loc.pres_mgmt.hide__presentation_code}
<span <span
class="text-xs preset-tonal-warning px-2 py-0.5 rounded-md leading-none" class="preset-tonal-warning rounded-md px-2 py-0.5 text-xs leading-none"
title="Presentation code {event_presentation_obj?.code} and abstract code {event_presentation_obj?.abstract_code}" title="Presentation code {event_presentation_obj?.code} and abstract code {event_presentation_obj?.abstract_code}">
>
<Barcode size="1em" /> <Barcode size="1em" />
{event_presentation_obj?.code ?? ''} {event_presentation_obj?.code ?? ''}
{event_presentation_obj?.abstract_code ?? {event_presentation_obj?.abstract_code ?? ''}
''}
</span> </span>
{:else if $ae_loc.trusted_access && $ae_loc.edit_mode} {:else if $ae_loc.trusted_access && $ae_loc.edit_mode}
<span <span
class="text-sm text-semibold text-success-800-400" class="text-semibold text-success-800-400 text-sm">
>
<Barcode size="1em" /> <Barcode size="1em" />
Code: Code:
<span <span
class="" class=""
title="No code provided for this presentation" title="No code provided for this presentation">
>
{@html event_presentation_obj?.code ?? {@html event_presentation_obj?.code ??
ae_snip.html__not_set} ae_snip.html__not_set}
</span> </span>
@@ -231,18 +240,13 @@
<div <div
class:hidden={!( class:hidden={!(
$ae_loc.trusted_access && $ae_loc.edit_mode $ae_loc.trusted_access && $ae_loc.edit_mode
)} )}>
> <span class="text-semibold text-success-800-400 text-sm">
<span
class="text-sm text-semibold text-success-800-400"
>
Date & Date &
<button <button
type="button" type="button"
onclick={() => { onclick={() => {
if ( if ($events_loc.pres_mgmt.time_hours == 12) {
$events_loc.pres_mgmt.time_hours == 12
) {
$events_loc.pres_mgmt.time_hours = 24; $events_loc.pres_mgmt.time_hours = 24;
$events_loc.pres_mgmt.datetime_format = $events_loc.pres_mgmt.datetime_format =
'datetime_long'; 'datetime_long';
@@ -255,12 +259,10 @@
$events_loc.pres_mgmt.time_format = $events_loc.pres_mgmt.time_format =
'time_12_short'; 'time_12_short';
} }
}} }}>
>
time time
</button> </button>
:</span :</span>
>
<CalendarDays size="1em" class="text-success-800-400" /> <CalendarDays size="1em" class="text-success-800-400" />
<Element_ae_obj_field_editor <Element_ae_obj_field_editor
object_type={'event_presentation'} object_type={'event_presentation'}
@@ -268,8 +270,12 @@
field_name={'start_datetime'} field_name={'start_datetime'}
field_type={'datetime'} field_type={'datetime'}
current_value={event_presentation_obj.start_datetime} current_value={event_presentation_obj.start_datetime}
on_success={() => events_func.load_ae_obj_id__event_presentation({ api_cfg: $ae_api, event_presentation_id: event_presentation_obj?.event_presentation_id })} on_success={() =>
> events_func.load_ae_obj_id__event_presentation({
api_cfg: $ae_api,
event_presentation_id:
event_presentation_obj?.event_presentation_id
})}>
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
event_presentation_obj.start_datetime, event_presentation_obj.start_datetime,
'dddd' 'dddd'
@@ -286,8 +292,12 @@
field_name={'end_datetime'} field_name={'end_datetime'}
field_type={'datetime'} field_type={'datetime'}
current_value={event_presentation_obj.end_datetime} current_value={event_presentation_obj.end_datetime}
on_success={() => events_func.load_ae_obj_id__event_presentation({ api_cfg: $ae_api, event_presentation_id: event_presentation_obj?.event_presentation_id })} on_success={() =>
> events_func.load_ae_obj_id__event_presentation({
api_cfg: $ae_api,
event_presentation_id:
event_presentation_obj?.event_presentation_id
})}>
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
event_presentation_obj.end_datetime, event_presentation_obj.end_datetime,
$events_loc.pres_mgmt.time_format $events_loc.pres_mgmt.time_format
@@ -298,8 +308,7 @@
<div <div
class:hidden={!$events_loc.pres_mgmt class:hidden={!$events_loc.pres_mgmt
.show_content__presentation_description && .show_content__presentation_description &&
!($ae_loc.trusted_access && $ae_loc.edit_mode)} !($ae_loc.trusted_access && $ae_loc.edit_mode)}>
>
<Element_ae_obj_field_editor <Element_ae_obj_field_editor
object_type={'event_presentation'} object_type={'event_presentation'}
object_id={event_presentation_obj?.event_presentation_id} object_id={event_presentation_obj?.event_presentation_id}
@@ -309,11 +318,15 @@
allow_null={true} allow_null={true}
display_block={true} display_block={true}
textarea_rows={15} textarea_rows={15}
on_success={() => events_func.load_ae_obj_id__event_presentation({ api_cfg: $ae_api, event_presentation_id: event_presentation_obj.event_presentation_id, log_lvl: 1 })} on_success={() =>
> events_func.load_ae_obj_id__event_presentation({
api_cfg: $ae_api,
event_presentation_id:
event_presentation_obj.event_presentation_id,
log_lvl: 1
})}>
<span <span
class="text-sm text-semibold text-success-800-400" class="text-semibold text-success-800-400 text-sm">
>
Description: Description:
</span> </span>
@@ -342,8 +355,7 @@
event_presentation_obj.event_presentation_id; event_presentation_obj.event_presentation_id;
} }
}} }}
class="btn btn-sm preset-tonal-surface hover:preset-filled-surface-500 text-xs" class="btn btn-sm preset-tonal-surface hover:preset-filled-surface-500 text-xs">
>
{#if $events_sess.pres_mgmt.show_content__presentation_description == event_presentation_obj.event_presentation_id} {#if $events_sess.pres_mgmt.show_content__presentation_description == event_presentation_obj.event_presentation_id}
<EyeOff size="1em" class="mx-1" /> <EyeOff size="1em" class="mx-1" />
<span>Hide Description</span> <span>Hide Description</span>
@@ -354,7 +366,7 @@
</button> </button>
<pre <pre
class="whitespace-pre-wrap p-3 bg-surface-100-900 rounded-lg text-sm" class="bg-surface-100-900 rounded-lg p-3 text-sm whitespace-pre-wrap"
class:hidden={$events_sess.pres_mgmt class:hidden={$events_sess.pres_mgmt
.show_content__presentation_description !== .show_content__presentation_description !==
event_presentation_obj.event_presentation_id}>{event_presentation_obj.description}</pre> event_presentation_obj.event_presentation_id}>{event_presentation_obj.description}</pre>
@@ -377,8 +389,7 @@
link_to_type={'event_presentation'} link_to_type={'event_presentation'}
link_to_id={event_presentation_obj.event_presentation_id} link_to_id={event_presentation_obj.event_presentation_id}
event_presenter_id_li={[]} event_presenter_id_li={[]}
log_lvl={2} log_lvl={2}></Comp_event_presenter_obj_li>
></Comp_event_presenter_obj_li>
<!-- Show files for this presentation --> <!-- Show files for this presentation -->
<Element_manage_event_file_li_wrap <Element_manage_event_file_li_wrap
@@ -393,8 +404,7 @@
allow_moderator={$events_loc.auth__kv.session[ allow_moderator={$events_loc.auth__kv.session[
$events_slct.event_session_id $events_slct.event_session_id
]} ]}
container_class_li={''} container_class_li={''} />
/>
</li> </li>
{/each} {/each}
</ul> </ul>

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
log_lvl?: number; log_lvl?: number;
container_class_li?: string | Array<string>; container_class_li?: string | Array<string>;
lq__event_session_obj_li?: any; lq__event_session_obj_li?: any;
@@ -12,9 +12,9 @@
hide__location_link?: boolean; hide__location_link?: boolean;
show__session_files?: boolean; show__session_files?: boolean;
show__session_presentations?: boolean; show__session_presentations?: boolean;
} }
let { let {
log_lvl = 0, log_lvl = 0,
container_class_li = [], container_class_li = [],
lq__event_session_obj_li = null, lq__event_session_obj_li = null,
@@ -27,29 +27,49 @@
hide__location_link = $bindable(false), hide__location_link = $bindable(false),
show__session_files = $bindable(false), show__session_files = $bindable(false),
show__session_presentations = $bindable(false) show__session_presentations = $bindable(false)
}: Props = $props(); }: Props = $props();
import { ae_util } from '$lib/ae_utils/ae_utils'; import { ae_util } from '$lib/ae_utils/ae_utils';
import { Bell, BellOff, CalendarDays, Check, ChevronDown, ChevronUp, Clock, Edit, Eye, EyeOff, FileSearch, LoaderCircle, Mail, MapPin, Presentation, Rocket, Search, SendHorizontal, User } from '@lucide/svelte'; import {
import { api } from '$lib/api/api'; Bell,
import Comp_event_presenter_obj_li from './[event_id]/(pres_mgmt)/presenter/ae_comp__event_presenter_obj_li_wrapper.svelte'; BellOff,
import Element_manage_event_file_li from '$lib/elements/element_manage_event_file_li_direct.svelte'; CalendarDays,
import Comp_event_session_alert from './[event_id]/(pres_mgmt)/session/ae_comp__event_session_alert.svelte'; Check,
ChevronDown,
ChevronUp,
Clock,
Edit,
Eye,
EyeOff,
FileSearch,
LoaderCircle,
Mail,
MapPin,
Presentation,
Rocket,
Search,
SendHorizontal,
User
} from '@lucide/svelte';
import { api } from '$lib/api/api';
import Comp_event_presenter_obj_li from './[event_id]/(pres_mgmt)/presenter/ae_comp__event_presenter_obj_li_wrapper.svelte';
import Element_manage_event_file_li from '$lib/elements/element_manage_event_file_li_direct.svelte';
import Comp_event_session_alert from './[event_id]/(pres_mgmt)/session/ae_comp__event_session_alert.svelte';
import { events_func } from '$lib/ae_events/ae_events_functions'; import { events_func } from '$lib/ae_events/ae_events_functions';
import { ae_loc, ae_api, ae_snip } from '$lib/stores/ae_stores'; import { ae_loc, ae_api, ae_snip } from '$lib/stores/ae_stores';
import { import {
events_loc, events_loc,
events_sess, events_sess,
events_slct events_slct
} from '$lib/stores/ae_events_stores'; } from '$lib/stores/ae_events_stores';
let show_details_kv: Record<string, boolean> = $state({}); let show_details_kv: Record<string, boolean> = $state({});
// Derived list of visible items (Standardized Pattern 2026-01-27) // Derived list of visible items (Standardized Pattern 2026-01-27)
// Supports both a liveQuery observable (lq__event_session_obj_li) and a // Supports both a liveQuery observable (lq__event_session_obj_li) and a
// plain pre-fetched array (event_session_obj_li) as a fallback. // plain pre-fetched array (event_session_obj_li) as a fallback.
let visible_session_obj_li = $derived( let visible_session_obj_li = $derived(
(() => { (() => {
const list = $lq__event_session_obj_li ?? event_session_obj_li; const list = $lq__event_session_obj_li ?? event_session_obj_li;
if (list === undefined || list === null) return null; if (list === undefined || list === null) return null;
@@ -67,38 +87,34 @@
); );
return filtered; return filtered;
})() })()
); );
function toggle_details(id: string) { function toggle_details(id: string) {
show_details_kv[id] = !show_details_kv[id]; show_details_kv[id] = !show_details_kv[id];
} }
</script> </script>
<section <section
class="ae_comp event_session_obj_li px-0.5 py-2 space-y-2 min-w-full w-full container overflow-x-auto {container_class_li}" class="ae_comp event_session_obj_li container w-full min-w-full space-y-2 overflow-x-auto px-0.5 py-2 {container_class_li}">
>
{#if visible_session_obj_li === null} {#if visible_session_obj_li === null}
<div class="flex flex-col items-center justify-center p-10 opacity-50"> <div class="flex flex-col items-center justify-center p-10 opacity-50">
<LoaderCircle size="3em" class="animate-spin mb-2" /> <LoaderCircle size="3em" class="mb-2 animate-spin" />
<p>Loading sessions...</p> <p>Loading sessions...</p>
</div> </div>
{:else if visible_session_obj_li.length > 0} {:else if visible_session_obj_li.length > 0}
<header <header
class="w-full flex flex-row gap-2 items-center justify-start mb-2 px-2" class="mb-2 flex w-full flex-row items-center justify-start gap-2 px-2">
> <h2 class="text-sm font-normal text-gray-500">Sessions:</h2>
<h2 class="text-sm text-gray-500 font-normal">Sessions:</h2>
<span <span
class="badge preset-tonal-success font-bold text-lg px-3 py-1" class="badge preset-tonal-success px-3 py-1 text-lg font-bold">
>
{visible_session_obj_li.length}<span {visible_session_obj_li.length}<span
class="text-gray-400 dark:text-gray-600">&times;</span class="text-gray-400 dark:text-gray-600">&times;</span>
>
</span> </span>
</header> </header>
<table class="table table-auto table-striped w-full"> <table class="table-striped table w-full table-auto">
<thead> <thead>
<tr class="bg-surface-100-900"> <tr class="bg-surface-100-900">
<th>Session</th> <th>Session</th>
@@ -112,8 +128,7 @@
<th <th
class:hidden={!$ae_loc.edit_mode || class:hidden={!$ae_loc.edit_mode ||
!$ae_loc.adv_mode || !$ae_loc.adv_mode ||
hide__admin}>Admin</th hide__admin}>Admin</th>
>
</tr> </tr>
</thead> </thead>
@@ -122,40 +137,34 @@
<tr <tr
class="relative transition-colors duration-200" class="relative transition-colors duration-200"
class:opacity-50={session_obj?.hide} class:opacity-50={session_obj?.hide}
class:preset-tonal-warning={!session_obj?.enable} class:preset-tonal-warning={!session_obj?.enable}>
>
<td> <td>
{#if session_obj?.alert && $ae_loc.trusted_access} {#if session_obj?.alert && $ae_loc.trusted_access}
<Comp_event_session_alert <Comp_event_session_alert
event_session_obj={session_obj} event_session_obj={session_obj}
{log_lvl} {log_lvl} />
/>
{/if} {/if}
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<a <a
href="/events/{session_obj?.event_id}/session/{session_obj?.event_session_id}" href="/events/{session_obj?.event_id}/session/{session_obj?.event_session_id}"
class="flex flex-row gap-2 items-center font-bold text-lg hover:text-primary-500 text-left transition-colors duration-200" class="hover:text-primary-500 flex flex-row items-center gap-2 text-left text-lg font-bold transition-colors duration-200">
>
{#if session_obj?.hide} {#if session_obj?.hide}
<EyeOff <EyeOff
size="1em" size="1em"
class="text-gray-400 flex-none" class="flex-none text-gray-400" />
/>
{:else} {:else}
<Presentation <Presentation
size="1em" size="1em"
class="text-primary-500 flex-none" class="text-primary-500 flex-none" />
/>
{/if} {/if}
<span>{session_obj?.name}</span> <span>{session_obj?.name}</span>
{#if session_obj?.file_count_all} {#if session_obj?.file_count_all}
<span <span
class="badge preset-tonal-success flex items-center gap-1 text-xs py-0 px-1" class="badge preset-tonal-success flex items-center gap-1 px-1 py-0 text-xs">
>
<Check size="1em" /> <Check size="1em" />
{session_obj.file_count_all} {session_obj.file_count_all}
@@ -170,8 +179,7 @@
onclick={() => onclick={() =>
toggle_details( toggle_details(
session_obj.event_session_id session_obj.event_session_id
)} )}>
>
{#if show_details_kv[session_obj.event_session_id]} {#if show_details_kv[session_obj.event_session_id]}
<ChevronUp size="1.2em" /> <ChevronUp size="1.2em" />
{:else} {:else}
@@ -184,36 +192,31 @@
<!-- Mobile Schedule Summary --> <!-- Mobile Schedule Summary -->
<div <div
class="md:hidden text-xs text-surface-500 flex flex-wrap gap-x-3 gap-y-1" class="text-surface-500 flex flex-wrap gap-x-3 gap-y-1 text-xs md:hidden">
>
<span class="flex items-center gap-1" <span class="flex items-center gap-1"
><CalendarDays size="1em" /> ><CalendarDays size="1em" />
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
session_obj?.start_datetime, session_obj?.start_datetime,
'date_short_month_day' 'date_short_month_day'
)}</span )}</span>
>
<span class="flex items-center gap-1" <span class="flex items-center gap-1"
><Clock size="1em" /> ><Clock size="1em" />
{ae_util.iso_datetime_formatter( {ae_util.iso_datetime_formatter(
session_obj?.start_datetime, session_obj?.start_datetime,
'time_12_short' 'time_12_short'
)}</span )}</span>
>
</div> </div>
{#if show_details_kv[session_obj.event_session_id]} {#if show_details_kv[session_obj.event_session_id]}
<div <div
class="p-2 bg-surface-500/5 rounded-lg border border-surface-500/10 mt-1" class="bg-surface-500/5 border-surface-500/10 mt-1 rounded-lg border p-2">
>
{#if show__session_presentations && $ae_loc.manager_access} {#if show__session_presentations && $ae_loc.manager_access}
<Comp_event_presenter_obj_li <Comp_event_presenter_obj_li
link_to_type={'event_session'} link_to_type={'event_session'}
link_to_id={session_obj?.event_session_id} link_to_id={session_obj?.event_session_id}
display_mode={'minimal'} display_mode={'minimal'}
{log_lvl} {log_lvl} />
/>
{/if} {/if}
{#if show__session_files && $ae_loc.manager_access} {#if show__session_files && $ae_loc.manager_access}
@@ -222,8 +225,7 @@
link_to_id={session_obj?.event_session_id} link_to_id={session_obj?.event_session_id}
allow_basic={true} allow_basic={true}
allow_moderator={true} allow_moderator={true}
display_mode={'minimal'} display_mode={'minimal'} />
/>
{/if} {/if}
</div> </div>
{/if} {/if}
@@ -236,8 +238,7 @@
>{ae_util.iso_datetime_formatter( >{ae_util.iso_datetime_formatter(
session_obj?.start_datetime, session_obj?.start_datetime,
'dddd, MMM D' 'dddd, MMM D'
)}</span )}</span>
>
<span class="text-surface-500 whitespace-nowrap" <span class="text-surface-500 whitespace-nowrap"
>{ae_util.iso_datetime_formatter( >{ae_util.iso_datetime_formatter(
@@ -246,17 +247,15 @@
)} {ae_util.iso_datetime_formatter( )} {ae_util.iso_datetime_formatter(
session_obj?.end_datetime, session_obj?.end_datetime,
'time_12_short' 'time_12_short'
)}</span )}</span>
>
</div> </div>
</td> </td>
<td class:hidden={hide__session_location}> <td class:hidden={hide__session_location}>
<div class="flex flex-col gap-1 min-w-32"> <div class="flex min-w-32 flex-col gap-1">
<span class="text-xs font-semibold" <span class="text-xs font-semibold"
>{session_obj?.event_location_name ?? >{session_obj?.event_location_name ??
'--'}</span '--'}</span>
>
<div class="flex gap-1"> <div class="flex gap-1">
{#if !hide__launcher_link} {#if !hide__launcher_link}
@@ -264,8 +263,7 @@
href="/events/{session_obj?.event_id}/launcher/{session_obj?.event_location_id}?session_id={session_obj?.event_session_id}" href="/events/{session_obj?.event_id}/launcher/{session_obj?.event_location_id}?session_id={session_obj?.event_session_id}"
class="btn btn-icon btn-xs preset-tonal-tertiary" class="btn btn-icon btn-xs preset-tonal-tertiary"
title="Svelte Launcher" title="Svelte Launcher"
><Rocket size="1em" /></a ><Rocket size="1em" /></a>
>
{/if} {/if}
{#if !hide__location_link} {#if !hide__location_link}
@@ -273,28 +271,25 @@
href="/events/{session_obj?.event_id}/location/{session_obj?.event_location_id}" href="/events/{session_obj?.event_id}/location/{session_obj?.event_location_id}"
class="btn btn-icon btn-xs preset-tonal-surface" class="btn btn-icon btn-xs preset-tonal-surface"
title="Location Details" title="Location Details"
><MapPin size="1em" /></a ><MapPin size="1em" /></a>
>
{/if} {/if}
</div> </div>
</div> </div>
</td> </td>
<td class:hidden={hide__session_poc}> <td class:hidden={hide__session_poc}>
<div class="flex flex-col text-xs min-w-32"> <div class="flex min-w-32 flex-col text-xs">
{#if session_obj?.poc_person_full_name} {#if session_obj?.poc_person_full_name}
<span <span
class="font-bold flex items-center gap-1" class="flex items-center gap-1 font-bold"
><User size="1em" /> ><User size="1em" />
{session_obj.poc_person_full_name}</span {session_obj.poc_person_full_name}</span>
>
{#if $ae_loc.trusted_access && session_obj?.poc_person_primary_email} {#if $ae_loc.trusted_access && session_obj?.poc_person_primary_email}
<a <a
href="mailto:{session_obj.poc_person_primary_email}" href="mailto:{session_obj.poc_person_primary_email}"
class="text-primary-500 hover:underline flex items-center gap-1" class="text-primary-500 flex items-center gap-1 hover:underline"
><Mail size="1em" /> Email</a ><Mail size="1em" /> Email</a>
>
{/if} {/if}
{:else} {:else}
<span class="opacity-30">--</span> <span class="opacity-30">--</span>
@@ -305,8 +300,7 @@
<td <td
class:hidden={!$ae_loc.edit_mode || class:hidden={!$ae_loc.edit_mode ||
!$ae_loc.adv_mode || !$ae_loc.adv_mode ||
hide__admin} hide__admin}>
>
<div class="flex gap-1"> <div class="flex gap-1">
<button <button
type="button" type="button"
@@ -321,15 +315,17 @@
fields: { hide: !session_obj.hide }, fields: { hide: !session_obj.hide },
log_lvl: 1 log_lvl: 1
}); });
events_func.load_ae_obj_id__event_session({ events_func.load_ae_obj_id__event_session(
{
api_cfg: $ae_api, api_cfg: $ae_api,
event_session_id: session_obj.event_session_id event_session_id:
}); session_obj.event_session_id
}} }
> );
}}>
{#if session_obj?.hide}<EyeOff {#if session_obj?.hide}<EyeOff
size="1.2em" size="1.2em" />{:else}<Eye
/>{:else}<Eye size="1.2em" />{/if} size="1.2em" />{/if}
</button> </button>
<button <button
@@ -342,18 +338,22 @@
api_cfg: $ae_api, api_cfg: $ae_api,
obj_type: 'event_session', obj_type: 'event_session',
obj_id: session_obj.event_session_id, obj_id: session_obj.event_session_id,
fields: { alert: !session_obj.alert }, fields: {
alert: !session_obj.alert
},
log_lvl: 1 log_lvl: 1
}); });
events_func.load_ae_obj_id__event_session({ events_func.load_ae_obj_id__event_session(
{
api_cfg: $ae_api, api_cfg: $ae_api,
event_session_id: session_obj.event_session_id event_session_id:
}); session_obj.event_session_id
}} }
> );
}}>
{#if session_obj?.alert}<Bell {#if session_obj?.alert}<Bell
size="1.2em" size="1.2em" />{:else}<BellOff
/>{:else}<BellOff size="1.2em" />{/if} size="1.2em" />{/if}
</button> </button>
</div> </div>
</td> </td>
@@ -363,9 +363,8 @@
</table> </table>
{:else} {:else}
<div <div
class="flex flex-col items-center justify-center p-20 opacity-50 text-center bg-surface-50 dark:bg-surface-900/50 rounded-lg border border-dashed border-surface-300" class="bg-surface-50 dark:bg-surface-900/50 border-surface-300 flex flex-col items-center justify-center rounded-lg border border-dashed p-20 text-center opacity-50">
> <FileSearch size="3em" class="mx-auto mb-2 opacity-20" />
<FileSearch size="3em" class="mb-2 opacity-20 mx-auto" />
<p class="text-xl">No sessions found matching your criteria.</p> <p class="text-xl">No sessions found matching your criteria.</p>

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
container_class_li?: string | Array<string>; container_class_li?: string | Array<string>;
lq__event_session_obj_li?: any; // New Shared Observable Pattern lq__event_session_obj_li?: any; // New Shared Observable Pattern
event_session_id_random_li?: Array<string>; event_session_id_random_li?: Array<string>;
@@ -12,9 +12,9 @@
hide__launcher_link?: boolean; hide__launcher_link?: boolean;
hide__location_link?: boolean; hide__location_link?: boolean;
log_lvl?: number; log_lvl?: number;
} }
let { let {
container_class_li = [], container_class_li = [],
lq__event_session_obj_li: lq__shared, lq__event_session_obj_li: lq__shared,
event_session_id_random_li = [], event_session_id_random_li = [],
@@ -27,15 +27,15 @@
hide__launcher_link = $bindable(false), hide__launcher_link = $bindable(false),
hide__location_link = $bindable(false), hide__location_link = $bindable(false),
log_lvl = 0 log_lvl = 0
}: Props = $props(); }: Props = $props();
// Imports // Imports
import Comp_event_session_obj_li from './ae_comp__event_session_obj_li.svelte'; import Comp_event_session_obj_li from './ae_comp__event_session_obj_li.svelte';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { db_events } from '$lib/ae_events/db_events'; import { db_events } from '$lib/ae_events/db_events';
// Logic: Use shared observable if provided, otherwise create internal one // Logic: Use shared observable if provided, otherwise create internal one
let lq__event_session_obj_li = $derived.by(() => { let lq__event_session_obj_li = $derived.by(() => {
if (lq__shared) return lq__shared; if (lq__shared) return lq__shared;
return liveQuery(async () => { return liveQuery(async () => {
@@ -53,7 +53,7 @@
} }
return null; return null;
}); });
}); });
</script> </script>
<Comp_event_session_obj_li <Comp_event_session_obj_li
@@ -65,5 +65,4 @@
{hide__launcher_link_legacy} {hide__launcher_link_legacy}
{hide__launcher_link} {hide__launcher_link}
{hide__location_link} {hide__location_link}
{log_lvl} {log_lvl}></Comp_event_session_obj_li>
></Comp_event_session_obj_li>

View File

@@ -1,50 +1,50 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
container_class_li?: string | Array<string>; container_class_li?: string | Array<string>;
// export let event_session_id_random_li: Array<string>; // export let event_session_id_random_li: Array<string>;
lq__event_session_obj_li: any; lq__event_session_obj_li: any;
log_lvl?: number; log_lvl?: number;
show_location_fields?: boolean; show_location_fields?: boolean;
hide_session_code?: boolean; hide_session_code?: boolean;
} }
let { let {
container_class_li = [], container_class_li = [],
lq__event_session_obj_li, lq__event_session_obj_li,
log_lvl = $bindable(0), log_lvl = $bindable(0),
show_location_fields = true, show_location_fields = true,
hide_session_code = false hide_session_code = false
}: Props = $props(); }: Props = $props();
// Imports // Imports
// import type { key_val } from '$lib/ae_stores'; // import type { key_val } from '$lib/ae_stores';
// import { liveQuery } from "dexie"; // import { liveQuery } from "dexie";
import { ae_util } from '$lib/ae_utils/ae_utils'; import { ae_util } from '$lib/ae_utils/ae_utils';
import { ListOrdered } from '@lucide/svelte'; import { ListOrdered } from '@lucide/svelte';
// Imports - events specific // Imports - events specific
// import { events_loc, events_sess, events_slct, events_trigger, events_trig_kv } from '$lib/stores/ae_events_stores'; // import { events_loc, events_sess, events_slct, events_trigger, events_trig_kv } from '$lib/stores/ae_events_stores';
// import { db_events } from "$lib/db_events"; // import { db_events } from "$lib/db_events";
// export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher'; // export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher';
// export let link_to_type: string; // export let link_to_type: string;
// export let link_to_id: string; // export let link_to_id: string;
// *** Functions and Logic // *** Functions and Logic
$effect(() => { $effect(() => {
if (log_lvl) { if (log_lvl) {
console.log( console.log(
`container_class_li: ${container_class_li}; show_location_fields: ${show_location_fields}` `container_class_li: ${container_class_li}; show_location_fields: ${show_location_fields}`
); );
// console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`); // console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`);
} }
}); });
let horiz_scroll_warning: boolean = $state(false); let horiz_scroll_warning: boolean = $state(false);
let horiz_check_element: HTMLElement | null = $state(null); let horiz_check_element: HTMLElement | null = $state(null);
// Check if element is scrolling horizontally // Check if element is scrolling horizontally
$effect(() => { $effect(() => {
if ( if (
horiz_check_element && horiz_check_element &&
horiz_check_element.scrollWidth > horiz_check_element.offsetWidth horiz_check_element.scrollWidth > horiz_check_element.offsetWidth
@@ -55,30 +55,27 @@
horiz_scroll_warning = false; horiz_scroll_warning = false;
// console.log('Element fits within the container. No horizontal scrolling.', horiz_check_element); // console.log('Element fits within the container. No horizontal scrolling.', horiz_check_element);
} }
}); });
</script> </script>
<section <section
class:border-r-2={horiz_scroll_warning} class:border-r-2={horiz_scroll_warning}
class:border-dashed={horiz_scroll_warning} class:border-dashed={horiz_scroll_warning}
class:border-warning-900-100={horiz_scroll_warning} class:border-warning-900-100={horiz_scroll_warning}
class="ae_comp event_session_obj_tbl {container_class_li} container overflow-auto max-w-screen" class="ae_comp event_session_obj_tbl {container_class_li} container max-w-screen overflow-auto">
>
{#if $lq__event_session_obj_li && $lq__event_session_obj_li?.length} {#if $lq__event_session_obj_li && $lq__event_session_obj_li?.length}
<div <div
bind:this={horiz_check_element} bind:this={horiz_check_element}
id="tbl_container" id="tbl_container"
class="space-y-2 pb-48" class="space-y-2 pb-48">
>
<h2 class="h3"> <h2 class="h3">
<span class="text-base"> Results: </span> <span class="text-base"> Results: </span>
{#if $lq__event_session_obj_li?.length} {#if $lq__event_session_obj_li?.length}
<span <span
class="text-3xl font-bold preset-filled-success-100-900 px-4 rounded-lg" class="preset-filled-success-100-900 rounded-lg px-4 text-3xl font-bold"
title="Count {$lq__event_session_obj_li.length ?? title="Count {$lq__event_session_obj_li.length ??
'None'}" 'None'}">
>
<ListOrdered size="1em" class="mx-4" /> <ListOrdered size="1em" class="mx-4" />
{$lq__event_session_obj_li.length ?? 'None'}&times; {$lq__event_session_obj_li.length ?? 'None'}&times;
</span> </span>
@@ -86,8 +83,7 @@
</h2> </h2>
<table <table
class="table table-auto table-striped w-full text-xs lg:text-sm" class="table-striped table w-full table-auto text-xs lg:text-sm">
>
<thead class=""> <thead class="">
<tr> <tr>
<th class="px-4 py-2">Name</th> <th class="px-4 py-2">Name</th>
@@ -105,8 +101,7 @@
<td class="px-4 py-2"> <td class="px-4 py-2">
<a <a
href="/events/{event_session_obj?.event_id}/session/{event_session_obj?.event_session_id}" href="/events/{event_session_obj?.event_id}/session/{event_session_obj?.event_session_id}"
class="text-blue-500 hover:text-blue-800 hover:underline" class="text-blue-500 hover:text-blue-800 hover:underline">
>
{event_session_obj?.name} {event_session_obj?.name}
</a> </a>
</td> </td>

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
// Exports // Exports
container_class_li?: string | Array<string>; container_class_li?: string | Array<string>;
// export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher' // export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher'
@@ -11,9 +11,9 @@
log_lvl?: number; log_lvl?: number;
show_location_fields?: boolean; show_location_fields?: boolean;
hide_session_code?: boolean; hide_session_code?: boolean;
} }
let { let {
container_class_li = [], container_class_li = [],
// event_session_id_random_li, // event_session_id_random_li,
event_session_obj_li = $bindable(), event_session_obj_li = $bindable(),
@@ -22,43 +22,43 @@
log_lvl = $bindable(0), log_lvl = $bindable(0),
show_location_fields = true, show_location_fields = true,
hide_session_code = false hide_session_code = false
}: Props = $props(); }: Props = $props();
// Imports // Imports
import Comp_event_session_obj_tbl from './ae_comp__event_session_obj_tbl.svelte'; import Comp_event_session_obj_tbl from './ae_comp__event_session_obj_tbl.svelte';
import { liveQuery } from 'dexie'; import { liveQuery } from 'dexie';
import { import {
events_loc, events_loc,
events_sess, events_sess,
events_slct, events_slct,
events_trigger events_trigger
} from '$lib/stores/ae_events_stores'; } from '$lib/stores/ae_events_stores';
import { db_events } from '$lib/ae_events/db_events'; import { db_events } from '$lib/ae_events/db_events';
$effect(() => { $effect(() => {
if (log_lvl) { if (log_lvl) {
console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`); console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`);
} }
}); });
// Variables // Variables
// let ae_promises: key_val = {}; // let ae_promises: key_val = {};
// let ae_tmp: key_val = {}; // let ae_tmp: key_val = {};
// let ae_triggers: key_val = {}; // let ae_triggers: key_val = {};
let event_session_id_random_li: Array<string> = $state([]); let event_session_id_random_li: Array<string> = $state([]);
let dq__where_type_id_val = $derived(`${link_to_type}_id_random`); let dq__where_type_id_val = $derived(`${link_to_type}_id_random`);
let dq__where_eq_id_val = $derived(link_to_id); let dq__where_eq_id_val = $derived(link_to_id);
// *** Functions and Logic // *** Functions and Logic
// OPTIMIZATION: If event_session_obj_li is provided (from API/reports), // OPTIMIZATION: If event_session_obj_li is provided (from API/reports),
// use it directly instead of fetching from IDB. The API returns fully // use it directly instead of fetching from IDB. The API returns fully
// enriched data with all joined fields (location names, file counts, etc.) // enriched data with all joined fields (location names, file counts, etc.)
// that aren't available in the base IDB session table. // that aren't available in the base IDB session table.
let lq__event_session_obj_li = $derived( let lq__event_session_obj_li = $derived(
liveQuery(async () => { liveQuery(async () => {
let results: any; let results: any;
@@ -129,7 +129,7 @@
// return null; // return null;
// } // }
}) })
); );
</script> </script>
{#if event_session_obj_li && event_session_obj_li?.length} {#if event_session_obj_li && event_session_obj_li?.length}
@@ -138,10 +138,9 @@
{lq__event_session_obj_li} {lq__event_session_obj_li}
{show_location_fields} {show_location_fields}
{hide_session_code} {hide_session_code}
{log_lvl} {log_lvl}></Comp_event_session_obj_tbl>
></Comp_event_session_obj_tbl>
{:else} {:else}
<section class="grow px-1 md:px-2 pb-28 flex flex-col gap-1 items-center"> <section class="flex grow flex-col items-center gap-1 px-1 pb-28 md:px-2">
<p>No sessions available to show in table.</p> <p>No sessions available to show in table.</p>
</section> </section>
{/if} {/if}

View File

@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { import {
ae_snip, ae_snip,
ae_loc, ae_loc,
ae_sess, ae_sess,
@@ -7,10 +7,18 @@
ae_trig, ae_trig,
slct, slct,
slct_trigger slct_trigger
} from '$lib/stores/ae_stores'; } from '$lib/stores/ae_stores';
import { TrendingUp, MapPin, Wrench, Search, GraduationCap, Plane, Settings } from '@lucide/svelte'; import {
TrendingUp,
MapPin,
Wrench,
Search,
GraduationCap,
Plane,
Settings
} from '@lucide/svelte';
interface Props { interface Props {
// import { events_loc, events_sess, events_slct, events_trigger, events_trig_kv } from '$lib/stores/ae_events_stores'; // import { events_loc, events_sess, events_slct, events_trigger, events_trig_kv } from '$lib/stores/ae_events_stores';
hide?: boolean; hide?: boolean;
event_id?: null | string; event_id?: null | string;
@@ -25,9 +33,9 @@
events__session_id?: null | string; // event_session_id — used for "Back to Session" link only events__session_id?: null | string; // event_session_id — used for "Back to Session" link only
events__session_search?: boolean; // event_id events__session_search?: boolean; // event_id
events__launcher_extra_params?: string; // extra URL params appended to the launcher link (e.g. 'iframe=true&launcher_menu=hide') events__launcher_extra_params?: string; // extra URL params appended to the launcher link (e.g. 'iframe=true&launcher_menu=hide')
} }
let { let {
hide = true, hide = true,
event_id = null, event_id = null,
ae_core = false, ae_core = false,
@@ -40,94 +48,87 @@
events__settings = false, events__settings = false,
events__session_id = null, events__session_id = null,
events__session_search = false events__session_search = false
}: Props = $props(); }: Props = $props();
// Build launcher URL segments separately so the href template stays simple (avoids ternaries in href attr) // Build launcher URL segments separately so the href template stays simple (avoids ternaries in href attr)
let launcher_loc_seg = $derived(events__launcher_id ? `/${events__launcher_id}` : ''); let launcher_loc_seg = $derived(
let launcher_sess_qry = $derived.by(() => { events__launcher_id ? `/${events__launcher_id}` : ''
);
let launcher_sess_qry = $derived.by(() => {
const parts: string[] = []; const parts: string[] = [];
if (events__launcher_session_id) parts.push(`session_id=${events__launcher_session_id}`); if (events__launcher_session_id)
if (events__launcher_extra_params) parts.push(events__launcher_extra_params); parts.push(`session_id=${events__launcher_session_id}`);
if (events__launcher_extra_params)
parts.push(events__launcher_extra_params);
return parts.length ? `?${parts.join('&')}` : ''; return parts.length ? `?${parts.join('&')}` : '';
}); });
</script> </script>
<!-- This is for common navigation links. --> <!-- This is for common navigation links. -->
<div <div
class="ae_comp__events_menu_nav w-full flex flex-row flex-wrap gap-1.5 items-center justify-between" class="ae_comp__events_menu_nav flex w-full flex-row flex-wrap items-center justify-between gap-1.5"
class:hidden={hide} class:hidden={hide}>
>
<span <span
class="ae_menu__navigation_options flex flex-row flex-wrap gap-0.5 items-center justify-around" class="ae_menu__navigation_options flex flex-row flex-wrap items-center justify-around gap-0.5">
>
<a <a
href="/core" href="/core"
class="btn btn-sm mx-1 ae_btn_warning" class="btn btn-sm ae_btn_warning mx-1"
class:hidden={!ae_core} class:hidden={!ae_core}>
>
<Settings size="1em" aria-hidden="true" /> <Settings size="1em" aria-hidden="true" />
Æ Core Æ Core
</a> </a>
<a <a
href="/events/{event_id}/reports" href="/events/{event_id}/reports"
class="btn btn-sm mx-1 ae_btn_info" class="btn btn-sm ae_btn_info mx-1"
class:hidden={!events__reports} class:hidden={!events__reports}>
>
<TrendingUp size="1em" aria-hidden="true" /> <TrendingUp size="1em" aria-hidden="true" />
Pres Mgmt Reports Pres Mgmt Reports
</a> </a>
<a <a
href="/events/{event_id}/locations" href="/events/{event_id}/locations"
class="btn btn-sm mx-1 ae_btn_info" class="btn btn-sm ae_btn_info mx-1"
class:hidden={!events__locations} class:hidden={!events__locations}>
>
<MapPin size="1em" aria-hidden="true" /> <MapPin size="1em" aria-hidden="true" />
Locations Locations
</a> </a>
<a <a
href="/events/{event_id}/settings" href="/events/{event_id}/settings"
class="btn btn-sm mx-1 ae_btn_warning" class="btn btn-sm ae_btn_warning mx-1"
class:hidden={!events__settings} class:hidden={!events__settings}>
>
<Wrench size="1em" aria-hidden="true" /> <Wrench size="1em" aria-hidden="true" />
Admin Tools Admin Tools
</a> </a>
</span> </span>
<span <span
class="ae_menu__navigation_options flex flex-row flex-wrap gap-0.5 items-center justify-around" class="ae_menu__navigation_options flex flex-row flex-wrap items-center justify-around gap-0.5">
>
<a <a
href="/events/{event_id}/pres_mgmt" href="/events/{event_id}/pres_mgmt"
class="btn btn-sm mx-1 ae_btn_info" class="btn btn-sm ae_btn_info mx-1"
class:hidden={!events__session_search} class:hidden={!events__session_search}>
>
<Search size="1em" aria-hidden="true" /> <Search size="1em" aria-hidden="true" />
Session Search Session Search
</a> </a>
<a <a
href="/events/{event_id}/session/{events__session_id}" href="/events/{event_id}/session/{events__session_id}"
class="btn btn-sm mx-1 ae_btn_info" class="btn btn-sm ae_btn_info mx-1"
class:hidden={!events__session_id} class:hidden={!events__session_id}>
>
<GraduationCap size="1em" aria-hidden="true" /> <GraduationCap size="1em" aria-hidden="true" />
Back to Session Back to Session
</a> </a>
<!-- eslint-disable-next-line svelte/valid-compile --> <!-- eslint-disable-next-line svelte/valid-compile -->
<a <a
href="/events/{event_id}/launcher{launcher_loc_seg}{launcher_sess_qry}" href="/events/{event_id}/launcher{launcher_loc_seg}{launcher_sess_qry}"
class="btn btn-sm mx-1 ae_btn_info" class="btn btn-sm ae_btn_info mx-1"
class:hidden={!event_id} class:hidden={!event_id}>
>
<Plane size="1em" aria-hidden="true" /> <Plane size="1em" aria-hidden="true" />
Launcher Launcher
</a> </a>
<a <a
href="/events/{event_id}/location/{events__location_id}" href="/events/{event_id}/location/{events__location_id}"
class="btn btn-sm mx-1 ae_btn_info" class="btn btn-sm ae_btn_info mx-1"
class:hidden={!events__location_id} class:hidden={!events__location_id}>
>
<MapPin size="1em" aria-hidden="true" /> <MapPin size="1em" aria-hidden="true" />
Session Location Session Location
</a> </a>

View File

@@ -1,11 +1,11 @@
<script lang="ts"> <script lang="ts">
interface Props { interface Props {
hide?: boolean; hide?: boolean;
} }
let { hide = true }: Props = $props(); let { hide = true }: Props = $props();
import { import {
ae_snip, ae_snip,
ae_loc, ae_loc,
ae_sess, ae_sess,
@@ -13,31 +13,50 @@
ae_trig, ae_trig,
slct, slct,
slct_trigger slct_trigger
} from '$lib/stores/ae_stores'; } from '$lib/stores/ae_stores';
import { import {
events_loc, events_loc,
events_sess, events_sess,
events_slct, events_slct,
events_trigger, events_trigger,
events_trig_kv events_trig_kv
} from '$lib/stores/ae_events_stores'; } from '$lib/stores/ae_events_stores';
import { Ban, Barcode, CheckCircle, ChevronDown, ChevronUp, Eye, EyeOff, List, MapPin, Pencil, Plane, QrCode, Save, Send, Sparkles, StickyNote, ToggleLeft, ToggleRight, UserRound, Wand2 } from '@lucide/svelte'; import {
Ban,
Barcode,
CheckCircle,
ChevronDown,
ChevronUp,
Eye,
EyeOff,
List,
MapPin,
Pencil,
Plane,
QrCode,
Save,
Send,
Sparkles,
StickyNote,
ToggleLeft,
ToggleRight,
UserRound,
Wand2
} from '@lucide/svelte';
</script> </script>
<!-- New standard events module menu 2025-06-20 --> <!-- New standard events module menu 2025-06-20 -->
<div <div
class="ae_comp__pres_mgmt_menu_opts w-full border-t border-gray-300 mt-1" class="ae_comp__pres_mgmt_menu_opts mt-1 w-full border-t border-gray-300"
class:hidden={hide} class:hidden={hide}>
> <h2 class="pb-1 text-center text-sm font-semibold">
<h2 class="text-sm font-semibold text-center pb-1">
<button <button
type="button" type="button"
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.hide__menu_opts = $events_loc.pres_mgmt.hide__menu_opts =
!$events_loc.pres_mgmt.hide__menu_opts; !$events_loc.pres_mgmt.hide__menu_opts;
}} }}
class="btn btn-sm preset-tonal-info border border-info-500" class="btn btn-sm preset-tonal-info border-info-500 border">
>
{#if $events_loc.pres_mgmt.hide__menu_opts} {#if $events_loc.pres_mgmt.hide__menu_opts}
<ChevronUp size="1em" class="m-1" /> <ChevronUp size="1em" class="m-1" />
{:else} {:else}
@@ -53,28 +72,24 @@
</h2> </h2>
<div <div
class="flex flex-row flex-wrap gap-1 items-center justify-between" class="flex flex-row flex-wrap items-center justify-between gap-1"
class:hidden={$events_loc.pres_mgmt.hide__menu_opts} class:hidden={$events_loc.pres_mgmt.hide__menu_opts}>
>
{#if $ae_loc.authenticated_access} {#if $ae_loc.authenticated_access}
<div class="flex flex-col gap-1 items-end justify-center"> <div class="flex flex-col items-end justify-center gap-1">
<span class="flex flex-col gap-1 items-end justify-center"> <span class="flex flex-col items-end justify-center gap-1">
<!-- Max person select options --> <!-- Max person select options -->
<span <span
class="flex flex-row gap-1 items-center justify-around w-full" class="flex w-full flex-row items-center justify-around gap-1">
>
<label <label
class="text-sm w-32 text-right" class="w-32 text-right text-sm"
for="qry_limit__people" for="qry_limit__people">
>
Max people: Max people:
</label> </label>
<!-- Not using: $events_loc.pres_mgmt.qry_limit__people --> <!-- Not using: $events_loc.pres_mgmt.qry_limit__people -->
<select <select
id="qry_limit__people" id="qry_limit__people"
bind:value={$ae_loc.person.qry_limit__people} bind:value={$ae_loc.person.qry_limit__people}
class="select w-20 text-sm preset-tonal-surface px-1" class="select preset-tonal-surface w-20 px-1 text-sm">
>
<option value="">-- not set --</option> <option value="">-- not set --</option>
<option value={25}>25</option> <option value={25}>25</option>
<option value={50}>50</option> <option value={50}>50</option>
@@ -91,12 +106,10 @@
<!-- Max presenters select options --> <!-- Max presenters select options -->
<span <span
class="flex flex-row gap-1 items-center justify-around w-full" class="flex w-full flex-row items-center justify-around gap-1">
>
<label <label
class="text-sm w-32 text-right" class="w-32 text-right text-sm"
for="qry_limit__presenters" for="qry_limit__presenters">
>
Max presenters: Max presenters:
</label> </label>
<select <select
@@ -104,8 +117,7 @@
bind:value={ bind:value={
$events_loc.pres_mgmt.qry_limit__presenters $events_loc.pres_mgmt.qry_limit__presenters
} }
class="select w-20 text-sm preset-tonal-surface px-1" class="select preset-tonal-surface w-20 px-1 text-sm">
>
<option value="">-- not set --</option> <option value="">-- not set --</option>
<option value={25}>25</option> <option value={25}>25</option>
<option value={50}>50</option> <option value={50}>50</option>
@@ -123,12 +135,10 @@
<!-- Max sessions select options --> <!-- Max sessions select options -->
<span <span
class="flex flex-row gap-1 items-center justify-around w-full" class="flex w-full flex-row items-center justify-around gap-1">
>
<label <label
class="text-sm w-32 text-right" class="w-32 text-right text-sm"
for="qry_limit__sessions" for="qry_limit__sessions">
>
Max sessions: Max sessions:
</label> </label>
<select <select
@@ -136,8 +146,7 @@
bind:value={ bind:value={
$events_loc.pres_mgmt.qry_limit__sessions $events_loc.pres_mgmt.qry_limit__sessions
} }
class="select w-20 text-sm preset-tonal-surface px-1" class="select preset-tonal-surface w-20 px-1 text-sm">
>
<option value="">-- not set --</option> <option value="">-- not set --</option>
<option value={25}>25</option> <option value={25}>25</option>
<option value={50}>50</option> <option value={50}>50</option>
@@ -150,19 +159,16 @@
<!-- Max files select options --> <!-- Max files select options -->
<span <span
class="flex flex-row gap-1 items-center justify-around w-full" class="flex w-full flex-row items-center justify-around gap-1">
>
<label <label
class="text-sm w-32 text-right" class="w-32 text-right text-sm"
for="qry_limit__files" for="qry_limit__files">
>
Max files: Max files:
</label> </label>
<select <select
id="qry_limit__files" id="qry_limit__files"
bind:value={$events_loc.pres_mgmt.qry_limit__files} bind:value={$events_loc.pres_mgmt.qry_limit__files}
class="select w-20 text-sm preset-tonal-surface px-1" class="select preset-tonal-surface w-20 px-1 text-sm">
>
<option value="">-- not set --</option> <option value="">-- not set --</option>
<option value={25}>25</option> <option value={25}>25</option>
<option value={50}>50</option> <option value={50}>50</option>
@@ -174,7 +180,7 @@
</span> </span>
</span> </span>
<span class="flex flex-col gap-1 items-end justify-center"> <span class="flex flex-col items-end justify-center gap-1">
<!-- Toggle between the showing hidden sessions --> <!-- Toggle between the showing hidden sessions -->
<!-- qry_hidden = all, not_hidden, hidden --> <!-- qry_hidden = all, not_hidden, hidden -->
<button <button
@@ -186,10 +192,13 @@
$events_loc.pres_mgmt.qry_hidden = 'all'; $events_loc.pres_mgmt.qry_hidden = 'all';
} }
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle between showing hidden sessions" title="Toggle between showing hidden sessions">
> {#if $events_loc.pres_mgmt.qry_hidden == 'all'}<ToggleRight
{#if $events_loc.pres_mgmt.qry_hidden == 'all'}<ToggleRight size="1em" class="m-1" />{:else}<ToggleLeft size="1em" class="m-1" />{/if} size="1em"
class="m-1" />{:else}<ToggleLeft
size="1em"
class="m-1" />{/if}
{#if $events_loc.pres_mgmt.qry_hidden == 'all'} {#if $events_loc.pres_mgmt.qry_hidden == 'all'}
<span class="grow"> <span class="grow">
<EyeOff size="1em" class="m-1" /> <EyeOff size="1em" class="m-1" />
@@ -218,10 +227,13 @@
$events_loc.pres_mgmt.qry_enabled = 'all'; $events_loc.pres_mgmt.qry_enabled = 'all';
} }
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle between showing disabled sessions" title="Toggle between showing disabled sessions">
> {#if $events_loc.pres_mgmt.qry_enabled == 'all'}<ToggleRight
{#if $events_loc.pres_mgmt.qry_enabled == 'all'}<ToggleRight size="1em" class="m-1" />{:else}<ToggleLeft size="1em" class="m-1" />{/if} size="1em"
class="m-1" />{:else}<ToggleLeft
size="1em"
class="m-1" />{/if}
{#if $events_loc.pres_mgmt.qry_enabled == 'all'} {#if $events_loc.pres_mgmt.qry_enabled == 'all'}
<span class="grow"> <span class="grow">
<Ban size="1em" class="m-1" /> <Ban size="1em" class="m-1" />
@@ -239,19 +251,18 @@
</div> </div>
{/if} {/if}
<div class="flex flex-col flex-wrap gap-1 items-center justify-evenly"> <div class="flex flex-col flex-wrap items-center justify-evenly gap-1">
<button <button
type="button" type="button"
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.save_search_text = $events_loc.pres_mgmt.save_search_text =
!$events_loc.pres_mgmt.save_search_text; !$events_loc.pres_mgmt.save_search_text;
}} }}
class="btn btn-sm justify-between w-full text-center" class="btn btn-sm w-full justify-between text-center"
class:ae_btn_surface={$events_loc.pres_mgmt.save_search_text} class:ae_btn_surface={$events_loc.pres_mgmt.save_search_text}
class:ae_btn_surface_outlined={!$events_loc.pres_mgmt class:ae_btn_surface_outlined={!$events_loc.pres_mgmt
.save_search_text} .save_search_text}
title="Save the search text for this session search?" title="Save the search text for this session search?">
>
{#if $events_loc.pres_mgmt.save_search_text} {#if $events_loc.pres_mgmt.save_search_text}
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
@@ -274,8 +285,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.hide__session_msg = true; $events_loc.pres_mgmt.hide__session_msg = true;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<StickyNote size="1em" class="m-1" /> <StickyNote size="1em" class="m-1" />
@@ -288,8 +298,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.hide__session_msg = false; $events_loc.pres_mgmt.hide__session_msg = false;
}} }}
class="btn btn-sm ae_btn_surface_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<StickyNote size="1em" class="m-1" /> <StickyNote size="1em" class="m-1" />
@@ -307,8 +316,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.hide__session_code = true; $events_loc.pres_mgmt.hide__session_code = true;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<Barcode size="1em" class="m-1" /> <Barcode size="1em" class="m-1" />
@@ -321,8 +329,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.hide__session_code = false; $events_loc.pres_mgmt.hide__session_code = false;
}} }}
class="btn btn-sm ae_btn_surface_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<Barcode size="1em" class="m-1" /> <Barcode size="1em" class="m-1" />
@@ -333,17 +340,16 @@
{/if} {/if}
</div> </div>
<div class="flex flex-col gap-1 items-center justify-center"> <div class="flex flex-col items-center justify-center gap-1">
{#if $ae_loc.trusted_access} {#if $ae_loc.trusted_access}
<div class="flex flex-col gap-1 items-center justify-center"> <div class="flex flex-col items-center justify-center gap-1">
{#if $events_loc.pres_mgmt.show__copy_access_link} {#if $events_loc.pres_mgmt.show__copy_access_link}
<button <button
type="button" type="button"
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show__copy_access_link = false; $events_loc.pres_mgmt.show__copy_access_link = false;
}} }}
class="btn btn-sm w-full ae_btn_surface" class="btn btn-sm ae_btn_surface w-full">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
Showing Copy Access Link Showing Copy Access Link
</button> </button>
@@ -353,8 +359,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show__copy_access_link = true; $events_loc.pres_mgmt.show__copy_access_link = true;
}} }}
class="btn btn-sm w-full ae_btn_surface_outlined" class="btn btn-sm ae_btn_surface_outlined w-full">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
Show Copy Access Link? Show Copy Access Link?
</button> </button>
@@ -366,8 +371,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show__email_access_link = false; $events_loc.pres_mgmt.show__email_access_link = false;
}} }}
class="btn btn-sm w-full ae_btn_surface" class="btn btn-sm ae_btn_surface w-full">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
Showing Email Access Link Showing Email Access Link
</button> </button>
@@ -377,8 +381,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show__email_access_link = true; $events_loc.pres_mgmt.show__email_access_link = true;
}} }}
class="btn btn-sm w-full ae_btn_surface_outlined" class="btn btn-sm ae_btn_surface_outlined w-full">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
Show Email Access Link? Show Email Access Link?
</button> </button>
@@ -387,16 +390,15 @@
{/if} {/if}
{#if $ae_loc.authenticated_access} {#if $ae_loc.authenticated_access}
<div class="flex flex-col gap-1 items-end justify-center"> <div class="flex flex-col items-end justify-center gap-1">
{#if $events_loc.pres_mgmt.show_content__session_qr} {#if $events_loc.pres_mgmt.show_content__session_qr}
<button <button
type="button" type="button"
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__session_qr = false; $events_loc.pres_mgmt.show_content__session_qr = false;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Showing Session QR Code" title="Showing Session QR Code">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<QrCode size="1em" class="m-1" /> <QrCode size="1em" class="m-1" />
@@ -409,9 +411,8 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__session_qr = true; $events_loc.pres_mgmt.show_content__session_qr = true;
}} }}
class="btn btn-sm ae_btn_surface_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center"
title="Show Session QR Code" title="Show Session QR Code">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<QrCode size="1em" class="m-1" /> <QrCode size="1em" class="m-1" />
@@ -426,9 +427,8 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__presenter_qr = false; $events_loc.pres_mgmt.show_content__presenter_qr = false;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Showing Presenter QR Code" title="Showing Presenter QR Code">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<QrCode size="1em" class="m-1" /> <QrCode size="1em" class="m-1" />
@@ -441,9 +441,8 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__presenter_qr = true; $events_loc.pres_mgmt.show_content__presenter_qr = true;
}} }}
class="btn btn-sm ae_btn_surface_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center"
title="Show Presenter QR Code" title="Show Presenter QR Code">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<QrCode size="1em" class="m-1" /> <QrCode size="1em" class="m-1" />
@@ -456,7 +455,7 @@
</div> </div>
{#if $ae_loc.authenticated_access} {#if $ae_loc.authenticated_access}
<div class="flex flex-col gap-1 items-center justify-center"> <div class="flex flex-col items-center justify-center gap-1">
<!-- Show/Hide launcher links (new version) --> <!-- Show/Hide launcher links (new version) -->
<button <button
type="button" type="button"
@@ -464,9 +463,12 @@
$events_loc.pres_mgmt.hide__launcher_link = $events_loc.pres_mgmt.hide__launcher_link =
!$events_loc.pres_mgmt.hide__launcher_link; !$events_loc.pres_mgmt.hide__launcher_link;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center">
> {#if $events_loc.pres_mgmt.hide__launcher_link}<ToggleLeft
{#if $events_loc.pres_mgmt.hide__launcher_link}<ToggleLeft size="1em" class="m-1" />{:else}<ToggleRight size="1em" class="m-1" />{/if} size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow"> <span class="grow">
<Plane size="1em" class="m-1" /> <Plane size="1em" class="m-1" />
{$events_loc.pres_mgmt.hide__launcher_link {$events_loc.pres_mgmt.hide__launcher_link
@@ -482,9 +484,12 @@
$events_loc.pres_mgmt.hide__launcher_link_legacy = $events_loc.pres_mgmt.hide__launcher_link_legacy =
!$events_loc.pres_mgmt.hide__launcher_link_legacy; !$events_loc.pres_mgmt.hide__launcher_link_legacy;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center">
> {#if $events_loc.pres_mgmt.hide__launcher_link_legacy}<ToggleLeft
{#if $events_loc.pres_mgmt.hide__launcher_link_legacy}<ToggleLeft size="1em" class="m-1" />{:else}<ToggleRight size="1em" class="m-1" />{/if} size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow"> <span class="grow">
<Send size="1em" class="m-1" /> <Send size="1em" class="m-1" />
{$events_loc.pres_mgmt.hide__launcher_link_legacy {$events_loc.pres_mgmt.hide__launcher_link_legacy
@@ -500,9 +505,12 @@
$events_loc.pres_mgmt.hide__location_link = $events_loc.pres_mgmt.hide__location_link =
!$events_loc.pres_mgmt.hide__location_link; !$events_loc.pres_mgmt.hide__location_link;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center">
> {#if $events_loc.pres_mgmt.hide__location_link}<ToggleLeft
{#if $events_loc.pres_mgmt.hide__location_link}<ToggleLeft size="1em" class="m-1" />{:else}<ToggleRight size="1em" class="m-1" />{/if} size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow"> <span class="grow">
<MapPin size="1em" class="m-1" /> <MapPin size="1em" class="m-1" />
{$events_loc.pres_mgmt.hide__location_link {$events_loc.pres_mgmt.hide__location_link
@@ -519,10 +527,13 @@
!$events_loc.pres_mgmt !$events_loc.pres_mgmt
.hide__session_li_location_field; .hide__session_li_location_field;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle showing the Location column in session lists and tables" title="Toggle showing the Location column in session lists and tables">
> {#if $events_loc.pres_mgmt.hide__session_li_location_field}<ToggleLeft
{#if $events_loc.pres_mgmt.hide__session_li_location_field}<ToggleLeft size="1em" class="m-1" />{:else}<ToggleRight size="1em" class="m-1" />{/if} size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow"> <span class="grow">
<!-- <span class="fas fa-door-open m-1"></span> --> <!-- <span class="fas fa-door-open m-1"></span> -->
{$events_loc.pres_mgmt.hide__session_li_location_field {$events_loc.pres_mgmt.hide__session_li_location_field
@@ -538,10 +549,13 @@
$events_loc.pres_mgmt.hide__session_li_poc_field = $events_loc.pres_mgmt.hide__session_li_poc_field =
!$events_loc.pres_mgmt.hide__session_li_poc_field; !$events_loc.pres_mgmt.hide__session_li_poc_field;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center"
title="Toggle showing the POC column in session lists and tables" title="Toggle showing the POC column in session lists and tables">
> {#if $events_loc.pres_mgmt.hide__session_li_poc_field}<ToggleLeft
{#if $events_loc.pres_mgmt.hide__session_li_poc_field}<ToggleLeft size="1em" class="m-1" />{:else}<ToggleRight size="1em" class="m-1" />{/if} size="1em"
class="m-1" />{:else}<ToggleRight
size="1em"
class="m-1" />{/if}
<span class="grow"> <span class="grow">
<!-- <span class="fas fa-user-tie m-1"></span> --> <!-- <span class="fas fa-user-tie m-1"></span> -->
{$events_loc.pres_mgmt.hide__session_li_poc_field {$events_loc.pres_mgmt.hide__session_li_poc_field
@@ -552,8 +566,7 @@
<!-- These are related to more content showing in lists. --> <!-- These are related to more content showing in lists. -->
<span <span
class="flex flex-col flex-wrap gap-1 items-center justify-evenly" class="flex flex-col flex-wrap items-center justify-evenly gap-1">
>
{#if $events_loc.pres_mgmt.show_content__session_files} {#if $events_loc.pres_mgmt.show_content__session_files}
<button <button
type="button" type="button"
@@ -561,8 +574,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__session_files = false; $events_loc.pres_mgmt.show_content__session_files = false;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<List size="1em" class="m-1" /> <List size="1em" class="m-1" />
@@ -576,8 +588,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__session_files = true; $events_loc.pres_mgmt.show_content__session_files = true;
}} }}
class="btn btn-sm ae_btn_surface_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<List size="1em" class="m-1" /> <List size="1em" class="m-1" />
@@ -593,8 +604,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__session_presentations = false; $events_loc.pres_mgmt.show_content__session_presentations = false;
}} }}
class="btn btn-sm ae_btn_surface justify-between w-full text-center" class="btn btn-sm ae_btn_surface w-full justify-between text-center">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<List size="1em" class="m-1" /> <List size="1em" class="m-1" />
@@ -608,8 +618,7 @@
onclick={() => { onclick={() => {
$events_loc.pres_mgmt.show_content__session_presentations = true; $events_loc.pres_mgmt.show_content__session_presentations = true;
}} }}
class="btn btn-sm ae_btn_surface_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_surface_outlined w-full justify-between text-center">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<List size="1em" class="m-1" /> <List size="1em" class="m-1" />
@@ -622,8 +631,7 @@
{/if} {/if}
<div <div
class="flex flex-row flex-wrap gap-1 items-center justify-evenly max-w-56" class="flex max-w-56 flex-row flex-wrap items-center justify-evenly gap-1">
>
{#if $ae_loc?.trusted_access} {#if $ae_loc?.trusted_access}
{#if $ae_loc?.edit_mode} {#if $ae_loc?.edit_mode}
<button <button
@@ -631,9 +639,8 @@
onclick={() => { onclick={() => {
$ae_loc.edit_mode = false; $ae_loc.edit_mode = false;
}} }}
class="btn btn-sm ae_btn_warning justify-between w-full text-center" class="btn btn-sm ae_btn_warning w-full justify-between text-center"
title="Turn off edit mode" title="Turn off edit mode">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<Pencil size="1em" class="m-1" /> <Pencil size="1em" class="m-1" />
@@ -646,9 +653,8 @@
onclick={() => { onclick={() => {
$ae_loc.edit_mode = true; $ae_loc.edit_mode = true;
}} }}
class="btn btn-sm ae_btn_warning_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_warning_outlined w-full justify-between text-center"
title="Turn on edit mode" title="Turn on edit mode">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<UserRound size="1em" class="m-1" /> <UserRound size="1em" class="m-1" />
@@ -663,9 +669,8 @@
onclick={() => { onclick={() => {
$ae_loc.adv_mode = false; $ae_loc.adv_mode = false;
}} }}
class="btn btn-sm ae_btn_warning justify-between w-full text-center" class="btn btn-sm ae_btn_warning w-full justify-between text-center"
title="Turn off advanced mode" title="Turn off advanced mode">
>
<ToggleRight size="1em" class="m-1" /> <ToggleRight size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<Sparkles size="1em" class="m-1" /> <Sparkles size="1em" class="m-1" />
@@ -678,9 +683,8 @@
onclick={() => { onclick={() => {
$ae_loc.adv_mode = true; $ae_loc.adv_mode = true;
}} }}
class="btn btn-sm ae_btn_warning_outlined justify-between w-full text-center" class="btn btn-sm ae_btn_warning_outlined w-full justify-between text-center"
title="Turn on advanced mode" title="Turn on advanced mode">
>
<ToggleLeft size="1em" class="m-1" /> <ToggleLeft size="1em" class="m-1" />
<span class="grow"> <span class="grow">
<Wand2 size="1em" class="m-1" /> <Wand2 size="1em" class="m-1" />