Files
OSIT-AE-App-Svelte/src/routes/events/[event_id]/(launcher)/launcher/+layout.svelte

1277 lines
45 KiB
Svelte

<script lang="ts">
let log_lvl: number = $state(1);
interface Props {
/** @type {import('./$types').LayoutData} */
data: any;
children?: import('svelte').Snippet;
}
let { data, children }: Props = $props();
// *** Import Svelte specific
// import { onMount, tick } from 'svelte';
import { goto } from '$app/navigation';
import { sineIn } from 'svelte/easing';
// *** Import other supporting libraries
import { liveQuery } from "dexie";
import { Drawer, Footer, Modal } from 'flowbite-svelte';
import { listen, idle, onIdle } from 'svelte-idle'
import {
// Brain,
// House, Library,
// RefreshCw,
Satellite
} from '@lucide/svelte';
// import { AppBar } from '@skeletonlabs/skeleton-svelte';
// *** Import Aether specific variables and functions
import type { key_val } from '$lib/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import { api } from '$lib/api';
import { db_events } from '$lib/ae_events/db_events';
import { ae_snip, ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger, time } from '$lib/ae_stores';
import { events_loc, events_sess, events_slct, events_trigger, events_trig } from '$lib/ae_events_stores';
// import { events_func } from '$lib/ae_events_functions';
import Launcher_cfg from '../launcher_cfg.svelte';
import Launcher_menu from '../launcher_menu.svelte';
import Launcher_session_view from '../launcher_session_view.svelte';
import Element_websocket_v2 from '$lib/element_websocket_v2.svelte';
// *** Set initial variables
// Quickly save the data passed from the parent(s) to the Svelte stores, localStorage, and other.
$slct.account_id = data.account_id;
// console.log(`$slct.account_id = `, $slct.account_id);
let ae_acct = data[$slct.account_id];
// console.log(`ae_acct = `, ae_acct);
$ae_sess.disable_sys_nav = true;
$ae_sess.disable_sys_header = true;
$ae_sess.disable_sys_footer = true;
// This is a just in case check...
if (!$events_loc?.launcher) {
$events_loc.launcher = {
app_mode: 'default',
controller: 'local',
controller_group_code: 'launcher-00',
ws_connect: false,
hide_drawer__cfg: true,
hide_drawer__debug: true,
}
}
// svelte-ignore state_referenced_locally
if (log_lvl > 1) {
console.log(`$events_loc.launcher:`, $events_loc.launcher);
}
// svelte-ignore state_referenced_locally
if (log_lvl) {
console.log(`event_id: ${data.params.event_id}`);
console.log(`event_location_id: ${data.params.event_location_id}`);
console.log(`event_session_id: ${data.url.searchParams.get('session_id')}`);
}
$events_slct.event_id = data.params.event_id;
$events_slct.event_location_id = data.params.event_location_id;
$events_slct.event_session_id = data.url.searchParams.get('session_id');
// console.log(`ae_acct.slct.event_id:`, ae_acct.slct.event_id);
// $events_slct.event_id = ae_acct.slct.event_id;
// $events_slct.event_obj = ae_acct.slct.event_obj;
$events_slct.event_location_obj_li = ae_acct.slct.event_location_obj_li ?? [''];
$events_slct.id_li__event_location = ae_acct.slct.id_li__event_location ?? [''];
// svelte-ignore state_referenced_locally
if (log_lvl > 1) {
console.log(`$events_slct.event_location_obj_li:`, $events_slct.event_location_obj_li);
console.log(`$events_slct.id_li__event_location:`, $events_slct.id_li__event_location);
}
// *** Functions and Logic
// Event
let lq__event_obj = $derived(liveQuery(async () => {
if (log_lvl) {
console.log(`lq__event_obj: event_id = ${$events_slct?.event_id}`);
}
let results = await db_events.event
.get($events_slct?.event_id ?? ''); // null or undefined does not reset things like '' does
if (log_lvl) {
console.log(`lq__event_obj: results = `, results);
}
// tmp_event_obj = { ...results };
// Check if results are different than the current session version stored under $events_slct
if ($events_slct.event_obj && results) {
if (JSON.stringify($events_slct.event_obj) !== JSON.stringify(results)) {
$events_slct.event_obj = { ...results};
if (log_lvl) {
console.log(`Session slct stored version has changed for ID = ${$events_slct.event_id}`, $events_slct.event_obj);
}
} else {
if (log_lvl) {
console.log(`Session slct stored version has not changed for ID = ${$events_slct.event_id}`);
}
}
}
return results;
}));
// Event File - For Event
let lq__event_event_file_obj_li = $derived(liveQuery(async () => {
let results = await db_events.file
.where('for_id_random')
.equals($events_slct.event_id ?? '')
.sortBy('filename');
return results;
}));
// Event File - For Location
let lq__location_event_file_obj_li = $derived(liveQuery(async () => {
let results = await db_events.file
// .where('event_location_id_random')
.where('for_id_random')
.equals($events_slct.event_location_id ?? '')
.sortBy('filename');
return results;
}));
// Event Location
let lq__event_location_obj = $derived(liveQuery(async () => {
let results = await db_events.location
.get($events_slct.event_location_id);
return results;
}));
let lq__event_location_obj_li = $derived(liveQuery(async () => {
let results = await db_events.location
.where('event_id')
.equals($events_slct.event_id)
.sortBy('name');
return results;
}));
// Event Session
let lq__event_session_obj = $derived(liveQuery(async () => {
let results = await db_events.session
.get($events_slct.event_session_id);
return results;
}));
// let lq__event_session_obj_li = $derived(liveQuery(async () => {
// let results = await db_events.session
// // .bulkGet(event_session_id_random_li);
// .where('event_location_id')
// .equals($events_slct.event_location_id)
// .sortBy('name');
// return results;
// }));
// let lq__event_session_obj_li = $derived(liveQuery(async () => {
// let results = await db_events.session
// .where('event_location_id')
// .equals($events_slct.event_location_id)
// // .and((x) => (x.archive_on === null || x.archive_on > (new Date()).toISOString()))
// // .and((x) => (x.archive_on === null || x.archive_on > (new Date()).toISOString())) // null or future events only
// // .and((x) => (x.archive_on < (new Date()).toISOString())) // past events only
// // .and((x) => (x.archive_on > (new Date()).toISOString())) // future events only
// // .orderBy('updated_on')
// // .toArray()
// .reverse()
// // .limit($idaa_loc.bb.qry__limit)
// .sortBy('name');
// // .sortBy('tmp_sort_1');
// // .sortBy('updated_on');
// // .sortBy('updated_on, created_on');
// // .sortBy('[updated_on+created_on]');
// // .sortBy('[created_on+updated_on]');
// return results;
// }));
let lq__event_session_obj_li = $derived(liveQuery(async () => {
log_lvl = 1;
if (log_lvl) {
console.log(`LQ - $lq__event_obj.cfg_json = `, $lq__event_obj?.cfg_json);
console.log(`LQ - $events_loc.filter__category_code = `, $events_loc.filter__category_code);
}
if ($events_sess.session_li_trigger && !$events_sess?.session_li) {
$events_sess.session_li = null;
$events_sess.session_li_trigger = false;
}
let results;
if ($events_sess?.session_li && $events_sess?.session_li?.length) {
// if (log_lvl) {
// console.log(`LQ - Using $events_sess.session_li to get event sessions.`);
// }
// // $events_sess.session_li_trigger = false;
// let event_session_id_random_li = []; // This is to prevent the array from constantly updating and triggering the liveQuery.
// for (let i = 0; i < $events_sess?.session_li.length; i++) {
// let event_session_obj = $events_sess?.session_li[i];
// let event_session_id_random = event_session_obj.event_session_id_random;
// event_session_id_random_li.push(event_session_id_random);
// }
// // let event_session_id_random_li = tmp_li;
// results = await db_events.session
// .bulkGet(event_session_id_random_li);
// } else if ($lq__event_obj?.cfg_json?.session_group_sort === 'DESC') {
// if (log_lvl) {
// console.log(`LQ - Using DESC sort for Event Session list event_id: ${$events_slct?.event_id}`);
// }
// results = await db_events.session
// // .orderBy('updated_on')
// .where('event_id')
// .equals($events_slct?.event_id ?? '') // null or undefined does not reset things like '' does
// .reverse()
// // .sortBy('tmp_sort_2');
// .sortBy('updated_on');
// // .sortBy('title');
// } else if ($events_loc.filter__category_code && $events_loc.filter__category_code.length > 0) {
// if (log_lvl) {
// console.log(`LQ - Using category filter: ${$events_loc.filter__category_code}`);
// }
// results = await db_events.session
// .where('event_id')
// .equals($events_slct?.event_id ?? '') // null or undefined does not reset things like '' does
// .and(session => session.category_code === $events_loc.filter__category_code)
// .reverse()
// .sortBy('tmp_sort_1');
} else if ($events_slct.event_location_id) {
if (log_lvl) {
// console.log(`$lq__event_obj.cfg_json = `, $lq__event_obj?.cfg_json);
console.log(`LQ - Using default sort for Event Session list event_id: ${$events_slct?.event_id}`);
}
results = await db_events.session
.where('event_location_id')
.equals($events_slct.event_location_id)
// .where('event_id')
// .equals($events_slct?.event_id ?? '') // null or undefined does not reset things like '' does
.reverse()
.sortBy('name');
// .sortBy('tmp_sort_1');
// .sortBy('updated_on');
}
// Check if results are different than the current session version stored under $events_slct
if ($events_slct.event_session_obj_li && JSON.stringify($events_slct.event_session_obj_li) !== JSON.stringify(results)) {
$events_slct.event_session_obj_li = [...results];
if (log_lvl) {
console.log(`Session slct li stored version has changed for ID = ${$events_slct.event_id}`, $events_slct.event_session_obj_li);
}
} else {
if (log_lvl > 1) {
console.log(`Session slct li stored version has not changed for ID = ${$events_slct.event_id}`);
}
}
return results;
}));
// $: if (!$events_sess.launcher.modal__open) {
// if ($events_loc.launcher.controller == 'local_push' && $events_sess.launcher.ws_connect_status == 'connected') {
// console.log(`Local Push Controller Command: ae_close:event_file_modal`);
// $events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
// $events_sess.launcher.controller_trigger_send = true;
// }
// }
let ae_promises: key_val = {
slct_event_session_id: null,
slct_event_presentation_li: null
};
let trigger_handle_ws_conn = $state(false);
let trigger_handle_ws_recv = $state(false);
let trigger_handle_ws_sent = $state(false);
/* *** BEGIN *** Handle WebSocket events */
function handle_ws_conn(ws_conn_status: any) {
log_lvl = 1;
if (log_lvl) {
console.log('*** handle_ws_conn() ***', ws_conn_status);
}
if (ws_conn_status.status == 'connected') {
$events_sess.launcher.ws = {}; // Reset WS related values on a new connection.
$events_sess.launcher.ws.status = 'connected';
} else {
$events_sess.launcher.ws = {}; // Reset WS related values when disconnected connection.
$events_sess.launcher.ws.status = 'disconnected';
}
$events_sess.launcher = $events_sess.launcher;
}
// This client received a WebSocket message.
// When this is called something seems to go wrong. It creates a loop when connected.
function handle_ws_recv(ws_recv_status: any) {
log_lvl = 1;
if (log_lvl) {
console.log('*** handle_ws_recv() ***', ws_recv_status);
}
if (ws_recv_status.type == 'cmd' && ws_recv_status.cmd) {
let cmd = ws_recv_status.cmd;
// console.log(cmd);
if ($events_loc.launcher.controller != 'remote') {
if (log_lvl) {
console.log('Ignoring WS command. Launcher is not set to be remotely controlled.', cmd);
}
return;
}
// AE Load (event session ID)
if (cmd.startsWith('ae_load:')) {
let cmd_parts = cmd.split(':');
let obj_parts = cmd_parts[1].split('=');
let obj_type = obj_parts[0];
let obj_id = obj_parts[1];
if (log_lvl) {
console.log(`ae_load: ${obj_type} ${obj_id}`);
}
if (log_lvl > 1) {
console.log(cmd);
}
if (obj_type == 'event_session') {
$events_slct.event_session_id = obj_id;
// $slct_trigger = 'event_session';
// $events_sess.launcher.show_launcher_message = false;
// data.url.searchParams.set('session_id', $events_slct.event_session_id);
// let new_url = data.url.toString();
// console.log(new_url);
// goto(new_url, {replaceState: false});
// ae_promises.slct_event_session_id = events_func.load_ae_obj_id__event_session({
// api_cfg: $ae_api,
// event_session_id: $events_slct.event_session_id,
// inc_file_li: true,
// inc_presentation_li: true,
// try_cache: true,
// log_lvl: log_lvl
// })
// .then(async (load_results) => {
// });
// tick();
console.log(`Current URL`, data.url);
let new_url = new URL(data.url);
new_url.pathname = `/events/${$lq__event_session_obj?.event_id}/launcher/${$lq__event_session_obj?.event_location_id}`;
new_url.searchParams.set('session_id', $events_slct.event_session_id);
console.log(`New URL: ${new_url}`);
let new_url_str = new_url.toString();
goto(new_url_str, {replaceState: false});
}
// AE Download (event file ID)
} else if (cmd.startsWith('ae_download:')) {
log_lvl = 1;
let cmd_parts = cmd.split(':');
let obj_parts = cmd_parts[1].split('=');
let obj_type = obj_parts[0];
let obj_id = obj_parts[1];
let obj_filename = cmd_parts[2];
let obj_extension = cmd_parts[3];
if (log_lvl) {
console.log(`ae_download: ${obj_type} ${obj_id} ${obj_filename} ${obj_extension}`);
}
if (log_lvl > 1) {
console.log(cmd);
}
ae_promises[obj_id] = api.download_hosted_file({
api_cfg: $ae_api,
hosted_file_id: obj_id, // +'x'
return_file: true,
filename: `${obj_filename}`,
auto_download: true,
log_lvl: 1
});
// AE Open (event file ID)
} else if (cmd.startsWith('ae_open:')) {
let cmd_parts = cmd.split(':');
let obj_parts = cmd_parts[1].split('=');
let obj_type = obj_parts[0];
let obj_id = obj_parts[1];
if (log_lvl) {
console.log(`ae_open: ${obj_type} ${obj_id}`);
}
if (log_lvl > 1) {
console.log(cmd);
}
// NOTE: This is not finished yet.
if (obj_type == 'event_file') {
// We are assuming this is for digital posters and needs to be opened in the modal.
$events_sess.launcher.modal__open_event_file_id = null;
clearInterval(idle_timer_interval);
$events_slct.event_file_id = obj_id;
$events_sess.launcher.modal__title = $events_sess.launcher.modal__title ?? '*';
$events_sess.launcher.modal__open_event_file_id = $events_slct.event_file_id;
// $events_sess.launcher.modal__event_file_obj = event_file_obj;
// $events_sess.launcher.modal__img_src = `/event/file/${event_file_obj.event_file_id_random}/download`;
// $events_slct.event_file_obj = event_file_obj;
// $slct_trigger = 'event_file';
// $events_sess.launcher.event_file_open.open_status = 'open';
// $events_sess.launcher.show_launcher_message = false;
// NOTE: This is not finished yet.
// This should now trigger the Svelte component for the event launcher file container. Currently this does nothing. Need to bind to something or use the "events_sess.launcher" object?
// let as_modal_result = open_event_file_as_modal({event_file_id: event_file_obj.event_file_id_random, method: 'modal', filename: event_file_obj.filename, extension: event_file_obj.extension, modal_title: poster_title});
// if (as_modal_result) {
// console.log($events_sess.launcher);
// console.log(event_file_obj);
// events_sess.launcher.set({...$events_sess.launcher, ...as_modal_result});
// }
}
// NOTE: This is not finished yet.
// AE Close (event file modal)
} else if (cmd.startsWith('ae_close:')) {
console.log();
let cmd_parts = cmd.split(':');
let what = cmd_parts[1];
// let obj_type = obj_parts[0];
// let obj_id = obj_parts[1];
if (what == 'event_file_modal') {
$events_sess.launcher.modal__title = '';
$events_sess.launcher.modal__open_event_file_id = null;
$events_sess.launcher.modal__event_file_obj = null;
// $events_sess.launcher.modal__img_src = null;
// $events_slct.event_file_id = null;
// $slct_trigger = 'event_file';
// $events_sess.launcher.event_file_open.open_status = 'close';
}
// WORKING! AE Refresh (now)
} else if (cmd.startsWith('ae_refresh:')) {
console.log();
let cmd_parts = cmd.split(':');
let what = cmd_parts[1];
// let obj_type = obj_parts[0];
// let obj_id = obj_parts[1];
if (what == 'now') {
// window.localStorage.clear();
location.reload();
} else {
console.log('OOPS? What went wrong?');
}
}
} else {
if (log_lvl) {
console.log('Unrecognized WS event received. Probably just a message.');
}
}
}
// This client sent a WebSocket message.
function handle_ws_sent(ws_sent_status: any) {
console.log('*** handle_ws_sent() ***', ws_sent_status);
let command = ws_sent_status.cmd;
console.log(`CMD: ${command}`);
$events_sess.launcher.controller_cmd = null;
$events_sess.launcher.controller_trigger_send = null;
}
/* *** END *** Handle WebSocket events */
$effect(() => {
if ($slct_trigger == 'event_file' && $events_slct.event_file_id && $events_sess.launcher?.event_file_open.open_status == 'open') {
$slct_trigger = null;
// handle_event_file_open();
}
// if ($events_sess.launcher.trigger_open_file) {
// $events_sess.launcher.trigger_modal_open_file = false;
// handle_event_file_open();
// }
});
$effect(() => {
if ($slct_trigger == 'event_file' && $events_sess.launcher?.event_file_open.open_status == 'close') {
$slct_trigger = null;
// Assuming just event file modal for now
// handle_event_file_close();
}
});
$effect(() => {
if (trigger_handle_ws_conn) {
let ws_conn_status = trigger_handle_ws_conn; // This a string status
trigger_handle_ws_conn = false;
handle_ws_conn(ws_conn_status);
}
});
$effect(() => {
if (trigger_handle_ws_recv) {
let ws_recv_status = trigger_handle_ws_recv; // This should be a key value object.
trigger_handle_ws_recv = false;
handle_ws_recv(ws_recv_status);
}
});
$effect(() => {
if (trigger_handle_ws_sent) {
let ws_sent_status = trigger_handle_ws_sent; // This should be a key value object.
trigger_handle_ws_sent = false;
handle_ws_sent(ws_sent_status);
}
});
async function handle_event_file_open () {
let event_file_obj;
if ($events_slct.event_file_obj && $events_slct.event_file_obj.event_file_id_random) {
console.log($events_slct.event_file_obj);
event_file_obj = $events_slct.event_file_obj;
} else {
console.log('Need to look up the event file details first.');
// let get_event_file_obj_result = await get_event_file_obj({event_file_id: $events_slct.event_file_id});
// event_file_obj = get_event_file_obj_result;
// console.log(event_file_obj);
}
// let as_modal_result = open_event_file_as_modal({
// event_file_id: event_file_obj.event_file_id_random,
// filename: event_file_obj.filename,
// extension: event_file_obj.extension,
// modal_title: ae_util.shorten_filename(event_file_obj.filename, 75)
// });
// if (as_modal_result) {
// console.log($events_sess.launcher);
// events_sess.launcher.set({...$events_sess.launcher, ...as_modal_result});
// // $events_sess.launcher.event_file_open = as_modal_result;
// }
}
async function handle_event_file_close () {
let as_modal_result = close_event_file_as_modal({
});
if (as_modal_result) {
events_sess.launcher.set({...$events_sess.launcher, ...as_modal_result});
}
}
if (!$events_loc.launcher.idle_timer) {
$events_loc.launcher.idle_timer = 4 * 60 * 1000;
}
if (!$events_loc.launcher.idle_cycle) {
$events_loc.launcher.idle_cycle = 5 * 1000;
}
if (!$events_loc.launcher.idle_loop_period) {
$events_loc.launcher.idle_loop_period = 1 * 60 * 1000;
}
// Safer to run this once the component has mounted and initialized???
listen({
timer: $events_loc.launcher.idle_timer, // $events_loc.launcher.idle_timer ?? 30 * 60 * 1000,
cycle: $events_loc.launcher.idle_cycle ?? 5 * 1000, // How frequently the idle status is checked
});
let idle_timer_interval: any = $state();
clearInterval(idle_timer_interval);
function handle_idle_client() {
// Start the digital poster screen saver after additional idle time.
if ($events_slct?.event_session_obj && $events_slct.event_session_obj?.type_code == 'poster') {
console.log('Open poster file in poster session...');
idle_timer_interval = setInterval(() => {
if (log_lvl) {
console.log('Screen saver tick!');
// console.log($events_loc.launcher.screen_saver_img_kv);
}
// console.log($events_loc.launcher.screen_saver_img_kv.length());
if ($events_loc.launcher.screen_saver_img_kv) {
console.log($events_loc.launcher.screen_saver_img_kv);
let modal_title: string = '';
const rand_index = Math.floor(Math.random() * Object.keys($events_loc.launcher.screen_saver_img_kv).length);
console.log(rand_index);
let event_file_obj = $events_loc.launcher.screen_saver_img_kv[Object.keys($events_loc.launcher.screen_saver_img_kv)[rand_index]];
$events_slct.event_file_id = event_file_obj.event_file_id_random;
$events_slct.event_file_obj = event_file_obj;
// $slct_trigger = 'event_file';
// $events_loc.launcher.event_file_open.open_status = 'open';
$events_sess.launcher.modal__open = event_file_obj.event_file_id_random;
if (!modal_title) {
modal_title = event_file_obj.filename;
}
$events_sess.launcher.modal__title = modal_title;
// $events_sess.launcher.modal__img_src = `/event/file/${event_file_obj.event_file_id_random}/download`;
return true;
}
console.log('No screen saver images found.');
return false;
}, $events_loc.launcher.idle_loop_period ?? 2 * 60 * 1000);
// console.log('User is no longer idle???');
} else {
return false;
}
}
$effect(() => {
if ($idle) {
log_lvl = 1;
console.log(`User is idle after ${$events_loc.launcher?.idle_timer} milliseconds.`);
handle_idle_client();
} else {
console.log('User is no longer idle.');
log_lvl = 0;
clearInterval(idle_timer_interval);
}
});
</script>
<svelte:head>
<!-- {ae_util.shorten_string({ string: $lq__event_obj?.name ?? '', max_length: 20, begin_length: 10, end_length: 4 })} -->
<title>
&AElig;:
{$lq__event_location_obj?.name ?? '-- not set --'}
({$lq__event_session_obj?.name ?? 'Æ loading...'})
- Launcher v3 -
{$events_loc?.title}
</title>
</svelte:head>
<!-- max-w-(--breakpoint-xl) -->
<div
class="
static
m-auto
border-x border-gray-200 dark:border-gray-600
mt-12 mb-14 sm:mb-12
h-full
w-full max-w-7xl
outline
"
>
<header
id="Main-Header"
class="
z-20
absolute top-0 left-0 right-0
w-full max-w-7xl
h-12
p-1 px-12 m-auto
flex flex-row items-center justify-around sm:justify-between
text-sm hover:text-base
bg-slate-200
opacity-90 hover:opacity-100
transition-all duration-1000
"
>
<h3 class="h4 text-center italic text-surface-600-400">
<button
class=""
onclick={() => {
$events_loc.launcher.hide__launcher_menu = !$events_loc.launcher.hide__launcher_menu;
}}
title="Toggle Launcher menu"
>
<!-- Be sure to explain what &AElig; (Aether) means in the title text or similar! -->
<Satellite
class="text-base mx-1 inline-block text-gray-500"
/>
<abbr title="Aether - Events Module Launcher">
Æ
Launcher
<span class="text-xs align-super font-normal" title="Version 3">v3</span>
</abbr>
</button>
</h3>
{#if $lq__event_obj}
<h2 class="hidden md:inline-block h3 text-center text-surface-600-400">{$lq__event_obj.cfg_json?.short_name}</h2>
<h3
class="h4 text-center italic text-surface-600-400"
title="Location ID: {$lq__event_location_obj?.event_location_id} Name: {$lq__event_location_obj?.name}"
>
<button
class="text-base"
onclick={() => {
$ae_loc.edit_mode = !$ae_loc.edit_mode;
}}
title="Toggle Edit Mode to show location options and more"
>
<span class="fas fa-map-marker-alt"></span>
<span class="sr-only">Location:</span>
</button>
{$lq__event_location_obj?.name}
</h3>
{:else}
<div class="flex flex-row gap-1 items-center justify-center">
<span class="fas fa-spinner fa-spin mx-1"></span>
<span>Loading event...</span>
</div>
{/if}
</header>
<!-- The menu should be to the left of the main session view. -->
<div
class="
h-full min-w-full w-full max-w-full
flex flex-col sm:flex-row flex-wrap sm:flex-nowrap gap-0
items-center
justify-center
py-1 px-0.5
bg-gray-100
"
>
<section
id="Main-Nav-Menu"
class="event_launcher_menu
h-full
basis-1/5
min-w-56 md:min-w-64 lg:min-w-72
max-w-xs
pt-0.5 pr-0.5
flex flex-col gap-1 items-center justify-start
border-r border-gray-200 dark:border-gray-700
hover:bg-surface-100-900
"
class:hidden={$events_loc.launcher.hide__launcher_menu}
>
<!-- overflow-y-auto -->
<!-- {#await $events_slct.id_li__event_location}
Loading location list... a
{:then event_location_obj_li} -->
<!-- {#if $lq__event_obj && $lq__event_location_obj_li && $lq__event_session_obj_li && event_location_obj_li && event_location_obj_li.length > 0} -->
<!-- {#if $lq__event_obj && $lq__event_location_obj_li} -->
<Launcher_menu
data_url={data.url}
lq__event_obj={lq__event_obj}
lq__event_event_file_obj_li={lq__event_event_file_obj_li}
lq__location_event_file_obj_li={lq__location_event_file_obj_li}
slct__event_file_id={$events_slct.event_file_id}
lq__event_location_obj_li={lq__event_location_obj_li}
lq__event_location_obj={lq__event_location_obj}
slct__event_location_id={$events_slct.event_location_id}
bind:loading__session_li_status={$events_sess.launcher.loading__session_li_status}
lq__event_session_obj_li={lq__event_session_obj_li}
bind:loading__session_id_status={$events_sess.launcher.loading__session_id_status}
lq__event_session_obj={lq__event_session_obj}
bind:slct__event_session_id={$events_slct.event_session_id}
bind:trigger_reload__event_session_obj_id={$events_sess.launcher.trigger_reload__event_session_obj_id}
bind:trigger_reload__event_session_obj_li={$events_sess.launcher.trigger_reload__event_session_obj_li}
bind:trigger_reload__event_location_obj_li={$events_sess.launcher.trigger_reload__event_location_obj_li}
>
</Launcher_menu>
<!-- {:else}
<div class="flex flex-row items-center justify-center">
<span class="fas fa-spinner fa-spin mx-1"></span>
<span>Loading location list...</span>
</div>
{/if} -->
<!-- {/await} -->
<!-- Root: slct Location ID: {$events_slct.event_location_id ?? '-- not set --'} -->
</section>
<section
id="Main-Content"
class="event_launcher_main
h-full
min-w-xs
max-w-full
py-1 px-0.5
basis-4/5
flex flex-col gap-1
items-center
justify-center
overflow-y-auto
"
>
<!-- {#if $events_trigger == 'load__event_session_obj' && $events_slct.event_session_id}
<Launcher_session_view
slct_event_session_id={$events_slct.event_session_id}
lq__event_location_obj={lq__event_location_obj}
lq__event_location_obj_li={lq__event_location_obj_li}
lq__event_session_obj={lq__event_session_obj}
lq__event_session_obj_li={lq__event_session_obj_li}
>
</Launcher_session_view>
{/if} -->
<!-- {$lq__event_session_obj?.name} -->
{#if !$events_slct.event_location_id}
<div class="flex flex-row items-center justify-center">
<span class="fas fa-exclamation mx-1"></span>
<span>You must select a location first</span>
<span class="fas fa-exclamation mx-1"></span>
</div>
{/if}
<!-- Using the loading__session_id_status is kind of a hacky way to determine if the session is still loading or not. -->
{#if $events_slct.event_session_id && $lq__event_session_obj && !$events_sess.launcher.loading__session_id_status}
<Launcher_session_view
bind:slct__event_session_id={$events_slct.event_session_id}
lq__event_session_obj={lq__event_session_obj}
bind:type_code={$lq__event_session_obj.type_code}
>
</Launcher_session_view>
{/if}
</section>
</div>
{@render children?.()}
</div>
<footer
id="Main-Footer"
class="
z-20
absolute bottom-0 left-0 right-0
w-full max-w-7xl
p-1 m-auto
flex flex-row items-center justify-between
sm:flex-row md:items-center md:justify-between
text-xs hover:text-base
bg-gray-200 border-t border-gray-200
dark:bg-gray-800 dark:border-gray-600
opacity-50 hover:opacity-100
transition-all duration-1000
"
>
<!-- <div>
[Help]
</div> -->
<div class="slct_location_name">
<span class="fas fa-map-marker-alt"></span>
{$lq__event_location_obj?.name}
</div>
<span
class="*:hover:inline px-1 rounded-md"
class:preset-tonal-warning={!$events_loc.launcher.ws_connect}
class:preset-tonal-success={$events_loc.launcher.ws_connect}
>
{#if $events_sess.launcher.ws_connect_status == 'connected'}
<span class="fas fa-wifi mx-1"></span>
<span class="hidden">
WebSocket Connected
</span>
{:else}
<span class="fas fa-times mx-1"></span>
<span class="hidden">
WebSocket Disconnected
</span>
{/if}
</span>
<span
class:hidden={$events_loc.launcher.app_mode != 'native'}
class="*:hover:inline px-1 rounded-md"
class:preset-tonal-warning={!$events_sess.launcher?.av_recording_status}
class:preset-tonal-success={$events_sess.launcher?.av_recording_status}
>
{#if $events_sess.launcher?.av_recording_status}
<span class="fas fa-video mx-1"></span>
<span class="hidden">
AV Recording Active
</span>
{:else}
<span class="fas fa-video-slash mx-1"></span>
<span class="hidden">
AV Recording Inactive
</span>
{/if}
</span>
<div class="current_datetime">
{ae_util.iso_datetime_formatter($time,'date_full_no_year')}
{#if $events_loc.launcher?.time_hours == 12}
{ae_util.iso_datetime_formatter($time,'time_12_long')}
{:else}
{ae_util.iso_datetime_formatter($time,'time_long')}
{/if}
</div>
</footer>
<div class="absolute top-0 left-0 z-20 text-center">
<button
type="button"
onclick={() => ($events_loc.launcher.hide_drawer__cfg = false)}
class="btn btn-sm p-2.5 preset-tonal-error hover:preset-filled-error-500 transition-all duration-1000"
class:opacity-25={!$ae_loc.trusted_access}
class:hover:opacity-75={!$ae_loc.trusted_access}
>
<span class="fas fa-biohazard"></span>
<span class="hidden">Launcher Config</span>
</button>
</div>
<Drawer
bgColor="bg-blue"
class="bg-orange-100 opacity-90 hover:opacity-97 transition-all duration-1000 border border-gray-300 dark:border-gray-600"
placement="left"
transitionType="fly"
transitionParams={
{
x: -320,
duration: 200,
easing: sineIn
}
}
width={'min-w-80 w-1/2 max-w-(--breakpoint-lg)'}
bind:hidden={$events_loc.launcher.hide_drawer__cfg}
id="sidebar1"
>
<Launcher_cfg></Launcher_cfg>
<hr />
<div class="flex flex-row flex-wrap gap-0.5 items-center justify-center">
<a href="/events/{$events_slct.event_id}" class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500">
<span class="fas fa-search m-1"></span>
Session Search
</a>
{#if $events_slct?.event_location_id}
<a href="/events/{$events_slct.event_id}/location/{$events_slct.event_location_id}"
class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500">
<span class="fas fa-map-marker m-1"></span>
View Selected Location
</a>
{/if}
{#if $events_slct?.event_session_id}
<a href="/events/{$events_slct.event_id}/session/{$events_slct.event_session_id}"
class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500">
<span class="fas fa-chalkboard-teacher m-1"></span>
View Selected Session
</a>
{/if}
<!-- <button
class="btn btn-sm variant-ghost-tertiary hover:variant-filled-tertiary"
>Test 1</button> -->
<!-- <button
class="btn btn-sm variant-ghost-tertiary hover:variant-filled-tertiary"
>Test 2</button> -->
</div>
</Drawer>
<Drawer
activateClickOutside={false}
backdrop={false}
class="bg-red-100 opacity-75 hover:opacity-95 transition-all duration-1000"
placement="bottom"
transitionType="fly"
transitionParams={
{
y: 320,
duration: 200,
easing: sineIn
}
}
width={'min-h-96 h-1/2'}
bind:hidden={$events_loc.launcher.hide_drawer__debug}
id="sidebar2"
>
<div class="flex flex-row items-center justify-between">
<h2
class="text-center mb-4 text-base font-semibold text-gray-500 dark:text-gray-400"
>
Debug
</h2>
<button
onclick={() => ($events_loc.launcher.hide_drawer__debug = true)}
class="mb-4 dark:text-white"
>
<span class="fas fa-times"></span>
<span class="hidden">Close Debug Drawer</span>
</button>
</div>
<div>
<!-- Show the launcher configuration in JSON format -->
<pre class="text-xs">
{JSON.stringify($events_loc.launcher, null, 2)}
</pre>
<hr />
<pre class="text-xs">
{JSON.stringify($ae_api, null, 2)}
</pre>
</div>
</Drawer>
<!-- Main modal -->
<!-- **NOTE:** The modal size is intentionally set to "". This makes it undefined and allows the modal to be as large as the content. **NOTE** -->
<!-- title={$events_sess.launcher?.modal__title} -->
<Modal
open={$events_sess.launcher?.modal__open_event_file_id}
autoclose={false}
placement="top-center"
size=""
class="
bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200
rounded-lg border-gray-200 dark:border-gray-700
divide-y divide-gray-200 dark:divide-gray-700 shadow-md
relative
flex flex-col
"
bodyClass='p-0 overflow-y-auto overscroll-contain'
headerClass='p-1 md:p-2 flex flex-row items-center justify-between'
footerClass='text-center'
onclose={async () => {
$events_sess.launcher.modal__open_event_file_id = null;
if ($events_loc.launcher.controller == 'local_push' && $events_sess.launcher.ws_connect_status == 'connected') {
// // This should work....????
// console.log(`TEST - FAIL??? Local Push Controller Command: ae_close:event_file_modal`);
// console.log(`Before: ${$events_sess.launcher.controller_trigger_send}`);
// // $events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
// // $events_sess.launcher.controller_trigger_send = true;
// // $events_sess = $events_sess;
// // events_sess.set($events_sess);
// // tick();
// // events_sess.set($events_sess);
// console.log(`After: ${$events_sess.launcher.controller_trigger_send}`);
}
}}
>
{#snippet header()}
<!-- <div class="flex flex-row items-center justify-between"> -->
<h3 class="text-lg font-semibold">
{$events_sess.launcher?.modal__title ?? 'Digital Poster Display'}
</h3>
<button
type="button"
onclick={() => {
$events_sess.launcher.modal__open_event_file_id = null;
if ($events_loc.launcher.controller == 'local_push' && $events_sess.launcher.ws_connect_status == 'connected') {
}
}}
title="Close Modal"
>
<span class="fas fa-times m-1"></span>
<span class="hidden ">Close</span>
</button>
<!-- </div> -->
{/snippet}
<!-- <svelte:fragment slot="header">
<div class="flex flex-row items-center justify-between">
<h3 class="text-lg font-semibold">
{$events_sess.launcher?.modal__title}
</h3>
</div>
</svelte:fragment> -->
<button
onclick={() => {
console.log(`TEST - THIS WORKS... Local Push Controller Command: ae_close:event_file_modal`);
// This is not terrible if we set autoclose to true.
$events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
$events_sess.launcher.controller_trigger_send = true;
// $events_sess.launcher.modal__open = false;
}}
class="absolute top-0 right-20 m-1 p-1 btn btn-sm preset-tonal-error hover:preset-filled-error-500"
class:hidden={$events_loc.launcher.controller != 'local_push' || $events_sess.launcher.ws_connect_status != 'connected'}
>
<span class="fas fa-times m-1"></span>
Close Remote Poster Display Only
</button>
<!-- Open: {$ae_api.base_url} {$events_sess.launcher.modal__open_event_file_id} -->
<!-- /event/file/{$events_slct.event_file_obj.event_file_id_random}/download?filename={$events_slct.event_file_obj.filename}&x_no_account_id_token=direct-download -->
<!-- <span class="aspect-9/16 max-h-96"> -->
{#if $events_sess.launcher.modal__open_event_file_id}
<img
src="{$ae_api.base_url}/event/file/{$events_sess.launcher.modal__open_event_file_id}/download?filename={$events_slct.event_file_obj.filename}&x_no_account_id_token=direct-download"
alt="Placeholder: /event/file/{$events_sess.launcher.modal__open_event_file_id}/download?filename={$events_slct.event_file_obj.filename}&x_no_account_id_token=direct-download"
class="margin-auto min-h-28 max-h-full max-w-full"
/>
{:else}
<div class="flex flex-row items-center justify-center p-4">
<span class="fas fa-info-circle mx-1"></span>
<span>No image selected</span>
</div>
{/if}
<!-- </span> -->
<button
onclick={() => {
console.log(`TEST - THIS WORKS... Local Push Controller Command: ae_close:event_file_modal`);
// This is not terrible if we set autoclose to true.
$events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
$events_sess.launcher.controller_trigger_send = true;
// $events_sess.launcher.modal__open = false;
}}
class="absolute bottom-0 left-20 m-1 p-1 btn btn-sm preset-tonal-error hover:preset-filled-error-500"
class:hidden={$events_loc.launcher.controller != 'local_push' || $events_sess.launcher.ws_connect_status != 'connected'}
>
<span class="fas fa-times m-1"></span>
Close Remote Poster Display Only
</button>
<!-- Need to add a re-open button... -->
<button
onclick={() => {
// $events_sess.launcher.modal__open = false;
$events_sess.launcher.modal__title = '';
$events_sess.launcher.modal__open_event_file_id = null;
$events_sess.launcher.modal__event_file_obj = null;
}}
class="absolute bottom-0 right-20 m-1 p-1 btn btn-sm preset-tonal-warning hover:preset-tonal-warning border border-warning-500"
class:hidden={!$ae_loc.trusted_access && ($events_loc.launcher.controller != 'local_push' || $events_sess.launcher.ws_connect_status != 'connected')}
>
<span class="fas fa-times m-1"></span>
Close Controller Poster Only
</button>
<!-- <svelte:fragment slot="footer">
<div class="text-center w-full">
<button
on:click={() => {
$events_sess.launcher.modal__open = false;
}}
class="btn btn-sm variant-soft-warning hover:variant-ghost-warning"
>
<span class="fas fa-times m-1"></span>
Close
</button>
</div>
</svelte:fragment> -->
</Modal>
<!-- {:else}
{$events_sess.launcher.modal__open_event_file_id}
{/if} -->
{#if $events_loc.launcher.controller_group_code && $events_loc.launcher.ws_connect}
<!-- {$ae_api.base_url} -->
<Element_websocket_v2
log_lvl={log_lvl}
bind:ws_connect={$events_loc.launcher.ws_connect}
bind:ws_connect_status={$events_sess.launcher.ws_connect_status}
ws_server={$ae_api.fqdn}
bind:group_id={$events_loc.launcher.controller_group_code}
bind:client_id={$events_loc.launcher.controller_client_id}
bind:cmd={$events_sess.launcher.controller_cmd}
type={'cmd'}
bind:trigger_send={$events_sess.launcher.controller_trigger_send}
bind:hide__ws_form={$events_loc.launcher.hide__ws_form}
bind:hide__ws_messages={$events_loc.launcher.hide__ws_messages}
bind:hide__ws_commands={$events_loc.launcher.hide__ws_commands}
bind:ws_conn_status={trigger_handle_ws_conn}
bind:ws_recv_status={trigger_handle_ws_recv}
bind:ws_sent_status={trigger_handle_ws_sent}
/>
<!-- on:ws_recv={handle_ws_recv} -->
{/if}