Quickly saving lots of changes before they might be lost.

This commit is contained in:
Scott Idem
2025-11-20 15:45:00 -05:00
parent 064942c647
commit 8223b964e1
30 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,509 @@
<script lang="ts">
interface Props {
/** @type {import('./$types').PageData} */
data: any;
log_lvl?: number;
}
let { data, log_lvl = 0 }: Props = $props();
// Imports (external and then internal)
import { browser } from '$app/environment';
import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import Element_data_store from '$lib/elements/element_data_store_v2.svelte';
import { liveQuery } from 'dexie';
import { Modal } from 'flowbite-svelte';
// import { core_func } from '$lib/ae_core_functions';
import { db_events } from '$lib/ae_events/db_events';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
import {
events_loc,
events_sess,
events_slct,
events_trigger
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import Comp_event_files_upload from '../../../ae_comp__event_files_upload.svelte';
import Element_manage_event_file_li_wrap from '$lib/elements/element_manage_event_file_li_direct.svelte';
import Comp_event_presenter_form_agree from './ae_comp__event_presenter_form_agree.svelte';
import Presenter_view from './presenter_view.svelte';
import Presenter_page_menu from './presenter_page_menu.svelte';
import MyClipboard from '$lib/app_components/e_app_clipboard.svelte';
// Exports
// export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher'
// Variables
// Quickly save the data passed from the parent(s) to the Svelte stores, localStorage, and other.
// $slct.account_id = data.account_id;
let ae_acct = data[$slct.account_id];
if (log_lvl) {
console.log(`ae_acct = `, ae_acct);
}
$ae_loc.url_origin = data.url.origin;
$events_slct.event_presenter_id = ae_acct.slct.event_presenter_id;
// $events_slct.event_presenter_obj = ae_acct.slct.event_presenter_obj;
$events_slct.event_file_obj_li = ae_acct.slct.event_file_obj_li;
$events_sess.pres_mgmt.show_modal__presenter_agree = false;
$events_sess.pres_mgmt.show_content__presenter_start = false;
let lq__event_obj = $derived(
liveQuery(async () => {
let results = await db_events.event.get(ae_acct.slct.event_id);
return results;
})
);
let lq__event_presenter_obj = $derived(
liveQuery(async () => {
let results = await db_events.presenter.get(ae_acct.slct.event_presenter_id);
return results;
})
);
let lq__event_presentation_obj = $derived(
liveQuery(async () => {
let results = await db_events.presentation.get(ae_acct.slct.event_presentation_id);
return results;
})
);
let lq__auth__event_presenter_obj = $derived(
liveQuery(async () => {
let results = await db_events.presenter.get(
$events_loc.auth__person?.presenter_id ?? null
);
return results;
})
);
// if (browser && $lq__event_presenter_obj) {
// console.log('Pres Mgmt [page]: +presenter.svelte');
// $events_slct.event_presenter_obj = $lq__event_presenter_obj;
// console.log(`$events_slct.event_presenter_obj = `, $events_slct.event_presenter_obj);
// }
// *** Functions and Logic
</script>
<svelte:head>
<title>
Presenter: {ae_util.shorten_string({
string: $lq__event_presenter_obj?.full_name,
max_length: 20,
begin_length: 10,
end_length: 4
})}
({$lq__event_presenter_obj?.event_presenter_id ?? 'loading...'}) - Pres Mgmt - {$events_loc?.title}
</title>
</svelte:head>
<section
class="
ae_events_pres_mgmt_event_presenter
md:container
flex flex-col gap-1
items-center
justify-start
mx-auto
py-1 px-2 pb-16
h-full
min-w-full
max-w-max
"
>
<Presenter_page_menu {data} {lq__event_obj} {lq__event_presenter_obj} />
{#if !$lq__event_presenter_obj}
<div>
<span class="fas fa-spinner fa-spin mx-1"></span>
<span>Loading presenter information...</span>
</div>
{:else if $lq__event_presenter_obj?.enable || $ae_loc.trusted_access}
<header class="ae_module_header">
<span class="flex flex-row flex-wrap gap-1 items-center justify-center">
<span class="fas fa-user m-1 text-neutral-800/80"></span>
<!-- Button to toggle between the regular presenter view and managing presenter files -->
<button
type="button"
onclick={() => {
if ($events_loc.pres_mgmt.show_content__presenter_view == 'manage_files') {
$events_loc.pres_mgmt.show_content__presenter_view = null;
} else {
$events_loc.pres_mgmt.show_content__presenter_view = 'manage_files';
}
}}
class="btn btn-md hover:preset-filled-secondary-500"
class:preset-filled-secondary-500={$events_loc.pres_mgmt
.show_content__presenter_view == 'manage_files'}
class:preset-filled-tertiary-500={$events_loc.pres_mgmt
.show_content__presenter_view != 'manage_files'}
class:hidden={!$ae_loc.authenticated_access}
title="View presenter information or manage files for the presenter"
>
{#if $events_loc.pres_mgmt.show_content__presenter_view == 'manage_files'}
<span class="fas fa-info m-1"></span>
<!-- View Details -->
Presenter Info?
{:else}
<span class="fas fa-file-archive m-1"></span>
Presenter Files?
<span
class="badge preset-tonal-success"
class:hidden={!$lq__event_presenter_obj?.file_count}
>
<!-- absolute -top-1.5 -right-1.5 z-10 -->
<span class="fas fa-file-alt m-1"></span>
{$lq__event_presenter_obj?.file_count}×
</span>
{/if}
</button>
</span>
<!-- <span class="grow flex flex-row flex-wrap gap-1 items-center justify-around"> -->
<h2
class="text-2xl font-bold text-center max-w-xs sm:max-w-lg md:max-w-2xl"
title="{$lq__event_presenter_obj?.full_name} ID: {$lq__event_presenter_obj?.event_presenter_id}"
>
{@html $lq__event_presenter_obj?.full_name ?? ae_snip.html__not_set}
<!-- <span class="text-sm text-gray-600 dark:text-gray-400">
Presenter ID: {$lq__event_presenter_obj?.event_presenter_id}
</span> -->
</h2>
<span class="flex flex-col gap-0.25 items-end justify-center font-normal">
<span class="text-sm text-gray-600 dark:text-gray-400">
{#if !$ae_loc.trusted_access && !$events_loc.auth__kv.presenter[$lq__event_presenter_obj?.event_presenter_id] && !$events_loc.auth__kv.session[$lq__event_presenter_obj.event_session_id]}
<!-- Only show the domain name of the email address. -->
<!-- ( -->
<!-- {$lq__event_presenter_obj.email.replace(/@.*$/, '@...')} -->
<!-- {$lq__event_presenter_obj.person_primary_email.substring(0, 1) + '...@example.com'} -->
<!-- ) -->
<!-- {@html $lq__event_presenter_obj?.person_primary_email ? $lq__event_presenter_obj?.person_primary_email.replace(/^(.{3}).*@/, '$1...@') : 'email'+ae_snip.html__not_set} -->
<!-- ) -->
Not signed in as presenter
{#if $lq__event_presenter_obj?.person_primary_email}
({$lq__event_presenter_obj.person_primary_email.replace(
/^(.{3}).*@/,
'$1...@'
)})
{:else}
<!-- email
{ae_snip.html__not_set} -->
{/if}
{:else}
({@html $lq__event_presenter_obj?.person_primary_email &&
$lq__event_presenter_obj?.person_primary_email.length
? $lq__event_presenter_obj?.person_primary_email
: 'email ' + ae_snip.html__not_set})
{/if}
</span>
<span class="flex flex-row flex-wrap gap-0.25 items-center justify-center">
{#if $lq__event_presenter_obj.person_id && $ae_loc.trusted_access}
<!-- A button to copy the access link to the clipboard. -->
<!-- Example: /events/CHs3F44Xq76/session/Wh8UnJlbIA0?person_id=fV1dl_IJ0yY&person_pass=abc123 -->
<!-- {#snippet btn_text()}
<span class="fas fa-copy m-1"></span>
Copy Access Link
{/snippet} -->
<MyClipboard
value={encodeURI(
`${$ae_loc.url_origin}/events/${$lq__event_presenter_obj.event_id}/session/${$lq__event_presenter_obj.event_session_id}?person_id=${$lq__event_presenter_obj.person_id}&person_pass=${$lq__event_presenter_obj.person_passcode}&presentation_id=${$lq__event_presenter_obj?.event_presentation_id}&presenter_id=${$lq__event_presenter_obj?.event_presenter_id}`
)}
btn_text="Copy Access Link"
btn_title="Copy the presenter access link to the clipboard."
btn_class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500 border border-warning-500 hover:preset-filled-warning-500"
></MyClipboard>
{/if}
{#if $events_loc.pres_mgmt?.require__presenter_agree && $events_loc?.pres_mgmt?.show__email_access_link && $lq__event_presenter_obj?.person_primary_email && ($ae_loc.public_access || !$events_loc.auth__person?.id)}
<button
type="button"
onclick={() => {
console.log('Email the access link');
if (!$lq__event_presenter_obj.person_primary_email) {
alert('No email address found for this presenter.');
return;
}
if (
confirm(
`This will send the sign in email to ${$lq__event_presenter_obj.person_primary_email}`
)
) {
console.log('Send the email to the presenter.');
} else {
console.log('Cancelled sending the email.');
return false;
}
events_func.email_sign_in__event_presenter({
api_cfg: $ae_api,
to_email: $lq__event_presenter_obj?.person_primary_email,
to_name: $lq__event_presenter_obj?.full_name ?? '-- not set --',
base_url: $ae_loc.url_origin,
person_id: $lq__event_presenter_obj?.person_id,
person_passcode:
$lq__event_presenter_obj?.person_passcode ??
'-- not set --',
event_id: $lq__event_presenter_obj?.event_id,
event_session_id: $lq__event_presenter_obj?.event_session_id,
event_presentation_id:
$lq__event_presenter_obj?.event_presentation_id,
event_presenter_id:
$lq__event_presenter_obj?.event_presenter_id,
session_name:
$lq__event_presenter_obj?.event_session_name ??
'-- not set --',
presentation_name:
$lq__event_presenter_obj?.event_presentation_name ??
'-- not set --'
});
}}
class="btn btn-sm preset-tonal-secondary border border-secondary-500 hover:preset-filled-secondary-500 m-0.25"
title="Email the access link to the presenter"
>
<span class="fas fa-envelope m-1"></span>
Email Access Link
</button>
{/if}
</span>
</span>
</header>
{#if !$events_loc.pres_mgmt.show_content__presenter_view || ($events_loc.pres_mgmt.show_content__presenter_view == 'default' && $lq__event_presenter_obj)}
<Presenter_view {lq__event_presenter_obj} {lq__event_presentation_obj} />
{#if $ae_loc.trusted_access || $lq__auth__event_presenter_obj?.agree}
<div class="m-1 flex flex-col flex-wrap gap-1 items-center justify-center w-full">
<!-- Message if they have agreed -->
<Element_data_store
ds_code="events__pres_mgmt__session_page_authorized_info"
ds_name="Default: Events - Pres Mgmt Session Authorized Info"
ds_type="html"
for_type="event"
for_id={$lq__event_presenter_obj?.event_id}
class_li="w-fit max-w-(--breakpoint-lg) flex flex-row gap-1"
show_edit={false}
show_edit_btn={true}
mount_reload_sec={1}
/>
</div>
{/if}
<h3 class="h5 text-center">
<span class="fas fa-tasks m-1 text-neutral-800/80"></span>
<span class="fas fa-mail-bulk m-1 text-neutral-800/80"></span>
Manage and Upload Presenter Files
<span
class="badge preset-tonal-success"
class:hidden={!$lq__event_presenter_obj?.file_count}
>
<span class="fas fa-file-alt m-1"></span>
{$lq__event_presenter_obj?.file_count}×
</span>
</h3>
<!-- Yes... This is a duplicate of what is shown when they press "Presenter Files" button. It can be cleaned up later. -->
{#if $ae_loc.trusted_access || $events_loc.auth__kv.presenter[$lq__event_presenter_obj?.event_presenter_id]}
<Comp_event_files_upload
class_li="border border-gray-300 rounded-md p-2 bg-gray-100 hover:bg-gray-200"
link_to_type="event_presenter"
link_to_id={$lq__event_presenter_obj?.event_presenter_id}
>
{#snippet label()}
<span>
<div class="text-lg">
<span class="fas fa-upload"></span>
<strong class="">Upload presenter (speaker) specific files</strong>
</div>
<div class="text-sm text-gray-600 dark:text-gray-400 italic">
<strong>Presenter (speaker) presentation files only</strong><br />
Recommended: PowerPoint (pptx) or Keynote (key)<br />
Media: Audio and videos files should be directly embedded in PowerPoint
(PPTX) files<br />
Supplemental files: mp4, PDF, Word Doc, Excel, txt, etc
</div>
</span>
{/snippet}
</Comp_event_files_upload>
{/if}
<div class="overflow-x-auto w-max max-w-full">
<Element_manage_event_file_li_wrap
link_to_type={'event_presenter'}
link_to_id={$lq__event_presenter_obj?.event_presenter_id}
allow_basic={$events_loc.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
] ||
$events_loc.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
allow_moderator={$events_loc.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
container_class_li={''}
/>
</div>
{:else if $events_loc.pres_mgmt.show_content__presenter_view == 'manage_files' && $ae_loc.authenticated_access}
<div>
<h3 class="h5 text-center">
<span class="fas fa-tasks m-1 text-neutral-800/80"></span>
<span class="fas fa-mail-bulk m-1 text-neutral-800/80"></span>
Manage and Upload Presenter Files
<span
class="badge preset-tonal-success"
class:hidden={!$lq__event_presenter_obj?.file_count}
>
<span class="fas fa-file-alt m-1"></span>
{$lq__event_presenter_obj?.file_count}×
</span>
</h3>
{#if $ae_loc.public_access || $events_loc.auth__kv.presenter[$lq__event_presenter_obj?.event_presenter_id]}
<Comp_event_files_upload
class_li="border border-gray-300 rounded-md p-2 bg-gray-100 hover:bg-gray-200"
link_to_type="event_presenter"
link_to_id={$lq__event_presenter_obj.event_presenter_id}
>
{#snippet label()}
<span>
<div class="text-lg">
<span class="fas fa-upload"></span>
<strong class=""
>Upload presenter (speaker) specific files</strong
>
</div>
<div class="text-sm text-gray-600 dark:text-gray-400 italic">
<strong>Presentation related files only</strong><br />
Recommended: PowerPoint (pptx) or Keynote (key)<br />
Media: Audio and videos files should be directly embedded in PowerPoint
(PPTX) files<br />
Supplemental files: mp4, PDF, Word Doc, Excel, txt, etc
</div>
</span>
{/snippet}
</Comp_event_files_upload>
{/if}
<div class="overflow-x-auto w-max max-w-full">
<Element_manage_event_file_li_wrap
link_to_type={'event_presenter'}
link_to_id={$lq__event_presenter_obj?.event_presenter_id}
allow_basic={$ae_loc.public_access ||
$events_loc.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
allow_moderator={$events_loc.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id
]}
container_class_li={''}
/>
</div>
</div>
<!-- Show message if the presenter has agreed -->
<!-- {#if
($ae_loc.trusted_access ||
$lq__auth__event_presenter_obj?.agree)
}
<div class="m-1 flex flex-col flex-wrap gap-1 items-center justify-center w-full">
<Element_data_store
ds_code="events__pres_mgmt__session_page_authorized_info"
ds_name="Default: Events - Pres Mgmt Session Authorized Info"
ds_type="html"
for_type="event"
for_id={$lq__event_presenter_obj?.event_id}
class_li="w-fit max-w-(--breakpoint-lg) flex flex-row gap-1"
show_edit={false}
show_edit_btn={true}
mount_reload_sec={1}
/>
</div>
{/if} -->
{/if}
{:else}
<div class="bg-red-100 p-4 border border-red-200 rounded-md">
<h2 class="h3">
<span class="fas fa-exclamation-triangle text-red-500 m-1"></span>
Presenter Disabled
</h2>
<p>
This presenter is currently disabled. Please contact the event organizer for more
information.
</p>
</div>
{/if}
</section>
<!-- Main modal -->
<Modal
title="{$lq__event_presenter_obj?.full_name} Presenter Consent and Release and Terms and Conditions"
bind:open={$events_sess.pres_mgmt.show_modal__presenter_agree}
autoclose={false}
placement="top-center"
class="bg-white dark:bg-gray-800 text-gray-800 dark:text-gray-200 rounded-lg border-gray-200 dark:border-gray-700 divide-gray-200 dark:divide-gray-700 shadow-md relative flex flex-col mx-auto w-full divide-y"
>
<Comp_event_presenter_form_agree {lq__event_presenter_obj} />
{#snippet footer()}
<div class="text-center w-full">
<button
onclick={() => {
$events_sess.pres_mgmt.show_modal__presenter_agree = false;
}}
class="btn btn-sm preset-tonal-warning hover:preset-tonal-warning border border-warning-500"
>
<span class="fas fa-times m-1"></span>
Close
</button>
</div>
{/snippet}
</Modal>
<style lang="postcss">
/* Use the div.ae_quick_modal_container to block background clicks when ung the section.ae_quick_popover. */
/* div.ae_quick_modal_container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
background-color: hsla(0, 0%, 50%, .75);
} */
/* The section.ae_quick_popover should be above the rest of the content and centered on the page. */
/* section.ae_quick_popover {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 100;
background-color: hsla(0, 0%, 97%, .97);
border: solid thin hsla(0, 0%, 0%, .9);
border-radius: .5rem;
box-shadow: 0 0 1rem hsla(0, 0%, 0%, .5);
min-height: 30%;
min-width: 80%;
} */
</style>

View File

@@ -0,0 +1,65 @@
/** @type {import('./$types').PageLoad} */
console.log(`ae_p_event_presenter [presenter_id] +page.ts: start`);
import { browser } from '$app/environment';
import { events_func } from '$lib/ae_events_functions';
export async function load({ params, parent }) {
// route
const log_lvl: number = 0;
const data = await parent();
// console.log(`ae events_pres_mgmt presenter [presenter_id] +page.ts data:`, data);
data.log_lvl = log_lvl;
const account_id = data.account_id;
const ae_acct = data[account_id];
// console.log(`ae_acct = `, ae_acct);
const event_presenter_id = params.presenter_id;
// if (!event_presenter_id) {
// console.log(`ae events_pres_mgmt presenter [presenter_id] +page.ts: The event_presenter_id was not found in the params.presenter_id!!!`);
// return false;
// }
ae_acct.slct.event_presenter_id = event_presenter_id;
if (browser) {
// Load event presenter object
const load_event_presenter_obj = events_func.load_ae_obj_id__event_presenter({
api_cfg: ae_acct.api,
event_presenter_id: event_presenter_id,
try_cache: true,
log_lvl: log_lvl
});
ae_acct.slct.event_presenter_obj = await load_event_presenter_obj;
// Load event files for the presenter
const load_event_file_obj_li = await events_func
.load_ae_obj_li__event_file({
api_cfg: ae_acct.api,
for_obj_type: 'event_presenter',
for_obj_id: event_presenter_id,
enabled: 'all',
hidden: 'all',
limit: 50,
try_cache: true
})
.then((event_file_obj_li) => {
if (log_lvl) {
console.log(`event_file_obj_li = `, event_file_obj_li);
}
return event_file_obj_li;
});
if (log_lvl) {
console.log(`load_event_file_obj_li = `, load_event_file_obj_li);
}
ae_acct.slct.event_file_obj_li = load_event_file_obj_li;
}
// WARNING: Precaution against shared data between sites and presentations.
data[account_id] = ae_acct;
return data;
}

View File

@@ -0,0 +1,426 @@
<script lang="ts">
interface Props {
// export let event_presenter_id: string;
lq__event_presenter_obj: any;
// export let lq__event_session_obj: any;
log_lvl?: number;
}
let { lq__event_presenter_obj, log_lvl = 0 }: Props = $props();
console.log(`ae_events_pres_mgmt session [slug] form_agree.svelte`);
// Imports (external and then internal)
// import { onMount } from 'svelte';
// import { liveQuery } from "dexie";
import type { key_val } from '$lib/stores/ae_stores';
import { ae_util } from '$lib/ae_utils/ae_utils';
import { api } from '$lib/api/api';
import Element_data_store from '$lib/elements/element_data_store_v2.svelte';
// import Element_ae_crud from '$lib/element_ae_crud.svelte';
import { ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger } from '$lib/stores/ae_stores';
// import { db_events } from "$lib/db_events";
import {
events_loc,
events_sess,
events_slct,
events_trigger
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
let ae_promises: key_val = $state({});
// let ae_tmp: key_val = {};
// let ae_triggers: key_val = {};
$events_sess.pres_mgmt.disable_submit__opt_out = false;
let tmp_agree = false;
let tmp_opt_out: key_val = {
audio: false,
video: false,
transcription_and_publication: false,
publication_in_app: false
};
// *** Functions and Logic
function preventDefault<T extends Event>(fn: (event: T) => void) {
return function (event: T) {
event.preventDefault();
fn(event);
};
}
async function handle_submit_form(event) {
console.log('*** handle_submit_form() ***');
$events_sess.pres_mgmt.disable_submit__opt_out = true;
$events_sess.pres_mgmt.submit_status = 'saving';
// Data in
let form_data = new FormData(event.target);
console.log(form_data);
let opt_out_di: key_val = ae_util.extract_prefixed_form_data({
prefix: null,
form_data: form_data,
trim_values: true,
bool_tf_str: true,
log_lvl: 0
});
console.log(`opt_out_di:`, opt_out_di);
// Data out
let opt_out_do: key_val = {};
opt_out_do.optout_audio = opt_out_di.optout_audio ?? false;
opt_out_do.optout_video = opt_out_di.optout_video ?? false;
opt_out_do.optout_transcription_and_publication =
opt_out_di.optout_transcription_and_publication ?? false;
opt_out_do.optout_publication_in_app = opt_out_di.optout_publication_in_app ?? false;
opt_out_do.optout_updated_on = new Date().toISOString();
console.log(`opt_out_do:`, opt_out_do);
let data_out = {
data_json: {
...$lq__event_presenter_obj.data_json,
...opt_out_do
}
};
ae_promises.update__event_presenter_obj = await handle_update__event_presenter({
obj_type: 'event_presenter',
obj_id: $lq__event_presenter_obj?.event_presenter_id_random,
data: data_out
});
console.log(ae_promises.update__event_presenter_obj);
$events_sess.pres_mgmt.disable_submit__opt_out = false;
$events_sess.pres_mgmt.submit_status = 'saved';
}
async function handle_update__event_presenter({ obj_type, obj_id, data }) {
console.log('*** handle_update__event_presenter() ***');
ae_promises.update__event_presenter_obj = api
.update_ae_obj_id_crud({
api_cfg: $ae_api,
obj_type: obj_type,
obj_id: obj_id,
fields: data,
key: $ae_api.api_crud_super_key,
return_obj: true,
log_lvl: log_lvl
})
.then(async function (update__obj_result) {
if (!update__obj_result) {
console.log('The result was null or false.');
return false;
} else {
console.log(`update__obj_result = `, update__obj_result);
}
$slct_trigger = 'load__event_presenter_obj_li';
return update__obj_result;
})
.catch(function (error: any) {
console.log('Something went wrong.');
console.log(error);
return false;
});
return ae_promises.update__event_presenter_obj;
}
</script>
{#if $lq__event_presenter_obj}
<h2 class="h3">
<span class="text-base">Presenter Agreement for:</span><br />
<strong
>{$lq__event_presenter_obj?.full_name}
{#if $lq__event_presenter_obj?.person_primary_email}
({$lq__event_presenter_obj?.person_primary_email ?? '-- not set --'})
{/if}
</strong>
</h2>
{#if !$lq__event_presenter_obj?.agree}
<div class="text-center text-red-500">
<div class="text-red-500">
<span class="fas fa-times text-red-500 m-1"></span>
Not Yet Agreed
</div>
<div class="bg-red-100 p-4 border border-red-200 rounded-md">
Waiting for agreement to the Guest Speaker Consent and Release and Terms and
Conditions before you can move on. Please review and mark as agreed below.
</div>
</div>
{/if}
<div class="bg-gray-100 p-4 border border-gray-200 rounded-md space-y-4">
<Element_data_store ds_code="event_presenter_agree_text" ds_type="html" class_li="p-2" />
</div>
<section class="text-lg border border-red-200 rounded-md bg-red-100 space-y-2">
<!-- Highlight the persons name, email, and that whole line. -->
<p class="text-lg bg-yellow-100 p-2">
<strong>{$lq__event_presenter_obj.full_name} ({$lq__event_presenter_obj.email})</strong>
agrees to the following terms and conditions for the presentation:
</p>
<h3 class="h4 text-center">
<span class="text-base">Presentation:</span>
"{$lq__event_presenter_obj?.event_presentation_name}"
</h3>
<div class="w-full">
<h3 class="h4 text-center">Opt-Out?</h3>
<form
class="modal-form {$ae_loc.hub.classes__form}"
onsubmit={preventDefault(handle_submit_form)}
>
<p>
Speaker does not permit the use of presentation materials as described in
section(s), above for: (please check for all that apply)
</p>
<label
class="label p-1 hover:preset-tonal-warning border border-warning-500 rounded-md"
for="optout_audio"
>
<input
type="checkbox"
class="checkbox preset-tonal-warning border border-warning-500 checked:preset-filled-warning-500 hover:preset-filled-error-500"
id="optout_audio"
name="optout_audio"
checked={$lq__event_presenter_obj.data_json?.optout_audio}
value={true}
/>
Opt-out - Audio Reproduction of Presentation
</label>
<label
class="label p-1 hover:preset-tonal-warning border border-warning-500 rounded-md"
for="optout_video"
>
<input
type="checkbox"
class="checkbox preset-tonal-warning border border-warning-500 checked:preset-filled-warning-500 hover:preset-filled-error-500"
id="optout_video"
name="optout_video"
checked={$lq__event_presenter_obj.data_json?.optout_video}
value={true}
/>
Opt-out - Video Reproduction of Presentation
</label>
<label
class="label p-1 hover:preset-tonal-warning border border-warning-500 rounded-md"
for="optout_transcription_and_publication"
>
<input
type="checkbox"
class="checkbox preset-tonal-warning border border-warning-500 checked:preset-filled-warning-500 hover:preset-filled-error-500"
id="optout_transcription_and_publication"
name="optout_transcription_and_publication"
checked={$lq__event_presenter_obj.data_json
?.optout_transcription_and_publication}
value={true}
/>
Opt-out - Transcription and Publication of Presentation on LCI Website
</label>
<label
class="label p-1 hover:preset-tonal-warning border border-warning-500 rounded-md"
for="optout_publication_in_app"
>
<input
type="checkbox"
class="checkbox preset-tonal-warning border border-warning-500 checked:preset-filled-warning-500 hover:preset-filled-error-500"
id="optout_publication_in_app"
name="optout_publication_in_app"
checked={$lq__event_presenter_obj.data_json?.optout_publication_in_app}
value={true}
/>
Opt-out - Publication of Presentation on LCI Congress App
</label>
<div class="text-center w-full">
<button
type="submit"
disabled={$events_sess.pres_mgmt?.disable_submit__opt_out}
onclick={() => {
console.log('*** Save button clicked ***');
}}
class="btn btn-md preset-tonal-warning border border-warning-500 hover:preset-filled-secondary-500 m-2"
>
<span class="fas fa-check m-1 text-orange-500"></span>
Save Opt-Out?
{#await ae_promises.update__event_presenter_obj}
<div class="modal-loading">
<span class="fas fa-spinner fa-spin"></span>
<span class="loading-text">
<!-- <ProgressRadial value={undefined} /> -->
Saving...
</span>
</div>
{:then update__event_presenter_obj_result}
{#if update__event_presenter_obj_result}
<div class="modal-loading">
<span class="fas fa-check-circle"></span>
<span class="loading-text">Successfully saved!</span>
</div>
{/if}
{:catch error}
<div class="modal-loading">
<span class="fas fa-exclamation-triangle"></span>
<span class="loading-text">Error: {error.message}</span>
</div>
{/await}
</button>
</div>
</form>
</div>
<div class="text-center w-full">
<h3 class="h4">Agree?</h3>
<!-- Agree (agreement) means this presenter has agreed to the terms and conditions. -->
{#if !$lq__event_presenter_obj?.agree}
<div>
Not Agreed:
<span class="fas fa-times text-red-500 m-1"></span>
<!-- <span class="fas fa-question text-red-500 m-1"></span> -->
</div>
<div>
Waiting for agreement to the Guest Speaker Consent and Release and Terms and
Conditions before you can move on.
</div>
{:else}
<div>
Agreed:
<span class="fas fa-check text-green-500 m-1"></span>
Marked as agreed
</div>
{/if}
{#if !$lq__event_presenter_obj?.agree}
<button
disabled={!$ae_loc.administrator_access &&
!$events_loc.auth__kv.presentation[
$lq__event_presenter_obj?.event_presentation_id_random
]}
onclick={() => {
console.log('Agree to the terms and conditions.');
$events_sess.pres_mgmt.status__presenter_agree = 'saving';
let event_presenter_data = {
agree: true,
data_json: {
...$lq__event_presenter_obj.data_json,
agree_updated_on: new Date().toISOString()
}
};
ae_promises.update__event_presenter_obj__agree = events_func
.update_ae_obj__event_presenter({
api_cfg: $ae_api,
event_presenter_id:
$lq__event_presenter_obj?.event_presenter_id_random,
data_kv: event_presenter_data,
log_lvl: log_lvl
})
.then(function (update_result) {
if (log_lvl) {
console.log('update_result:', update_result);
}
$events_sess.pres_mgmt.status__presenter_agree = 'saved';
});
}}
class="btn btn-lg preset-tonal-primary border border-primary-500 hover:preset-filled-success-500 m-2"
>
<span class="fa fa-check m-1 text-orange-500"></span>
Mark as agreed?
{#await ae_promises.update__event_presenter_obj__agree}
<div class="modal-loading">
<span class="fas fa-spinner fa-spin"></span>
<span class="loading-text"> Saving... </span>
</div>
{:then update__event_presenter_obj__agree_result}
{#if $events_sess.pres_mgmt.status__presenter_agree}
<div class="modal-loading">
<span class="fas fa-check-circle"></span>
<span class="loading-text">Successfully saved!</span>
</div>
{/if}
{:catch error}
<div class="modal-loading">
<span class="fas fa-exclamation-triangle"></span>
<span class="loading-text">Error: {error.message}</span>
</div>
{/await}
</button>
{:else}
<button
disabled={!$ae_loc.administrator_access &&
!$events_loc.auth__kv.presentation[
$lq__event_presenter_obj?.event_presentation_id_random
]}
onclick={() => {
console.log('Revoke agreement to the terms and conditions.');
$events_sess.pres_mgmt.status__presenter_agree = 'saving';
let event_presenter_data = {
agree: false,
data_json: {
...$lq__event_presenter_obj.data_json,
agree_updated_on: new Date().toISOString()
}
};
ae_promises.update__event_presenter_obj__agree = events_func
.update_ae_obj__event_presenter({
api_cfg: $ae_api,
event_presenter_id:
$lq__event_presenter_obj?.event_presenter_id_random,
data_kv: event_presenter_data,
log_lvl: log_lvl
})
.then(function (update_result) {
if (log_lvl) {
console.log('update_result:', update_result);
}
$events_sess.pres_mgmt.status__presenter_agree = 'saved';
});
}}
class="btn btn-lg preset-tonal-warning border border-warning-500 hover:preset-filled-error-500 m-2"
>
<span class="fas fa-times m-1 text-orange-500"></span>
Change to not agreed?
{#await ae_promises.update__event_presenter_obj__agree}
<div class="modal-loading">
<span class="fas fa-spinner fa-spin"></span>
<span class="loading-text"> Saving... </span>
</div>
{:then update__event_presenter_obj__agree_result}
{#if $events_sess.pres_mgmt.status__presenter_agree}
<div class="modal-loading">
<span class="fas fa-check-circle"></span>
<span class="loading-text">Successfully saved!</span>
</div>
{/if}
{:catch error}
<div class="modal-loading">
<span class="fas fa-exclamation-triangle"></span>
<span class="loading-text">Error: {error.message}</span>
</div>
{/await}
</button>
{/if}
</div>
</section>
{/if}

View File

@@ -0,0 +1,507 @@
<script lang="ts">
interface Props {
// export let data: any;
log_lvl?: number;
// import Sign_in_out from './sign_in_out.svelte'; // Should this be used here later???
lq__event_obj: any;
lq__event_presenter_obj: any;
}
let { log_lvl = 0, lq__event_obj, lq__event_presenter_obj }: Props = $props();
import { goto } from '$app/navigation';
import type { key_val } from '$lib/stores/ae_stores';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
import {
events_loc,
events_sess,
events_slct,
events_trigger,
events_trig_kv
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import Element_ae_crud from '$lib/elements/element_ae_crud.svelte';
import Element_data_store from '$lib/elements/element_data_store_v2.svelte';
import Comp__events_menu_nav from './../../../ae_comp__events_menu_nav.svelte';
let ae_tmp: key_val = $state({});
let ae_triggers: key_val = $state({});
</script>
<!-- New standard page specific menu 2025-06-20 -->
<div class="pres_mgmt__presenter_view_menu ae_container_module_menu">
<!-- BEGIN: The menu button options -->
<div class="flex flex-row flex-wrap gap-1 items-center justify-around w-full">
<Comp__events_menu_nav
hide={false}
event_id={$lq__event_presenter_obj?.event_id_random}
events__reports={$lq__event_presenter_obj?.event_id && $ae_loc.trusted_access}
events__session_id={$lq__event_presenter_obj?.event_session_id_random}
events__session_search={$events_slct.event_id}
/>
<span
class="ae_menu__object_options flex flex-row flex-wrap gap-0.5 items-center justify-around"
>
<!-- Button to toggle between the regular presenter view and managing presenter files -->
<button
type="button"
onclick={() => {
if ($events_loc.pres_mgmt.show_content__presenter_view == 'manage_files') {
$events_loc.pres_mgmt.show_content__presenter_view = null;
} else {
$events_loc.pres_mgmt.show_content__presenter_view = 'manage_files';
}
}}
class={ae_snip.classes__events_pres_mgmt_menu__button_special}
class:preset-filled-primary-500={$events_loc.pres_mgmt
.show_content__presenter_view == 'manage_files'}
class:preset-tonal-primary={$events_loc.pres_mgmt.show_content__presenter_view !=
'manage_files'}
class:hidden={!$ae_loc.authenticated_access || 1 == 1}
title="View presenter information or manage files for the presenter"
>
{#if $events_loc.pres_mgmt.show_content__presenter_view == 'manage_files'}
<span class="fas fa-info m-1"></span>
<!-- View Details -->
Presenter Info?
{:else}
<span class="fas fa-file-archive m-1"></span>
Presenter Files?
<span
class="badge badge-icon preset-tonal-success absolute -top-1.5 -right-1.5 z-10"
class:hidden={!$lq__event_presenter_obj?.file_count}
>
{$lq__event_presenter_obj?.file_count}×
</span>
{/if}
</button>
<!-- Button to toggle between showing and not showing the extended options menu -->
<button
type="button"
onclick={() => {
if ($events_loc.pres_mgmt.show_menu__presenter == 'options') {
$events_loc.pres_mgmt.show_menu__presenter = null;
} else {
$events_loc.pres_mgmt.show_menu__presenter = 'options';
}
}}
class="btn btn-sm mx-1"
class:ae_btn_info_filled={$events_loc.pres_mgmt.show_menu__presenter == 'options'}
class:ae_btn_info={$events_loc.pres_mgmt.show_menu__presenter != 'options'}
class:hidden={!$ae_loc.trusted_access}
title="Options for the presenter"
>
<span class="fas fa-cog m-1"></span>
{#if $events_loc.pres_mgmt.show_menu__presenter == 'options'}
Hide
{:else}
<span class="hidden"> Show </span>
{/if}
Options?
</button>
<button
type="button"
onclick={() => {
if ($events_loc.pres_mgmt.show_menu__presenter == 'help') {
$events_loc.pres_mgmt.show_menu__presenter = null;
} else {
$events_loc.pres_mgmt.show_menu__presenter = 'help';
}
}}
class="btn btn-sm mx-1"
class:ae_btn_info_filled={$events_loc.pres_mgmt.show_menu__presenter == 'help'}
class:ae_btn_info={$events_loc.pres_mgmt.show_menu__presenter != 'help'}
title="Help and information about the presenter"
>
<span class="fas fa-question-circle m-1"></span>
{#if $events_loc.pres_mgmt.show_menu__presenter == 'help'}
Hide Help?
{:else}
Help?
{/if}
</button>
</span>
{#if $events_loc.pres_mgmt?.require__presenter_agree}
<span class="ae_menu__action_options flex flex-row items-center justify-around">
{#if $lq__event_presenter_obj?.agree}
<!-- {#if $ae_loc.trusted_access || $events_loc.auth__kv.presenter[$lq__event_presenter_obj.event_presenter_id_random]} -->
<button
type="button"
disabled={!$ae_loc.trusted_access &&
!$events_loc.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id_random
]}
onclick={() => {
$events_slct.event_presentation_id =
$lq__event_presenter_obj?.event_presentation_id_random;
// $events_slct.event_presentation_obj = $events_slct.event_presentation_obj;
$events_slct.event_presenter_id =
$lq__event_presenter_obj?.event_presenter_id_random;
// $lq__event_presenter_obj = $lq__event_presenter_obj;
$events_sess.pres_mgmt.show_modal__presenter_agree =
$lq__event_presenter_obj?.event_presenter_id_random;
}}
class="btn btn-sm mx-1 font-bold ae_btn_success_filled"
title="Agreed to terms and conditions"
>
<span
class="fas fa-check text-green-500 px-1"
title="Agreed to terms and conditions"
></span>
<span> Agreed </span>
</button>
{:else}
<button
type="button"
disabled={!$ae_loc.trusted_access &&
!$events_loc.auth__kv.presenter[
$lq__event_presenter_obj?.event_presenter_id_random
]}
onclick={() => {
$events_slct.event_presentation_id =
$lq__event_presenter_obj?.event_presentation_id_random;
// $events_slct.event_presentation_obj = $events_slct.event_presentation_obj;
$events_slct.event_presenter_id =
$lq__event_presenter_obj?.event_presenter_id_random;
// $lq__event_presenter_obj = $lq__event_presenter_obj;
$events_sess.pres_mgmt.show_modal__presenter_agree =
$lq__event_presenter_obj?.event_presenter_id_random;
}}
class="btn btn-sm mx-1 font-bold ae_btn_warning_filled"
title="View terms and conditions"
>
<span
class="fas fa-times bg-red-500 text-white px-1 mx-1"
title="Not agreed to terms and conditions"
></span>
<span> Not yet agreed </span>
</button>
{/if}
</span>
{/if}
</div>
<!-- END: The menu button options -->
<!-- BEGIN: The expanded menu area for information and options -->
<div
class="flex flex-row flex-wrap items-center justify-around w-full bg-blue-100 hover:bg-blue-200 border border-blue-200 hover:border-blue-400 p-2 rounded-md"
class:hidden={$events_loc.pres_mgmt.show_menu__presenter != 'options'}
>
<Element_ae_crud
trigger_patch={ae_triggers.priority}
api_cfg={$ae_api}
object_type={'event_presenter'}
object_id={$lq__event_presenter_obj?.event_presenter_id_random}
field_name={'priority'}
field_type={'button'}
field_value={ae_tmp.value__priority}
allow_null={true}
hide_edit_btn={true}
outline_element={false}
show_crud={false}
display_inline={true}
class_li={'m-1'}
on:ae_crud_updated={(e) => {
console.log(`ae_crud_updated:`, e.detail);
events_func.load_ae_obj_id__event_presenter({
api_cfg: $ae_api,
event_presenter_id: $lq__event_presenter_obj?.event_presenter_id_random,
log_lvl: log_lvl
});
}}
>
<!-- {@html $lq__event_presenter_obj?.priority ? '<span class="fas fa-star m-1"></span> High Priority' : '<span class="far fa-star m-1"></span> Priority not set'} -->
<button
onclick={() => {
ae_tmp.value__priority = !$lq__event_presenter_obj?.priority;
ae_triggers.priority = true;
}}
class="btn btn-sm m-1 *:hover:inline"
class:ae_btn_surface_outlined={!$lq__event_presenter_obj?.priority}
class:ae_btn_success={$lq__event_presenter_obj?.priority}
>
{#if $lq__event_presenter_obj?.priority}
<span class="fas fa-star m-1"></span>
<!-- <span class="fas fa-arrow-down m-1"></span> -->
<span class="hidden"> Not Priority? </span>
{:else}
<!-- <span class="fas fa-toggle-off m-1"></span> -->
<span class="far fa-star m-1"></span>
<span class="hidden"> Priority </span>
?
{/if}
</button>
</Element_ae_crud>
<Element_ae_crud
trigger_patch={ae_triggers.hide}
api_cfg={$ae_api}
object_type={'event_presenter'}
object_id={$lq__event_presenter_obj?.event_presenter_id_random}
field_name={'hide'}
field_type={'button'}
field_value={ae_tmp.value__hide}
allow_null={false}
hide_edit_btn={true}
outline_element={false}
show_crud={false}
display_inline={true}
class_li={'m-1'}
on:ae_crud_updated={(e) => {
console.log(`ae_crud_updated:`, e.detail);
events_func.load_ae_obj_id__event_presenter({
api_cfg: $ae_api,
event_presenter_id: $lq__event_presenter_obj?.event_presenter_id_random,
log_lvl: log_lvl
});
}}
>
<!-- {($lq__event_presenter_obj?.hide ? 'Hidden' : 'Not Hidden')} -->
<button
onclick={() => {
ae_tmp.value__hide = !$lq__event_presenter_obj?.hide;
// $events_slct.exhibit_tracking_obj.hide = !$lq__event_presenter_obj?.hide;
ae_triggers.hide = true;
}}
class="btn btn-sm m-1 *:hover:inline"
class:ae_btn_success_outlined={!$lq__event_presenter_obj?.hide}
class:ae_btn_warning={$lq__event_presenter_obj?.hide}
disabled={!$ae_loc.trusted_access}
>
{#if $lq__event_presenter_obj?.hide}
<span class="fas fa-toggle-on m-1"></span>
Unhide?
{:else}
<!-- <span class="fas fa-toggle-off m-1"></span> -->
<span class="fas fa-eye m-1"></span>
<span class="hidden"> Not Hidden </span>
{/if}
<!-- {@html ($lq__event_presenter_obj?.hide ? '<span class="fas fa-eye m-1"></span> Unhide?' : '<span class="fas fa-eye-slash m-1"></span> Hide?')} -->
</button>
</Element_ae_crud>
<!-- Enable/Disable -->
<Element_ae_crud
trigger_patch={ae_triggers.enable}
api_cfg={$ae_api}
object_type={'event_presenter'}
object_id={$lq__event_presenter_obj?.event_presenter_id_random}
field_name={'enable'}
field_type={'button'}
field_value={ae_tmp.value__enable}
allow_null={false}
hide_edit_btn={true}
outline_element={false}
show_crud={false}
display_inline={true}
class_li={'m-1'}
on:ae_crud_updated={(e) => {
console.log(`ae_crud_updated:`, e.detail);
events_func
.load_ae_obj_id__event_presenter({
api_cfg: $ae_api,
event_presenter_id: $lq__event_presenter_obj?.event_presenter_id_random,
log_lvl: 1
})
.then(function (load_results) {
// Maybe reload page?
// window.location.reload();
});
}}
>
<!-- {($lq__event_presenter_obj?.enable ? 'Enabled' : 'Disabled')} -->
<button
onclick={() => {
ae_tmp.value__enable = !$lq__event_presenter_obj?.enable;
ae_triggers.enable = true;
}}
class="btn btn-sm"
class:ae_btn_success_outlined={$lq__event_presenter_obj?.enable}
class:ae_btn_error={!$lq__event_presenter_obj?.enable}
disabled={!$ae_loc.manager_access}
>
{#if $lq__event_presenter_obj?.enable}
<span class="fas fa-toggle-on m-1"></span>
Enabled
{:else}
<span class="fas fa-toggle-off m-1"></span>
Enable?
{/if}
<!-- {@html ($lq__event_presenter_obj?.enable ? '<span class="fas fa-toggle-on m-1"></span> Disable?' : '<span class="fas fa-toggle-off m-1"></span> Enable?')} -->
</button>
</Element_ae_crud>
<!-- Sort -->
<!-- Group -->
{#if $ae_loc.manager_access}
<button
onclick={() => {
if (!confirm('Are you sure you want to delete this presenter?')) {
return false;
}
events_func
.delete_ae_obj_id__event_presenter({
api_cfg: $ae_api,
event_presenter_id: $lq__event_presenter_obj.event_presenter_id,
method: 'delete'
})
.then(function (delete_results) {
$events_slct.event_presenter_id = null;
$events_slct.event_presenter_obj = {};
goto(
`/events/${$lq__event_presenter_obj.event_id}/session/${$lq__event_presenter_obj.event_session_id}`
);
});
}}
class="btn btn-sm mx-1 ae_btn_error"
type="button"
title="Delete record permanently"
>
<span class="fas fa-minus-circle mx-1"></span>
Delete
</button>
{:else if $ae_loc.trusted_access}
<button
onclick={() => {
if (!confirm('Are you sure you want to remove (disable) this presenter?')) {
return false;
}
events_func
.delete_ae_obj_id__event_presenter({
api_cfg: $ae_api,
event_presenter_id: $lq__event_presenter_obj.event_presenter_id,
method: 'disable'
})
.then(function (delete_results) {
$events_slct.event_presenter_id = null;
$events_slct.event_presenter_obj = {};
goto(
`/events/${$lq__event_presenter_obj.event_id}/session/${$lq__event_presenter_obj.event_session_id}`
);
});
}}
class="btn btn-sm mx-1 ae_btn_warning"
type="button"
title="Disable record"
>
<span class="fas fa-minus mx-1"></span>
Delete
</button>
{/if}
{#if $ae_loc.administrator_access}
{#if $events_loc.pres_mgmt.show_content__presenter_qr}
<button
onclick={() => {
$events_loc.pres_mgmt.show_content__presenter_qr = false;
}}
class="btn btn-sm ae_btn_surface"
>
<span class="fas fa-toggle-on m-1"></span>
Showing QR Code
</button>
{:else}
<button
onclick={() => {
$events_loc.pres_mgmt.show_content__presenter_qr = true;
}}
class="btn btn-sm ae_btn_surface_outlined"
>
<span class="fas fa-toggle-off m-1"></span>
Show QR Code?
</button>
{/if}
{/if}
{#if $ae_loc.trusted_access}
{#if $ae_loc.edit_mode}
<button
onclick={() => {
$ae_loc.edit_mode = false;
}}
class="btn btn-sm ae_btn_warning"
>
<!-- <span class="fas fa-toggle-on m-1"></span> -->
<span class="fas fa-edit m-1"></span>
Edit Mode On
</button>
{:else}
<button
onclick={() => {
$ae_loc.edit_mode = true;
}}
class="btn btn-sm ae_btn_warning_outlined"
>
<span class="fas fa-toggle-off m-1"></span>
<!-- <span class="fas fa-edit m-1"></span> -->
Edit Mode?
</button>
{/if}
{/if}
</div>
<!-- END: The expanded menu area for information and options -->
<Element_data_store
ds_code="events__pres_mgmt__presenter_page_help"
ds_name="Default: Events - Pres Mgmt Presenter Page Help"
ds_type="html"
for_type="event"
for_id={$lq__event_presenter_obj?.event_id}
class_li="ae_container_module_help"
show_edit={false}
show_edit_btn={true}
hide={$events_loc.pres_mgmt.show_menu__presenter != 'help'}
/>
<div>
<button
type="button"
onclick={() => {
$events_loc.pres_mgmt.show_menu__presenter =
!$events_loc.pres_mgmt.show_menu__presenter;
}}
class="btn btn-sm mx-1 ae_btn_info_filled"
class:hidden={!$events_loc.pres_mgmt.show_menu__presenter}
title="Collapse the expanded menu"
>
<span class="fas fa-chevron-up m-1"></span>
{#if $events_loc.pres_mgmt.show_menu__presenter}
Hide
<!-- Collapse -->
{:else}
Show
{/if}
<!-- Menu? -->
</button>
</div>
</div>
<!-- End of the new standard page specific menu -->

View File

@@ -0,0 +1,364 @@
<script lang="ts">
interface Props {
log_lvl?: number;
container_class_li?: string | Array<string>;
display_mode?: string; // 'default', 'compact', 'minimal', 'launcher'
link_to_type: string;
link_to_id: string;
lq__event_presenter_obj_li: any;
}
let {
log_lvl = 0,
container_class_li = [],
display_mode = 'default',
link_to_type,
link_to_id,
lq__event_presenter_obj_li
}: Props = $props();
// Imports
import type { key_val } from '$lib/stores/ae_stores';
// import { ae_util } from '$lib/ae_utils/ae_utils';
// import { api, send_email } from '$lib/api';
// import Element_ae_crud from '$lib/element_ae_crud.svelte';
// import Element_data_store from '$lib/element_data_store_v2.svelte';
// import { liveQuery } from "dexie";
import { core_func } from '$lib/ae_core/ae_core_functions';
// import { db_events } from "$lib/ae_events/db_events";
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
import {
events_loc,
events_sess,
events_slct,
events_trigger,
events_trig_kv
} from '$lib/stores/ae_events_stores';
import { events_func } from '$lib/ae_events_functions';
import { ae_util } from '$lib/ae_utils/ae_utils';
if (log_lvl) {
console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`);
}
// Variables
// let ae_promises: key_val = {};
let ae_tmp: key_val = $state({});
// let ae_triggers: key_val = {};
// *** Functions and Logic
</script>
<div class="float-right flex flex-row items-center">
<button
type="button"
onclick={() => {
console.log('*** Refresh button clicked ***');
ae_tmp.show__file_li = false;
console.log(`$lq__event_presenter_obj_li:`, $lq__event_presenter_obj_li);
events_func.load_ae_obj_li__event_presenter({
api_cfg: $ae_api,
for_obj_type: link_to_type,
for_obj_id: link_to_id,
log_lvl: log_lvl
});
}}
class="btn btn-sm p-1 m-1 preset-tonal-tertiary hover:preset-tonal-warning border border-warning-500 transition hover:transition-all *:hover:inline"
class:hidden={!$ae_loc.edit_mode || !$ae_loc.trusted_access || display_mode != 'default'}
title="Refresh the list of presenters"
>
<span class="fas fa-sync-alt m-1"></span>
<span class="hidden"> Presenters </span>
</button>
</div>
<section
class="
ae_comp event_presenter_obj_li
border-1 border-dashed border-y-transparent border-r-transparent
sm:border-l-red-400 md:border-l-yellow-400 lg:border-l-gray-100
sm:dark:border-l-red-600 md:dark:border-l-yellow-600 lg:dark:border-l-gray-700
px-0.5 py-2 space-y-2
min-w-full
w-full
container overflow-x-scroll {container_class_li}
"
>
<h3
class:hidden={$lq__event_presenter_obj_li?.length < 2 && !$ae_loc.edit_mode}
class="h5 text-success-800-400"
>
<span class="text-sm">
Presenters:
{#if $lq__event_presenter_obj_li?.length}
<span
class="text-3xl font-bold preset-filled-success-100-900 px-4 rounded-lg"
title="Count {$lq__event_presenter_obj_li.length ?? 'None'}"
>
<span class="fas fa-list-ol mx-4"></span>
{$lq__event_presenter_obj_li.length ?? 'None'}&times;
</span>
{/if}
<!-- {#if !$lq__event_presenter_obj_li?.length}
<span class="text-sm text-gray-500">
No presenters available to show at this time
</span>
{/if} -->
</span>
</h3>
<!-- Show presenters for this LiveQuery -->
{#if $lq__event_presenter_obj_li?.length}
<!-- <strong class="text-sm">Presenters:
{#if $ae_loc.administrator_access}
({$lq__event_presenter_obj_li?.length})
{/if}
</strong> -->
<ul class="space-y-1 px-4 m-2 bg-gray-100 rounded-md">
{#each $lq__event_presenter_obj_li as event_presenter_obj}
<!-- This is a hack. I can not get the LiveQuery to work with specific presentation IDs. It only works with the session ID. I need to figure out how to get the presenters for the specific presentation. -->
<!-- {#if event_presenter_obj.event_presentation_id_random == event_presentation_obj.event_presentation_id_random} -->
<li
class:dim={event_presenter_obj?.hide}
class:dim_warning={!event_presenter_obj?.enable}
class:hidden={!event_presenter_obj?.enable && !$ae_loc.administrator_access}
>
<a
href="/events/{event_presenter_obj.event_id}/presenter/{event_presenter_obj.event_presenter_id}"
class:btn-sm={display_mode != 'default'}
class="
ae_obj__event_presenter
btn preset-tonal-primary border border-primary-500
hover:preset-filled-primary-500
font-bold min-w-64 max-w-96 my-0.5
overflow-hidden
"
title="Person ID: {event_presenter_obj.person_id_random}; Email: {event_presenter_obj.person_primary_email}"
>
{#if event_presenter_obj?.given_name && event_presenter_obj?.given_name != 'Group'}
<span class="fas fa-user m-0.5 text-xs text-surface-800-200"></span>
{:else if event_presenter_obj?.given_name == 'Group'}
<span class="fas fa-users m-0.5 text-xs text-surface-800-200"></span>
{:else}
<span class="fas fa-user-slash m-0.5 text-xs text-surface-800-200"
></span>
{/if}
{#if event_presenter_obj.priority}
<span class="fas fa-star m-0.5 text-xs text-yellow-800-200"></span>
{/if}
<span class="text-center grow">
{#if event_presenter_obj?.given_name && event_presenter_obj?.given_name != 'Group'}
{event_presenter_obj?.full_name}
{:else if event_presenter_obj?.given_name == 'Group'}
{ae_util.shorten_string({
string: event_presenter_obj?.affiliations,
max_length: 25
})}
{:else}
--not set--
{/if}
</span>
{#if event_presenter_obj?.file_count}
<span
class="badge preset-tonal-success hover:preset-filled-success-500"
title="{event_presenter_obj.file_count} files"
>
<span class="fas fa-file-alt mx-1"></span>
{event_presenter_obj?.file_count}×
<!-- {event_presenter_obj?.file_count ? `(${event_presenter_obj?.file_count}&times; files)` : '(0 files)'} -->
</span>
{/if}
</a>
{#if $events_loc?.pres_mgmt?.show__email_access_link && event_presenter_obj?.person_primary_email && ($ae_loc.administrator_access || !$events_loc.auth__person?.id)}
<button
type="button"
onclick={() => {
console.log('Email the access link');
if (!event_presenter_obj.person_primary_email) {
alert('No email address found for this presenter.');
return;
}
if (
confirm(
`This will send the sign in email to ${event_presenter_obj.person_primary_email}`
)
) {
console.log('Send the email to the presenter.');
} else {
console.log('Cancelled sending the email.');
return false;
}
events_func.email_sign_in__event_presenter({
api_cfg: $ae_api,
to_email: event_presenter_obj.person_primary_email,
to_name: event_presenter_obj?.full_name ?? '-- not set --',
base_url: $ae_loc.url_origin,
person_id: event_presenter_obj?.person_id_random,
person_passcode:
event_presenter_obj.person_passcode ?? '-- not set --',
event_id: event_presenter_obj.event_id_random,
event_session_id: event_presenter_obj.event_session_id_random,
event_presentation_id:
event_presenter_obj.event_presentation_id_random,
event_presenter_id:
event_presenter_obj.event_presenter_id_random,
session_name:
event_presenter_obj?.event_session_name ?? '-- not set --',
presentation_name:
event_presenter_obj?.event_presentation_name ??
'-- not set --'
});
}}
class="btn preset-tonal-secondary border border-secondary-500 hover:preset-filled-secondary-500 my-0.5 transition-all hover:transition-all"
class:btn-sm={display_mode != 'default'}
title="Email the access link to the presenter"
>
<span class="fas fa-envelope mx-1"></span>
Email Access Link
</button>
{/if}
{#if $events_loc.pres_mgmt?.require__presenter_agree}
{#if event_presenter_obj?.agree}
<!-- {#if $ae_loc.trusted_access || $events_loc.auth__kv.presenter[event_presenter_obj.event_presenter_id_random]} -->
<button
type="button"
disabled={!$ae_loc.trusted_access &&
!$events_loc.auth__kv.presenter[
event_presenter_obj.event_presenter_id_random
]}
onclick={() => {
console.log('View terms and conditions');
$events_slct.event_presentation_id =
event_presenter_obj.event_presentation_id_random;
// $events_slct.event_presentation_obj = $lq__event_presentation_obj;
$events_slct.event_presenter_id =
event_presenter_obj.event_presenter_id_random;
// $events_slct.event_presenter_obj = event_presenter_obj;
$events_sess.pres_mgmt.show_modal__presenter_agree =
event_presenter_obj.event_presenter_id_random;
}}
class="btn preset-tonal-success hover:preset-filled-success-500 my-0.5"
class:btn-sm={display_mode != 'default'}
title="Agreed to terms and conditions"
>
<span
class="fas fa-check text-green-500 px-1"
title="Agreed to terms and conditions"
></span>
Agreed
</button>
{:else}
<button
type="button"
disabled={!$ae_loc.trusted_access &&
!$events_loc.auth__kv.presenter[
event_presenter_obj.event_presenter_id_random
]}
onclick={() => {
console.log('View terms and conditions');
$events_slct.event_presentation_id =
event_presenter_obj.event_presentation_id_random;
// $events_slct.event_presentation_obj = $lq__event_presentation_obj;
$events_slct.event_presenter_id =
event_presenter_obj.event_presenter_id_random;
// $events_slct.event_presenter_obj = event_presenter_obj;
$events_sess.pres_mgmt.show_modal__presenter_agree =
event_presenter_obj.event_presenter_id_random;
}}
class="btn preset-tonal-warning border border-warning-500 hover:preset-filled-warning-500 my-0.5"
class:btn-sm={display_mode != 'default'}
title="View terms and conditions"
>
<span
class="fas fa-times bg-red-500 text-white px-1 mx-1"
title="Not agreed to terms and conditions"
></span>
Not yet agreed
</button>
{/if}
{/if}
<div class="float-right space-2 flex flex-row items-center">
{#if $ae_loc.administrator_access && !event_presenter_obj.person_id_random}
<button
type="button"
onclick={async () => {
console.log('Add Person');
if (
!confirm(
`Add a new person to the account? You will be able to edit their details after the person record is created.\n\n${$ae_loc.account_name}\nID: ${$slct.account_id}`
)
) {
return;
}
let person_data = {
account_id_random: $slct.account_id,
// user_id_random: user_obj.user_id_random,
given_name: 'New',
family_name: 'Presenter',
primary_email: 'test+newpres@oneskyit.com',
code: 'new_presenter',
// Random number between 100000 and 999999
passcode: Math.floor(Math.random() * 900000) + 100000,
enable: true
};
let new_person_obj = await core_func.create_ae_obj__person({
api_cfg: $ae_api,
// user_id: $ae_loc.user_id,
data_kv: person_data,
log_lvl: log_lvl
});
console.log('new_person_obj:', new_person_obj);
// We then need to update the event_presenter with the new person_id.
events_func.update_ae_obj__event_presenter({
api_cfg: $ae_api,
event_presenter_id:
event_presenter_obj.event_presenter_id_random,
data_kv: {
person_id_random: new_person_obj.person_id_random
},
log_lvl: log_lvl
});
}}
class:hidden={!$ae_loc.edit_mode}
class="btn btn-sm preset-tonal-warning hover:preset-filled-warning-500"
>
<span class="fas fa-plus mx-1"></span>
Add Person
</button>
{/if}
</div>
</li>
<!-- {/if} -->
{/each}
</ul>
{:else}
<!-- <p class:hidden={display_mode != 'default'}>
No presenters available to show at this time
</p> -->
{/if}
</section>

View File

@@ -0,0 +1,67 @@
<script lang="ts">
interface Props {
container_class_li?: string | Array<string>;
display_mode?: string; // 'default', 'compact', 'minimal', 'launcher'
event_presenter_id_random_li?: Array<string>;
link_to_type: string;
link_to_id: string;
// export let lq__event_presentation_obj
log_lvl?: number;
}
let {
container_class_li = [],
display_mode = 'default',
event_presenter_id_random_li = [],
link_to_type,
link_to_id,
log_lvl = 0
}: Props = $props();
// Imports
import Comp_event_presenter_obj_li from './ae_comp__event_presenter_obj_li.svelte';
import { liveQuery } from 'dexie';
import { db_events } from '$lib/ae_events/db_events';
if (log_lvl) {
console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`);
}
// Variables
// let ae_promises: key_val = {};
// let ae_tmp: key_val = {};
// let ae_triggers: key_val = {};
let dq__where_type_id_val: string = `${link_to_type}_id`;
let dq__where_eq_id_val: string = link_to_id;
// *** Functions and Logic
let lq__event_presenter_obj_li = $derived(
liveQuery(async () => {
if (link_to_type && link_to_id) {
let results = await db_events.presenter
.where(dq__where_type_id_val)
.equals(dq__where_eq_id_val)
.sortBy('name');
return results;
} else if (event_presenter_id_random_li.length > 0) {
let results = await db_events.presenter.bulkGet(event_presenter_id_random_li);
return results;
} else {
return null;
}
})
);
</script>
<Comp_event_presenter_obj_li
{container_class_li}
{display_mode}
{link_to_type}
{link_to_id}
{lq__event_presenter_obj_li}
{log_lvl}
></Comp_event_presenter_obj_li>

View File

@@ -0,0 +1,425 @@
<script lang="ts">
interface Props {
// Exports
container_class_li?: string | Array<string>;
// export let event_presenter_id_random_li: Array<string>;
lq__event_presenter_obj_li: any;
// export let allow_moderator: boolean = false;
show_presentation_fields?: boolean;
show_session_fields?: boolean;
hide_session_code?: boolean;
log_lvl?: number;
}
let {
container_class_li = [],
lq__event_presenter_obj_li,
show_presentation_fields = false,
show_session_fields = false,
hide_session_code = false,
log_lvl = $bindable(0)
}: Props = $props();
// Imports
import { ae_util } from '$lib/ae_utils/ae_utils';
import {
ae_snip,
ae_loc,
ae_sess,
ae_api,
ae_trig,
slct,
slct_trigger
} from '$lib/stores/ae_stores';
// export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher'
// export let link_to_type: string;
// export let link_to_id: string;
// export let allow_basic: boolean = false;
if (log_lvl) {
console.log(
`container_class_li: ${container_class_li}; show_presentation_fields: ${show_presentation_fields}; show_session_fields: ${show_session_fields}`
);
// console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`);
}
// Variables
// let ae_promises: key_val = {};
// let ae_tmp: key_val = {};
// let ae_triggers: key_val = {};
// *** Functions and Logic
// let lq__event_presenter_obj = liveQuery(
// () => db_events.presenter.get($events_slct.event_presenter_id)
// );
// let lq_kv__event_presenter_obj_li = liveQuery(
// () => db_events.presenter
// .bulkGet(event_presenter_id_random_li)
// );
function generate_presenter_export_csv(ae_obj_li) {
console.log(`*** generate_presenter_export_csv() ***`, ae_obj_li);
// We need to create a list with the column names and then a list of lists with the data.
let csv_data = [];
let csv_columns = [
'Presenter ID',
'Name',
'Email',
'Agree',
'Files',
'Code',
'Session',
'Start datetime',
'Presentation',
'Presentation time',
'Updated On'
];
csv_data.push(csv_columns);
for (let i = 0; i < ae_obj_li.length; i++) {
let csv_row = [];
csv_row.push(ae_obj_li[i].event_presenter_id);
csv_row.push(ae_obj_li[i].full_name ?? ae_obj_li[i].given_name);
csv_row.push(ae_obj_li[i].email ?? '');
csv_row.push(ae_obj_li[i].agree ? 'Yes' : 'No');
csv_row.push(ae_obj_li[i].file_count ?? '0');
csv_row.push(ae_obj_li[i].event_session_code ?? '');
csv_row.push(ae_obj_li[i].event_session_name ?? '');
csv_row.push(
ae_obj_li[i].event_session_start_datetime
? ae_util.iso_datetime_formatter(
ae_obj_li[i].event_session_start_datetime,
'datetime_iso_12_no_seconds'
)
: ''
);
csv_row.push(ae_obj_li[i].event_presentation_name ?? '');
csv_row.push(
ae_obj_li[i].event_presentation_start_datetime
? ae_util.iso_datetime_formatter(
ae_obj_li[i].event_presentation_start_datetime,
'time_12_short'
)
: ''
);
csv_row.push(
ae_obj_li[i].updated_on
? ae_util.iso_datetime_formatter(
ae_obj_li[i].updated_on,
'datetime_iso_12_no_seconds'
)
: ''
);
csv_data.push(csv_row);
}
console.log('CSV Data:', csv_data);
let csv_content_str = '';
csv_data.forEach(function (row) {
csv_content_str += row.join(';');
csv_content_str += '\n';
});
const blob = new Blob([csv_content_str], { type: 'text/csv;charset=utf-8;' });
const obj_url = URL.createObjectURL(blob);
const download_link = document.createElement('a');
download_link.setAttribute('href', obj_url);
download_link.setAttribute(
'download',
`presenter_list_${ae_util.iso_datetime_formatter()}.csv`
);
download_link.setAttribute('style', 'display: none;');
download_link.textContent = 'Download CSV';
// document.querySelector('body').appendChild(download_link);
document.getElementById('download_csv_container').appendChild(download_link);
// Automatically download the file
download_link.click();
return csv_data;
}
let horiz_scroll_warning: boolean = $state(false);
let horiz_check_element: HTMLElement | null = $state(null);
// Check if element is scrolling horizontally
$effect(() => {
if (
horiz_check_element &&
horiz_check_element.scrollWidth > horiz_check_element.offsetWidth
) {
horiz_scroll_warning = true;
// console.log('Element is too wide for the container. Horizontal scrolling detected.');
} else {
horiz_scroll_warning = false;
// console.log('Element fits within the container. No horizontal scrolling.', horiz_check_element);
}
});
</script>
<section
class:border-r-2={horiz_scroll_warning}
class:border-dashed={horiz_scroll_warning}
class:border-warning-900-100={horiz_scroll_warning}
class="ae_comp event_presenter_obj_tbl {container_class_li} container overflow-auto max-w-screen"
>
{#if $lq__event_presenter_obj_li && $lq__event_presenter_obj_li?.length}
<div bind:this={horiz_check_element} id="tbl_container" class="space-y-2 pb-8">
<header class="flex flex-row flex-wrap gap-1 items-center justify-between">
<h2 class="h3">
<span class="text-base"> Results: </span>
{#if $lq__event_presenter_obj_li.length}
<span
class="text-3xl font-bold preset-filled-success-100-900 px-4 rounded-lg"
title="Count {$lq__event_presenter_obj_li.length ?? 'None'}"
>
<span class="fas fa-list-ol mx-4"></span>
{$lq__event_presenter_obj_li.length ?? 'None'}&times;
</span>
{/if}
</h2>
<div
class="flex flex-row flex-wrap gap-1 items-center justify-end"
class:hidden={!$ae_loc.edit_mode}
>
<button
class="btn btn-sm preset-tonal-warning border border-warning-500 mb-1 generate_csv_btn"
onclick={() => {
if (
!confirm(
'Generate and download a CSV file with the presenter list?'
)
) {
return false;
}
let csv_data = generate_presenter_export_csv(
$lq__event_presenter_obj_li
);
console.log('CSV Data:', csv_data);
}}
>
<span class="fas fa-file-csv mx-1"></span>
Export Presenters CSV
</button>
<span id="download_csv_container"></span>
{#if show_session_fields}
<button
type="button"
onclick={() => {
show_session_fields = !show_session_fields;
}}
class="btn btn-sm {show_session_fields
? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}"
title="Show or hide the session-related column fields."
>
<span class="fas fa-toggle-on m-1"></span>
Showing Session Fields
</button>
{:else}
<button
type="button"
onclick={() => {
show_session_fields = !show_session_fields;
}}
class="btn btn-sm {show_session_fields
? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}"
title="Show or hide the session-related column fields."
>
<span class="fas fa-toggle-off m-1"></span>
Show Session Fields
</button>
{/if}
<!-- Show or hide the session code -->
{#if !hide_session_code}
<button
type="button"
onclick={() => {
hide_session_code = true;
}}
class="btn btn-sm ae_btn_surface"
title="Hide the session code column from view. Currently showing the Session Code column."
>
<span class="fas fa-toggle-on m-1"></span>
Showing Session Code
</button>
{:else}
<button
type="button"
onclick={() => {
hide_session_code = false;
}}
class="btn btn-sm ae_btn_surface_outlined"
title="Show the session code column. Currently hiding the Session Code column from view."
>
<span class="fas fa-toggle-off m-1"></span>
Show Session Code
</button>
{/if}
{#if show_presentation_fields}
<button
type="button"
onclick={() => {
show_presentation_fields = !show_presentation_fields;
}}
class="btn btn-sm {show_presentation_fields
? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}"
title="Show or hide the extra presentation-related column fields."
>
<span class="fas fa-toggle-on m-1"></span>
Showing Presentation Fields
</button>
{:else}
<button
type="button"
onclick={() => {
show_presentation_fields = !show_presentation_fields;
}}
class="btn btn-sm {show_presentation_fields
? 'ae_btn_surface'
: 'ae_btn_surface_outlined'}"
title="Show or hide the extra presentation-related column fields."
>
<span class="fas fa-toggle-off m-1"></span>
Show Presentation Fields
</button>
{/if}
</div>
</header>
<table class="table table-auto table-striped w-full text-xs lg:text-sm">
<thead>
<tr>
<th class="px-4 py-2">Name</th>
<th class="px-4 py-2">Email</th>
<th class="px-4 py-2">Agree</th>
<th class="px-4 py-2">Files</th>
{#if show_session_fields}
<th class="px-4 py-2" class:hidden={hide_session_code}> Code </th>
<th class="px-4 py-2"> Session </th>
<th class="px-4 py-2">Start datetime</th>
{/if}
{#if show_presentation_fields}
<th class="px-4 py-2">Presentation</th>
<th class="px-4 py-2">Presentation time</th>
{/if}
<th class="px-4 py-2"> Updated On </th>
</tr>
</thead>
<tbody class="">
{#each $lq__event_presenter_obj_li as event_presenter_obj}
<tr class:dim={event_presenter_obj?.hide}>
<td class="px-4 py-2">
<span class="fas fa-user"></span>
<a
href="/events/{event_presenter_obj?.event_id_random}/presenter/{event_presenter_obj?.event_presenter_id_random}"
class="text-blue-500 underline hover:text-blue-800"
>
{event_presenter_obj?.full_name ?? '-- not set --'}
</a>
</td>
<td class="px-4 py-2">
<span class="fas fa-envelope"></span>
{#if event_presenter_obj?.email}
<a
href="mailto:{event_presenter_obj?.email}"
class="text-blue-500 underline hover:text-blue-800"
>
{event_presenter_obj?.email}
</a>
{:else}
<span class="dim">-- not set --</span>
{/if}
</td>
<td class="px-4 py-2">{event_presenter_obj?.agree ? 'Yes' : 'No'}</td>
<td class="px-4 py-2">{event_presenter_obj?.file_count ?? '0'}</td>
{#if show_session_fields}
<td class="px-4 py-2 lg:text-xs" class:hidden={hide_session_code}>
{event_presenter_obj?.event_session_code ?? '-- not set --'}
</td>
<td class="px-4 py-2 lg:text-xs">
<span class="fas fa-chalkboard-teacher"></span>
<a
href="/events/{event_presenter_obj?.event_id}/session/{event_presenter_obj?.event_session_id}"
class="text-blue-500 underline hover:text-blue-800"
>
{#if event_presenter_obj?.event_session_name}
{event_presenter_obj?.event_session_name}
{:else}
<span class="dim">-- not set --</span>
{/if}
</a>
</td>
<td class="px-4 py-2 text-sm">
{#if event_presenter_obj?.event_session_start_datetime}
{ae_util.iso_datetime_formatter(
event_presenter_obj?.event_session_start_datetime,
'datetime_iso_12_no_seconds'
)}
{:else}
<span class="dim">-- not set --</span>
{/if}
</td>
{/if}
{#if show_presentation_fields}
<td class="px-4 py-2 lg:text-xs"
>{event_presenter_obj?.event_presentation_name}</td
>
<td class="px-4 py-2 lg:text-xs">
{#if event_presenter_obj?.event_presentation_start_datetime}
{ae_util.iso_datetime_formatter(
event_presenter_obj?.event_presentation_start_datetime,
'time_12_short'
)}
{:else}
<span class="dim">-- not set --</span>
{/if}
</td>
{/if}
<td class="px-4 py-2 text-sm">
{#if event_presenter_obj?.updated_on}
{ae_util.iso_datetime_formatter(
event_presenter_obj?.updated_on,
'datetime_iso_12_no_seconds'
)}
{:else}
<span class="dim">-- not set --</span>
{/if}
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:else}
<p class="text-sm">No presenters available to show.</p>
{/if}
</section>
<style>
.dim {
opacity: 0.5;
color: #999;
}
</style>

View File

@@ -0,0 +1,139 @@
<script lang="ts">
interface Props {
// Exports
container_class_li?: string | Array<string>;
// display_mode?: string; // 'default', 'compact', 'minimal', 'launcher'
// event_presenter_id_random_li?: Array<string>;
event_presenter_obj_li?: Array<any>;
link_to_type?: string;
link_to_id?: string;
// export let lq__event_presentation_obj
show_presentation_fields?: boolean;
show_session_fields?: boolean;
hide_session_code?: boolean;
log_lvl?: number;
}
let {
container_class_li = [],
// display_mode = 'default',
// event_presenter_id_random_li = $bindable(),
event_presenter_obj_li = $bindable(),
link_to_type,
link_to_id,
show_presentation_fields = false,
show_session_fields = false,
hide_session_code = false,
log_lvl = $bindable(0)
}: Props = $props();
// Imports
import Comp_event_presenter_obj_tbl from './ae_comp__event_presenter_obj_tbl.svelte';
import { liveQuery } from 'dexie';
import {
events_loc,
events_sess,
events_slct,
events_trigger
} from '$lib/stores/ae_events_stores';
import { db_events } from '$lib/ae_events/db_events';
if (log_lvl) {
console.log(`link_to_type: ${link_to_type}; link_to_id: ${link_to_id}`);
}
// Variables
// let ae_promises: key_val = {};
// let ae_tmp: key_val = {};
// let ae_triggers: key_val = {};
let event_presenter_id_random_li: Array<string> = $state([]);
let dq__where_type_id_val: string = `${link_to_type}_id`;
let dq__where_eq_id_val: string = link_to_id ?? '';
// *** Functions and Logic
let lq__event_presenter_obj_li = $derived(
liveQuery(async () => {
let results: any;
// let event_presenter_id_random_li = []; // This is to prevent the array from constantly updating and triggering the liveQuery.
// for (let i = 0; i < $events_sess?.event_presenter_obj_li.length; i++) {
// let event_presenter_obj = $events_sess?.event_presenter_obj_li[i];
// let event_presenter_id_random = event_presenter_obj.event_presenter_id_random;
// event_presenter_id_random_li.push(event_presenter_id_random);
// }
if (event_presenter_obj_li?.length) {
if (log_lvl) {
console.log(`LQ - Using event_presenter_obj_li to get event presenters.`);
}
event_presenter_id_random_li = []; // This is to prevent the array from constantly updating and triggering the liveQuery.
for (let i = 0; i < event_presenter_obj_li.length; i++) {
let event_presenter_obj = event_presenter_obj_li[i];
let event_presenter_id_random = event_presenter_obj.event_presenter_id_random;
event_presenter_id_random_li.push(event_presenter_id_random);
}
// if (event_presenter_id_random_li.length) {
results = await db_events.presenter.bulkGet(event_presenter_id_random_li);
// }
} else if (link_to_type && link_to_id) {
console.log(
`Trying where: ${dq__where_type_id_val}; equals: ${dq__where_eq_id_val}`
);
event_presenter_id_random_li = [];
results = await db_events.presenter
.where(dq__where_type_id_val)
.equals(dq__where_eq_id_val)
.sortBy('name');
} else {
event_presenter_id_random_li = [];
results = [];
}
// Check if results are different than the current session version stored under $events_slct
if (
$events_slct.event_presenter_obj_li &&
JSON.stringify($events_slct.event_presenter_obj_li) !== JSON.stringify(results)
) {
$events_slct.event_presenter_obj_li = [...results];
if (log_lvl) {
console.log(
`Session slct li stored version has changed for ID = ${$events_slct.journal_id}`,
$events_slct.event_presenter_obj_li
);
}
} else {
if (log_lvl > 1) {
console.log(
`Session slct li stored version has not changed for ID = ${$events_slct.journal_id}`
);
}
}
return results;
})
);
</script>
<!-- {#if $lq__event_presenter_obj_li && $lq__event_presenter_obj_li?.length} -->
<!-- {#if event_presenter_id_random_li && event_presenter_id_random_li?.length > 0} -->
{#if event_presenter_obj_li && event_presenter_obj_li?.length}
<!-- {#if event_presenter_id_random_li && event_presenter_id_random_li?.length} -->
<Comp_event_presenter_obj_tbl
{container_class_li}
{lq__event_presenter_obj_li}
{show_presentation_fields}
{show_session_fields}
{hide_session_code}
{log_lvl}
></Comp_event_presenter_obj_tbl>
{:else}
<section class="grow px-1 md:px-2 pb-28 flex flex-col gap-1 items-center">
<p>No presenters available to show in table.</p>
</section>
{/if}