refactor(launcher): standardize helper names and apply batch formatting
- Renamed internal 'preventDefault' to 'prevent_default' in launcher files. - Fixed native 'event.preventDefault()' call in launcher_file_cont.svelte. - Applied batch formatting (printWidth: 80) across the (launcher) module.
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
This directory contains the files for the new Event Launcher module (v3). Detailed documentation to follow.
|
This directory contains the files for the new Event Launcher module (v3). Detailed documentation to follow.
|
||||||
|
|
||||||
This should be able to run in 3 modes:
|
This should be able to run in 3 modes:
|
||||||
* Default - What most users will see for demo purposes
|
|
||||||
* Onsite - This is what is set onsite, usually just in the Speaker Ready Room
|
- Default - What most users will see for demo purposes
|
||||||
* Native App - This is for the native app version of Aether and used on the MacBook laptops in each of the session rooms
|
- Onsite - This is what is set onsite, usually just in the Speaker Ready Room
|
||||||
|
- Native App - This is for the native app version of Aether and used on the MacBook laptops in each of the session rooms
|
||||||
|
|||||||
@@ -18,57 +18,102 @@
|
|||||||
>
|
>
|
||||||
<!-- Content omitted for brevity, preserved in file -->
|
<!-- Content omitted for brevity, preserved in file -->
|
||||||
<div class="col-span-full flex flex-col gap-3">
|
<div class="col-span-full flex flex-col gap-3">
|
||||||
|
|
||||||
<!-- 1. App Mode Selection -->
|
<!-- 1. App Mode Selection -->
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Operational Environment</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Operational Environment</label
|
||||||
|
>
|
||||||
<div class="grid grid-cols-3 gap-1 bg-surface-500/5 p-1 rounded-lg">
|
<div class="grid grid-cols-3 gap-1 bg-surface-500/5 p-1 rounded-lg">
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => $events_loc.launcher.app_mode = 'default'}
|
type="button"
|
||||||
|
onclick={() => ($events_loc.launcher.app_mode = 'default')}
|
||||||
class="btn btn-xs text-[9px] font-bold"
|
class="btn btn-xs text-[9px] font-bold"
|
||||||
class:preset-filled-primary-500={$events_loc.launcher.app_mode === 'default'}
|
class:preset-filled-primary-500={$events_loc.launcher
|
||||||
class:opacity-40={$events_loc.launcher.app_mode !== 'default'}
|
.app_mode === 'default'}
|
||||||
>Web</button>
|
class:opacity-40={$events_loc.launcher.app_mode !==
|
||||||
<button type="button"
|
'default'}>Web</button
|
||||||
onclick={() => $events_loc.launcher.app_mode = 'native'}
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => ($events_loc.launcher.app_mode = 'native')}
|
||||||
class="btn btn-xs text-[9px] font-bold"
|
class="btn btn-xs text-[9px] font-bold"
|
||||||
class:preset-filled-primary-500={$events_loc.launcher.app_mode === 'native'}
|
class:preset-filled-primary-500={$events_loc.launcher
|
||||||
class:opacity-40={$events_loc.launcher.app_mode !== 'native'}
|
.app_mode === 'native'}
|
||||||
>App</button>
|
class:opacity-40={$events_loc.launcher.app_mode !==
|
||||||
<button type="button"
|
'native'}>App</button
|
||||||
onclick={() => $events_loc.launcher.app_mode = 'onsite'}
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => ($events_loc.launcher.app_mode = 'onsite')}
|
||||||
class="btn btn-xs text-[9px] font-bold"
|
class="btn btn-xs text-[9px] font-bold"
|
||||||
class:preset-filled-primary-500={$events_loc.launcher.app_mode === 'onsite'}
|
class:preset-filled-primary-500={$events_loc.launcher
|
||||||
class:opacity-40={$events_loc.launcher.app_mode !== 'onsite'}
|
.app_mode === 'onsite'}
|
||||||
>Onsite</button>
|
class:opacity-40={$events_loc.launcher.app_mode !==
|
||||||
|
'onsite'}>Onsite</button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 2. UI Layout Toggles -->
|
<!-- 2. UI Layout Toggles -->
|
||||||
<div class="flex flex-col gap-1 border-t border-surface-500/10 pt-2 mt-1">
|
<div
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Interface Visibility</label>
|
class="flex flex-col gap-1 border-t border-surface-500/10 pt-2 mt-1"
|
||||||
|
>
|
||||||
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Interface Visibility</label
|
||||||
|
>
|
||||||
<div class="grid grid-cols-2 gap-2 p-1">
|
<div class="grid grid-cols-2 gap-2 p-1">
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="checkbox" bind:checked={$events_loc.launcher.hide__launcher_header} class="checkbox checkbox-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500">Hide Header</span>
|
type="checkbox"
|
||||||
|
bind:checked={
|
||||||
|
$events_loc.launcher.hide__launcher_header
|
||||||
|
}
|
||||||
|
class="checkbox checkbox-sm"
|
||||||
|
/>
|
||||||
|
<span class="text-xs group-hover:text-primary-500"
|
||||||
|
>Hide Header</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="checkbox" bind:checked={$events_loc.launcher.hide__launcher_menu} class="checkbox checkbox-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500">Hide Menu</span>
|
type="checkbox"
|
||||||
|
bind:checked={$events_loc.launcher.hide__launcher_menu}
|
||||||
|
class="checkbox checkbox-sm"
|
||||||
|
/>
|
||||||
|
<span class="text-xs group-hover:text-primary-500"
|
||||||
|
>Hide Menu</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="checkbox" bind:checked={$events_loc.launcher.hide__launcher_footer} class="checkbox checkbox-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500">Hide Footer</span>
|
type="checkbox"
|
||||||
|
bind:checked={
|
||||||
|
$events_loc.launcher.hide__launcher_footer
|
||||||
|
}
|
||||||
|
class="checkbox checkbox-sm"
|
||||||
|
/>
|
||||||
|
<span class="text-xs group-hover:text-primary-500"
|
||||||
|
>Hide Footer</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="checkbox" bind:checked={$events_loc.launcher.hide__session_datetimes} class="checkbox checkbox-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500">Hide Times</span>
|
type="checkbox"
|
||||||
|
bind:checked={
|
||||||
|
$events_loc.launcher.hide__session_datetimes
|
||||||
|
}
|
||||||
|
class="checkbox checkbox-sm"
|
||||||
|
/>
|
||||||
|
<span class="text-xs group-hover:text-primary-500"
|
||||||
|
>Hide Times</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 3. Time Format Toggle -->
|
<!-- 3. Time Format Toggle -->
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if ($events_loc.launcher.time_format == 'time_12_short') {
|
if ($events_loc.launcher.time_format == 'time_12_short') {
|
||||||
$events_loc.launcher.time_format = 'time_short';
|
$events_loc.launcher.time_format = 'time_short';
|
||||||
@@ -81,21 +126,42 @@
|
|||||||
class="btn btn-xs preset-tonal-surface w-full text-[10px]"
|
class="btn btn-xs preset-tonal-surface w-full text-[10px]"
|
||||||
>
|
>
|
||||||
<span class="fas fa-clock mr-2 opacity-50"></span>
|
<span class="fas fa-clock mr-2 opacity-50"></span>
|
||||||
Clock Format: <strong>{$events_loc.launcher.time_hours}-hour</strong>
|
Clock Format:
|
||||||
|
<strong>{$events_loc.launcher.time_hours}-hour</strong>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- 4. Advanced Toggles (Edit Mode Only) -->
|
<!-- 4. Advanced Toggles (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-2">
|
<div
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Technical Layout</label>
|
class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-2"
|
||||||
|
>
|
||||||
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Technical Layout</label
|
||||||
|
>
|
||||||
<div class="grid grid-cols-1 gap-2 p-1">
|
<div class="grid grid-cols-1 gap-2 p-1">
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="checkbox" bind:checked={$events_loc.launcher.hide__ws_element} class="checkbox checkbox-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500 italic">Hide WebSocket Debugger</span>
|
type="checkbox"
|
||||||
|
bind:checked={$events_loc.launcher.hide__ws_element}
|
||||||
|
class="checkbox checkbox-sm"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="text-xs group-hover:text-primary-500 italic"
|
||||||
|
>Hide WebSocket Debugger</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="checkbox" bind:checked={$events_loc.launcher.hide__modal_header_title} class="checkbox checkbox-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500 italic">Hide Poster Modal Title</span>
|
type="checkbox"
|
||||||
|
bind:checked={
|
||||||
|
$events_loc.launcher.hide__modal_header_title
|
||||||
|
}
|
||||||
|
class="checkbox checkbox-sm"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="text-xs group-hover:text-primary-500 italic"
|
||||||
|
>Hide Poster Modal Title</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
}
|
}
|
||||||
let { on_expand }: Props = $props();
|
let { on_expand }: Props = $props();
|
||||||
|
|
||||||
const ws_connected = $derived($events_sess.launcher.ws_connect_status === 'connected');
|
const ws_connected = $derived(
|
||||||
|
$events_sess.launcher.ws_connect_status === 'connected'
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Launcher_Cfg_Section
|
<Launcher_Cfg_Section
|
||||||
@@ -16,27 +18,39 @@
|
|||||||
icon="fa-gamepad"
|
icon="fa-gamepad"
|
||||||
bind:state={$events_loc.launcher.section_state__controller}
|
bind:state={$events_loc.launcher.section_state__controller}
|
||||||
{on_expand}
|
{on_expand}
|
||||||
description="Mode: {$events_loc.launcher?.controller} | WS: {ws_connected ? 'Connected' : 'Offline'}"
|
description="Mode: {$events_loc.launcher?.controller} | WS: {ws_connected
|
||||||
|
? 'Connected'
|
||||||
|
: 'Offline'}"
|
||||||
>
|
>
|
||||||
<!-- Content omitted for brevity, preserved in file -->
|
<!-- Content omitted for brevity, preserved in file -->
|
||||||
<div class="col-span-full flex flex-col gap-3">
|
<div class="col-span-full flex flex-col gap-3">
|
||||||
|
|
||||||
<!-- 1. Connection Status Badge -->
|
<!-- 1. Connection Status Badge -->
|
||||||
<div class="flex items-center justify-between bg-surface-500/5 p-2 rounded border border-surface-500/10">
|
<div
|
||||||
|
class="flex items-center justify-between bg-surface-500/5 p-2 rounded border border-surface-500/10"
|
||||||
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="fas fa-plug opacity-50"></span>
|
<span class="fas fa-plug opacity-50"></span>
|
||||||
<span class="text-[10px] font-bold uppercase tracking-wider">WebSocket Link</span>
|
<span class="text-[10px] font-bold uppercase tracking-wider"
|
||||||
|
>WebSocket Link</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
{#if ws_connected}
|
{#if ws_connected}
|
||||||
<span class="badge variant-filled-success text-[8px] animate-pulse">Connected</span>
|
<span
|
||||||
|
class="badge variant-filled-success text-[8px] animate-pulse"
|
||||||
|
>Connected</span
|
||||||
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="badge variant-filled-error text-[8px]">Disconnected</span>
|
<span class="badge variant-filled-error text-[8px]"
|
||||||
|
>Disconnected</span
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 2. Controller Mode Selection -->
|
<!-- 2. Controller Mode Selection -->
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Controller Strategy</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Controller Strategy</label
|
||||||
|
>
|
||||||
<select
|
<select
|
||||||
bind:value={$events_loc.launcher.controller}
|
bind:value={$events_loc.launcher.controller}
|
||||||
class="select select-sm text-xs preset-tonal-surface h-8"
|
class="select select-sm text-xs preset-tonal-surface h-8"
|
||||||
@@ -49,7 +63,8 @@
|
|||||||
|
|
||||||
<!-- 3. Connection Actions -->
|
<!-- 3. Connection Actions -->
|
||||||
<div class="grid grid-cols-2 gap-2 mt-1">
|
<div class="grid grid-cols-2 gap-2 mt-1">
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if ($events_loc.launcher.ws_connect) {
|
if ($events_loc.launcher.ws_connect) {
|
||||||
$events_sess.launcher.trigger__ws_disconnect = true;
|
$events_sess.launcher.trigger__ws_disconnect = true;
|
||||||
@@ -70,7 +85,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$events_sess.launcher.controller_cmd = 'ae_refresh:now';
|
$events_sess.launcher.controller_cmd = 'ae_refresh:now';
|
||||||
$events_sess.launcher.controller_trigger_send = 'trigger';
|
$events_sess.launcher.controller_trigger_send = 'trigger';
|
||||||
@@ -84,25 +100,43 @@
|
|||||||
|
|
||||||
<!-- 4. Technical Config (Edit Mode Only) -->
|
<!-- 4. Technical Config (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-2">
|
<div
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Channel Configuration</label>
|
class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-2"
|
||||||
|
>
|
||||||
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Channel Configuration</label
|
||||||
|
>
|
||||||
<div class="flex gap-1">
|
<div class="flex gap-1">
|
||||||
<input
|
<input
|
||||||
bind:value={$events_loc.launcher.controller_group_code}
|
bind:value={$events_loc.launcher.controller_group_code}
|
||||||
placeholder="Group Code"
|
placeholder="Group Code"
|
||||||
class="input input-sm grow text-[10px] h-7 preset-tonal-surface font-mono"
|
class="input input-sm grow text-[10px] h-7 preset-tonal-surface font-mono"
|
||||||
readonly={!$events_sess.launcher.controller_unlock_group_code}
|
readonly={!$events_sess.launcher
|
||||||
ondblclick={() => $events_sess.launcher.controller_unlock_group_code = true}
|
.controller_unlock_group_code}
|
||||||
|
ondblclick={() =>
|
||||||
|
($events_sess.launcher.controller_unlock_group_code = true)}
|
||||||
/>
|
/>
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => $events_sess.launcher.controller_unlock_group_code = !$events_sess.launcher.controller_unlock_group_code}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
($events_sess.launcher.controller_unlock_group_code =
|
||||||
|
!$events_sess.launcher
|
||||||
|
.controller_unlock_group_code)}
|
||||||
class="btn btn-xs preset-tonal-surface"
|
class="btn btn-xs preset-tonal-surface"
|
||||||
title="Toggle Unlock"
|
title="Toggle Unlock"
|
||||||
>
|
>
|
||||||
<span class="fas {$events_sess.launcher.controller_unlock_group_code ? 'fa-lock-open text-primary-500' : 'fa-lock'}"></span>
|
<span
|
||||||
|
class="fas {$events_sess.launcher
|
||||||
|
.controller_unlock_group_code
|
||||||
|
? 'fa-lock-open text-primary-500'
|
||||||
|
: 'fa-lock'}"
|
||||||
|
></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-[8px] opacity-40 italic ml-1">Double-click input to unlock editing. Changing code triggers reconnect.</p>
|
<p class="text-[8px] opacity-40 italic ml-1">
|
||||||
|
Double-click input to unlock editing. Changing code triggers
|
||||||
|
reconnect.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -34,34 +34,56 @@
|
|||||||
icon="fa-heartbeat"
|
icon="fa-heartbeat"
|
||||||
bind:state={$events_loc.launcher.section_state__health}
|
bind:state={$events_loc.launcher.section_state__health}
|
||||||
{on_expand}
|
{on_expand}
|
||||||
description="Heartbeat: {$events_sess.launcher.heartbeat_info.last_timestamp || 'Pending'}"
|
description="Heartbeat: {$events_sess.launcher.heartbeat_info
|
||||||
|
.last_timestamp || 'Pending'}"
|
||||||
>
|
>
|
||||||
<!-- Content omitted for brevity in instruction, but preserved in file -->
|
<!-- Content omitted for brevity in instruction, but preserved in file -->
|
||||||
<!-- Telemetry Dashboard -->
|
<!-- Telemetry Dashboard -->
|
||||||
<div class="col-span-full flex flex-col gap-3 bg-surface-500/5 p-3 rounded-lg border border-surface-500/10">
|
<div
|
||||||
|
class="col-span-full flex flex-col gap-3 bg-surface-500/5 p-3 rounded-lg border border-surface-500/10"
|
||||||
|
>
|
||||||
<!-- CPU Usage (Mock Logic if load not available yet) -->
|
<!-- CPU Usage (Mock Logic if load not available yet) -->
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex justify-between text-[9px] uppercase font-bold opacity-60">
|
<div
|
||||||
<span>CPU Architecture: {$ae_loc.native_device?.meta_json?.arch || '...'}</span>
|
class="flex justify-between text-[9px] uppercase font-bold opacity-60"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
>CPU Architecture: {$ae_loc.native_device?.meta_json
|
||||||
|
?.arch || '...'}</span
|
||||||
|
>
|
||||||
<span>Load: Healthy</span>
|
<span>Load: Healthy</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full h-1.5 bg-surface-500/20 rounded-full overflow-hidden">
|
<div
|
||||||
<div class="h-full bg-primary-500 transition-all duration-1000" style="width: 15%"></div>
|
class="w-full h-1.5 bg-surface-500/20 rounded-full overflow-hidden"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="h-full bg-primary-500 transition-all duration-1000"
|
||||||
|
style="width: 15%"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- RAM Usage -->
|
<!-- RAM Usage -->
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex justify-between text-[9px] uppercase font-bold opacity-60">
|
<div
|
||||||
|
class="flex justify-between text-[9px] uppercase font-bold opacity-60"
|
||||||
|
>
|
||||||
<span>Memory (RAM)</span>
|
<span>Memory (RAM)</span>
|
||||||
<span>{ram_usage_pct}% Used</span>
|
<span>{ram_usage_pct}% Used</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full h-1.5 bg-surface-500/20 rounded-full overflow-hidden">
|
<div
|
||||||
<div class="h-full transition-all duration-1000 {get_usage_color(ram_usage_pct)}" style="width: {ram_usage_pct}%"></div>
|
class="w-full h-1.5 bg-surface-500/20 rounded-full overflow-hidden"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="h-full transition-all duration-1000 {get_usage_color(
|
||||||
|
ram_usage_pct
|
||||||
|
)}"
|
||||||
|
style="width: {ram_usage_pct}%"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-[8px] opacity-40 text-right italic">
|
<div class="text-[8px] opacity-40 text-right italic">
|
||||||
Free: {$ae_loc.native_device?.meta_json?.free_mem || '...'} / {$ae_loc.native_device?.meta_json?.total_mem || '...'}
|
Free: {$ae_loc.native_device?.meta_json?.free_mem || '...'} / {$ae_loc
|
||||||
|
.native_device?.meta_json?.total_mem || '...'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,26 +91,45 @@
|
|||||||
<!-- Heartbeat & Sync Info -->
|
<!-- Heartbeat & Sync Info -->
|
||||||
<div class="grid grid-cols-2 gap-x-2 gap-y-2 w-full text-[10px] p-1">
|
<div class="grid grid-cols-2 gap-x-2 gap-y-2 w-full text-[10px] p-1">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="opacity-50 text-[8px] uppercase font-bold">Last Heartbeat</span>
|
<span class="opacity-50 text-[8px] uppercase font-bold"
|
||||||
<span class="font-mono {$events_sess.launcher.heartbeat_info.status === 'success' ? 'text-success-500' : 'text-error-500'}">
|
>Last Heartbeat</span
|
||||||
{$events_sess.launcher.heartbeat_info.last_timestamp || 'Pending...'}
|
>
|
||||||
|
<span
|
||||||
|
class="font-mono {$events_sess.launcher.heartbeat_info
|
||||||
|
.status === 'success'
|
||||||
|
? 'text-success-500'
|
||||||
|
: 'text-error-500'}"
|
||||||
|
>
|
||||||
|
{$events_sess.launcher.heartbeat_info.last_timestamp ||
|
||||||
|
'Pending...'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col text-right">
|
<div class="flex flex-col text-right">
|
||||||
<span class="opacity-50 text-[8px] uppercase font-bold">Local File Cache</span>
|
<span class="opacity-50 text-[8px] uppercase font-bold"
|
||||||
|
>Local File Cache</span
|
||||||
|
>
|
||||||
<span class="font-mono">
|
<span class="font-mono">
|
||||||
{$events_sess.launcher.sync_stats.cached} / {$events_sess.launcher.sync_stats.total}
|
{$events_sess.launcher.sync_stats.cached} / {$events_sess
|
||||||
|
.launcher.sync_stats.total}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if $events_sess.launcher.sync_stats.currently_syncing}
|
{#if $events_sess.launcher.sync_stats.currently_syncing}
|
||||||
<div class="col-span-full bg-primary-500/10 p-2 rounded border border-primary-500/20 animate-pulse mt-1">
|
<div
|
||||||
|
class="col-span-full bg-primary-500/10 p-2 rounded border border-primary-500/20 animate-pulse mt-1"
|
||||||
|
>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="fas fa-sync fa-spin text-primary-500"></span>
|
<span class="fas fa-sync fa-spin text-primary-500"></span>
|
||||||
<div class="flex flex-col truncate">
|
<div class="flex flex-col truncate">
|
||||||
<span class="text-[8px] uppercase font-bold text-primary-500">Syncing File...</span>
|
<span
|
||||||
<span class="truncate italic opacity-80">{$events_sess.launcher.sync_stats.currently_syncing}</span>
|
class="text-[8px] uppercase font-bold text-primary-500"
|
||||||
|
>Syncing File...</span
|
||||||
|
>
|
||||||
|
<span class="truncate italic opacity-80"
|
||||||
|
>{$events_sess.launcher.sync_stats
|
||||||
|
.currently_syncing}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -97,18 +138,27 @@
|
|||||||
|
|
||||||
<!-- Device Metadata (Edit Mode Only) -->
|
<!-- Device Metadata (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="col-span-full mt-1 pt-2 border-t border-surface-500/10 flex flex-col gap-1 text-[9px] opacity-60 px-1">
|
<div
|
||||||
|
class="col-span-full mt-1 pt-2 border-t border-surface-500/10 flex flex-col gap-1 text-[9px] opacity-60 px-1"
|
||||||
|
>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span>Hostname:</span>
|
<span>Hostname:</span>
|
||||||
<span class="font-mono">{$ae_loc.native_device.info_hostname || '...'}</span>
|
<span class="font-mono"
|
||||||
|
>{$ae_loc.native_device.info_hostname || '...'}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between gap-4">
|
<div class="flex justify-between gap-4">
|
||||||
<span>IP Addresses:</span>
|
<span>IP Addresses:</span>
|
||||||
<span class="font-mono truncate">{$ae_loc.native_device.info_ip_list || '...'}</span>
|
<span class="font-mono truncate"
|
||||||
|
>{$ae_loc.native_device.info_ip_list || '...'}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 opacity-40">
|
<div class="mt-2 opacity-40">
|
||||||
<label class="text-[8px] uppercase font-bold">Raw Device JSON</label>
|
<label class="text-[8px] uppercase font-bold"
|
||||||
<pre class="text-[7px] max-h-32 overflow-y-auto bg-black/20 p-1 rounded mt-1">
|
>Raw Device JSON</label
|
||||||
|
>
|
||||||
|
<pre
|
||||||
|
class="text-[7px] max-h-32 overflow-y-auto bg-black/20 p-1 rounded mt-1">
|
||||||
{JSON.stringify($ae_loc.native_device, null, 2)}
|
{JSON.stringify($ae_loc.native_device, null, 2)}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,19 +14,31 @@
|
|||||||
if (!val) return;
|
if (!val) return;
|
||||||
|
|
||||||
if (val == 'delete_idbs') {
|
if (val == 'delete_idbs') {
|
||||||
if (confirm('Are you sure you want to delete ALL IndexedDB databases?')) {
|
if (
|
||||||
|
confirm(
|
||||||
|
'Are you sure you want to delete ALL IndexedDB databases?'
|
||||||
|
)
|
||||||
|
) {
|
||||||
indexedDB.deleteDatabase('ae_archives_db');
|
indexedDB.deleteDatabase('ae_archives_db');
|
||||||
indexedDB.deleteDatabase('ae_core_db');
|
indexedDB.deleteDatabase('ae_core_db');
|
||||||
indexedDB.deleteDatabase('ae_events_db');
|
indexedDB.deleteDatabase('ae_events_db');
|
||||||
indexedDB.deleteDatabase('ae_journals_db');
|
indexedDB.deleteDatabase('ae_journals_db');
|
||||||
indexedDB.deleteDatabase('ae_posts_db');
|
indexedDB.deleteDatabase('ae_posts_db');
|
||||||
indexedDB.deleteDatabase('ae_sponsorships_db');
|
indexedDB.deleteDatabase('ae_sponsorships_db');
|
||||||
alert('All IndexedDB databases deleted. Please reload the app.');
|
alert(
|
||||||
|
'All IndexedDB databases deleted. Please reload the app.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (val == 'delete_idbs_events') {
|
} else if (val == 'delete_idbs_events') {
|
||||||
if (confirm('Are you sure you want to delete ONLY the Events IndexedDB database?')) {
|
if (
|
||||||
|
confirm(
|
||||||
|
'Are you sure you want to delete ONLY the Events IndexedDB database?'
|
||||||
|
)
|
||||||
|
) {
|
||||||
indexedDB.deleteDatabase('ae_events_db');
|
indexedDB.deleteDatabase('ae_events_db');
|
||||||
alert('Events IndexedDB database deleted. Please reload the app.');
|
alert(
|
||||||
|
'Events IndexedDB database deleted. Please reload the app.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (val == 'delete_local') {
|
} else if (val == 'delete_local') {
|
||||||
if (confirm('Are you sure you want to delete ALL local config?')) {
|
if (confirm('Are you sure you want to delete ALL local config?')) {
|
||||||
@@ -37,7 +49,11 @@
|
|||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
} else if (val == 'delete_local_events') {
|
} else if (val == 'delete_local_events') {
|
||||||
if (confirm('Are you sure you want to delete ONLY the Events local config?')) {
|
if (
|
||||||
|
confirm(
|
||||||
|
'Are you sure you want to delete ONLY the Events local config?'
|
||||||
|
)
|
||||||
|
) {
|
||||||
localStorage.removeItem('ae_events_loc');
|
localStorage.removeItem('ae_events_loc');
|
||||||
location.reload();
|
location.reload();
|
||||||
}
|
}
|
||||||
@@ -54,20 +70,26 @@
|
|||||||
description="Cache wiping and global menu toggles"
|
description="Cache wiping and global menu toggles"
|
||||||
>
|
>
|
||||||
<div class="col-span-full flex flex-col gap-3">
|
<div class="col-span-full flex flex-col gap-3">
|
||||||
|
|
||||||
<!-- 1. Reset Actions -->
|
<!-- 1. Reset Actions -->
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1 text-error-500">Maintenance & Resets</label>
|
<label
|
||||||
|
class="text-[9px] font-bold uppercase opacity-50 ml-1 text-error-500"
|
||||||
|
>Maintenance & Resets</label
|
||||||
|
>
|
||||||
<select
|
<select
|
||||||
bind:value={selected_reset}
|
bind:value={selected_reset}
|
||||||
onchange={(e) => handle_reset_action((e.target as HTMLSelectElement).value)}
|
onchange={(e) =>
|
||||||
|
handle_reset_action((e.target as HTMLSelectElement).value)}
|
||||||
class="select select-sm text-xs preset-tonal-surface h-8 text-error-500 border-error-500/20"
|
class="select select-sm text-xs preset-tonal-surface h-8 text-error-500 border-error-500/20"
|
||||||
>
|
>
|
||||||
<option value="">-- Select a reset action --</option>
|
<option value="">-- Select a reset action --</option>
|
||||||
<option value="delete_idbs">Delete ALL Databases</option>
|
<option value="delete_idbs">Delete ALL Databases</option>
|
||||||
<option value="delete_idbs_events">Delete Events DB Only</option>
|
<option value="delete_idbs_events">Delete Events DB Only</option
|
||||||
|
>
|
||||||
<option value="delete_local">Wipe ALL Local Storage</option>
|
<option value="delete_local">Wipe ALL Local Storage</option>
|
||||||
<option value="delete_local_events">Wipe Events Storage Only</option>
|
<option value="delete_local_events"
|
||||||
|
>Wipe Events Storage Only</option
|
||||||
|
>
|
||||||
</select>
|
</select>
|
||||||
<span class="text-[8px] opacity-40 italic ml-1 leading-tight">
|
<span class="text-[8px] opacity-40 italic ml-1 leading-tight">
|
||||||
* Destructive actions require browser confirmation.
|
* Destructive actions require browser confirmation.
|
||||||
@@ -76,31 +98,48 @@
|
|||||||
|
|
||||||
<!-- 2. UI Toggles -->
|
<!-- 2. UI Toggles -->
|
||||||
<div class="grid grid-cols-2 gap-2 mt-1">
|
<div class="grid grid-cols-2 gap-2 mt-1">
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => ($ae_loc.sys_menu.hide = !$ae_loc.sys_menu.hide)}
|
onclick={() => ($ae_loc.sys_menu.hide = !$ae_loc.sys_menu.hide)}
|
||||||
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
||||||
title="Show/Hide Aether global system menu"
|
title="Show/Hide Aether global system menu"
|
||||||
>
|
>
|
||||||
<span class="fas {$ae_loc.sys_menu.hide ? 'fa-eye' : 'fa-eye-slash'} mr-2"></span>
|
<span
|
||||||
|
class="fas {$ae_loc.sys_menu.hide
|
||||||
|
? 'fa-eye'
|
||||||
|
: 'fa-eye-slash'} mr-2"
|
||||||
|
></span>
|
||||||
{$ae_loc.sys_menu.hide ? 'Show' : 'Hide'} Sys Menu
|
{$ae_loc.sys_menu.hide ? 'Show' : 'Hide'} Sys Menu
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => ($ae_loc.debug_menu.hide = !$ae_loc.debug_menu.hide)}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
($ae_loc.debug_menu.hide = !$ae_loc.debug_menu.hide)}
|
||||||
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
||||||
title="Show/Hide Aether global debug menu"
|
title="Show/Hide Aether global debug menu"
|
||||||
>
|
>
|
||||||
<span class="fas {$ae_loc.debug_menu.hide ? 'fa-bug' : 'fa-bug-slash'} mr-2"></span>
|
<span
|
||||||
|
class="fas {$ae_loc.debug_menu.hide
|
||||||
|
? 'fa-bug'
|
||||||
|
: 'fa-bug-slash'} mr-2"
|
||||||
|
></span>
|
||||||
{$ae_loc.debug_menu.hide ? 'Show' : 'Hide'} Debug
|
{$ae_loc.debug_menu.hide ? 'Show' : 'Hide'} Debug
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 3. Connection Summary (Edit Mode Only) -->
|
<!-- 3. Connection Summary (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="col-span-full border-t border-surface-500/20 pt-2 mt-1 flex flex-col gap-1">
|
<div
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">API Context</label>
|
class="col-span-full border-t border-surface-500/20 pt-2 mt-1 flex flex-col gap-1"
|
||||||
<div class="bg-black/10 p-2 rounded text-[9px] font-mono opacity-60 break-all leading-tight">
|
>
|
||||||
Endpoint: {$ae_api.base_url}<br/>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>API Context</label
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="bg-black/10 p-2 rounded text-[9px] font-mono opacity-60 break-all leading-tight"
|
||||||
|
>
|
||||||
|
Endpoint: {$ae_api.base_url}<br />
|
||||||
Account: {$ae_loc.account_id}
|
Account: {$ae_loc.account_id}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,15 +14,20 @@
|
|||||||
let remote_status = $state('');
|
let remote_status = $state('');
|
||||||
let system_status = $state('');
|
let system_status = $state('');
|
||||||
|
|
||||||
async function handle_remote_control(action: 'next' | 'prev' | 'start' | 'stop') {
|
async function handle_remote_control(
|
||||||
|
action: 'next' | 'prev' | 'start' | 'stop'
|
||||||
|
) {
|
||||||
remote_status = `Sending ${action}...`;
|
remote_status = `Sending ${action}...`;
|
||||||
const res = await native.control_presentation({ app: remote_app, action });
|
const res = await native.control_presentation({
|
||||||
|
app: remote_app,
|
||||||
|
action
|
||||||
|
});
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
remote_status = `Success: ${action}`;
|
remote_status = `Success: ${action}`;
|
||||||
} else {
|
} else {
|
||||||
remote_status = `Error: ${res.error}`;
|
remote_status = `Error: ${res.error}`;
|
||||||
}
|
}
|
||||||
setTimeout(() => remote_status = '', 3000);
|
setTimeout(() => (remote_status = ''), 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handle_system_action(promise: Promise<any>, label: string) {
|
async function handle_system_action(promise: Promise<any>, label: string) {
|
||||||
@@ -33,11 +38,13 @@
|
|||||||
} else {
|
} else {
|
||||||
system_status = `Error: ${res.error || 'Unknown error'}`;
|
system_status = `Error: ${res.error || 'Unknown error'}`;
|
||||||
}
|
}
|
||||||
setTimeout(() => system_status = '', 3000);
|
setTimeout(() => (system_status = ''), 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modal state for dangerous actions
|
// Modal state for dangerous actions
|
||||||
let show_power_confirm = $state<{ action: string, label: string } | null>(null);
|
let show_power_confirm = $state<{ action: string; label: string } | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Launcher_Cfg_Section
|
<Launcher_Cfg_Section
|
||||||
@@ -45,39 +52,53 @@
|
|||||||
icon="fa-laptop-code"
|
icon="fa-laptop-code"
|
||||||
bind:state={$events_loc.launcher.section_state__native_os}
|
bind:state={$events_loc.launcher.section_state__native_os}
|
||||||
{on_expand}
|
{on_expand}
|
||||||
description="OS: {$ae_loc.native_device?.meta_json?.platform || '...'} | Kiosk & Apps"
|
description="OS: {$ae_loc.native_device?.meta_json?.platform ||
|
||||||
|
'...'} | Kiosk & Apps"
|
||||||
>
|
>
|
||||||
<!-- Content omitted for brevity, preserved in file -->
|
<!-- Content omitted for brevity, preserved in file -->
|
||||||
{#if system_status}
|
{#if system_status}
|
||||||
<div class="col-span-full text-[10px] text-center italic bg-surface-500/10 py-1 rounded animate-pulse text-primary-500 border border-primary-500/20">
|
<div
|
||||||
|
class="col-span-full text-[10px] text-center italic bg-surface-500/10 py-1 rounded animate-pulse text-primary-500 border border-primary-500/20"
|
||||||
|
>
|
||||||
{system_status}
|
{system_status}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- 1. Window & Folders (Common) -->
|
<!-- 1. Window & Folders (Common) -->
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Folders & View</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Folders & View</label
|
||||||
|
>
|
||||||
<div class="grid grid-cols-2 gap-1">
|
<div class="grid grid-cols-2 gap-1">
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => native.open_folder($ae_loc.local_file_cache_path)}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
native.open_folder($ae_loc.local_file_cache_path)}
|
||||||
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
|
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
|
||||||
>
|
>
|
||||||
<span class="fas fa-folder-open mr-2 w-3"></span> Cache
|
<span class="fas fa-folder-open mr-2 w-3"></span> Cache
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => native.open_folder($ae_loc.host_file_temp_path)}
|
onclick={() => native.open_folder($ae_loc.host_file_temp_path)}
|
||||||
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
|
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
|
||||||
>
|
>
|
||||||
<span class="fas fa-folder-open mr-2 w-3"></span> Temp
|
<span class="fas fa-folder-open mr-2 w-3"></span> Temp
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => native.window_control({ action: 'maximize' })}
|
onclick={() => native.window_control({ action: 'maximize' })}
|
||||||
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
||||||
>
|
>
|
||||||
<span class="fas fa-expand mr-1"></span> Maximize
|
<span class="fas fa-expand mr-1"></span> Maximize
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => handle_system_action(native.window_control({ action: 'kiosk', value: true }), 'Kiosk Mode')}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
handle_system_action(
|
||||||
|
native.window_control({ action: 'kiosk', value: true }),
|
||||||
|
'Kiosk Mode'
|
||||||
|
)}
|
||||||
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500"
|
||||||
>
|
>
|
||||||
<span class="fas fa-desktop mr-1"></span> Kiosk
|
<span class="fas fa-desktop mr-1"></span> Kiosk
|
||||||
@@ -88,47 +109,94 @@
|
|||||||
<!-- 2. Presentation Remote Control (Common) -->
|
<!-- 2. Presentation Remote Control (Common) -->
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<div class="flex flex-row justify-between items-center px-1">
|
<div class="flex flex-row justify-between items-center px-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50">Remote Control</label>
|
<label class="text-[9px] font-bold uppercase opacity-50"
|
||||||
<select bind:value={remote_app} class="select select-sm py-0 h-5 text-[9px] w-24 preset-tonal-surface">
|
>Remote Control</label
|
||||||
|
>
|
||||||
|
<select
|
||||||
|
bind:value={remote_app}
|
||||||
|
class="select select-sm py-0 h-5 text-[9px] w-24 preset-tonal-surface"
|
||||||
|
>
|
||||||
<option value="powerpoint">PowerPoint</option>
|
<option value="powerpoint">PowerPoint</option>
|
||||||
<option value="keynote">Keynote</option>
|
<option value="keynote">Keynote</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-4 gap-1">
|
<div class="grid grid-cols-4 gap-1">
|
||||||
<button type="button" onclick={() => handle_remote_control('prev')} class="btn btn-sm preset-tonal-secondary" title="Previous Slide">
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => handle_remote_control('prev')}
|
||||||
|
class="btn btn-sm preset-tonal-secondary"
|
||||||
|
title="Previous Slide"
|
||||||
|
>
|
||||||
<span class="fas fa-step-backward"></span>
|
<span class="fas fa-step-backward"></span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" onclick={() => handle_remote_control('start')} class="btn btn-sm preset-tonal-success" title="Start/Resume Slideshow">
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => handle_remote_control('start')}
|
||||||
|
class="btn btn-sm preset-tonal-success"
|
||||||
|
title="Start/Resume Slideshow"
|
||||||
|
>
|
||||||
<span class="fas fa-play"></span>
|
<span class="fas fa-play"></span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" onclick={() => handle_remote_control('stop')} class="btn btn-sm preset-tonal-error" title="Stop Slideshow">
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => handle_remote_control('stop')}
|
||||||
|
class="btn btn-sm preset-tonal-error"
|
||||||
|
title="Stop Slideshow"
|
||||||
|
>
|
||||||
<span class="fas fa-stop"></span>
|
<span class="fas fa-stop"></span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" onclick={() => handle_remote_control('next')} class="btn btn-sm preset-tonal-secondary" title="Next Slide">
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => handle_remote_control('next')}
|
||||||
|
class="btn btn-sm preset-tonal-secondary"
|
||||||
|
title="Next Slide"
|
||||||
|
>
|
||||||
<span class="fas fa-step-forward"></span>
|
<span class="fas fa-step-forward"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{#if remote_status}
|
{#if remote_status}
|
||||||
<div class="text-[9px] text-center italic animate-pulse text-primary-500">{remote_status}</div>
|
<div
|
||||||
|
class="text-[9px] text-center italic animate-pulse text-primary-500"
|
||||||
|
>
|
||||||
|
{remote_status}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 3. Technical Management (Edit Mode Only) -->
|
<!-- 3. Technical Management (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-3">
|
<div
|
||||||
|
class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-3"
|
||||||
|
>
|
||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50">System Actions</label>
|
<label class="text-[9px] font-bold uppercase opacity-50"
|
||||||
|
>System Actions</label
|
||||||
|
>
|
||||||
<div class="grid grid-cols-1 gap-1">
|
<div class="grid grid-cols-1 gap-1">
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => handle_system_action(native.set_display_layout({ mode: 'extend' }), 'Extend Display')}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
handle_system_action(
|
||||||
|
native.set_display_layout({
|
||||||
|
mode: 'extend'
|
||||||
|
}),
|
||||||
|
'Extend Display'
|
||||||
|
)}
|
||||||
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500 justify-start"
|
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500 justify-start"
|
||||||
>
|
>
|
||||||
<span class="fas fa-columns mr-2 w-3"></span> Extend Mode
|
<span class="fas fa-columns mr-2 w-3"></span> Extend Mode
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => handle_system_action(native.set_wallpaper({ path: $ae_loc.site_header_image_path }), 'Wallpaper')}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
handle_system_action(
|
||||||
|
native.set_wallpaper({
|
||||||
|
path: $ae_loc.site_header_image_path
|
||||||
|
}),
|
||||||
|
'Wallpaper'
|
||||||
|
)}
|
||||||
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500 justify-start"
|
class="btn btn-xs preset-tonal-surface hover:preset-filled-primary-500 justify-start"
|
||||||
disabled={!$ae_loc.site_header_image_path}
|
disabled={!$ae_loc.site_header_image_path}
|
||||||
>
|
>
|
||||||
@@ -137,16 +205,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 text-error-500">Power</label>
|
<label
|
||||||
|
class="text-[9px] font-bold uppercase opacity-50 text-error-500"
|
||||||
|
>Power</label
|
||||||
|
>
|
||||||
<div class="grid grid-cols-1 gap-1">
|
<div class="grid grid-cols-1 gap-1">
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => show_power_confirm = { action: 'reboot', label: 'Reboot Laptop' }}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
(show_power_confirm = {
|
||||||
|
action: 'reboot',
|
||||||
|
label: 'Reboot Laptop'
|
||||||
|
})}
|
||||||
class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500 justify-start"
|
class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500 justify-start"
|
||||||
>
|
>
|
||||||
<span class="fas fa-sync-alt mr-2 w-3"></span> Reboot
|
<span class="fas fa-sync-alt mr-2 w-3"></span> Reboot
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => show_power_confirm = { action: 'shutdown', label: 'Shutdown Laptop' }}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
(show_power_confirm = {
|
||||||
|
action: 'shutdown',
|
||||||
|
label: 'Shutdown Laptop'
|
||||||
|
})}
|
||||||
class="btn btn-xs preset-tonal-error hover:preset-filled-error-500 justify-start"
|
class="btn btn-xs preset-tonal-error hover:preset-filled-error-500 justify-start"
|
||||||
>
|
>
|
||||||
<span class="fas fa-power-off mr-2 w-3"></span> Shutdown
|
<span class="fas fa-power-off mr-2 w-3"></span> Shutdown
|
||||||
@@ -156,7 +237,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Terminal Access</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Terminal Access</label
|
||||||
|
>
|
||||||
<div class="flex gap-1">
|
<div class="flex gap-1">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -164,17 +247,26 @@
|
|||||||
placeholder="ls -la"
|
placeholder="ls -la"
|
||||||
class="input input-sm grow text-[10px] preset-tonal-surface h-7"
|
class="input input-sm grow text-[10px] preset-tonal-surface h-7"
|
||||||
/>
|
/>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
test_cmd_result = 'Running...';
|
test_cmd_result = 'Running...';
|
||||||
const res = await native.run_cmd({ cmd: $events_sess.launcher.manual_cmd || 'uptime' });
|
const res = await native.run_cmd({
|
||||||
test_cmd_result = (res as any).stdout || (res as any).error || 'No Output';
|
cmd:
|
||||||
|
$events_sess.launcher.manual_cmd || 'uptime'
|
||||||
|
});
|
||||||
|
test_cmd_result =
|
||||||
|
(res as any).stdout ||
|
||||||
|
(res as any).error ||
|
||||||
|
'No Output';
|
||||||
}}
|
}}
|
||||||
class="btn btn-sm preset-filled-secondary hover:preset-filled-primary-500 text-[10px] h-7"
|
class="btn btn-sm preset-filled-secondary hover:preset-filled-primary-500 text-[10px] h-7"
|
||||||
>Run</button>
|
>Run</button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
{#if test_cmd_result}
|
{#if test_cmd_result}
|
||||||
<pre class="text-[8px] bg-black text-green-500 p-2 mt-1 overflow-x-auto rounded border border-surface-500/50 max-h-24 shadow-inner">{test_cmd_result}</pre>
|
<pre
|
||||||
|
class="text-[8px] bg-black text-green-500 p-2 mt-1 overflow-x-auto rounded border border-surface-500/50 max-h-24 shadow-inner">{test_cmd_result}</pre>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -183,19 +275,36 @@
|
|||||||
|
|
||||||
<!-- Power Confirmation Modal -->
|
<!-- Power Confirmation Modal -->
|
||||||
{#if show_power_confirm}
|
{#if show_power_confirm}
|
||||||
<div class="fixed inset-0 z-[1000] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4">
|
<div
|
||||||
<div class="card p-6 w-full max-w-sm preset-filled-surface-100-900 border border-error-500 shadow-2xl animate-in zoom-in-95 duration-200">
|
class="fixed inset-0 z-[1000] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"
|
||||||
<h4 class="h4 text-error-500 font-bold mb-2">Confirm System Action</h4>
|
>
|
||||||
|
<div
|
||||||
|
class="card p-6 w-full max-w-sm preset-filled-surface-100-900 border border-error-500 shadow-2xl animate-in zoom-in-95 duration-200"
|
||||||
|
>
|
||||||
|
<h4 class="h4 text-error-500 font-bold mb-2">
|
||||||
|
Confirm System Action
|
||||||
|
</h4>
|
||||||
<p class="text-sm opacity-80 mb-6">
|
<p class="text-sm opacity-80 mb-6">
|
||||||
Are you sure you want to <strong>{show_power_confirm.action}</strong> this host machine?
|
Are you sure you want to <strong
|
||||||
|
>{show_power_confirm.action}</strong
|
||||||
|
> this host machine?
|
||||||
</p>
|
</p>
|
||||||
<div class="flex justify-end gap-2">
|
<div class="flex justify-end gap-2">
|
||||||
<button type="button" onclick={() => show_power_confirm = null} class="btn btn-sm preset-tonal-surface">Cancel</button>
|
<button
|
||||||
<button type="button"
|
type="button"
|
||||||
|
onclick={() => (show_power_confirm = null)}
|
||||||
|
class="btn btn-sm preset-tonal-surface">Cancel</button
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
const action = show_power_confirm?.action;
|
const action = show_power_confirm?.action;
|
||||||
show_power_confirm = null;
|
show_power_confirm = null;
|
||||||
if (action) handle_system_action(native.power_control({ action: action as any }), action);
|
if (action)
|
||||||
|
handle_system_action(
|
||||||
|
native.power_control({ action: action as any }),
|
||||||
|
action
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
class="btn btn-sm preset-filled-error"
|
class="btn btn-sm preset-filled-error"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -14,16 +14,21 @@
|
|||||||
icon="fa-id-badge"
|
icon="fa-id-badge"
|
||||||
bind:state={$events_loc.launcher.section_state__screen_saver}
|
bind:state={$events_loc.launcher.section_state__screen_saver}
|
||||||
{on_expand}
|
{on_expand}
|
||||||
description="Idle: {($events_loc.launcher.idle_timer / 60000).toFixed(1)}m | Auto-Posters"
|
description="Idle: {($events_loc.launcher.idle_timer / 60000).toFixed(
|
||||||
|
1
|
||||||
|
)}m | Auto-Posters"
|
||||||
>
|
>
|
||||||
<!-- Content omitted for brevity, preserved in file -->
|
<!-- Content omitted for brevity, preserved in file -->
|
||||||
<div class="col-span-full flex flex-col gap-3">
|
<div class="col-span-full flex flex-col gap-3">
|
||||||
|
|
||||||
<!-- 1. Technical Timers (Edit Mode Only) -->
|
<!-- 1. Technical Timers (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Screen Saver Timers (ms)</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
<div class="grid grid-cols-1 gap-2 bg-surface-500/5 p-2 rounded border border-surface-500/10">
|
>Screen Saver Timers (ms)</label
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-1 gap-2 bg-surface-500/5 p-2 rounded border border-surface-500/10"
|
||||||
|
>
|
||||||
<div class="flex justify-between items-center gap-4">
|
<div class="flex justify-between items-center gap-4">
|
||||||
<span class="text-[10px] opacity-60">Idle Wait</span>
|
<span class="text-[10px] opacity-60">Idle Wait</span>
|
||||||
<input
|
<input
|
||||||
@@ -43,7 +48,9 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-center gap-4">
|
<div class="flex justify-between items-center gap-4">
|
||||||
<span class="text-[10px] opacity-60">Image Rotation</span>
|
<span class="text-[10px] opacity-60"
|
||||||
|
>Image Rotation</span
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
min={750}
|
min={750}
|
||||||
@@ -55,13 +62,18 @@
|
|||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- 2. Read Only Summary (Normal Mode) -->
|
<!-- 2. Read Only Summary (Normal Mode) -->
|
||||||
<div class="bg-surface-500/5 p-3 rounded-lg border border-surface-500/10 flex flex-col gap-2">
|
<div
|
||||||
|
class="bg-surface-500/5 p-3 rounded-lg border border-surface-500/10 flex flex-col gap-2"
|
||||||
|
>
|
||||||
<div class="flex justify-between items-center text-xs">
|
<div class="flex justify-between items-center text-xs">
|
||||||
<span class="opacity-60">Active Idle Timeout:</span>
|
<span class="opacity-60">Active Idle Timeout:</span>
|
||||||
<span class="font-bold text-primary-500">{($events_loc.launcher.idle_timer / 60000).toFixed(1)} minutes</span>
|
<span class="font-bold text-primary-500"
|
||||||
|
>{($events_loc.launcher.idle_timer / 60000).toFixed(1)} minutes</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-[9px] opacity-40 italic">
|
<p class="text-[9px] opacity-40 italic">
|
||||||
The screen saver automatically rotates digital posters when no activity is detected for the specified time.
|
The screen saver automatically rotates digital posters when
|
||||||
|
no activity is detected for the specified time.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -13,7 +13,15 @@
|
|||||||
on_toggle?: (new_state: 'collapsed' | 'auto' | 'pinned') => void;
|
on_toggle?: (new_state: 'collapsed' | 'auto' | 'pinned') => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { title, icon, state = $bindable(), description, children, on_expand, on_toggle }: Props = $props();
|
let {
|
||||||
|
title,
|
||||||
|
icon,
|
||||||
|
state = $bindable(),
|
||||||
|
description,
|
||||||
|
children,
|
||||||
|
on_expand,
|
||||||
|
on_toggle
|
||||||
|
}: Props = $props();
|
||||||
|
|
||||||
function toggle_expand() {
|
function toggle_expand() {
|
||||||
if (state === 'collapsed') {
|
if (state === 'collapsed') {
|
||||||
@@ -40,39 +48,65 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section
|
<section
|
||||||
class="w-full transition-all duration-300 border rounded-lg overflow-hidden mb-2 { !is_open ? 'preset-outlined-surface-300-700' : '' } { state === 'auto' ? 'preset-outlined-primary-500 shadow-xl' : '' } { state === 'pinned' ? 'preset-outlined-warning-500 shadow-xl' : '' }"
|
class="w-full transition-all duration-300 border rounded-lg overflow-hidden mb-2 {!is_open
|
||||||
|
? 'preset-outlined-surface-300-700'
|
||||||
|
: ''} {state === 'auto'
|
||||||
|
? 'preset-outlined-primary-500 shadow-xl'
|
||||||
|
: ''} {state === 'pinned'
|
||||||
|
? 'preset-outlined-warning-500 shadow-xl'
|
||||||
|
: ''}"
|
||||||
>
|
>
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<header
|
<header
|
||||||
class="flex flex-row items-center justify-between p-2 cursor-pointer transition-colors { !is_open ? 'bg-surface-500/5' : '' } { state === 'auto' ? 'bg-primary-500/10' : '' } { state === 'pinned' ? 'bg-warning-500/10' : '' }"
|
class="flex flex-row items-center justify-between p-2 cursor-pointer transition-colors {!is_open
|
||||||
|
? 'bg-surface-500/5'
|
||||||
|
: ''} {state === 'auto' ? 'bg-primary-500/10' : ''} {state ===
|
||||||
|
'pinned'
|
||||||
|
? 'bg-warning-500/10'
|
||||||
|
: ''}"
|
||||||
onclick={toggle_expand}
|
onclick={toggle_expand}
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<span class="fas {icon} w-5 text-center opacity-70 { state === 'auto' ? 'text-primary-500' : '' } { state === 'pinned' ? 'text-warning-500' : '' }"></span>
|
<span
|
||||||
|
class="fas {icon} w-5 text-center opacity-70 {state === 'auto'
|
||||||
|
? 'text-primary-500'
|
||||||
|
: ''} {state === 'pinned' ? 'text-warning-500' : ''}"
|
||||||
|
></span>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="text-sm font-bold tracking-tight uppercase { !is_open ? 'opacity-50' : '' }">{title}</span>
|
<span
|
||||||
|
class="text-sm font-bold tracking-tight uppercase {!is_open
|
||||||
|
? 'opacity-50'
|
||||||
|
: ''}">{title}</span
|
||||||
|
>
|
||||||
{#if description && !is_open}
|
{#if description && !is_open}
|
||||||
<span class="text-[9px] opacity-40 italic truncate max-w-[180px]">{description}</span>
|
<span
|
||||||
|
class="text-[9px] opacity-40 italic truncate max-w-[180px]"
|
||||||
|
>{description}</span
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<!-- Pin Toggle -->
|
<!-- Pin Toggle -->
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={toggle_pin}
|
onclick={toggle_pin}
|
||||||
class="btn btn-icon btn-xs transition-all hover:scale-110"
|
class="btn btn-icon btn-xs transition-all hover:scale-110"
|
||||||
class:opacity-20={state !== 'pinned'}
|
class:opacity-20={state !== 'pinned'}
|
||||||
class:text-warning-500={state === 'pinned'}
|
class:text-warning-500={state === 'pinned'}
|
||||||
title={state === 'pinned' ? 'Unpin Section' : 'Pin Section (Stay open)'}
|
title={state === 'pinned'
|
||||||
|
? 'Unpin Section'
|
||||||
|
: 'Pin Section (Stay open)'}
|
||||||
>
|
>
|
||||||
<span class="fas fa-thumbtack text-[10px]"></span>
|
<span class="fas fa-thumbtack text-[10px]"></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Collapse Icon -->
|
<!-- Collapse Icon -->
|
||||||
<span class="fas transition-transform duration-300 opacity-30"
|
<span
|
||||||
|
class="fas transition-transform duration-300 opacity-30"
|
||||||
class:fa-chevron-right={!is_open}
|
class:fa-chevron-right={!is_open}
|
||||||
class:fa-chevron-down={is_open}
|
class:fa-chevron-down={is_open}
|
||||||
class:rotate-180={is_open}
|
class:rotate-180={is_open}
|
||||||
@@ -82,19 +116,29 @@
|
|||||||
|
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
{#if is_open}
|
{#if is_open}
|
||||||
<div transition:slide={{ duration: 300 }} class="p-3 bg-white/5 dark:bg-black/5">
|
<div
|
||||||
|
transition:slide={{ duration: 300 }}
|
||||||
|
class="p-3 bg-white/5 dark:bg-black/5"
|
||||||
|
>
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="mb-2 flex justify-between items-center px-1">
|
<div class="mb-2 flex justify-between items-center px-1">
|
||||||
<span class="text-[8px] uppercase font-bold tracking-widest text-primary-500/60 flex items-center gap-1">
|
<span
|
||||||
|
class="text-[8px] uppercase font-bold tracking-widest text-primary-500/60 flex items-center gap-1"
|
||||||
|
>
|
||||||
<span class="fas fa-edit"></span> Technical Mode
|
<span class="fas fa-edit"></span> Technical Mode
|
||||||
</span>
|
</span>
|
||||||
{#if state === 'pinned'}
|
{#if state === 'pinned'}
|
||||||
<span class="badge variant-filled-warning text-[8px] uppercase">Pinned</span>
|
<span
|
||||||
|
class="badge variant-filled-warning text-[8px] uppercase"
|
||||||
|
>Pinned</span
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-1 gap-4 lg:gap-3">
|
<div
|
||||||
|
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-1 gap-4 lg:gap-3"
|
||||||
|
>
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,58 +14,87 @@
|
|||||||
icon="fa-sync"
|
icon="fa-sync"
|
||||||
bind:state={$events_loc.launcher.section_state__sync_timers}
|
bind:state={$events_loc.launcher.section_state__sync_timers}
|
||||||
{on_expand}
|
{on_expand}
|
||||||
description="Prefix: {$ae_loc.native_device?.hash_prefix_length || 2} | Loops: Active"
|
description="Prefix: {$ae_loc.native_device?.hash_prefix_length ||
|
||||||
|
2} | Loops: Active"
|
||||||
>
|
>
|
||||||
<!-- Content omitted for brevity, preserved in file -->
|
<!-- Content omitted for brevity, preserved in file -->
|
||||||
{#if $ae_loc.native_device}
|
{#if $ae_loc.native_device}
|
||||||
<div class="grid grid-cols-1 gap-3">
|
<div class="grid grid-cols-1 gap-3">
|
||||||
|
|
||||||
<!-- Technical Timers (Edit Mode Only) -->
|
<!-- Technical Timers (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Polling Periods (ms)</label>
|
<label
|
||||||
|
class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Polling Periods (ms)</label
|
||||||
|
>
|
||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-[8px] opacity-60">Event Data</span>
|
<span class="text-[8px] opacity-60">Event Data</span
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
bind:value={$ae_loc.native_device.check_event_loop_period}
|
bind:value={
|
||||||
|
$ae_loc.native_device
|
||||||
|
.check_event_loop_period
|
||||||
|
}
|
||||||
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-[8px] opacity-60">Device Config</span>
|
<span class="text-[8px] opacity-60"
|
||||||
|
>Device Config</span
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
bind:value={$ae_loc.native_device.check_event_device_loop_period}
|
bind:value={
|
||||||
|
$ae_loc.native_device
|
||||||
|
.check_event_device_loop_period
|
||||||
|
}
|
||||||
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-[8px] opacity-60">Room/Location</span>
|
<span class="text-[8px] opacity-60"
|
||||||
|
>Room/Location</span
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
bind:value={$ae_loc.native_device.check_event_location_loop_period}
|
bind:value={
|
||||||
|
$ae_loc.native_device
|
||||||
|
.check_event_location_loop_period
|
||||||
|
}
|
||||||
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-[8px] opacity-60">Session Loop</span>
|
<span class="text-[8px] opacity-60"
|
||||||
|
>Session Loop</span
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
bind:value={$ae_loc.native_device.check_event_session_loop_period}
|
bind:value={
|
||||||
|
$ae_loc.native_device
|
||||||
|
.check_event_session_loop_period
|
||||||
|
}
|
||||||
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
class="input input-sm text-[10px] h-7 preset-tonal-surface"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1 mt-1 border-t border-surface-500/10 pt-2">
|
<div
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Cache Structure</label>
|
class="flex flex-col gap-1 mt-1 border-t border-surface-500/10 pt-2"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Cache Structure</label
|
||||||
|
>
|
||||||
<div class="flex items-center justify-between px-1">
|
<div class="flex items-center justify-between px-1">
|
||||||
<span class="text-[9px]">Hash Prefix Length</span>
|
<span class="text-[9px]">Hash Prefix Length</span>
|
||||||
<select
|
<select
|
||||||
bind:value={$ae_loc.native_device.hash_prefix_length}
|
bind:value={
|
||||||
|
$ae_loc.native_device.hash_prefix_length
|
||||||
|
}
|
||||||
class="select select-sm h-6 py-0 text-[10px] w-16 preset-tonal-surface"
|
class="select select-sm h-6 py-0 text-[10px] w-16 preset-tonal-surface"
|
||||||
>
|
>
|
||||||
<option value={1}>1 char</option>
|
<option value={1}>1 char</option>
|
||||||
@@ -73,26 +102,51 @@
|
|||||||
<option value={3}>3 chars</option>
|
<option value={3}>3 chars</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-[8px] opacity-40 italic mt-1">* Prefix change requires a full app reload to take effect.</p>
|
<p class="text-[8px] opacity-40 italic mt-1">
|
||||||
|
* Prefix change requires a full app reload to take
|
||||||
|
effect.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Read Only Summary (Normal Mode) -->
|
<!-- Read Only Summary (Normal Mode) -->
|
||||||
<div class="bg-surface-500/5 p-2 rounded border border-surface-500/10 flex flex-col gap-1">
|
<div
|
||||||
<div class="flex justify-between text-[9px] opacity-60 font-mono">
|
class="bg-surface-500/5 p-2 rounded border border-surface-500/10 flex flex-col gap-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex justify-between text-[9px] opacity-60 font-mono"
|
||||||
|
>
|
||||||
<span>Event Sync:</span>
|
<span>Event Sync:</span>
|
||||||
<span>{($ae_loc.native_device.check_event_loop_period / 1000).toFixed(1)}s</span>
|
<span
|
||||||
|
>{(
|
||||||
|
$ae_loc.native_device.check_event_loop_period /
|
||||||
|
1000
|
||||||
|
).toFixed(1)}s</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between text-[9px] opacity-60 font-mono">
|
<div
|
||||||
|
class="flex justify-between text-[9px] opacity-60 font-mono"
|
||||||
|
>
|
||||||
<span>Room Monitor:</span>
|
<span>Room Monitor:</span>
|
||||||
<span>{($ae_loc.native_device.check_event_location_loop_period / 1000).toFixed(1)}s</span>
|
<span
|
||||||
|
>{(
|
||||||
|
$ae_loc.native_device
|
||||||
|
.check_event_location_loop_period / 1000
|
||||||
|
).toFixed(1)}s</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between text-[9px] opacity-60 font-mono border-t border-surface-500/10 pt-1">
|
<div
|
||||||
|
class="flex justify-between text-[9px] opacity-60 font-mono border-t border-surface-500/10 pt-1"
|
||||||
|
>
|
||||||
<span>Prefix Sharding:</span>
|
<span>Prefix Sharding:</span>
|
||||||
<span>{$ae_loc.native_device.hash_prefix_length || 2} chars</span>
|
<span
|
||||||
|
>{$ae_loc.native_device.hash_prefix_length || 2} chars</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="text-[8px] opacity-40 italic">Enable Edit Mode to adjust polling intervals.</p>
|
<p class="text-[8px] opacity-40 italic">
|
||||||
|
Enable Edit Mode to adjust polling intervals.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -27,11 +27,11 @@
|
|||||||
action_status = `Executing ${label}...`;
|
action_status = `Executing ${label}...`;
|
||||||
|
|
||||||
// Simulate async work
|
// Simulate async work
|
||||||
await new Promise(r => setTimeout(r, 1500));
|
await new Promise((r) => setTimeout(r, 1500));
|
||||||
|
|
||||||
is_loading = false;
|
is_loading = false;
|
||||||
action_status = `Finished: ${label}`;
|
action_status = `Finished: ${label}`;
|
||||||
setTimeout(() => action_status = '', 3000);
|
setTimeout(() => (action_status = ''), 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modal state for destructive actions
|
// Modal state for destructive actions
|
||||||
@@ -47,24 +47,30 @@
|
|||||||
>
|
>
|
||||||
<!-- A. TOP STATUS BAR (Optional) -->
|
<!-- A. TOP STATUS BAR (Optional) -->
|
||||||
{#if action_status}
|
{#if action_status}
|
||||||
<div class="col-span-full text-[10px] text-center italic bg-primary-500/10 py-1 rounded animate-pulse text-primary-500 border border-primary-500/20">
|
<div
|
||||||
|
class="col-span-full text-[10px] text-center italic bg-primary-500/10 py-1 rounded animate-pulse text-primary-500 border border-primary-500/20"
|
||||||
|
>
|
||||||
{action_status}
|
{action_status}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- B. COMMON GRID SECTION (Read Only / High Level) -->
|
<!-- B. COMMON GRID SECTION (Read Only / High Level) -->
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Standard Actions</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Standard Actions</label
|
||||||
|
>
|
||||||
|
|
||||||
<!-- Action Buttons -->
|
<!-- Action Buttons -->
|
||||||
<div class="grid grid-cols-2 gap-1">
|
<div class="grid grid-cols-2 gap-1">
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => handle_test_action('Primary')}
|
onclick={() => handle_test_action('Primary')}
|
||||||
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
|
class="btn btn-xs preset-tonal-primary hover:preset-filled-primary-500 justify-start"
|
||||||
>
|
>
|
||||||
<span class="fas fa-bolt mr-2 w-3 text-center"></span> Primary
|
<span class="fas fa-bolt mr-2 w-3 text-center"></span> Primary
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => handle_test_action('Secondary')}
|
onclick={() => handle_test_action('Secondary')}
|
||||||
class="btn btn-xs preset-tonal-secondary hover:preset-filled-secondary-500 justify-start"
|
class="btn btn-xs preset-tonal-secondary hover:preset-filled-secondary-500 justify-start"
|
||||||
>
|
>
|
||||||
@@ -75,39 +81,68 @@
|
|||||||
<!-- Toggles & Checkboxes -->
|
<!-- Toggles & Checkboxes -->
|
||||||
<div class="flex flex-col gap-1 mt-1 bg-surface-500/5 p-2 rounded">
|
<div class="flex flex-col gap-1 mt-1 bg-surface-500/5 p-2 rounded">
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="checkbox" bind:checked={toggle_val} class="checkbox checkbox-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500 transition-colors">Toggle Feature Alpha</span>
|
type="checkbox"
|
||||||
|
bind:checked={toggle_val}
|
||||||
|
class="checkbox checkbox-sm"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="text-xs group-hover:text-primary-500 transition-colors"
|
||||||
|
>Toggle Feature Alpha</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
<label class="flex items-center gap-2 cursor-pointer group">
|
<label class="flex items-center gap-2 cursor-pointer group">
|
||||||
<input type="radio" name="demo" value="a" class="radio radio-sm" />
|
<input
|
||||||
<span class="text-xs group-hover:text-primary-500 transition-colors">Mode A</span>
|
type="radio"
|
||||||
|
name="demo"
|
||||||
|
value="a"
|
||||||
|
class="radio radio-sm"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="text-xs group-hover:text-primary-500 transition-colors"
|
||||||
|
>Mode A</span
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- C. STATUS & GAUGES SECTION -->
|
<!-- C. STATUS & GAUGES SECTION -->
|
||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Current Status</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Current Status</label
|
||||||
|
>
|
||||||
|
|
||||||
<div class="flex flex-col gap-2 p-2 border border-surface-500/10 rounded-lg">
|
<div
|
||||||
|
class="flex flex-col gap-2 p-2 border border-surface-500/10 rounded-lg"
|
||||||
|
>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class="text-[10px] font-medium">Engine Health</span>
|
<span class="text-[10px] font-medium">Engine Health</span>
|
||||||
<span class="badge variant-filled-success text-[8px] uppercase">Stable</span>
|
<span class="badge variant-filled-success text-[8px] uppercase"
|
||||||
|
>Stable</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Progress / Gauge Example -->
|
<!-- Progress / Gauge Example -->
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<div class="flex justify-between text-[8px] uppercase opacity-60">
|
<div
|
||||||
|
class="flex justify-between text-[8px] uppercase opacity-60"
|
||||||
|
>
|
||||||
<span>Processing Load</span>
|
<span>Processing Load</span>
|
||||||
<span>45%</span>
|
<span>45%</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full h-1.5 bg-surface-500/20 rounded-full overflow-hidden">
|
<div
|
||||||
<div class="h-full bg-success-500 transition-all duration-1000" style="width: 45%"></div>
|
class="w-full h-1.5 bg-surface-500/20 rounded-full overflow-hidden"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="h-full bg-success-500 transition-all duration-1000"
|
||||||
|
style="width: 45%"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => handle_test_action('Refresh')}
|
onclick={() => handle_test_action('Refresh')}
|
||||||
class="btn btn-xs preset-outlined-surface-500 w-full text-[10px]"
|
class="btn btn-xs preset-outlined-surface-500 w-full text-[10px]"
|
||||||
>
|
>
|
||||||
@@ -118,22 +153,34 @@
|
|||||||
|
|
||||||
<!-- D. TECHNICAL SECTION (Edit Mode Only) -->
|
<!-- D. TECHNICAL SECTION (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-3">
|
<div
|
||||||
|
class="col-span-full border-t border-surface-500/20 pt-3 mt-1 flex flex-col gap-3"
|
||||||
|
>
|
||||||
<!-- Dangerous Actions -->
|
<!-- Dangerous Actions -->
|
||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 text-warning-500">System Config</label>
|
<label
|
||||||
<button type="button"
|
class="text-[9px] font-bold uppercase opacity-50 text-warning-500"
|
||||||
onclick={() => show_confirm = true}
|
>System Config</label
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => (show_confirm = true)}
|
||||||
class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500 justify-start"
|
class="btn btn-xs preset-tonal-warning hover:preset-filled-warning-500 justify-start"
|
||||||
>
|
>
|
||||||
<span class="fas fa-exclamation-triangle mr-2 w-3"></span> Reset All
|
<span class="fas fa-exclamation-triangle mr-2 w-3"
|
||||||
|
></span> Reset All
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 text-error-500">Danger Zone</label>
|
<label
|
||||||
<button type="button" class="btn btn-xs preset-tonal-error hover:preset-filled-error-500 justify-start">
|
class="text-[9px] font-bold uppercase opacity-50 text-error-500"
|
||||||
|
>Danger Zone</label
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-xs preset-tonal-error hover:preset-filled-error-500 justify-start"
|
||||||
|
>
|
||||||
<span class="fas fa-trash-alt mr-2 w-3"></span> Wipe Cache
|
<span class="fas fa-trash-alt mr-2 w-3"></span> Wipe Cache
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,7 +189,10 @@
|
|||||||
<!-- Form Inputs -->
|
<!-- Form Inputs -->
|
||||||
<div class="grid grid-cols-1 gap-2">
|
<div class="grid grid-cols-1 gap-2">
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Raw Settings</label>
|
<label
|
||||||
|
class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
|
>Raw Settings</label
|
||||||
|
>
|
||||||
<div class="flex gap-1">
|
<div class="flex gap-1">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@@ -150,7 +200,10 @@
|
|||||||
placeholder="Enter string parameter..."
|
placeholder="Enter string parameter..."
|
||||||
class="input input-sm grow text-[10px] preset-tonal-surface h-7"
|
class="input input-sm grow text-[10px] preset-tonal-surface h-7"
|
||||||
/>
|
/>
|
||||||
<select bind:value={select_val} class="select select-sm h-7 py-0 text-[10px] w-24 preset-tonal-surface">
|
<select
|
||||||
|
bind:value={select_val}
|
||||||
|
class="select select-sm h-7 py-0 text-[10px] w-24 preset-tonal-surface"
|
||||||
|
>
|
||||||
<option value="option1">Global</option>
|
<option value="option1">Global</option>
|
||||||
<option value="option2">Local</option>
|
<option value="option2">Local</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -158,7 +211,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<span class="text-[8px] opacity-60 ml-1">Threshold (ms)</span>
|
<span class="text-[8px] opacity-60 ml-1"
|
||||||
|
>Threshold (ms)</span
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
bind:value={number_input}
|
bind:value={number_input}
|
||||||
@@ -169,8 +224,11 @@
|
|||||||
|
|
||||||
<!-- Terminal / Output Log -->
|
<!-- Terminal / Output Log -->
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50 ml-1">Debug Output</label>
|
<label class="text-[9px] font-bold uppercase opacity-50 ml-1"
|
||||||
<pre class="text-[8px] bg-black text-green-500 p-2 overflow-x-auto rounded border border-surface-500/50 max-h-24 shadow-inner">
|
>Debug Output</label
|
||||||
|
>
|
||||||
|
<pre
|
||||||
|
class="text-[8px] bg-black text-green-500 p-2 overflow-x-auto rounded border border-surface-500/50 max-h-24 shadow-inner">
|
||||||
[LOG] System Initialized
|
[LOG] System Initialized
|
||||||
[INFO] Store synced with IndexedDB
|
[INFO] Store synced with IndexedDB
|
||||||
[DEBUG] active_tab: template
|
[DEBUG] active_tab: template
|
||||||
@@ -183,16 +241,29 @@
|
|||||||
|
|
||||||
<!-- Confirmation Modal Demo -->
|
<!-- Confirmation Modal Demo -->
|
||||||
{#if show_confirm}
|
{#if show_confirm}
|
||||||
<div class="fixed inset-0 z-[1000] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4">
|
<div
|
||||||
<div class="card p-6 w-full max-w-sm preset-filled-surface-100-900 border border-warning-500 shadow-2xl animate-in zoom-in-95 duration-200">
|
class="fixed inset-0 z-[1000] flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="card p-6 w-full max-w-sm preset-filled-surface-100-900 border border-warning-500 shadow-2xl animate-in zoom-in-95 duration-200"
|
||||||
|
>
|
||||||
<h4 class="h4 text-warning-500 font-bold mb-2">Confirm Action</h4>
|
<h4 class="h4 text-warning-500 font-bold mb-2">Confirm Action</h4>
|
||||||
<p class="text-sm opacity-80 mb-6">
|
<p class="text-sm opacity-80 mb-6">
|
||||||
Are you sure you want to perform this test operation? This demonstrate the standard confirmation pattern.
|
Are you sure you want to perform this test operation? This
|
||||||
|
demonstrate the standard confirmation pattern.
|
||||||
</p>
|
</p>
|
||||||
<div class="flex justify-end gap-2">
|
<div class="flex justify-end gap-2">
|
||||||
<button type="button" onclick={() => show_confirm = false} class="btn btn-sm preset-tonal-surface">Cancel</button>
|
<button
|
||||||
<button type="button"
|
type="button"
|
||||||
onclick={() => { show_confirm = false; handle_test_action('Confirm'); }}
|
onclick={() => (show_confirm = false)}
|
||||||
|
class="btn btn-sm preset-tonal-surface">Cancel</button
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => {
|
||||||
|
show_confirm = false;
|
||||||
|
handle_test_action('Confirm');
|
||||||
|
}}
|
||||||
class="btn btn-sm preset-filled-warning"
|
class="btn btn-sm preset-filled-warning"
|
||||||
>
|
>
|
||||||
Yes, Proceed
|
Yes, Proceed
|
||||||
|
|||||||
@@ -10,8 +10,12 @@
|
|||||||
let { on_expand }: Props = $props();
|
let { on_expand }: Props = $props();
|
||||||
|
|
||||||
let update_source: 'url' | 'file' = $state('file');
|
let update_source: 'url' | 'file' = $state('file');
|
||||||
let update_path = $state('~/OSIT/Speaker Ready System/Admin Share/Custom Applications/osit_binaries/');
|
let update_path = $state(
|
||||||
let update_url = $state('https://dev-demo.oneskyit.com/updates/ae_native.zip');
|
'~/OSIT/Speaker Ready System/Admin Share/Custom Applications/osit_binaries/'
|
||||||
|
);
|
||||||
|
let update_url = $state(
|
||||||
|
'https://dev-demo.oneskyit.com/updates/ae_native.zip'
|
||||||
|
);
|
||||||
|
|
||||||
let update_status = $state('');
|
let update_status = $state('');
|
||||||
let is_checking = $state(false);
|
let is_checking = $state(false);
|
||||||
@@ -22,9 +26,10 @@
|
|||||||
update_status = 'Checking for updates...';
|
update_status = 'Checking for updates...';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const args = update_source === 'url'
|
const args =
|
||||||
? { source: 'url' as const, url: update_url }
|
update_source === 'url'
|
||||||
: { source: 'file' as const, path: update_path };
|
? { source: 'url' as const, url: update_url }
|
||||||
|
: { source: 'file' as const, path: update_path };
|
||||||
|
|
||||||
const res = await native.update_app(args);
|
const res = await native.update_app(args);
|
||||||
|
|
||||||
@@ -43,7 +48,9 @@
|
|||||||
|
|
||||||
async function handle_install() {
|
async function handle_install() {
|
||||||
update_status = 'Initiating installation...';
|
update_status = 'Initiating installation...';
|
||||||
alert('Installation logic is OS-specific. This will typically swap the application bundle and restart.');
|
alert(
|
||||||
|
'Installation logic is OS-specific. This will typically swap the application bundle and restart.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -56,18 +63,31 @@
|
|||||||
>
|
>
|
||||||
<!-- Content omitted for brevity, preserved in file -->
|
<!-- Content omitted for brevity, preserved in file -->
|
||||||
<div class="col-span-full flex flex-col gap-2">
|
<div class="col-span-full flex flex-col gap-2">
|
||||||
|
|
||||||
<!-- TECHNICAL: Source Config (Edit Mode Only) -->
|
<!-- TECHNICAL: Source Config (Edit Mode Only) -->
|
||||||
{#if $ae_loc.edit_mode}
|
{#if $ae_loc.edit_mode}
|
||||||
<div class="flex flex-col gap-2 bg-surface-500/5 p-2 rounded border border-surface-500/10 mb-1">
|
<div
|
||||||
|
class="flex flex-col gap-2 bg-surface-500/5 p-2 rounded border border-surface-500/10 mb-1"
|
||||||
|
>
|
||||||
<div class="flex flex-row justify-between items-center px-1">
|
<div class="flex flex-row justify-between items-center px-1">
|
||||||
<label class="text-[9px] font-bold uppercase opacity-50">Source Type</label>
|
<label class="text-[9px] font-bold uppercase opacity-50"
|
||||||
|
>Source Type</label
|
||||||
|
>
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<label class="flex items-center gap-1 text-[10px]">
|
<label class="flex items-center gap-1 text-[10px]">
|
||||||
<input type="radio" bind:group={update_source} value="file" class="radio radio-sm" /> Local
|
<input
|
||||||
|
type="radio"
|
||||||
|
bind:group={update_source}
|
||||||
|
value="file"
|
||||||
|
class="radio radio-sm"
|
||||||
|
/> Local
|
||||||
</label>
|
</label>
|
||||||
<label class="flex items-center gap-1 text-[10px]">
|
<label class="flex items-center gap-1 text-[10px]">
|
||||||
<input type="radio" bind:group={update_source} value="url" class="radio radio-sm" /> Web
|
<input
|
||||||
|
type="radio"
|
||||||
|
bind:group={update_source}
|
||||||
|
value="url"
|
||||||
|
class="radio radio-sm"
|
||||||
|
/> Web
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -91,7 +111,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- COMMON: Check Button -->
|
<!-- COMMON: Check Button -->
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={handle_check_update}
|
onclick={handle_check_update}
|
||||||
disabled={is_checking}
|
disabled={is_checking}
|
||||||
class="btn btn-sm preset-filled-tertiary hover:preset-filled-primary-500 text-[10px] w-full"
|
class="btn btn-sm preset-filled-tertiary hover:preset-filled-primary-500 text-[10px] w-full"
|
||||||
@@ -104,13 +125,16 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
{#if update_status}
|
{#if update_status}
|
||||||
<div class="text-[9px] text-center italic p-1 border border-surface-500/20 rounded bg-surface-500/5 mt-1">
|
<div
|
||||||
|
class="text-[9px] text-center italic p-1 border border-surface-500/20 rounded bg-surface-500/5 mt-1"
|
||||||
|
>
|
||||||
{update_status}
|
{update_status}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if download_result}
|
{#if download_result}
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={handle_install}
|
onclick={handle_install}
|
||||||
class="btn btn-sm preset-filled-success hover:preset-filled-primary-500 text-[10px] w-full animate-bounce mt-2 shadow-lg"
|
class="btn btn-sm preset-filled-success hover:preset-filled-primary-500 text-[10px] w-full animate-bounce mt-2 shadow-lg"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -58,9 +58,7 @@
|
|||||||
// *** Set initial variables
|
// *** Set initial variables
|
||||||
let ae_acct = data[$slct.account_id];
|
let ae_acct = data[$slct.account_id];
|
||||||
|
|
||||||
import {
|
import { online } from 'svelte/reactivity/window';
|
||||||
online
|
|
||||||
} from 'svelte/reactivity/window';
|
|
||||||
|
|
||||||
$ae_sess.disable_sys_nav = true;
|
$ae_sess.disable_sys_nav = true;
|
||||||
$ae_sess.disable_sys_header = true;
|
$ae_sess.disable_sys_header = true;
|
||||||
@@ -80,7 +78,9 @@
|
|||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log(`event_id: ${data.params.event_id}`);
|
console.log(`event_id: ${data.params.event_id}`);
|
||||||
console.log(`event_location_id: ${data.params.event_location_id}`);
|
console.log(`event_location_id: ${data.params.event_location_id}`);
|
||||||
console.log(`event_session_id: ${data.url.searchParams.get('session_id')}`);
|
console.log(
|
||||||
|
`event_session_id: ${data.url.searchParams.get('session_id')}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$events_slct.event_id = data.params.event_id;
|
$events_slct.event_id = data.params.event_id;
|
||||||
$events_slct.event_location_id = data.params.event_location_id;
|
$events_slct.event_location_id = data.params.event_location_id;
|
||||||
@@ -89,11 +89,19 @@
|
|||||||
// String-Only ID Vision: Sync the device ID from the native environment
|
// String-Only ID Vision: Sync the device ID from the native environment
|
||||||
const native_dev = $ae_loc.native_device;
|
const native_dev = $ae_loc.native_device;
|
||||||
if (native_dev) {
|
if (native_dev) {
|
||||||
$events_slct.event_device_id = native_dev.event_device_id || native_dev.id || native_dev.event_device_id_random || native_dev.id_random;
|
$events_slct.event_device_id =
|
||||||
|
native_dev.event_device_id ||
|
||||||
|
native_dev.id ||
|
||||||
|
native_dev.event_device_id_random ||
|
||||||
|
native_dev.id_random;
|
||||||
}
|
}
|
||||||
|
|
||||||
$events_slct.event_location_obj_li = ae_acct.slct.event_location_obj_li ?? [''];
|
$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 ?? [''];
|
''
|
||||||
|
];
|
||||||
|
$events_slct.id_li__event_location = ae_acct.slct.id_li__event_location ?? [
|
||||||
|
''
|
||||||
|
];
|
||||||
|
|
||||||
// *** Functions and Logic
|
// *** Functions and Logic
|
||||||
|
|
||||||
@@ -105,7 +113,10 @@
|
|||||||
let results = await db_events.event.get(id);
|
let results = await db_events.event.get(id);
|
||||||
|
|
||||||
if ($events_slct.event_obj && results) {
|
if ($events_slct.event_obj && results) {
|
||||||
if (JSON.stringify($events_slct.event_obj) !== JSON.stringify(results)) {
|
if (
|
||||||
|
JSON.stringify($events_slct.event_obj) !==
|
||||||
|
JSON.stringify(results)
|
||||||
|
) {
|
||||||
$events_slct.event_obj = { ...results };
|
$events_slct.event_obj = { ...results };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,7 +129,10 @@
|
|||||||
if (!id) return null;
|
if (!id) return null;
|
||||||
let results = await db_events.device.get(id);
|
let results = await db_events.device.get(id);
|
||||||
if ($events_slct.event_device_obj && results) {
|
if ($events_slct.event_device_obj && results) {
|
||||||
if (JSON.stringify($events_slct.event_device_obj) !== JSON.stringify(results)) {
|
if (
|
||||||
|
JSON.stringify($events_slct.event_device_obj) !==
|
||||||
|
JSON.stringify(results)
|
||||||
|
) {
|
||||||
$events_slct.event_device_obj = { ...results };
|
$events_slct.event_device_obj = { ...results };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,14 +143,20 @@
|
|||||||
let lq__event_event_file_obj_li = liveQuery(async () => {
|
let lq__event_event_file_obj_li = liveQuery(async () => {
|
||||||
const id = $events_slct.event_id;
|
const id = $events_slct.event_id;
|
||||||
if (!id) return [];
|
if (!id) return [];
|
||||||
return await db_events.file.where('for_id').equals(id).sortBy('filename');
|
return await db_events.file
|
||||||
|
.where('for_id')
|
||||||
|
.equals(id)
|
||||||
|
.sortBy('filename');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event File - For Location
|
// Event File - For Location
|
||||||
let lq__location_event_file_obj_li = liveQuery(async () => {
|
let lq__location_event_file_obj_li = liveQuery(async () => {
|
||||||
const id = $events_slct.event_location_id;
|
const id = $events_slct.event_location_id;
|
||||||
if (!id) return [];
|
if (!id) return [];
|
||||||
return await db_events.file.where('for_id').equals(id).sortBy('filename');
|
return await db_events.file
|
||||||
|
.where('for_id')
|
||||||
|
.equals(id)
|
||||||
|
.sortBy('filename');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event Location
|
// Event Location
|
||||||
@@ -149,7 +169,10 @@
|
|||||||
let lq__event_location_obj_li = liveQuery(async () => {
|
let lq__event_location_obj_li = liveQuery(async () => {
|
||||||
const id = $events_slct.event_id;
|
const id = $events_slct.event_id;
|
||||||
if (!id) return [];
|
if (!id) return [];
|
||||||
return await db_events.location.where('event_id').equals(id).sortBy('name');
|
return await db_events.location
|
||||||
|
.where('event_id')
|
||||||
|
.equals(id)
|
||||||
|
.sortBy('name');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Event Session (Main View Trigger)
|
// Event Session (Main View Trigger)
|
||||||
@@ -157,24 +180,37 @@
|
|||||||
let lq__event_session_obj = liveQuery(async () => {
|
let lq__event_session_obj = liveQuery(async () => {
|
||||||
const id = $events_slct.event_session_id;
|
const id = $events_slct.event_session_id;
|
||||||
if (!id) return null;
|
if (!id) return null;
|
||||||
if (log_lvl) console.log(`🔍 [Trace] Launcher Layout LQ: Fetching session_id=${id}`);
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`🔍 [Trace] Launcher Layout LQ: Fetching session_id=${id}`
|
||||||
|
);
|
||||||
const start = performance.now();
|
const start = performance.now();
|
||||||
let results = await db_events.session.get(id);
|
let results = await db_events.session.get(id);
|
||||||
if (log_lvl) console.log(`📦 [Trace] Launcher Layout LQ: Result obtained in ${(performance.now() - start).toFixed(2)}ms (Result=${results?.name || 'NOT FOUND'})`);
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`📦 [Trace] Launcher Layout LQ: Result obtained in ${(performance.now() - start).toFixed(2)}ms (Result=${results?.name || 'NOT FOUND'})`
|
||||||
|
);
|
||||||
return results;
|
return results;
|
||||||
});
|
});
|
||||||
|
|
||||||
let lq__event_session_obj_li = liveQuery(async () => {
|
let lq__event_session_obj_li = liveQuery(async () => {
|
||||||
const id = $events_slct.event_location_id;
|
const id = $events_slct.event_location_id;
|
||||||
if (!id) return [];
|
if (!id) return [];
|
||||||
if (log_lvl > 1) console.log(`LQ - Using default sort for Event Session list location_id: ${id}`);
|
if (log_lvl > 1)
|
||||||
|
console.log(
|
||||||
|
`LQ - Using default sort for Event Session list location_id: ${id}`
|
||||||
|
);
|
||||||
let results = await db_events.session
|
let results = await db_events.session
|
||||||
.where('event_location_id')
|
.where('event_location_id')
|
||||||
.equals(id)
|
.equals(id)
|
||||||
.reverse()
|
.reverse()
|
||||||
.sortBy('name');
|
.sortBy('name');
|
||||||
|
|
||||||
if ($events_slct.event_session_obj_li && JSON.stringify($events_slct.event_session_obj_li) !== JSON.stringify(results)) {
|
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 || [])];
|
$events_slct.event_session_obj_li = [...(results || [])];
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
@@ -210,7 +246,10 @@
|
|||||||
$events_slct.event_session_id = obj_id;
|
$events_slct.event_session_id = obj_id;
|
||||||
let new_url = new 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.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);
|
new_url.searchParams.set(
|
||||||
|
'session_id',
|
||||||
|
$events_slct.event_session_id
|
||||||
|
);
|
||||||
goto(new_url.toString(), { replaceState: false });
|
goto(new_url.toString(), { replaceState: false });
|
||||||
}
|
}
|
||||||
} else if (cmd.startsWith('ae_download:')) {
|
} else if (cmd.startsWith('ae_download:')) {
|
||||||
@@ -283,9 +322,12 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!$events_loc.launcher.idle_timer) $events_loc.launcher.idle_timer = 5 * 60 * 1000;
|
if (!$events_loc.launcher.idle_timer)
|
||||||
if (!$events_loc.launcher.idle_cycle) $events_loc.launcher.idle_cycle = 5 * 1000;
|
$events_loc.launcher.idle_timer = 5 * 60 * 1000;
|
||||||
if (!$events_loc.launcher.idle_loop_period) $events_loc.launcher.idle_loop_period = 3 * 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 = 3 * 60 * 1000;
|
||||||
|
|
||||||
listen({
|
listen({
|
||||||
timer: $events_loc.launcher.idle_timer,
|
timer: $events_loc.launcher.idle_timer,
|
||||||
@@ -296,26 +338,43 @@
|
|||||||
let saver_looping: boolean = $state(false);
|
let saver_looping: boolean = $state(false);
|
||||||
|
|
||||||
function handle_idle_client() {
|
function handle_idle_client() {
|
||||||
if ($lq__event_session_obj && $lq__event_session_obj?.type_code == 'poster') {
|
if (
|
||||||
|
$lq__event_session_obj &&
|
||||||
|
$lq__event_session_obj?.type_code == 'poster'
|
||||||
|
) {
|
||||||
if (saver_looping) return false;
|
if (saver_looping) return false;
|
||||||
saver_looping = true;
|
saver_looping = true;
|
||||||
|
|
||||||
idle_timer_interval = setInterval(() => {
|
idle_timer_interval = setInterval(
|
||||||
if ($events_loc.launcher.screen_saver_img_kv) {
|
() => {
|
||||||
const keys = Object.keys($events_loc.launcher.screen_saver_img_kv);
|
if ($events_loc.launcher.screen_saver_img_kv) {
|
||||||
const rand_index = Math.floor(Math.random() * keys.length);
|
const keys = Object.keys(
|
||||||
let event_file_obj = $events_loc.launcher.screen_saver_img_kv[keys[rand_index]];
|
$events_loc.launcher.screen_saver_img_kv
|
||||||
|
);
|
||||||
|
const rand_index = Math.floor(
|
||||||
|
Math.random() * keys.length
|
||||||
|
);
|
||||||
|
let event_file_obj =
|
||||||
|
$events_loc.launcher.screen_saver_img_kv[
|
||||||
|
keys[rand_index]
|
||||||
|
];
|
||||||
|
|
||||||
$events_slct.event_file_id = event_file_obj.event_file_id;
|
$events_slct.event_file_id =
|
||||||
$events_slct.event_file_obj = event_file_obj;
|
event_file_obj.event_file_id;
|
||||||
$events_sess.launcher.modal__open_event_file_id = null;
|
$events_slct.event_file_obj = event_file_obj;
|
||||||
$events_sess.launcher.modal__title = event_file_obj.filename ?? '*';
|
$events_sess.launcher.modal__open_event_file_id = null;
|
||||||
$events_sess.launcher.modal__open_event_file_id = $events_slct.event_file_id;
|
$events_sess.launcher.modal__title =
|
||||||
$events_sess.launcher.modal__event_file_obj = event_file_obj;
|
event_file_obj.filename ?? '*';
|
||||||
return true;
|
$events_sess.launcher.modal__open_event_file_id =
|
||||||
}
|
$events_slct.event_file_id;
|
||||||
return false;
|
$events_sess.launcher.modal__event_file_obj =
|
||||||
}, $events_loc.launcher.idle_loop_period ?? 2 * 60 * 1000);
|
event_file_obj;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
$events_loc.launcher.idle_loop_period ?? 2 * 60 * 1000
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
saver_looping = false;
|
saver_looping = false;
|
||||||
return false;
|
return false;
|
||||||
@@ -376,7 +435,8 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<h3 class="h4 text-center italic text-surface-600-400">
|
<h3 class="h4 text-center italic text-surface-600-400">
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
class=""
|
class=""
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$events_loc.launcher.hide__launcher_menu =
|
$events_loc.launcher.hide__launcher_menu =
|
||||||
@@ -387,20 +447,26 @@
|
|||||||
<Satellite class="text-base mx-1 inline-block text-gray-500" />
|
<Satellite class="text-base mx-1 inline-block text-gray-500" />
|
||||||
<abbr title="Aether - Events Module Launcher">
|
<abbr title="Aether - Events Module Launcher">
|
||||||
Æ Launcher
|
Æ Launcher
|
||||||
<span class="text-xs align-super font-normal" title="Version 3">v3</span>
|
<span
|
||||||
|
class="text-xs align-super font-normal"
|
||||||
|
title="Version 3">v3</span
|
||||||
|
>
|
||||||
</abbr>
|
</abbr>
|
||||||
</button>
|
</button>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{#if $lq__event_obj}
|
{#if $lq__event_obj}
|
||||||
<h2 class="hidden md:inline-block h3 text-center text-surface-600-400">
|
<h2
|
||||||
|
class="hidden md:inline-block h3 text-center text-surface-600-400"
|
||||||
|
>
|
||||||
{$lq__event_obj.cfg_json?.short_name}
|
{$lq__event_obj.cfg_json?.short_name}
|
||||||
</h2>
|
</h2>
|
||||||
<h3
|
<h3
|
||||||
class="h4 text-center italic text-surface-600-400"
|
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}"
|
title="Location ID: {$lq__event_location_obj?.event_location_id} Name: {$lq__event_location_obj?.name}"
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
class="text-base"
|
class="text-base"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$ae_loc.edit_mode = !$ae_loc.edit_mode;
|
$ae_loc.edit_mode = !$ae_loc.edit_mode;
|
||||||
@@ -455,9 +521,13 @@
|
|||||||
{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}
|
slct__event_location_id={$events_slct.event_location_id}
|
||||||
bind:loading__session_li_status={$events_sess.launcher.loading__session_li_status}
|
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}
|
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:slct__event_session_id={$events_slct.event_session_id}
|
||||||
bind:trigger_reload__event_session_obj_id={
|
bind:trigger_reload__event_session_obj_id={
|
||||||
@@ -487,7 +557,9 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
{#if !$events_slct.event_location_id}
|
{#if !$events_slct.event_location_id}
|
||||||
<div class="flex flex-row items-center justify-center p-8 opacity-50">
|
<div
|
||||||
|
class="flex flex-row items-center justify-center p-8 opacity-50"
|
||||||
|
>
|
||||||
<span class="fas fa-map-marker-alt mx-2 text-2xl"></span>
|
<span class="fas fa-map-marker-alt mx-2 text-2xl"></span>
|
||||||
<span>Please select a location from the menu</span>
|
<span>Please select a location from the menu</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -500,7 +572,9 @@
|
|||||||
bind:type_code={$lq__event_session_obj.type_code}
|
bind:type_code={$lq__event_session_obj.type_code}
|
||||||
></Launcher_session_view>
|
></Launcher_session_view>
|
||||||
{:else if $events_slct.event_session_id}
|
{:else if $events_slct.event_session_id}
|
||||||
<div class="flex flex-col items-center justify-center p-8 opacity-50">
|
<div
|
||||||
|
class="flex flex-col items-center justify-center p-8 opacity-50"
|
||||||
|
>
|
||||||
<LoaderCircle class="animate-spin mb-2" />
|
<LoaderCircle class="animate-spin mb-2" />
|
||||||
<span>Loading session details...</span>
|
<span>Loading session details...</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -537,7 +611,8 @@
|
|||||||
class="slct_location_name transition-all duration-1000"
|
class="slct_location_name transition-all duration-1000"
|
||||||
title="Location ID: {$lq__event_location_obj?.event_location_id} Name: {$lq__event_location_obj?.name} | Device ID: {$lq__event_device_obj?.event_device_id} Name: {$lq__event_device_obj?.name}"
|
title="Location ID: {$lq__event_location_obj?.event_location_id} Name: {$lq__event_location_obj?.name} | Device ID: {$lq__event_device_obj?.event_device_id} Name: {$lq__event_device_obj?.name}"
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
class=""
|
class=""
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$ae_loc.edit_mode = !$ae_loc.edit_mode;
|
$ae_loc.edit_mode = !$ae_loc.edit_mode;
|
||||||
@@ -579,10 +654,13 @@
|
|||||||
|
|
||||||
<span
|
<span
|
||||||
class:hidden={!$events_loc.launcher.ws_connect}
|
class:hidden={!$events_loc.launcher.ws_connect}
|
||||||
class:preset-tonal-warning={$events_sess.launcher.ws_connect_status != 'connected'}
|
class:preset-tonal-warning={$events_sess.launcher.ws_connect_status !=
|
||||||
class:preset-tonal-success={$events_sess.launcher.ws_connect_status == 'connected'}
|
'connected'}
|
||||||
|
class:preset-tonal-success={$events_sess.launcher.ws_connect_status ==
|
||||||
|
'connected'}
|
||||||
class="group px-1 rounded-md transition-all duration-1000"
|
class="group px-1 rounded-md transition-all duration-1000"
|
||||||
title="WebSocket is {$events_sess.launcher.ws_connect_status == 'connected'
|
title="WebSocket is {$events_sess.launcher.ws_connect_status ==
|
||||||
|
'connected'
|
||||||
? 'connected'
|
? 'connected'
|
||||||
: 'disconnected'} API: {$ae_api?.base_url}"
|
: 'disconnected'} API: {$ae_api?.base_url}"
|
||||||
>
|
>
|
||||||
@@ -595,7 +673,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="current_datetime font-mono px-2 hover:font-bold hover:bg-white transition-all">
|
<div
|
||||||
|
class="current_datetime font-mono px-2 hover:font-bold hover:bg-white transition-all"
|
||||||
|
>
|
||||||
<span class="hidden md:inline">
|
<span class="hidden md:inline">
|
||||||
<span class="fas fa-calendar-alt"></span>
|
<span class="fas fa-calendar-alt"></span>
|
||||||
{ae_util.iso_datetime_formatter($time, 'date_full_no_year')}
|
{ae_util.iso_datetime_formatter($time, 'date_full_no_year')}
|
||||||
@@ -612,7 +692,8 @@
|
|||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<div class="absolute top-0 left-0 z-20 text-center">
|
<div class="absolute top-0 left-0 z-20 text-center">
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => ($events_loc.launcher.hide_drawer__cfg = false)}
|
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="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:opacity-25={!$ae_loc.trusted_access}
|
||||||
@@ -639,7 +720,9 @@
|
|||||||
|
|
||||||
<hr class="my-2 border-gray-300 dark:border-gray-600" />
|
<hr class="my-2 border-gray-300 dark:border-gray-600" />
|
||||||
|
|
||||||
<div class="flex flex-row flex-wrap gap-0.5 items-center justify-center max-w-md">
|
<div
|
||||||
|
class="flex flex-row flex-wrap gap-0.5 items-center justify-center max-w-md"
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
href="/events/{$events_slct.event_id}"
|
href="/events/{$events_slct.event_id}"
|
||||||
class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500"
|
class="btn btn-sm preset-tonal-primary hover:preset-filled-primary-500"
|
||||||
@@ -682,10 +765,13 @@
|
|||||||
id="sidebar2"
|
id="sidebar2"
|
||||||
>
|
>
|
||||||
<div class="flex flex-row items-center justify-between">
|
<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">
|
<h2
|
||||||
|
class="text-center mb-4 text-base font-semibold text-gray-500 dark:text-gray-400"
|
||||||
|
>
|
||||||
Debug
|
Debug
|
||||||
</h2>
|
</h2>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => ($events_loc.launcher.hide_drawer__debug = true)}
|
onclick={() => ($events_loc.launcher.hide_drawer__debug = true)}
|
||||||
class="mb-4 dark:text-white"
|
class="mb-4 dark:text-white"
|
||||||
>
|
>
|
||||||
@@ -729,7 +815,8 @@
|
|||||||
>
|
>
|
||||||
{$events_sess.launcher?.modal__title ?? 'Digital Poster Display'}
|
{$events_sess.launcher?.modal__title ?? 'Digital Poster Display'}
|
||||||
</h3>
|
</h3>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
class="btn flex-row-reverse group transition-all justify-self-end"
|
class="btn flex-row-reverse group transition-all justify-self-end"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$events_sess.launcher.modal__open_event_file_id = null;
|
$events_sess.launcher.modal__open_event_file_id = null;
|
||||||
@@ -741,7 +828,8 @@
|
|||||||
</button>
|
</button>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
|
$events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
|
||||||
$events_sess.launcher.controller_trigger_send = true;
|
$events_sess.launcher.controller_trigger_send = true;
|
||||||
@@ -766,8 +854,8 @@
|
|||||||
{#if $events_sess.launcher.modal__open_event_file_id}
|
{#if $events_sess.launcher.modal__open_event_file_id}
|
||||||
<img
|
<img
|
||||||
src="{$ae_api.base_url}/v3/action/event_file/{$events_sess.launcher
|
src="{$ae_api.base_url}/v3/action/event_file/{$events_sess.launcher
|
||||||
.modal__open_event_file_id}/download?filename={$events_slct.event_file_obj
|
.modal__open_event_file_id}/download?filename={$events_slct
|
||||||
.filename}&key={$ae_api.account_id}"
|
.event_file_obj.filename}&key={$ae_api.account_id}"
|
||||||
alt="Poster"
|
alt="Poster"
|
||||||
class="min-h-28 min-w-md max-h-full max-w-full"
|
class="min-h-28 min-w-md max-h-full max-w-full"
|
||||||
/>
|
/>
|
||||||
@@ -778,7 +866,8 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
|
$events_sess.launcher.controller_cmd = `ae_close:event_file_modal`;
|
||||||
$events_sess.launcher.controller_trigger_send = true;
|
$events_sess.launcher.controller_trigger_send = true;
|
||||||
@@ -800,7 +889,8 @@
|
|||||||
Close Remote Poster Display Only
|
Close Remote Poster Display Only
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$events_sess.launcher.modal__title = '';
|
$events_sess.launcher.modal__title = '';
|
||||||
$events_sess.launcher.modal__open_event_file_id = null;
|
$events_sess.launcher.modal__open_event_file_id = null;
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ export async function load({ params, parent, url }) {
|
|||||||
let ae_acct = data[account_id];
|
let ae_acct = data[account_id];
|
||||||
|
|
||||||
if (!ae_acct) {
|
if (!ae_acct) {
|
||||||
console.warn(`ae Events - [event_id] launcher +layout.ts: Account ${account_id} not found in data. Initializing ghost acct.`);
|
console.warn(
|
||||||
|
`ae Events - [event_id] launcher +layout.ts: Account ${account_id} not found in data. Initializing ghost acct.`
|
||||||
|
);
|
||||||
ae_acct = {
|
ae_acct = {
|
||||||
api: data.ae_api || {},
|
api: data.ae_api || {},
|
||||||
slct: {
|
slct: {
|
||||||
@@ -30,7 +32,10 @@ export async function load({ params, parent, url }) {
|
|||||||
const event_id = params.event_id;
|
const event_id = params.event_id;
|
||||||
|
|
||||||
if (browser) {
|
if (browser) {
|
||||||
if (log_lvl) console.log(`ae_events Launcher - [event_id] launcher +layout.ts (Non-Blocking)`);
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`ae_events Launcher - [event_id] launcher +layout.ts (Non-Blocking)`
|
||||||
|
);
|
||||||
|
|
||||||
// OPTIMIZATION: Fire these in the background without 'await'.
|
// OPTIMIZATION: Fire these in the background without 'await'.
|
||||||
// The UI components (menu, session_view) already use LiveQuery/Dexie
|
// The UI components (menu, session_view) already use LiveQuery/Dexie
|
||||||
|
|||||||
@@ -49,12 +49,21 @@
|
|||||||
$events_slct.event_id = data.params.event_id;
|
$events_slct.event_id = data.params.event_id;
|
||||||
$events_slct.event_location_id = data.params.event_location_id;
|
$events_slct.event_location_id = data.params.event_location_id;
|
||||||
|
|
||||||
$events_slct.event_location_obj_li = ae_acct.slct.event_location_obj_li ?? [''];
|
$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 ?? [''];
|
''
|
||||||
|
];
|
||||||
|
$events_slct.id_li__event_location = ae_acct.slct.id_li__event_location ?? [
|
||||||
|
''
|
||||||
|
];
|
||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log(`$events_slct.event_location_obj_li:`, $events_slct.event_location_obj_li);
|
console.log(
|
||||||
|
`$events_slct.event_location_obj_li:`,
|
||||||
|
$events_slct.event_location_obj_li
|
||||||
|
);
|
||||||
}
|
}
|
||||||
$events_slct.event_session_obj_li = ae_acct.slct.event_session_obj_li ?? [''];
|
$events_slct.event_session_obj_li = ae_acct.slct.event_session_obj_li ?? [
|
||||||
|
''
|
||||||
|
];
|
||||||
|
|
||||||
// Set the local storage values
|
// Set the local storage values
|
||||||
if (!$events_loc.launcher) {
|
if (!$events_loc.launcher) {
|
||||||
@@ -135,7 +144,8 @@
|
|||||||
|
|
||||||
ni_data['name'] = network_interface;
|
ni_data['name'] = network_interface;
|
||||||
|
|
||||||
let ni_details = result.networkInterfaces[network_interface];
|
let ni_details =
|
||||||
|
result.networkInterfaces[network_interface];
|
||||||
// console.log(ni_details);
|
// console.log(ni_details);
|
||||||
|
|
||||||
for (let i = 0; i < ni_details.length; i++) {
|
for (let i = 0; i < ni_details.length; i++) {
|
||||||
@@ -155,12 +165,13 @@
|
|||||||
event_device_data['info_ip_list'] = ip_address_li.join('; ');
|
event_device_data['info_ip_list'] = ip_address_li.join('; ');
|
||||||
console.log(event_device_data['info_ip_list']);
|
console.log(event_device_data['info_ip_list']);
|
||||||
|
|
||||||
let event_device_obj_up_promise = events_func.update_ae_obj__event_device({
|
let event_device_obj_up_promise = events_func
|
||||||
api_cfg: $ae_api,
|
.update_ae_obj__event_device({
|
||||||
event_device_id: event_device_id,
|
api_cfg: $ae_api,
|
||||||
data_kv: event_device_data,
|
event_device_id: event_device_id,
|
||||||
log_lvl: 0
|
data_kv: event_device_data,
|
||||||
})
|
log_lvl: 0
|
||||||
|
})
|
||||||
.then(function (up_event_device_result) {
|
.then(function (up_event_device_result) {
|
||||||
// console.log('UPDATED DEVICE INFO!!! UPDATED DEVICE INFO!!! UPDATED DEVICE INFO!!!');
|
// console.log('UPDATED DEVICE INFO!!! UPDATED DEVICE INFO!!! UPDATED DEVICE INFO!!!');
|
||||||
if (up_event_device_result) {
|
if (up_event_device_result) {
|
||||||
@@ -177,6 +188,4 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="hidden">
|
<div class="hidden">This is for forcing data loading.</div>
|
||||||
This is for forcing data loading.
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ export async function load({ params, parent, url }) {
|
|||||||
let ae_acct = data[account_id];
|
let ae_acct = data[account_id];
|
||||||
|
|
||||||
if (!ae_acct) {
|
if (!ae_acct) {
|
||||||
console.warn(`ae Events - [event_id] launcher [event_location_id] +page.ts: Account ${account_id} not found in data. Initializing ghost acct.`);
|
console.warn(
|
||||||
|
`ae Events - [event_id] launcher [event_location_id] +page.ts: Account ${account_id} not found in data. Initializing ghost acct.`
|
||||||
|
);
|
||||||
ae_acct = {
|
ae_acct = {
|
||||||
api: data.ae_api || {},
|
api: data.ae_api || {},
|
||||||
slct: {
|
slct: {
|
||||||
@@ -61,7 +63,9 @@ export async function load({ params, parent, url }) {
|
|||||||
log_lvl: 0
|
log_lvl: 0
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
console.log(`ae pres_mgmt launcher [slug] +page.ts: browser = false or location_id missing`);
|
console.log(
|
||||||
|
`ae pres_mgmt launcher [slug] +page.ts: browser = false or location_id missing`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: Precaution against shared data between sites and sessions.
|
// WARNING: Precaution against shared data between sites and sessions.
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
let { log_lvl = 1 } = $props();
|
let { log_lvl = 1 } = $props();
|
||||||
|
|
||||||
let currently_syncing: string | null = $state(null);
|
let currently_syncing: string | null = $state(null);
|
||||||
let sync_results: Record<string, 'success' | 'error' | 'pending'> = $state({});
|
let sync_results: Record<string, 'success' | 'error' | 'pending'> = $state(
|
||||||
|
{}
|
||||||
|
);
|
||||||
let sync_stats = $state({ total: 0, cached: 0, missing: 0 });
|
let sync_stats = $state({ total: 0, cached: 0, missing: 0 });
|
||||||
let last_heartbeat: string | null = $state(null);
|
let last_heartbeat: string | null = $state(null);
|
||||||
|
|
||||||
@@ -49,7 +51,10 @@
|
|||||||
$ae_loc.native_device.home_directory = info.home_directory;
|
$ae_loc.native_device.home_directory = info.home_directory;
|
||||||
$ae_loc.native_device.tmp_directory = info.tmp_directory;
|
$ae_loc.native_device.tmp_directory = info.tmp_directory;
|
||||||
|
|
||||||
if (log_lvl) console.log('Sync: Native OS metadata hydrated.', { home: info.home_directory });
|
if (log_lvl)
|
||||||
|
console.log('Sync: Native OS metadata hydrated.', {
|
||||||
|
home: info.home_directory
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Sync: Metadata hydration FAILED:', err);
|
console.error('Sync: Metadata hydration FAILED:', err);
|
||||||
@@ -66,8 +71,14 @@
|
|||||||
|
|
||||||
// Timers run in both browser and native for dev/testing
|
// Timers run in both browser and native for dev/testing
|
||||||
timer__event = setInterval(() => run_sync_cycle(), loop_info.event);
|
timer__event = setInterval(() => run_sync_cycle(), loop_info.event);
|
||||||
timer__device = setInterval(() => run_device_heartbeat(), loop_info.device);
|
timer__device = setInterval(
|
||||||
timer__location = setInterval(() => refresh_location_config(), loop_info.location);
|
() => run_device_heartbeat(),
|
||||||
|
loop_info.device
|
||||||
|
);
|
||||||
|
timer__location = setInterval(
|
||||||
|
() => refresh_location_config(),
|
||||||
|
loop_info.location
|
||||||
|
);
|
||||||
timer__session = setInterval(() => run_sync_cycle(), loop_info.session);
|
timer__session = setInterval(() => run_sync_cycle(), loop_info.session);
|
||||||
|
|
||||||
// Immediate first run
|
// Immediate first run
|
||||||
@@ -88,22 +99,42 @@
|
|||||||
const cache_root = $ae_loc.local_file_cache_path;
|
const cache_root = $ae_loc.local_file_cache_path;
|
||||||
const prefix_len = $ae_loc.native_device?.hash_prefix_length || 2;
|
const prefix_len = $ae_loc.native_device?.hash_prefix_length || 2;
|
||||||
|
|
||||||
if (!location_id || !cache_root || is_syncing || !$ae_loc.is_native) return;
|
if (!location_id || !cache_root || is_syncing || !$ae_loc.is_native)
|
||||||
|
return;
|
||||||
|
|
||||||
is_syncing = true;
|
is_syncing = true;
|
||||||
try {
|
try {
|
||||||
const sessions = await db_events.session.where('event_location_id').equals(location_id).toArray();
|
const sessions = await db_events.session
|
||||||
const session_ids = sessions.map(s => s.event_session_id);
|
.where('event_location_id')
|
||||||
|
.equals(location_id)
|
||||||
|
.toArray();
|
||||||
|
const session_ids = sessions.map((s) => s.event_session_id);
|
||||||
if (session_ids.length === 0) return;
|
if (session_ids.length === 0) return;
|
||||||
|
|
||||||
const presentations = await db_events.presentation.where('event_session_id').anyOf(session_ids).toArray();
|
const presentations = await db_events.presentation
|
||||||
const presentation_ids = presentations.map(p => p.event_presentation_id);
|
.where('event_session_id')
|
||||||
|
.anyOf(session_ids)
|
||||||
|
.toArray();
|
||||||
|
const presentation_ids = presentations.map(
|
||||||
|
(p) => p.event_presentation_id
|
||||||
|
);
|
||||||
|
|
||||||
const presenters = await db_events.presenter.where('event_session_id').anyOf(session_ids).toArray();
|
const presenters = await db_events.presenter
|
||||||
const presenter_ids = presenters.map(p => p.event_presenter_id);
|
.where('event_session_id')
|
||||||
|
.anyOf(session_ids)
|
||||||
|
.toArray();
|
||||||
|
const presenter_ids = presenters.map((p) => p.event_presenter_id);
|
||||||
|
|
||||||
const all_for_ids = [...session_ids, ...presentation_ids, ...presenter_ids, $events_slct.event_id];
|
const all_for_ids = [
|
||||||
const files = await db_events.file.where('for_id').anyOf(all_for_ids).toArray();
|
...session_ids,
|
||||||
|
...presentation_ids,
|
||||||
|
...presenter_ids,
|
||||||
|
$events_slct.event_id
|
||||||
|
];
|
||||||
|
const files = await db_events.file
|
||||||
|
.where('for_id')
|
||||||
|
.anyOf(all_for_ids)
|
||||||
|
.toArray();
|
||||||
|
|
||||||
sync_stats.total = files.length;
|
sync_stats.total = files.length;
|
||||||
let cached_count = 0;
|
let cached_count = 0;
|
||||||
@@ -111,7 +142,10 @@
|
|||||||
|
|
||||||
for (const file_obj of files) {
|
for (const file_obj of files) {
|
||||||
if (!file_obj.hash_sha256) continue;
|
if (!file_obj.hash_sha256) continue;
|
||||||
if (sync_results[file_obj.event_file_id] === 'success') { cached_count++; continue; }
|
if (sync_results[file_obj.event_file_id] === 'success') {
|
||||||
|
cached_count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const exists = await native.check_hash_file_cache({
|
const exists = await native.check_hash_file_cache({
|
||||||
cache_root,
|
cache_root,
|
||||||
@@ -127,17 +161,22 @@
|
|||||||
|
|
||||||
missing_count++;
|
missing_count++;
|
||||||
currently_syncing = file_obj.filename;
|
currently_syncing = file_obj.filename;
|
||||||
$events_sess.launcher.sync_stats.currently_syncing = currently_syncing;
|
$events_sess.launcher.sync_stats.currently_syncing =
|
||||||
|
currently_syncing;
|
||||||
|
|
||||||
// Use the PROVEN endpoint path from api.ts that is known to work in Default Mode.
|
// Use the PROVEN endpoint path from api.ts that is known to work in Default Mode.
|
||||||
const url = `${$ae_api.base_url}/v3/action/hosted_file/${file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(file_obj.filename)}&key=${$ae_api.account_id}`;
|
const url = `${$ae_api.base_url}/v3/action/hosted_file/${file_obj.hosted_file_id}/download?return_file=true&filename=${encodeURIComponent(file_obj.filename)}&key=${$ae_api.account_id}`;
|
||||||
const result = await native.download_to_cache({
|
const result = await native.download_to_cache({
|
||||||
url, cache_root, hash: file_obj.hash_sha256,
|
url,
|
||||||
api_key: $ae_api.api_secret_key, account_id: $ae_api.account_id,
|
cache_root,
|
||||||
|
hash: file_obj.hash_sha256,
|
||||||
|
api_key: $ae_api.api_secret_key,
|
||||||
|
account_id: $ae_api.account_id,
|
||||||
hash_prefix_length: prefix_len
|
hash_prefix_length: prefix_len
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.success) sync_results[file_obj.event_file_id] = 'success';
|
if (result.success)
|
||||||
|
sync_results[file_obj.event_file_id] = 'success';
|
||||||
}
|
}
|
||||||
sync_stats.cached = cached_count;
|
sync_stats.cached = cached_count;
|
||||||
sync_stats.missing = missing_count;
|
sync_stats.missing = missing_count;
|
||||||
@@ -165,15 +204,23 @@
|
|||||||
async function run_device_heartbeat() {
|
async function run_device_heartbeat() {
|
||||||
const dev = $ae_loc.native_device;
|
const dev = $ae_loc.native_device;
|
||||||
// String-Only ID Vision: Prioritize semantic string IDs, then generic, then legacy random strings
|
// String-Only ID Vision: Prioritize semantic string IDs, then generic, then legacy random strings
|
||||||
const device_id = dev?.event_device_id || dev?.id || dev?.event_device_id_random || dev?.id_random;
|
const device_id =
|
||||||
|
dev?.event_device_id ||
|
||||||
|
dev?.id ||
|
||||||
|
dev?.event_device_id_random ||
|
||||||
|
dev?.id_random;
|
||||||
|
|
||||||
if (!device_id) {
|
if (!device_id) {
|
||||||
if (log_lvl) console.warn('Sync: Heartbeat skipped, no device_id found in $ae_loc.native_device.');
|
if (log_lvl)
|
||||||
|
console.warn(
|
||||||
|
'Sync: Heartbeat skipped, no device_id found in $ae_loc.native_device.'
|
||||||
|
);
|
||||||
$events_sess.launcher.heartbeat_info.status = 'error';
|
$events_sess.launcher.heartbeat_info.status = 'error';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log_lvl > 1) console.log(`Sync: Running heartbeat for device: ${device_id}`);
|
if (log_lvl > 1)
|
||||||
|
console.log(`Sync: Running heartbeat for device: ${device_id}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let info = null;
|
let info = null;
|
||||||
@@ -183,7 +230,10 @@
|
|||||||
|
|
||||||
const update_payload: any = {
|
const update_payload: any = {
|
||||||
// Use standard SQL format YYYY-MM-DD HH:mm:ss for MySQL compatibility
|
// Use standard SQL format YYYY-MM-DD HH:mm:ss for MySQL compatibility
|
||||||
heartbeat: ae_util.iso_datetime_formatter(new Date(), 'datetime_iso')
|
heartbeat: ae_util.iso_datetime_formatter(
|
||||||
|
new Date(),
|
||||||
|
'datetime_iso'
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (info) {
|
if (info) {
|
||||||
@@ -194,7 +244,8 @@
|
|||||||
release: info.release,
|
release: info.release,
|
||||||
arch: info.arch,
|
arch: info.arch,
|
||||||
cpus: info.cpus,
|
cpus: info.cpus,
|
||||||
total_mem: Math.round(info.total_mem / (1024 * 1024)) + 'MB',
|
total_mem:
|
||||||
|
Math.round(info.total_mem / (1024 * 1024)) + 'MB',
|
||||||
free_mem: Math.round(info.free_mem / (1024 * 1024)) + 'MB'
|
free_mem: Math.round(info.free_mem / (1024 * 1024)) + 'MB'
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
@@ -243,42 +294,70 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Monitor Overlay (Hidden by default, triggered by config modal or secret gesture) -->
|
<!-- Monitor Overlay (Hidden by default, triggered by config modal or secret gesture) -->
|
||||||
<div class="fixed bottom-4 right-4 z-[9999] flex flex-col items-end gap-2 pointer-events-none">
|
<div
|
||||||
|
class="fixed bottom-4 right-4 z-[9999] flex flex-col items-end gap-2 pointer-events-none"
|
||||||
|
>
|
||||||
{#if show_monitor}
|
{#if show_monitor}
|
||||||
<div class="bg-black/90 text-white p-3 rounded-lg border border-primary-500 shadow-2xl text-[10px] font-mono min-w-48 pointer-events-auto">
|
<div
|
||||||
<div class="flex justify-between border-b border-primary-500 pb-1 mb-2">
|
class="bg-black/90 text-white p-3 rounded-lg border border-primary-500 shadow-2xl text-[10px] font-mono min-w-48 pointer-events-auto"
|
||||||
<span class="font-bold text-primary-400">NATIVE SYNC MONITOR</span>
|
>
|
||||||
<button type="button" onclick={() => show_monitor = false} class="text-error-500 hover:text-error-400">×</button>
|
<div
|
||||||
|
class="flex justify-between border-b border-primary-500 pb-1 mb-2"
|
||||||
|
>
|
||||||
|
<span class="font-bold text-primary-400"
|
||||||
|
>NATIVE SYNC MONITOR</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onclick={() => (show_monitor = false)}
|
||||||
|
class="text-error-500 hover:text-error-400">×</button
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-2 gap-x-4 gap-y-1 mb-2">
|
<div class="grid grid-cols-2 gap-x-4 gap-y-1 mb-2">
|
||||||
<span class="opacity-70 text-primary-300">Room Status:</span>
|
<span class="opacity-70 text-primary-300">Room Status:</span>
|
||||||
<span class="text-right">{sync_stats.cached} / {sync_stats.total} Files</span>
|
<span class="text-right"
|
||||||
|
>{sync_stats.cached} / {sync_stats.total} Files</span
|
||||||
|
>
|
||||||
|
|
||||||
<span class="opacity-70 text-primary-300">Prefix Len:</span>
|
<span class="opacity-70 text-primary-300">Prefix Len:</span>
|
||||||
<span class="text-right">{$ae_loc.native_device?.hash_prefix_length || 2} chars</span>
|
<span class="text-right"
|
||||||
|
>{$ae_loc.native_device?.hash_prefix_length || 2} chars</span
|
||||||
|
>
|
||||||
|
|
||||||
<span class="opacity-70 text-primary-300">Heartbeat:</span>
|
<span class="opacity-70 text-primary-300">Heartbeat:</span>
|
||||||
<span class="text-right {last_heartbeat ? 'text-success-500' : 'text-error-500'}">
|
<span
|
||||||
|
class="text-right {last_heartbeat
|
||||||
|
? 'text-success-500'
|
||||||
|
: 'text-error-500'}"
|
||||||
|
>
|
||||||
{last_heartbeat || 'Pending...'}
|
{last_heartbeat || 'Pending...'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="border-t border-white/10 pt-2 flex flex-col gap-1">
|
<div class="border-t border-white/10 pt-2 flex flex-col gap-1">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class:text-primary-500={timer__event}>Event Loop:</span>
|
<span class:text-primary-500={timer__event}
|
||||||
|
>Event Loop:</span
|
||||||
|
>
|
||||||
<span>{loop_info.event / 1000}s</span>
|
<span>{loop_info.event / 1000}s</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class:text-primary-500={timer__device}>Device Loop:</span>
|
<span class:text-primary-500={timer__device}
|
||||||
|
>Device Loop:</span
|
||||||
|
>
|
||||||
<span>{loop_info.device / 1000}s</span>
|
<span>{loop_info.device / 1000}s</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class:text-primary-500={timer__location}>Location Loop:</span>
|
<span class:text-primary-500={timer__location}
|
||||||
|
>Location Loop:</span
|
||||||
|
>
|
||||||
<span>{loop_info.location / 1000}s</span>
|
<span>{loop_info.location / 1000}s</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<span class:text-primary-500={timer__session}>Session Loop:</span>
|
<span class:text-primary-500={timer__session}
|
||||||
|
>Session Loop:</span
|
||||||
|
>
|
||||||
<span>{loop_info.session / 1000}s</span>
|
<span>{loop_info.session / 1000}s</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -286,23 +365,30 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if currently_syncing}
|
{#if currently_syncing}
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => show_monitor = !show_monitor}
|
type="button"
|
||||||
|
onclick={() => (show_monitor = !show_monitor)}
|
||||||
class="bg-black/80 text-white p-2 rounded-lg text-[10px] border border-primary-500 animate-pulse shadow-2xl pointer-events-auto transition-transform active:scale-95"
|
class="bg-black/80 text-white p-2 rounded-lg text-[10px] border border-primary-500 animate-pulse shadow-2xl pointer-events-auto transition-transform active:scale-95"
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-2 text-left">
|
<div class="flex items-center gap-2 text-left">
|
||||||
<span class="fas fa-sync fa-spin text-primary-500 text-sm"></span>
|
<span class="fas fa-sync fa-spin text-primary-500 text-sm"
|
||||||
|
></span>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<span class="font-bold">Syncing Room Files...</span>
|
<span class="font-bold">Syncing Room Files...</span>
|
||||||
<span class="opacity-70 truncate max-w-48">{currently_syncing}</span>
|
<span class="opacity-70 truncate max-w-48"
|
||||||
<span class="text-[8px] mt-1 text-primary-300">Monitor Ready (Click to View)</span>
|
>{currently_syncing}</span
|
||||||
|
>
|
||||||
|
<span class="text-[8px] mt-1 text-primary-300"
|
||||||
|
>Monitor Ready (Click to View)</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Secret button area to toggle monitor when not syncing -->
|
<!-- Secret button area to toggle monitor when not syncing -->
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => show_monitor = !show_monitor}
|
type="button"
|
||||||
|
onclick={() => (show_monitor = !show_monitor)}
|
||||||
class="w-8 h-8 opacity-0 hover:opacity-20 bg-primary-500 rounded-full pointer-events-auto flex items-center justify-center transition-opacity"
|
class="w-8 h-8 opacity-0 hover:opacity-20 bg-primary-500 rounded-full pointer-events-auto flex items-center justify-center transition-opacity"
|
||||||
title="Toggle Sync Monitor"
|
title="Toggle Sync Monitor"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -43,8 +43,11 @@
|
|||||||
*/
|
*/
|
||||||
function handle_section_expand(current_key: string) {
|
function handle_section_expand(current_key: string) {
|
||||||
const launcher = $events_loc.launcher;
|
const launcher = $events_loc.launcher;
|
||||||
Object.keys(launcher).forEach(key => {
|
Object.keys(launcher).forEach((key) => {
|
||||||
if (key.startsWith('section_state__') && key !== `section_state__${current_key}`) {
|
if (
|
||||||
|
key.startsWith('section_state__') &&
|
||||||
|
key !== `section_state__${current_key}`
|
||||||
|
) {
|
||||||
if (launcher[key] === 'auto') {
|
if (launcher[key] === 'auto') {
|
||||||
launcher[key] = 'collapsed';
|
launcher[key] = 'collapsed';
|
||||||
}
|
}
|
||||||
@@ -60,13 +63,18 @@
|
|||||||
flex flex-col gap-4 items-center justify-start
|
flex flex-col gap-4 items-center justify-start
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div class="w-full flex flex-row items-center justify-between border-b border-surface-500/20 pb-2">
|
<div
|
||||||
<h2 class="text-center text-lg font-bold text-gray-700 dark:text-gray-200">
|
class="w-full flex flex-row items-center justify-between border-b border-surface-500/20 pb-2"
|
||||||
|
>
|
||||||
|
<h2
|
||||||
|
class="text-center text-lg font-bold text-gray-700 dark:text-gray-200"
|
||||||
|
>
|
||||||
<span class="fas fa-cog mr-2 opacity-50"></span>
|
<span class="fas fa-cog mr-2 opacity-50"></span>
|
||||||
Launcher Configuration
|
Launcher Configuration
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => ($events_loc.launcher.hide_drawer__cfg = true)}
|
onclick={() => ($events_loc.launcher.hide_drawer__cfg = true)}
|
||||||
class="btn btn-icon dark:text-white hover:bg-surface-500/10 transition-colors"
|
class="btn btn-icon dark:text-white hover:bg-surface-500/10 transition-colors"
|
||||||
>
|
>
|
||||||
@@ -77,24 +85,27 @@
|
|||||||
|
|
||||||
<!-- Category Tabs -->
|
<!-- Category Tabs -->
|
||||||
<div class="w-full grid grid-cols-3 gap-1 bg-surface-500/10 p-1 rounded-lg">
|
<div class="w-full grid grid-cols-3 gap-1 bg-surface-500/10 p-1 rounded-lg">
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => active_tab = 'system'}
|
type="button"
|
||||||
|
onclick={() => (active_tab = 'system')}
|
||||||
class="btn btn-sm text-[10px] uppercase font-bold transition-all"
|
class="btn btn-sm text-[10px] uppercase font-bold transition-all"
|
||||||
class:preset-filled-primary-500={active_tab === 'system'}
|
class:preset-filled-primary-500={active_tab === 'system'}
|
||||||
class:opacity-50={active_tab !== 'system'}
|
class:opacity-50={active_tab !== 'system'}
|
||||||
>
|
>
|
||||||
<span class="fas fa-microchip mr-1"></span> System
|
<span class="fas fa-microchip mr-1"></span> System
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => active_tab = 'sync'}
|
type="button"
|
||||||
|
onclick={() => (active_tab = 'sync')}
|
||||||
class="btn btn-sm text-[10px] uppercase font-bold transition-all"
|
class="btn btn-sm text-[10px] uppercase font-bold transition-all"
|
||||||
class:preset-filled-primary-500={active_tab === 'sync'}
|
class:preset-filled-primary-500={active_tab === 'sync'}
|
||||||
class:opacity-50={active_tab !== 'sync'}
|
class:opacity-50={active_tab !== 'sync'}
|
||||||
>
|
>
|
||||||
<span class="fas fa-sync mr-1"></span> Sync
|
<span class="fas fa-sync mr-1"></span> Sync
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => active_tab = 'general'}
|
type="button"
|
||||||
|
onclick={() => (active_tab = 'general')}
|
||||||
class="btn btn-sm text-[10px] uppercase font-bold transition-all"
|
class="btn btn-sm text-[10px] uppercase font-bold transition-all"
|
||||||
class:preset-filled-primary-500={active_tab === 'general'}
|
class:preset-filled-primary-500={active_tab === 'general'}
|
||||||
class:opacity-50={active_tab !== 'general'}
|
class:opacity-50={active_tab !== 'general'}
|
||||||
@@ -105,16 +116,22 @@
|
|||||||
|
|
||||||
<!-- Tab Content -->
|
<!-- Tab Content -->
|
||||||
<div class="w-full flex flex-col gap-2 min-h-[400px]">
|
<div class="w-full flex flex-col gap-2 min-h-[400px]">
|
||||||
|
|
||||||
{#if active_tab === 'system'}
|
{#if active_tab === 'system'}
|
||||||
<div class="animate-in fade-in slide-in-from-left-2 duration-300">
|
<div class="animate-in fade-in slide-in-from-left-2 duration-300">
|
||||||
{#if $ae_loc.is_native}
|
{#if $ae_loc.is_native}
|
||||||
<Launcher_Cfg_Health on_expand={() => handle_section_expand('health')} />
|
<Launcher_Cfg_Health
|
||||||
<Launcher_Cfg_Native_OS on_expand={() => handle_section_expand('native_os')} />
|
on_expand={() => handle_section_expand('health')}
|
||||||
<Launcher_Cfg_Updates on_expand={() => handle_section_expand('updates')} />
|
/>
|
||||||
|
<Launcher_Cfg_Native_OS
|
||||||
|
on_expand={() => handle_section_expand('native_os')}
|
||||||
|
/>
|
||||||
|
<Launcher_Cfg_Updates
|
||||||
|
on_expand={() => handle_section_expand('updates')}
|
||||||
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="card p-8 text-center opacity-50 italic text-sm">
|
<div class="card p-8 text-center opacity-50 italic text-sm">
|
||||||
Native OS features are only available when running in the Aether Desktop app.
|
Native OS features are only available when running in
|
||||||
|
the Aether Desktop app.
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -122,33 +139,47 @@
|
|||||||
|
|
||||||
{#if active_tab === 'sync'}
|
{#if active_tab === 'sync'}
|
||||||
<div class="animate-in fade-in slide-in-from-bottom-2 duration-300">
|
<div class="animate-in fade-in slide-in-from-bottom-2 duration-300">
|
||||||
<Launcher_Cfg_Sync_Timers on_expand={() => handle_section_expand('sync_timers')} />
|
<Launcher_Cfg_Sync_Timers
|
||||||
|
on_expand={() => handle_section_expand('sync_timers')}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if active_tab === 'general'}
|
{#if active_tab === 'general'}
|
||||||
<div class="animate-in fade-in slide-in-from-right-2 duration-300">
|
<div class="animate-in fade-in slide-in-from-right-2 duration-300">
|
||||||
<Launcher_Cfg_Controller on_expand={() => handle_section_expand('controller')} />
|
<Launcher_Cfg_Controller
|
||||||
<Launcher_Cfg_App_Modes on_expand={() => handle_section_expand('app_modes')} />
|
on_expand={() => handle_section_expand('controller')}
|
||||||
<Launcher_Cfg_Screen_Saver on_expand={() => handle_section_expand('screen_saver')} />
|
/>
|
||||||
<Launcher_Cfg_Local_Actions on_expand={() => handle_section_expand('local_actions')} />
|
<Launcher_Cfg_App_Modes
|
||||||
|
on_expand={() => handle_section_expand('app_modes')}
|
||||||
|
/>
|
||||||
|
<Launcher_Cfg_Screen_Saver
|
||||||
|
on_expand={() => handle_section_expand('screen_saver')}
|
||||||
|
/>
|
||||||
|
<Launcher_Cfg_Local_Actions
|
||||||
|
on_expand={() => handle_section_expand('local_actions')}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Global Actions Footer -->
|
<!-- Global Actions Footer -->
|
||||||
<div class="w-full flex flex-col gap-2 border-t border-surface-500/20 pt-4 mt-auto">
|
<div
|
||||||
|
class="w-full flex flex-col gap-2 border-t border-surface-500/20 pt-4 mt-auto"
|
||||||
|
>
|
||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<button type="button"
|
<button
|
||||||
onclick={() => ($events_loc.launcher.hide_drawer__debug = false)}
|
type="button"
|
||||||
|
onclick={() =>
|
||||||
|
($events_loc.launcher.hide_drawer__debug = false)}
|
||||||
class="btn btn-sm preset-tonal-error hover:preset-filled-error-500 transition-all"
|
class="btn btn-sm preset-tonal-error hover:preset-filled-error-500 transition-all"
|
||||||
>
|
>
|
||||||
<span class="fas fa-bug mr-2"></span>
|
<span class="fas fa-bug mr-2"></span>
|
||||||
Open Debug
|
Open Debug
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => location.reload()}
|
onclick={() => location.reload()}
|
||||||
class="btn btn-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition-all"
|
class="btn btn-sm preset-tonal-secondary hover:preset-filled-secondary-500 transition-all"
|
||||||
>
|
>
|
||||||
@@ -157,7 +188,9 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="text-[9px] text-center opacity-40 uppercase font-bold tracking-widest mt-2">
|
<p
|
||||||
|
class="text-[9px] text-center opacity-40 uppercase font-bold tracking-widest mt-2"
|
||||||
|
>
|
||||||
Aether Platform • Events Launcher v3.0
|
Aether Platform • Events Launcher v3.0
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -57,7 +57,11 @@
|
|||||||
import { api } from '$lib/api/api';
|
import { api } from '$lib/api/api';
|
||||||
import { ae_loc, ae_api, ae_sess, slct } from '$lib/stores/ae_stores';
|
import { ae_loc, ae_api, ae_sess, slct } from '$lib/stores/ae_stores';
|
||||||
import { core_func } from '$lib/ae_core/ae_core_functions';
|
import { core_func } from '$lib/ae_core/ae_core_functions';
|
||||||
import { events_loc, events_sess, events_slct } from '$lib/stores/ae_events_stores';
|
import {
|
||||||
|
events_loc,
|
||||||
|
events_sess,
|
||||||
|
events_slct
|
||||||
|
} from '$lib/stores/ae_events_stores';
|
||||||
import { events_func } from '$lib/ae_events_functions';
|
import { events_func } from '$lib/ae_events_functions';
|
||||||
|
|
||||||
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';
|
||||||
@@ -78,8 +82,11 @@
|
|||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (screen_saver_exts.includes(event_file_obj.extension)) {
|
if (screen_saver_exts.includes(event_file_obj.extension)) {
|
||||||
if (!$events_loc.launcher.screen_saver_img_kv) $events_loc.launcher.screen_saver_img_kv = {};
|
if (!$events_loc.launcher.screen_saver_img_kv)
|
||||||
$events_loc.launcher.screen_saver_img_kv[event_file_id] = { ...event_file_obj };
|
$events_loc.launcher.screen_saver_img_kv = {};
|
||||||
|
$events_loc.launcher.screen_saver_img_kv[event_file_id] = {
|
||||||
|
...event_file_obj
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -98,7 +105,10 @@
|
|||||||
open_file_status = 'checking_cache';
|
open_file_status = 'checking_cache';
|
||||||
open_file_status_message = 'Checking local cache...';
|
open_file_status_message = 'Checking local cache...';
|
||||||
|
|
||||||
const exists = await native.check_hash_file_cache({ cache_root, hash: event_file_obj.hash_sha256 });
|
const exists = await native.check_hash_file_cache({
|
||||||
|
cache_root,
|
||||||
|
hash: event_file_obj.hash_sha256
|
||||||
|
});
|
||||||
|
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
open_file_status = 'downloading_file';
|
open_file_status = 'downloading_file';
|
||||||
@@ -118,7 +128,7 @@
|
|||||||
if (!dl_result.success) {
|
if (!dl_result.success) {
|
||||||
open_file_status = 'error';
|
open_file_status = 'error';
|
||||||
open_file_status_message = `Download failed: ${dl_result.error}`;
|
open_file_status_message = `Download failed: ${dl_result.error}`;
|
||||||
setTimeout(() => open_file_clicked = false, 5000);
|
setTimeout(() => (open_file_clicked = false), 5000);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -141,7 +151,7 @@
|
|||||||
open_file_status_message = `Failed to open: ${launch_result.error}`;
|
open_file_status_message = `Failed to open: ${launch_result.error}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => open_file_clicked = false, 5000);
|
setTimeout(() => (open_file_clicked = false), 5000);
|
||||||
return launch_result.success;
|
return launch_result.success;
|
||||||
}
|
}
|
||||||
// 2. ONSITE MODE (Browser with Modified Extensions)
|
// 2. ONSITE MODE (Browser with Modified Extensions)
|
||||||
@@ -151,7 +161,11 @@
|
|||||||
open_file_status_message = 'Downloading (Onsite Mode)...';
|
open_file_status_message = 'Downloading (Onsite Mode)...';
|
||||||
|
|
||||||
let filename = event_file_obj.filename;
|
let filename = event_file_obj.filename;
|
||||||
if ((event_file_obj.extension === 'ppt' || event_file_obj.extension === 'pptx') && event_file_obj.open_in_os === 'win') {
|
if (
|
||||||
|
(event_file_obj.extension === 'ppt' ||
|
||||||
|
event_file_obj.extension === 'pptx') &&
|
||||||
|
event_file_obj.open_in_os === 'win'
|
||||||
|
) {
|
||||||
filename = event_file_obj.filename + 'win';
|
filename = event_file_obj.filename + 'win';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +181,7 @@
|
|||||||
log_lvl: 1
|
log_lvl: 1
|
||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => open_file_clicked = false, 5000);
|
setTimeout(() => (open_file_clicked = false), 5000);
|
||||||
return dl_promise;
|
return dl_promise;
|
||||||
}
|
}
|
||||||
// 3. DEFAULT MODE (Standard Browser)
|
// 3. DEFAULT MODE (Standard Browser)
|
||||||
@@ -193,14 +207,14 @@
|
|||||||
$events_sess.launcher.controller_trigger_send = true;
|
$events_sess.launcher.controller_trigger_send = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => open_file_clicked = false, 5000);
|
setTimeout(() => (open_file_clicked = false), 5000);
|
||||||
return dl_promise;
|
return dl_promise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.prevent_default();
|
event.preventDefault();
|
||||||
fn(event);
|
fn(event);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -209,21 +223,34 @@
|
|||||||
<div
|
<div
|
||||||
class:justify-between={!hide_meta}
|
class:justify-between={!hide_meta}
|
||||||
class:justify-center={hide_meta}
|
class:justify-center={hide_meta}
|
||||||
class:hidden={hide_draft && (event_file_obj.file_purpose == 'outline' || event_file_obj.file_purpose == 'draft')}
|
class:hidden={hide_draft &&
|
||||||
|
(event_file_obj.file_purpose == 'outline' ||
|
||||||
|
event_file_obj.file_purpose == 'draft')}
|
||||||
class="event_launcher_file_cont grow flex flex-col md:flex-row flex-wrap gap-1 items-center justify-center max-w-full transition-all"
|
class="event_launcher_file_cont grow flex flex-col md:flex-row flex-wrap gap-1 items-center justify-center max-w-full transition-all"
|
||||||
>
|
>
|
||||||
{#if open_file_clicked}
|
{#if open_file_clicked}
|
||||||
<div class="open_file_clicked alert" in:fade={{ duration: 250 }} out:fade={{ duration: 2000 }}>
|
<div
|
||||||
|
class="open_file_clicked alert"
|
||||||
|
in:fade={{ duration: 250 }}
|
||||||
|
out:fade={{ duration: 2000 }}
|
||||||
|
>
|
||||||
<div class="alert_msg_pulse">
|
<div class="alert_msg_pulse">
|
||||||
<strong>*** {open_file_status_message || 'Please wait while this file downloads...'} ***</strong>
|
<strong
|
||||||
|
>*** {open_file_status_message ||
|
||||||
|
'Please wait while this file downloads...'} ***</strong
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<p>Most files will automatically be opened full screen.</p>
|
<p>Most files will automatically be opened full screen.</p>
|
||||||
<p>PowerPoint or KeyNote will attempt to display in presenter view.</p>
|
<p>
|
||||||
|
PowerPoint or KeyNote will attempt to display in presenter view.
|
||||||
|
</p>
|
||||||
<p>Please close the file when finished.</p>
|
<p>Please close the file when finished.</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<span class="event_file_action grow max-w-full flex flex-row flex-wrap gap-1 items-center justify-center">
|
<span
|
||||||
|
class="event_file_action grow max-w-full flex flex-row flex-wrap gap-1 items-center justify-center"
|
||||||
|
>
|
||||||
{#if session_type == 'poster' || open_method == 'modal'}
|
{#if session_type == 'poster' || open_method == 'modal'}
|
||||||
<AE_Comp_Hosted_Files_Download_Button
|
<AE_Comp_Hosted_Files_Download_Button
|
||||||
hosted_file_id={event_file_id}
|
hosted_file_id={event_file_id}
|
||||||
@@ -239,10 +266,19 @@
|
|||||||
>
|
>
|
||||||
{#snippet label()}
|
{#snippet label()}
|
||||||
{#if screen_saver_exts.includes(event_file_obj.extension)}
|
{#if screen_saver_exts.includes(event_file_obj.extension)}
|
||||||
<span class="fas fa-chart-bar m-1" class:hidden={hide_launch_icon}></span> Open Poster
|
<span
|
||||||
|
class="fas fa-chart-bar m-1"
|
||||||
|
class:hidden={hide_launch_icon}
|
||||||
|
></span> Open Poster
|
||||||
{:else}
|
{:else}
|
||||||
<span class="fas fa-paper-plane m-1" class:hidden={hide_launch_icon}></span>
|
<span
|
||||||
{ae_util.shorten_filename({ filename: event_file_obj.filename, max_length: max_filename_length })}
|
class="fas fa-paper-plane m-1"
|
||||||
|
class:hidden={hide_launch_icon}
|
||||||
|
></span>
|
||||||
|
{ae_util.shorten_filename({
|
||||||
|
filename: event_file_obj.filename,
|
||||||
|
max_length: max_filename_length
|
||||||
|
})}
|
||||||
{/if}
|
{/if}
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</AE_Comp_Hosted_Files_Download_Button>
|
</AE_Comp_Hosted_Files_Download_Button>
|
||||||
@@ -260,27 +296,48 @@
|
|||||||
<span class="fas fa-spinner fa-spin mx-0.5"></span>
|
<span class="fas fa-spinner fa-spin mx-0.5"></span>
|
||||||
<span>
|
<span>
|
||||||
{#if $ae_sess.api_download_kv[file_id]}
|
{#if $ae_sess.api_download_kv[file_id]}
|
||||||
{$ae_sess.api_download_kv[file_id].percent_completed}%
|
{$ae_sess.api_download_kv[file_id]
|
||||||
|
.percent_completed}%
|
||||||
{:else}
|
{:else}
|
||||||
...
|
...
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
{:then result}
|
{:then result}
|
||||||
<span class="fas fa-{ae_util.file_extension_icon(event_file_obj.extension)} mx-0.5"></span>
|
<span
|
||||||
|
class="fas fa-{ae_util.file_extension_icon(
|
||||||
|
event_file_obj.extension
|
||||||
|
)} mx-0.5"
|
||||||
|
></span>
|
||||||
{event_file_obj.extension}
|
{event_file_obj.extension}
|
||||||
{#if result === null || result === false}
|
{#if result === null || result === false}
|
||||||
<span class="text-error-500"><span class="fas fa-exclamation-triangle mx-1"></span>Failed!</span>
|
<span class="text-error-500"
|
||||||
|
><span
|
||||||
|
class="fas fa-exclamation-triangle mx-1"
|
||||||
|
></span>Failed!</span
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<span class="text-error-500" title={error?.message}><span class="fas fa-exclamation-circle mx-0.5"></span>Error!</span>
|
<span class="text-error-500" title={error?.message}
|
||||||
|
><span class="fas fa-exclamation-circle mx-0.5"
|
||||||
|
></span>Error!</span
|
||||||
|
>
|
||||||
{/await}
|
{/await}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="grow {text_size} {text_size_md} w-full max-w-full overflow-hidden text-ellipsis {btn_text_align}">
|
<span
|
||||||
{ae_util.shorten_string({ string: event_file_obj.filename_no_ext, begin_length: 45, max_length: 65 })}
|
class="grow {text_size} {text_size_md} w-full max-w-full overflow-hidden text-ellipsis {btn_text_align}"
|
||||||
|
>
|
||||||
|
{ae_util.shorten_string({
|
||||||
|
string: event_file_obj.filename_no_ext,
|
||||||
|
begin_length: 45,
|
||||||
|
max_length: 65
|
||||||
|
})}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="badge my-0 py-0.5 preset-tonal-success hover:preset-filled-success-500 text-xs xl:text-sm" class:hidden={!event_file_obj.file_purpose}>
|
<span
|
||||||
|
class="badge my-0 py-0.5 preset-tonal-success hover:preset-filled-success-500 text-xs xl:text-sm"
|
||||||
|
class:hidden={!event_file_obj.file_purpose}
|
||||||
|
>
|
||||||
{event_file_obj.file_purpose}
|
{event_file_obj.file_purpose}
|
||||||
</span>
|
</span>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
@@ -288,7 +345,10 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="event_file_meta grow text-sm text-gray-500 flex flex-col sm:flex-row gap-1 wrap items-center justify-between w-64 max-w-80 font-mono" class:hidden={hide_meta}>
|
<span
|
||||||
|
class="event_file_meta grow text-sm text-gray-500 flex flex-col sm:flex-row gap-1 wrap items-center justify-between w-64 max-w-80 font-mono"
|
||||||
|
class:hidden={hide_meta}
|
||||||
|
>
|
||||||
<Element_ae_crud
|
<Element_ae_crud
|
||||||
trigger_patch={ae_triggers.open_in_os}
|
trigger_patch={ae_triggers.open_in_os}
|
||||||
api_cfg={$ae_api}
|
api_cfg={$ae_api}
|
||||||
@@ -298,13 +358,20 @@
|
|||||||
field_type={'button'}
|
field_type={'button'}
|
||||||
field_value={ae_tmp.value__open_in_os}
|
field_value={ae_tmp.value__open_in_os}
|
||||||
on:ae_crud_updated={() => {
|
on:ae_crud_updated={() => {
|
||||||
events_func.load_ae_obj_id__event_file({ api_cfg: $ae_api, event_file_id: event_file_obj?.event_file_id, log_lvl });
|
events_func.load_ae_obj_id__event_file({
|
||||||
|
api_cfg: $ae_api,
|
||||||
|
event_file_id: event_file_obj?.event_file_id,
|
||||||
|
log_lvl
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if (!event_file_obj?.open_in_os) ae_tmp.value__open_in_os = 'win';
|
if (!event_file_obj?.open_in_os)
|
||||||
else if (event_file_obj?.open_in_os == 'win') ae_tmp.value__open_in_os = 'mac';
|
ae_tmp.value__open_in_os = 'win';
|
||||||
|
else if (event_file_obj?.open_in_os == 'win')
|
||||||
|
ae_tmp.value__open_in_os = 'mac';
|
||||||
else ae_tmp.value__open_in_os = null;
|
else ae_tmp.value__open_in_os = null;
|
||||||
ae_triggers.open_in_os = true;
|
ae_triggers.open_in_os = true;
|
||||||
}}
|
}}
|
||||||
@@ -313,20 +380,37 @@
|
|||||||
class:preset-tonal-warning={event_file_obj?.open_in_os == 'mac'}
|
class:preset-tonal-warning={event_file_obj?.open_in_os == 'mac'}
|
||||||
disabled={!$ae_loc.trusted_access}
|
disabled={!$ae_loc.trusted_access}
|
||||||
>
|
>
|
||||||
{#if event_file_obj?.open_in_os == 'win'}<span class="fab fa-windows m-1"></span>
|
{#if event_file_obj?.open_in_os == 'win'}<span
|
||||||
{:else if event_file_obj?.open_in_os == 'mac'}<span class="fab fa-apple m-1"></span>
|
class="fab fa-windows m-1"
|
||||||
|
></span>
|
||||||
|
{:else if event_file_obj?.open_in_os == 'mac'}<span
|
||||||
|
class="fab fa-apple m-1"
|
||||||
|
></span>
|
||||||
{:else}<span class="fas fa-folder-open m-1"></span>{/if}
|
{:else}<span class="fas fa-folder-open m-1"></span>{/if}
|
||||||
</button>
|
</button>
|
||||||
</Element_ae_crud>
|
</Element_ae_crud>
|
||||||
|
|
||||||
<span class="event_file_created_on text-xs text-center flex flex-row gap-1 items-center justify-end w-24 md:w-44 preset-filled-surface-100-900 rounded px-1 py-0.5" class:hidden={hide_created_on}>
|
<span
|
||||||
|
class="event_file_created_on text-xs text-center flex flex-row gap-1 items-center justify-end w-24 md:w-44 preset-filled-surface-100-900 rounded px-1 py-0.5"
|
||||||
|
class:hidden={hide_created_on}
|
||||||
|
>
|
||||||
<span class="fas fa-calendar-day"></span>
|
<span class="fas fa-calendar-day"></span>
|
||||||
<span class="w-18">{ae_util.iso_datetime_formatter(event_file_obj.created_on, 'date_short')}</span>
|
<span class="w-18"
|
||||||
|
>{ae_util.iso_datetime_formatter(
|
||||||
|
event_file_obj.created_on,
|
||||||
|
'date_short'
|
||||||
|
)}</span
|
||||||
|
>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="event_file_size text-xs text-center flex flex-row gap-1 items-center justify-end preset-filled-surface-100-900 w-22 max-w-28 rounded py-0.5" class:hidden={hide_size}>
|
<span
|
||||||
|
class="event_file_size text-xs text-center flex flex-row gap-1 items-center justify-end preset-filled-surface-100-900 w-22 max-w-28 rounded py-0.5"
|
||||||
|
class:hidden={hide_size}
|
||||||
|
>
|
||||||
<span class="fas fa-save"></span>
|
<span class="fas fa-save"></span>
|
||||||
{#if event_file_obj.file_size}{ae_util.format_bytes(event_file_obj.file_size)}{/if}
|
{#if event_file_obj.file_size}{ae_util.format_bytes(
|
||||||
|
event_file_obj.file_size
|
||||||
|
)}{/if}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,19 +141,26 @@
|
|||||||
hide_created_on={true}
|
hide_created_on={true}
|
||||||
hide_os={true}
|
hide_os={true}
|
||||||
hide_size={true}
|
hide_size={true}
|
||||||
show_bak_download={$ae_loc.trusted_access && $ae_loc.edit_mode}
|
show_bak_download={$ae_loc.trusted_access &&
|
||||||
|
$ae_loc.edit_mode}
|
||||||
btn_size={'btn-sm'}
|
btn_size={'btn-sm'}
|
||||||
btn_text_align={'text-center'}
|
btn_text_align={'text-center'}
|
||||||
text_size={'text-xs'}
|
text_size={'text-xs'}
|
||||||
text_size_md={'text-xs'}
|
text_size_md={'text-xs'}
|
||||||
session_type={event_file_obj?.event_session_type_code ?? 'oral'}
|
session_type={event_file_obj?.event_session_type_code ??
|
||||||
open_method={event_file_obj?.event_session_type_code == 'poster'
|
'oral'}
|
||||||
|
open_method={event_file_obj?.event_session_type_code ==
|
||||||
|
'poster'
|
||||||
? 'modal'
|
? 'modal'
|
||||||
: null}
|
: null}
|
||||||
modal_title={$lq__event_session_obj?.name}
|
modal_title={$lq__event_session_obj?.name}
|
||||||
bind:modal__title={$events_sess.launcher.modal__title}
|
bind:modal__title={$events_sess.launcher.modal__title}
|
||||||
bind:modal__open_event_file_id={$events_sess.launcher.modal__open_event_file_id}
|
bind:modal__open_event_file_id={
|
||||||
bind:modal__event_file_obj={$events_sess.launcher.modal__event_file_obj}
|
$events_sess.launcher.modal__open_event_file_id
|
||||||
|
}
|
||||||
|
bind:modal__event_file_obj={
|
||||||
|
$events_sess.launcher.modal__event_file_obj
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -179,19 +186,26 @@
|
|||||||
hide_created_on={true}
|
hide_created_on={true}
|
||||||
hide_os={true}
|
hide_os={true}
|
||||||
hide_size={true}
|
hide_size={true}
|
||||||
show_bak_download={$ae_loc.trusted_access && $ae_loc.edit_mode}
|
show_bak_download={$ae_loc.trusted_access &&
|
||||||
|
$ae_loc.edit_mode}
|
||||||
btn_size={'btn-sm'}
|
btn_size={'btn-sm'}
|
||||||
btn_text_align={'text-center'}
|
btn_text_align={'text-center'}
|
||||||
text_size={'text-xs'}
|
text_size={'text-xs'}
|
||||||
text_size_md={'text-xs'}
|
text_size_md={'text-xs'}
|
||||||
session_type={event_file_obj?.event_session_type_code ?? 'oral'}
|
session_type={event_file_obj?.event_session_type_code ??
|
||||||
open_method={event_file_obj?.event_session_type_code == 'poster'
|
'oral'}
|
||||||
|
open_method={event_file_obj?.event_session_type_code ==
|
||||||
|
'poster'
|
||||||
? 'modal'
|
? 'modal'
|
||||||
: null}
|
: null}
|
||||||
modal_title={$lq__event_session_obj?.name}
|
modal_title={$lq__event_session_obj?.name}
|
||||||
bind:modal__title={$events_sess.launcher.modal__title}
|
bind:modal__title={$events_sess.launcher.modal__title}
|
||||||
bind:modal__open_event_file_id={$events_sess.launcher.modal__open_event_file_id}
|
bind:modal__open_event_file_id={
|
||||||
bind:modal__event_file_obj={$events_sess.launcher.modal__event_file_obj}
|
$events_sess.launcher.modal__open_event_file_id
|
||||||
|
}
|
||||||
|
bind:modal__event_file_obj={
|
||||||
|
$events_sess.launcher.modal__event_file_obj
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -214,7 +228,8 @@
|
|||||||
flex flex-row gap-1 items-center justify-center
|
flex flex-row gap-1 items-center justify-center
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if ($events_loc.launcher.show_content__hidden_files) {
|
if ($events_loc.launcher.show_content__hidden_files) {
|
||||||
$events_loc.launcher.show_content__hidden_files = false;
|
$events_loc.launcher.show_content__hidden_files = false;
|
||||||
@@ -235,14 +250,16 @@
|
|||||||
title="Toggle showing hidden files. Including files marked as 'draft'."
|
title="Toggle showing hidden files. Including files marked as 'draft'."
|
||||||
>
|
>
|
||||||
{#if $events_loc.launcher.show_content__hidden_files}
|
{#if $events_loc.launcher.show_content__hidden_files}
|
||||||
<span class="fas fa-eye-slash m-1 text-neutral-800/80"></span>
|
<span class="fas fa-eye-slash m-1 text-neutral-800/80"
|
||||||
|
></span>
|
||||||
Hide Files
|
Hide Files
|
||||||
{:else}
|
{:else}
|
||||||
<span class="fas fa-eye m-1 text-neutral-800/80"></span>
|
<span class="fas fa-eye m-1 text-neutral-800/80"></span>
|
||||||
All Files
|
All Files
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
$events_loc.launcher.show_content__hidden_sessions =
|
$events_loc.launcher.show_content__hidden_sessions =
|
||||||
!$events_loc.launcher.show_content__hidden_sessions;
|
!$events_loc.launcher.show_content__hidden_sessions;
|
||||||
@@ -257,7 +274,8 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
{#if $events_loc.launcher.show_content__hidden_sessions}
|
{#if $events_loc.launcher.show_content__hidden_sessions}
|
||||||
<span class="fas fa-eye-slash m-1 text-neutral-800/80"></span>
|
<span class="fas fa-eye-slash m-1 text-neutral-800/80"
|
||||||
|
></span>
|
||||||
Hide Sessions
|
Hide Sessions
|
||||||
{:else}
|
{:else}
|
||||||
<span class="fas fa-eye m-1 text-neutral-800/80"></span>
|
<span class="fas fa-eye m-1 text-neutral-800/80"></span>
|
||||||
|
|||||||
@@ -27,24 +27,30 @@
|
|||||||
|
|
||||||
{#if $lq__event_file_obj_li && $lq__event_file_obj_li.length}
|
{#if $lq__event_file_obj_li && $lq__event_file_obj_li.length}
|
||||||
<section class="event_presentation_file_list my-1">
|
<section class="event_presentation_file_list my-1">
|
||||||
<div class="text-[10px] text-surface-600-400 uppercase font-bold tracking-wider opacity-70">
|
<div
|
||||||
|
class="text-[10px] text-surface-600-400 uppercase font-bold tracking-wider opacity-70"
|
||||||
|
>
|
||||||
Presentation Files:
|
Presentation Files:
|
||||||
</div>
|
</div>
|
||||||
<ul class="space-y-1">
|
<ul class="space-y-1">
|
||||||
{#each $lq__event_file_obj_li as event_file_obj}
|
{#each $lq__event_file_obj_li as event_file_obj}
|
||||||
<li
|
<li
|
||||||
class="flex flex-col md:flex-row flex-wrap gap-1 items-center justify-start"
|
class="flex flex-col md:flex-row flex-wrap gap-1 items-center justify-start"
|
||||||
class:hidden={!$events_loc.launcher.show_content__hidden_files &&
|
class:hidden={!$events_loc.launcher
|
||||||
event_file_obj.hide}
|
.show_content__hidden_files && event_file_obj.hide}
|
||||||
>
|
>
|
||||||
<Event_launcher_file_cont
|
<Event_launcher_file_cont
|
||||||
event_file_id={event_file_obj.event_file_id}
|
event_file_id={event_file_obj.event_file_id}
|
||||||
{event_file_obj}
|
{event_file_obj}
|
||||||
hide_created_on={false}
|
hide_created_on={false}
|
||||||
bind:hide_draft={$events_loc.launcher.hide_content__draft_files}
|
bind:hide_draft={
|
||||||
|
$events_loc.launcher.hide_content__draft_files
|
||||||
|
}
|
||||||
show_bak_download={$ae_loc.trusted_access}
|
show_bak_download={$ae_loc.trusted_access}
|
||||||
session_type={event_file_obj?.event_session_type_code ?? 'oral'}
|
session_type={event_file_obj?.event_session_type_code ??
|
||||||
open_method={event_file_obj?.event_session_type_code == 'poster'
|
'oral'}
|
||||||
|
open_method={event_file_obj?.event_session_type_code ==
|
||||||
|
'poster'
|
||||||
? 'modal'
|
? 'modal'
|
||||||
: null}
|
: null}
|
||||||
modal_title={lq__event_presentation_obj?.name}
|
modal_title={lq__event_presentation_obj?.name}
|
||||||
@@ -52,7 +58,9 @@
|
|||||||
bind:modal__open_event_file_id={
|
bind:modal__open_event_file_id={
|
||||||
$events_sess.launcher.modal__open_event_file_id
|
$events_sess.launcher.modal__open_event_file_id
|
||||||
}
|
}
|
||||||
bind:modal__event_file_obj={$events_sess.launcher.modal__event_file_obj}
|
bind:modal__event_file_obj={
|
||||||
|
$events_sess.launcher.modal__event_file_obj
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -89,17 +89,21 @@
|
|||||||
{#each $lq__event_file_obj_li as event_file_obj, index}
|
{#each $lq__event_file_obj_li as event_file_obj, index}
|
||||||
<li
|
<li
|
||||||
class="flex flex-col md:flex-row flex-wrap gap-1 items-center justify-start"
|
class="flex flex-col md:flex-row flex-wrap gap-1 items-center justify-start"
|
||||||
class:hidden={!$events_loc.launcher.show_content__hidden_files &&
|
class:hidden={!$events_loc.launcher
|
||||||
event_file_obj.hide}
|
.show_content__hidden_files && event_file_obj.hide}
|
||||||
>
|
>
|
||||||
<Event_launcher_file_cont
|
<Event_launcher_file_cont
|
||||||
event_file_id={event_file_obj.event_file_id}
|
event_file_id={event_file_obj.event_file_id}
|
||||||
{event_file_obj}
|
{event_file_obj}
|
||||||
hide_created_on={false}
|
hide_created_on={false}
|
||||||
bind:hide_draft={$events_loc.launcher.hide_content__draft_files}
|
bind:hide_draft={
|
||||||
|
$events_loc.launcher.hide_content__draft_files
|
||||||
|
}
|
||||||
show_bak_download={$ae_loc.trusted_access}
|
show_bak_download={$ae_loc.trusted_access}
|
||||||
session_type={event_file_obj?.event_session_type_code ?? 'oral'}
|
session_type={event_file_obj?.event_session_type_code ??
|
||||||
open_method={event_file_obj?.event_session_type_code == 'poster'
|
'oral'}
|
||||||
|
open_method={event_file_obj?.event_session_type_code ==
|
||||||
|
'poster'
|
||||||
? 'modal'
|
? 'modal'
|
||||||
: null}
|
: null}
|
||||||
modal_title={lq__event_presenter_obj?.event_presentation_name}
|
modal_title={lq__event_presenter_obj?.event_presentation_name}
|
||||||
@@ -107,7 +111,9 @@
|
|||||||
bind:modal__open_event_file_id={
|
bind:modal__open_event_file_id={
|
||||||
$events_sess.launcher.modal__open_event_file_id
|
$events_sess.launcher.modal__open_event_file_id
|
||||||
}
|
}
|
||||||
bind:modal__event_file_obj={$events_sess.launcher.modal__event_file_obj}
|
bind:modal__event_file_obj={
|
||||||
|
$events_sess.launcher.modal__event_file_obj
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -88,8 +88,8 @@
|
|||||||
{#each $lq__event_file_obj_li as event_file_obj, index}
|
{#each $lq__event_file_obj_li as event_file_obj, index}
|
||||||
<li
|
<li
|
||||||
class="flex flex-col md:flex-row wrap gap items-center justify-center"
|
class="flex flex-col md:flex-row wrap gap items-center justify-center"
|
||||||
class:hidden={!$events_loc.launcher.show_content__hidden_files &&
|
class:hidden={!$events_loc.launcher
|
||||||
event_file_obj.hide}
|
.show_content__hidden_files && event_file_obj.hide}
|
||||||
>
|
>
|
||||||
<Event_launcher_file_cont
|
<Event_launcher_file_cont
|
||||||
event_file_id={event_file_obj.event_file_id}
|
event_file_id={event_file_obj.event_file_id}
|
||||||
@@ -97,8 +97,10 @@
|
|||||||
hide_created_on={false}
|
hide_created_on={false}
|
||||||
hide_meta={true}
|
hide_meta={true}
|
||||||
show_bak_download={$ae_loc.trusted_access}
|
show_bak_download={$ae_loc.trusted_access}
|
||||||
session_type={event_file_obj?.event_session_type_code ?? 'oral'}
|
session_type={event_file_obj?.event_session_type_code ??
|
||||||
open_method={event_file_obj?.event_session_type_code == 'poster'
|
'oral'}
|
||||||
|
open_method={event_file_obj?.event_session_type_code ==
|
||||||
|
'poster'
|
||||||
? 'modal'
|
? 'modal'
|
||||||
: null}
|
: null}
|
||||||
modal_title={lq__event_presenter_obj?.event_presentation_name}
|
modal_title={lq__event_presenter_obj?.event_presentation_name}
|
||||||
@@ -106,7 +108,9 @@
|
|||||||
bind:modal__open_event_file_id={
|
bind:modal__open_event_file_id={
|
||||||
$events_sess.launcher.modal__open_event_file_id
|
$events_sess.launcher.modal__open_event_file_id
|
||||||
}
|
}
|
||||||
bind:modal__event_file_obj={$events_sess.launcher.modal__event_file_obj}
|
bind:modal__event_file_obj={
|
||||||
|
$events_sess.launcher.modal__event_file_obj
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -69,7 +69,9 @@
|
|||||||
let lq__event_file_obj_li = $derived(
|
let lq__event_file_obj_li = $derived(
|
||||||
liveQuery(async () => {
|
liveQuery(async () => {
|
||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log(`lq__event_file_obj: event_file_id = ${$events_slct?.event_file_id}`);
|
console.log(
|
||||||
|
`lq__event_file_obj: event_file_id = ${$events_slct?.event_file_id}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let results = await db_events.file
|
let results = await db_events.file
|
||||||
// .where('event_session_id')
|
// .where('event_session_id')
|
||||||
@@ -83,7 +85,10 @@
|
|||||||
|
|
||||||
// Check if results are different than the current $events_slct.event_file_obj_li
|
// Check if results are different than the current $events_slct.event_file_obj_li
|
||||||
if ($events_slct.event_file_obj_li && results) {
|
if ($events_slct.event_file_obj_li && results) {
|
||||||
if (JSON.stringify($events_slct.event_file_obj_li) !== JSON.stringify(results)) {
|
if (
|
||||||
|
JSON.stringify($events_slct.event_file_obj_li) !==
|
||||||
|
JSON.stringify(results)
|
||||||
|
) {
|
||||||
$events_slct.event_file_obj_li = [...results];
|
$events_slct.event_file_obj_li = [...results];
|
||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log(
|
console.log(
|
||||||
@@ -136,7 +141,10 @@
|
|||||||
.sortBy(sort_by);
|
.sortBy(sort_by);
|
||||||
// .sortBy('name')
|
// .sortBy('name')
|
||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
console.log(`lq__event_presentation_obj_li: results = `, results);
|
console.log(
|
||||||
|
`lq__event_presentation_obj_li: results = `,
|
||||||
|
results
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if results are different than the current $events_slct.event_presentation_obj_li
|
// Check if results are different than the current $events_slct.event_presentation_obj_li
|
||||||
@@ -189,7 +197,8 @@
|
|||||||
// Check if results are different than the current $events_slct.event_presenter_obj_li
|
// Check if results are different than the current $events_slct.event_presenter_obj_li
|
||||||
if ($events_slct.event_presenter_obj_li && results) {
|
if ($events_slct.event_presenter_obj_li && results) {
|
||||||
if (
|
if (
|
||||||
JSON.stringify($events_slct.event_presenter_obj_li) !== JSON.stringify(results)
|
JSON.stringify($events_slct.event_presenter_obj_li) !==
|
||||||
|
JSON.stringify(results)
|
||||||
) {
|
) {
|
||||||
$events_slct.event_presenter_obj_li = { ...results };
|
$events_slct.event_presenter_obj_li = { ...results };
|
||||||
if (log_lvl) {
|
if (log_lvl) {
|
||||||
@@ -277,9 +286,12 @@
|
|||||||
$events_loc.launcher.hide__session_datetimes}
|
$events_loc.launcher.hide__session_datetimes}
|
||||||
class="shrink event_session_datetimes"
|
class="shrink event_session_datetimes"
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
if ($events_loc.launcher.time_format == 'time_12_short') {
|
if (
|
||||||
|
$events_loc.launcher.time_format == 'time_12_short'
|
||||||
|
) {
|
||||||
// $events_loc.launcher.datetime_format = 'datetime_long';
|
// $events_loc.launcher.datetime_format = 'datetime_long';
|
||||||
$events_loc.launcher.time_format = 'time_short';
|
$events_loc.launcher.time_format = 'time_short';
|
||||||
$events_loc.launcher.time_hours = 24;
|
$events_loc.launcher.time_hours = 24;
|
||||||
@@ -319,8 +331,10 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
class:justify-between={$events_loc.launcher.hide__session_datetimes}
|
class:justify-between={$events_loc.launcher
|
||||||
class:justify-end={!$events_loc.launcher.hide__session_datetimes}
|
.hide__session_datetimes}
|
||||||
|
class:justify-end={!$events_loc.launcher
|
||||||
|
.hide__session_datetimes}
|
||||||
class="grow flex flex-row gap-2 items-center"
|
class="grow flex flex-row gap-2 items-center"
|
||||||
>
|
>
|
||||||
<h2
|
<h2
|
||||||
@@ -363,7 +377,10 @@
|
|||||||
<span class="fas fa-file-archive"></span>
|
<span class="fas fa-file-archive"></span>
|
||||||
Session Files:
|
Session Files:
|
||||||
|
|
||||||
<span class:hidden={!$ae_loc.trusted_access || !$ae_loc.edit_mode}>
|
<span
|
||||||
|
class:hidden={!$ae_loc.trusted_access ||
|
||||||
|
!$ae_loc.edit_mode}
|
||||||
|
>
|
||||||
({$lq__event_file_obj_li?.length}×)
|
({$lq__event_file_obj_li?.length}×)
|
||||||
</span>
|
</span>
|
||||||
</strong>
|
</strong>
|
||||||
@@ -384,22 +401,29 @@
|
|||||||
{#each $lq__event_file_obj_li as event_file_obj, index}
|
{#each $lq__event_file_obj_li as event_file_obj, index}
|
||||||
<li
|
<li
|
||||||
class="flex flex-row flex-wrap gap-1 items-center justify-center"
|
class="flex flex-row flex-wrap gap-1 items-center justify-center"
|
||||||
class:hidden={!$events_loc.launcher.show_content__hidden_files &&
|
class:hidden={!$events_loc.launcher
|
||||||
|
.show_content__hidden_files &&
|
||||||
event_file_obj.hide}
|
event_file_obj.hide}
|
||||||
>
|
>
|
||||||
<Event_launcher_file_cont
|
<Event_launcher_file_cont
|
||||||
event_file_id={event_file_obj.event_file_id}
|
event_file_id={event_file_obj.event_file_id}
|
||||||
{event_file_obj}
|
{event_file_obj}
|
||||||
hide_created_on={true}
|
hide_created_on={true}
|
||||||
show_bak_download={$ae_loc.trusted_access && $ae_loc.edit_mode}
|
show_bak_download={$ae_loc.trusted_access &&
|
||||||
session_type={event_file_obj?.event_session_type_code ?? 'oral'}
|
$ae_loc.edit_mode}
|
||||||
open_method={event_file_obj?.event_session_type_code == 'poster'
|
session_type={event_file_obj?.event_session_type_code ??
|
||||||
|
'oral'}
|
||||||
|
open_method={event_file_obj?.event_session_type_code ==
|
||||||
|
'poster'
|
||||||
? 'modal'
|
? 'modal'
|
||||||
: null}
|
: null}
|
||||||
modal_title={$lq__event_session_obj?.name}
|
modal_title={$lq__event_session_obj?.name}
|
||||||
bind:modal__title={$events_sess.launcher.modal__title}
|
bind:modal__title={
|
||||||
|
$events_sess.launcher.modal__title
|
||||||
|
}
|
||||||
bind:modal__open_event_file_id={
|
bind:modal__open_event_file_id={
|
||||||
$events_sess.launcher.modal__open_event_file_id
|
$events_sess.launcher
|
||||||
|
.modal__open_event_file_id
|
||||||
}
|
}
|
||||||
bind:modal__event_file_obj={
|
bind:modal__event_file_obj={
|
||||||
$events_sess.launcher.modal__event_file_obj
|
$events_sess.launcher.modal__event_file_obj
|
||||||
@@ -449,7 +473,9 @@
|
|||||||
<!-- Maybe set max with? max-w-(--breakpoint-md) -->
|
<!-- Maybe set max with? max-w-(--breakpoint-md) -->
|
||||||
<ul class="event_presentation_list max-w-full space-y-2">
|
<ul class="event_presentation_list max-w-full space-y-2">
|
||||||
{#each $lq__event_presentation_obj_li as event_presentation_obj}
|
{#each $lq__event_presentation_obj_li as event_presentation_obj}
|
||||||
<li class="border-b-2 border-gray-300 my-1 py-1 text-center md:text-left">
|
<li
|
||||||
|
class="border-b-2 border-gray-300 my-1 py-1 text-center md:text-left"
|
||||||
|
>
|
||||||
<!-- The presentation information -->
|
<!-- The presentation information -->
|
||||||
<div
|
<div
|
||||||
class="event_presentation_datetime_name flex flex-row justify-evenly gap-4"
|
class="event_presentation_datetime_name flex flex-row justify-evenly gap-4"
|
||||||
@@ -479,12 +505,17 @@
|
|||||||
class="event_presentation_single_presenter italic text-sm text-gray-500"
|
class="event_presentation_single_presenter italic text-sm text-gray-500"
|
||||||
>
|
>
|
||||||
{#if $lq__event_presenter_obj_li[index]?.given_name && $lq__event_presenter_obj_li[index]?.given_name != 'Group'}
|
{#if $lq__event_presenter_obj_li[index]?.given_name && $lq__event_presenter_obj_li[index]?.given_name != 'Group'}
|
||||||
<span class="fas fa-user"></span>
|
<span class="fas fa-user"
|
||||||
{$lq__event_presenter_obj_li[index]?.full_name}
|
></span>
|
||||||
|
{$lq__event_presenter_obj_li[
|
||||||
|
index
|
||||||
|
]?.full_name}
|
||||||
{:else if $lq__event_presenter_obj_li[index]?.given_name == 'Group'}
|
{:else if $lq__event_presenter_obj_li[index]?.given_name == 'Group'}
|
||||||
<span class="fas fa-users"></span>
|
<span class="fas fa-users"
|
||||||
{$lq__event_presenter_obj_li[index]
|
></span>
|
||||||
?.affiliations}
|
{$lq__event_presenter_obj_li[
|
||||||
|
index
|
||||||
|
]?.affiliations}
|
||||||
{:else}
|
{:else}
|
||||||
--not set--
|
--not set--
|
||||||
{/if}
|
{/if}
|
||||||
@@ -495,7 +526,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Presentation-level files -->
|
<!-- Presentation-level files -->
|
||||||
<Launcher_presentation_view lq__event_presentation_obj={event_presentation_obj} />
|
<Launcher_presentation_view
|
||||||
|
lq__event_presentation_obj={event_presentation_obj}
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- The presenter list -->
|
<!-- The presenter list -->
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,9 @@
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!event_location_id) {
|
if (!event_location_id) {
|
||||||
console.warn(`handle_load_ae_obj_li__event_session: No event_location_id provided.`);
|
console.warn(
|
||||||
|
`handle_load_ae_obj_li__event_session: No event_location_id provided.`
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,8 +86,12 @@
|
|||||||
inc_all_file_li: false, // Also include files under presentations and presenters as well?
|
inc_all_file_li: false, // Also include files under presentations and presenters as well?
|
||||||
inc_presentation_li: true,
|
inc_presentation_li: true,
|
||||||
inc_presenter_li: true,
|
inc_presenter_li: true,
|
||||||
enabled: $events_loc.launcher.show_content__enabled_sessions ? 'all' : 'enabled',
|
enabled: $events_loc.launcher.show_content__enabled_sessions
|
||||||
hidden: $events_loc.launcher.show_content__hidden_sessions ? 'all' : 'not_hidden',
|
? 'all'
|
||||||
|
: 'enabled',
|
||||||
|
hidden: $events_loc.launcher.show_content__hidden_sessions
|
||||||
|
? 'all'
|
||||||
|
: 'not_hidden',
|
||||||
limit: 49,
|
limit: 49,
|
||||||
try_cache: true,
|
try_cache: true,
|
||||||
log_lvl: 1
|
log_lvl: 1
|
||||||
@@ -126,7 +132,9 @@
|
|||||||
<div class="text-xs text-surface-600-400">
|
<div class="text-xs text-surface-600-400">
|
||||||
<strong>
|
<strong>
|
||||||
Location:
|
Location:
|
||||||
<span class:hidden={!$ae_loc.trusted_access || !$ae_loc.edit_mode}>
|
<span
|
||||||
|
class:hidden={!$ae_loc.trusted_access || !$ae_loc.edit_mode}
|
||||||
|
>
|
||||||
({$lq__event_location_obj_li?.length}×)
|
({$lq__event_location_obj_li?.length}×)
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@@ -161,11 +169,14 @@
|
|||||||
if (slct_event_location_id) {
|
if (slct_event_location_id) {
|
||||||
loading__session_li_status = 'loading';
|
loading__session_li_status = 'loading';
|
||||||
|
|
||||||
$events_loc.launcher.slct.event_location_id = slct_event_location_id;
|
$events_loc.launcher.slct.event_location_id =
|
||||||
|
slct_event_location_id;
|
||||||
$events_slct.event_location_id = slct_event_location_id;
|
$events_slct.event_location_id = slct_event_location_id;
|
||||||
|
|
||||||
// Load the sessions for this location
|
// Load the sessions for this location
|
||||||
await handle_load_ae_obj_li__event_session(slct_event_location_id);
|
await handle_load_ae_obj_li__event_session(
|
||||||
|
slct_event_location_id
|
||||||
|
);
|
||||||
|
|
||||||
new_url = `/events/${$events_slct.event_id}/launcher/${slct_event_location_id}`;
|
new_url = `/events/${$events_slct.event_id}/launcher/${slct_event_location_id}`;
|
||||||
|
|
||||||
@@ -188,7 +199,9 @@
|
|||||||
goto(new_url, { replaceState: false }); // Updates the URL history without reloading the page
|
goto(new_url, { replaceState: false }); // Updates the URL history without reloading the page
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<option value="" class="italic text-surface-800-200"> -- select -- </option>
|
<option value="" class="italic text-surface-800-200">
|
||||||
|
-- select --
|
||||||
|
</option>
|
||||||
{#each $lq__event_location_obj_li as event_location_obj}
|
{#each $lq__event_location_obj_li as event_location_obj}
|
||||||
<option value={event_location_obj?.id}>
|
<option value={event_location_obj?.id}>
|
||||||
{event_location_obj?.name}
|
{event_location_obj?.name}
|
||||||
|
|||||||
@@ -78,12 +78,18 @@
|
|||||||
// BEFORE calling goto. This triggers the LiveQuery in the layout instantly.
|
// BEFORE calling goto. This triggers the LiveQuery in the layout instantly.
|
||||||
slct__event_session_id = event_session_id;
|
slct__event_session_id = event_session_id;
|
||||||
|
|
||||||
if (log_lvl) console.log(`[UI Trace] UI setting slct__event_session_id = ${slct__event_session_id} (+${(performance.now() - start).toFixed(2)}ms)`);
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`[UI Trace] UI setting slct__event_session_id = ${slct__event_session_id} (+${(performance.now() - start).toFixed(2)}ms)`
|
||||||
|
);
|
||||||
|
|
||||||
handle_load_ae_obj_id__event_session(event_session_id);
|
handle_load_ae_obj_id__event_session(event_session_id);
|
||||||
|
|
||||||
if ($events_loc.launcher.controller == 'local_push') {
|
if ($events_loc.launcher.controller == 'local_push') {
|
||||||
if (log_lvl) console.log(`[UI Trace] Local Push Controller Command: ae_load:event_session=${event_session_id}`);
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`[UI Trace] Local Push Controller Command: ae_load:event_session=${event_session_id}`
|
||||||
|
);
|
||||||
$events_sess.launcher.controller_cmd = `ae_load:event_session=${event_session_id}`;
|
$events_sess.launcher.controller_cmd = `ae_load:event_session=${event_session_id}`;
|
||||||
$events_sess.launcher.controller_trigger_send = true;
|
$events_sess.launcher.controller_trigger_send = true;
|
||||||
}
|
}
|
||||||
@@ -91,11 +97,21 @@
|
|||||||
data_url.searchParams.set('session_id', event_session_id);
|
data_url.searchParams.set('session_id', event_session_id);
|
||||||
|
|
||||||
let new_url = data_url.toString();
|
let new_url = data_url.toString();
|
||||||
if (log_lvl) console.log(`[UI Trace] Initiating SvelteKit goto... (+${(performance.now() - start).toFixed(2)}ms)`);
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`[UI Trace] Initiating SvelteKit goto... (+${(performance.now() - start).toFixed(2)}ms)`
|
||||||
|
);
|
||||||
|
|
||||||
// Use noscroll and keepfocus to speed up the transition
|
// Use noscroll and keepfocus to speed up the transition
|
||||||
goto(new_url, { replaceState: false, noscroll: true, keepfocus: true }).then(() => {
|
goto(new_url, {
|
||||||
if (log_lvl) console.log(`🏁 [Trace] Total Navigation Roundtrip: ${(performance.now() - start).toFixed(2)}ms`);
|
replaceState: false,
|
||||||
|
noscroll: true,
|
||||||
|
keepfocus: true
|
||||||
|
}).then(() => {
|
||||||
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`🏁 [Trace] Total Navigation Roundtrip: ${(performance.now() - start).toFixed(2)}ms`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -121,12 +137,17 @@
|
|||||||
log_lvl: log_lvl
|
log_lvl: log_lvl
|
||||||
})
|
})
|
||||||
.then(async (load_results) => {
|
.then(async (load_results) => {
|
||||||
if (log_lvl) console.log(`[UI Trace] handle_load_ae_obj_id: Library returned results in ${(performance.now() - start).toFixed(2)}ms.`);
|
if (log_lvl)
|
||||||
|
console.log(
|
||||||
|
`[UI Trace] handle_load_ae_obj_id: Library returned results in ${(performance.now() - start).toFixed(2)}ms.`
|
||||||
|
);
|
||||||
|
|
||||||
if (load_results) {
|
if (load_results) {
|
||||||
$events_slct.event_session_obj = load_results;
|
$events_slct.event_session_obj = load_results;
|
||||||
$events_slct.event_file_obj_li = load_results.event_file_li ?? [];
|
$events_slct.event_file_obj_li =
|
||||||
$events_slct.event_presentation_obj_li = load_results.event_presentation_li ?? [];
|
load_results.event_file_li ?? [];
|
||||||
|
$events_slct.event_presentation_obj_li =
|
||||||
|
load_results.event_presentation_li ?? [];
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -145,7 +166,9 @@
|
|||||||
<div class="text-xs text-surface-600-400">
|
<div class="text-xs text-surface-600-400">
|
||||||
<strong>
|
<strong>
|
||||||
Sessions:
|
Sessions:
|
||||||
<span class:hidden={!$ae_loc.trusted_access || !$ae_loc.edit_mode}>
|
<span
|
||||||
|
class:hidden={!$ae_loc.trusted_access || !$ae_loc.edit_mode}
|
||||||
|
>
|
||||||
({$lq__event_session_obj_li?.length}×)
|
({$lq__event_session_obj_li?.length}×)
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@@ -177,22 +200,28 @@
|
|||||||
transition-all
|
transition-all
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<button type="button"
|
<button
|
||||||
|
type="button"
|
||||||
onmouseenter={() => {
|
onmouseenter={() => {
|
||||||
// Start a 750 ms timer to prevent changing the session too quickly.
|
// Start a 750 ms timer to prevent changing the session too quickly.
|
||||||
hover_timer = setTimeout(async () => {
|
hover_timer = setTimeout(async () => {
|
||||||
// Only run if the session ID has changed
|
// Only run if the session ID has changed
|
||||||
if (slct__event_session_id === event_session_obj?.id) {
|
if (
|
||||||
|
slct__event_session_id ===
|
||||||
|
event_session_obj?.id
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trigger_reload__event_session_obj_id = event_session_obj?.id;
|
trigger_reload__event_session_obj_id =
|
||||||
|
event_session_obj?.id;
|
||||||
}, hover_timer_wait);
|
}, hover_timer_wait);
|
||||||
}}
|
}}
|
||||||
onmouseleave={() => {
|
onmouseleave={() => {
|
||||||
clearTimeout(hover_timer);
|
clearTimeout(hover_timer);
|
||||||
}}
|
}}
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
trigger_reload__event_session_obj_id = event_session_obj?.id;
|
trigger_reload__event_session_obj_id =
|
||||||
|
event_session_obj?.id;
|
||||||
|
|
||||||
$events_slct.event_file_id = null;
|
$events_slct.event_file_id = null;
|
||||||
$events_slct.event_file_obj = null;
|
$events_slct.event_file_obj = null;
|
||||||
@@ -216,9 +245,12 @@
|
|||||||
event_session_obj?.id}
|
event_session_obj?.id}
|
||||||
class:preset-tonal-secondary={slct__event_session_id !=
|
class:preset-tonal-secondary={slct__event_session_id !=
|
||||||
event_session_obj?.id}
|
event_session_obj?.id}
|
||||||
class:border-secondary-500={slct__event_session_id != event_session_obj?.id}
|
class:border-secondary-500={slct__event_session_id !=
|
||||||
class:font-bold={slct__event_session_id === event_session_obj?.id}
|
event_session_obj?.id}
|
||||||
class:hidden={!$events_loc.launcher.show_content__hidden_sessions &&
|
class:font-bold={slct__event_session_id ===
|
||||||
|
event_session_obj?.id}
|
||||||
|
class:hidden={!$events_loc.launcher
|
||||||
|
.show_content__hidden_sessions &&
|
||||||
event_session_obj?.hide}
|
event_session_obj?.hide}
|
||||||
class:dim={event_session_obj?.hide}
|
class:dim={event_session_obj?.hide}
|
||||||
title={`Session: ${event_session_obj?.name}\nID: ${event_session_obj?.id} | ${ae_util.iso_datetime_formatter(event_session_obj?.start_datetime, $events_loc.launcher.time_format)}`}
|
title={`Session: ${event_session_obj?.name}\nID: ${event_session_obj?.id} | ${ae_util.iso_datetime_formatter(event_session_obj?.start_datetime, $events_loc.launcher.time_format)}`}
|
||||||
@@ -226,7 +258,9 @@
|
|||||||
<!-- hover:scale-115 -->
|
<!-- hover:scale-115 -->
|
||||||
<!-- hover:z-index-10 -->
|
<!-- hover:z-index-10 -->
|
||||||
|
|
||||||
<span class="border-r border-surface-400-600 pr-1 min-w-28">
|
<span
|
||||||
|
class="border-r border-surface-400-600 pr-1 min-w-28"
|
||||||
|
>
|
||||||
{#if slct__event_session_id === event_session_obj?.id}
|
{#if slct__event_session_id === event_session_obj?.id}
|
||||||
<span class="fas fa-calendar-check"></span>
|
<span class="fas fa-calendar-check"></span>
|
||||||
{:else}
|
{:else}
|
||||||
@@ -234,7 +268,8 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<span
|
<span
|
||||||
class="text-xs"
|
class="text-xs"
|
||||||
class:hidden={slct__event_session_id === event_session_obj?.id}
|
class:hidden={slct__event_session_id ===
|
||||||
|
event_session_obj?.id}
|
||||||
>
|
>
|
||||||
{ae_util.iso_datetime_formatter(
|
{ae_util.iso_datetime_formatter(
|
||||||
event_session_obj?.start_datetime,
|
event_session_obj?.start_datetime,
|
||||||
|
|||||||
Reference in New Issue
Block a user