It has been a long two or three weeks...

This commit is contained in:
Scott Idem
2024-03-15 17:48:14 -04:00
parent 68b0efb6c9
commit 0400aa429b
13 changed files with 725 additions and 222 deletions

21
package-lock.json generated
View File

@@ -1750,12 +1750,15 @@
"dev": true
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/brace-expansion": {
@@ -2225,9 +2228,9 @@
"dev": true
},
"node_modules/electron-to-chromium": {
"version": "1.4.704",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.704.tgz",
"integrity": "sha512-OK01+86Qvby1V6cTiowVbhp25aX4DLZnwar+NocAOXdzKAByd+jq5156bmo4kHwevWMknznW18Y/Svfk2dU91A==",
"version": "1.4.707",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.707.tgz",
"integrity": "sha512-qRq74Mo7ChePOU6GHdfAJ0NREXU8vQTlVlfWz3wNygFay6xrd/fY2J7oGHwrhFeU30OVctGLdTh/FcnokTWpng==",
"dev": true
},
"node_modules/emoji-regex": {
@@ -2688,9 +2691,9 @@
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"funding": [
{
"type": "individual",

View File

@@ -215,4 +215,24 @@ input:required {
div.btn-group button:last-child {
border-top-right-radius: .25rem;
border-bottom-right-radius: .25rem;
} */
} */
.ae_md_hide {
/* outline: medium dashed green; */
/* display: none; */
}
@media (max-width: 767px) {
.ae_md_hide {
/* outline: medium dashed red; */
display: none;
}
}
@media (min-width: 768px) {
.ae_lg_hide {
/* outline: medium dashed blue; */
display: none;
}
}

View File

@@ -178,6 +178,13 @@ async function handle_load_ae_obj_li__exhibit({api_cfg, event_id, try_cache=true
let params = {};
let params_json: key_val = {};
// params_json['and_qry'] = {};
// params_json['and_qry']['license_max'] = 10;
params_json['and_in_li'] = {
license_max : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
};
// if (fulltext_search_qry_str && fulltext_search_qry_str.length > 2) {
// params_json['ft_qry'] = {
// 'default_qry_str': fulltext_search_qry_str,
@@ -203,7 +210,7 @@ async function handle_load_ae_obj_li__exhibit({api_cfg, event_id, try_cache=true
// order_by_li: {'priority': 'DESC', 'sort': 'DESC', 'created_on': 'DESC', 'updated_on': 'DESC'},
limit: limit,
offset: offset,
// params_json: params_json,
params_json: params_json,
params: params,
log_lvl: 2
})

View File

@@ -59,6 +59,10 @@ let events_local_data_struct: key_val = {
// // 'LNDF-67-89-92': { 'key': 'example@oneskyit.com', 'updated_on': '2024-03-13T08:05:29Z'}
// },
edit_license_li: false,
// The "tab" is a key value list of exhibit ID and tab name. This is intentionally using local storage to store the current tab for each exhibit.
// example: {'LNDF-67-89-92': 'start', 'OFLN-32-38-14': 'add_scan'}
tab: {},
},
// Presentation Management (Distributing)
@@ -119,7 +123,9 @@ let events_session_data_struct: key_val = {
'passcode': '',
'session_count': 0,
'updated_on': new Date().toISOString()
}
},
qr_scan_result: null,
},
// Presentation Management (Distributing)
@@ -132,7 +138,10 @@ console.log(`AE Stores - App Events Session Storage Data:`, events_session_data_
export let events_sess = writable(events_session_data_struct);
/* *** BEGIN *** Initialize ae_events_slct */
/* *** BEGIN *** Initialize events_slct and events_trigger */
/* The slct and slct_trigger variable should not be stored in local storage. Only use session storage because browser tabs can be open to different events, badges, exhibits, etc. */
// Intended for temporary session storage.
// Updated 2024-03-06
let events_slct_obj_template: key_val = {
// Top level
@@ -144,15 +153,19 @@ let events_slct_obj_template: key_val = {
'abstract_id': null,
'abstract_obj': {},
'abstract_obj_li': [],
'badge_id': null,
'badge_obj': {},
'badge_obj_li': [],
'badge_template_id': null,
'badge_template_obj': {},
'badge_template_obj_li': [],
'device_id': null,
'device_obj': {},
'device_obj_li': [],
'exhibit_id': null,
'exhibit_obj': {},
'exhibit_obj_li': [],
@@ -165,32 +178,38 @@ let events_slct_obj_template: key_val = {
'file_id': null,
'file_obj': {},
'file_obj_li': [],
'location_id': null,
'location_obj': {},
'location_obj_li': [],
'person_id': null,
'person_obj': {},
'person_obj_li': [],
'presentation_id': null,
'presentation_obj': {},
'presentation_obj_li': [],
'presenter_id': null,
'presenter_obj': {},
'presenter_obj_li': [],
'session_id': null,
'session_obj': {},
'session_obj_li': [],
};
// console.log(`AE Stores - Selected Events Objects:`, events_slct_obj_template);
// This works, but does not uses local storage:
// export let slct = writable(events_slct_obj_template);
// This works, and uses *session* (not local) storage:
export let events_slct = writable(events_slct_obj_template);
// This works and uses *local* storage:
export let events_slct: Writable<key_val> = localStorageStore('ae_events_slct', events_slct_obj_template);
// export let events_slct: Writable<key_val> = localStorageStore('ae_events_slct', events_slct_obj_template);
/* *** BEGIN *** Initialize ae_events_trigger */
/* *** BEGIN *** Initialize events_trigger */
// Intended for temporary session storage.
// Updated 2024-03-06
export let events_trigger: any = writable(null);
// console.log(`AE Stores - Selected Trigger:`, ae_events_trigger);
// console.log(`AE Events Stores - Events Trigger:`, events_trigger);

View File

@@ -213,20 +213,21 @@ export let ae_api = writable(ae_api_data_struct);
let ae_trig_template: key_val = {};
export let ae_trig = writable(ae_trig_template);
/* *** BEGIN *** Initialize slct_trigger and slct variables. The slct variable can be stored with local storage. */
// Updated 2024-02-27
export let slct_trigger: any = writable(null);
// console.log(`AE Stores - Selected Trigger:`, slct_trigger);
/* *** BEGIN *** Initialize slct and slct_trigger */
/* The slct and slct_trigger variable should not be stored in local storage. Only use session storage because browser tabs can be open to different accounts, events, sponsorships, etc. */
// Intended for temporary session storage.
// Updated 2024-03-15
let slct_obj_template: key_val = {
'account_id': ae_account_id,
'account_obj': {},
'event_id': null,
'event_obj': {},
'event_obj_li': [],
'event_exhibit_id': null,
'event_exhibit_obj': {},
'event_exhibit_obj_li': [],
// 'event_exhibit_id': null,
// 'event_exhibit_obj': {},
// 'event_exhibit_obj_li': [],
'event_presentation_id': null,
'event_presentation_obj': {},
'event_presentation_obj_li': [],
@@ -251,8 +252,15 @@ let slct_obj_template: key_val = {
};
// console.log(`AE Stores - Selected Objects:`, slct_obj_template);
// This works, but does not uses local storage:
// export let slct = writable(slct_obj_template);
// This works, and uses *session* (not local) storage:
export let slct = writable(slct_obj_template);
// This works and uses local storage:
export let slct: Writable<key_val> = localStorageStore('ae_slct', slct_obj_template);
// This works and uses *local* storage:
// export let slct: Writable<key_val> = localStorageStore('ae_slct', slct_obj_template);
/* *** BEGIN *** Initialize slct_trigger */
// Intended for temporary session storage.
// Updated 2024-02-27
export let slct_trigger: any = writable(null);
// console.log(`AE Stores - Selected Trigger:`, slct_trigger);

View File

@@ -243,6 +243,94 @@ export let extract_prefixed_form_data = function extract_prefixed_form_data({pre
}
/* This utility function processes specific data string.
* MECARD
* OBJ = OBJ:ot:example,oi:asdf1234
* ot = Aether object type; oi = Aether object ID random
* KV = KV:"key":"value"
* JS = {"id":123,"name":"example name"}
* http or https?
* Common short keys used:
* bdg: Badge ID Random
* reg: Registration ID Random
* exid: External ID
* gn: Given First Name
* fn: Family Last Name
* em: Email Address
*/
// Updated 2022-02-11
export let process_data_string = function process_data_string(data_string) {
console.log('*** process_data_string() ***');
// console.log(data_string);
let obj = {};
let colon_index = data_string.indexOf(':')
if (colon_index) {
let data_string_type = data_string.slice(0, colon_index);
console.log(data_string_type);
obj['qr_type'] = data_string_type;
if (data_string_type == 'MECARD') {
let mecard_str = data_string.slice(colon_index+1);
console.log(mecard_str);
obj['str'] = mecard_str;
} else if (data_string_type == 'OBJ') {
let key_value_str = data_string.slice(colon_index+1);
console.log(key_value_str);
let key_value_array = key_value_str.split(',');
// console.log(key_value_array);
let ot_colon_index = key_value_array[0].indexOf(':')
let obj_type = key_value_array[0].slice(ot_colon_index+1);
// console.log(obj_type);
let oi_colon_index = key_value_array[1].indexOf(':')
let obj_id = key_value_array[1].slice(oi_colon_index+1);
// console.log(obj_id);
obj['type'] = obj_type;
obj['id'] = obj_id;
} else if (data_string_type == 'JSON') {
let partial_json_str = data_string.slice(colon_index+1);
console.log(partial_json_str);
let json_str = `{${partial_json_str}}`;
console.log(json_str);
obj['json'] = JSON.parse(json_str);
} else if (data_string_type == 'STR') {
let str = data_string.slice(colon_index+1);
console.log(str);
obj['str'] = str;
} else if (data_string_type == 'http' || data_string_type == 'https') {
console.log(`http or https: ${data_string}`);
obj['type'] = 'url';
obj['url'] = data_string;
} else {
console.log('The unknown data string type was found. Returning the string part.')
let unknown_str = data_string.slice(colon_index+1);
console.log(unknown_str);
obj['str'] = unknown_str;
}
} else {
console.log('The data string type was not found. Returning the entire string.')
console.log(data_string);
obj['qr_type'] = 'UNKNOWN';
obj['str'] = data_string;
// return false;
}
console.log(obj);
return obj; // Returns an object
}
// NOTE: I know there is a better more efficient way to do this, but I don't have time for that right now.
export let process_permission_checks = function process_permission_checks(access_type: string) {
// let access_checks = { 'access_type': null, 'super_check': null };
@@ -523,6 +611,7 @@ export let ae_util = {
iso_datetime_formatter: iso_datetime_formatter,
number_w_commas: number_w_commas,
extract_prefixed_form_data: extract_prefixed_form_data,
process_data_string: process_data_string,
process_permission_checks: process_permission_checks,
handle_url_and_message: handle_url_and_message,
create_a_element: create_a_element,

View File

@@ -784,7 +784,7 @@ export let get_ae_obj_li_for_obj_id_crud = async function get_ae_obj_li_for_obj_
if (params_json) {
// NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
// Max charcters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
// Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
console.log('JSON Object:', params_json);
// NOTE: "jp" stands for "JSON Params"
params['jp'] = encodeURIComponent(JSON.stringify(params_json));
@@ -796,7 +796,7 @@ export let get_ae_obj_li_for_obj_id_crud = async function get_ae_obj_li_for_obj_
// if (json_obj) {
// // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
// // Max charcters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
// // Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
// console.log('JSON Object:', json_obj);
// params['json_str'] = encodeURIComponent(JSON.stringify(json_obj));
// if (params['json_str'].length > 2083) {

View File

@@ -3,6 +3,8 @@ import Dexie, { type Table } from 'dexie';
export interface Badge {
// id?: number;
id_random: string;
event_badge_id_random: string;
event_id_random: string;
full_name: string;
full_name_override: null|string;
email: string;
@@ -23,14 +25,26 @@ export interface Badge {
export interface Exhibit {
// id?: number;
id_random: string;
event_exhibit_id_random: string;
event_id_random: string;
code: string;
name: string;
tagline: null|string;
description: null|string;
staff_passcode: null
data_json: string;
data_json: null|string;
leads_api_access: null|boolean;
leads_custom_questions_json: null|string;
leads_device_sm_qty: null|number;
leads_device_lg_qty: null|number;
license_max: number;
license_li_json: string;
license_li_json: null|string;
cfg_json: string;
enable: boolean;
hide: boolean;
priority: boolean
sort: number;
group: string;
created_on: Date;
updated_on: Date;
}

View File

@@ -278,7 +278,7 @@ function handle_qr_manual_entry() {
<section
class="ae_element qr_scanner border border-2 border-primary p-2 space-y-2 flex flex-col gap-1 justify-center items-center"
class="ae_element qr_scanner border border-2 border-primary space-y-2 flex flex-col gap-1 justify-center items-center min-w-full max-w-full"
class:not_started={scanning_status == 'not_started'}
class:paused={scanning_status == 'paused'}
class:scanning={scanning_status == 'scanning'}
@@ -292,7 +292,7 @@ function handle_qr_manual_entry() {
<!-- <legend class="d_none">QR Scanner:</legend> -->
<div
class="ae_container qr_scanning_container flex flex-col gap-1 justify-center"
class="ae_container qr_scanning_container"
>
<div
class="ae_options"
@@ -300,10 +300,10 @@ function handle_qr_manual_entry() {
{#if scanning_status == 'not_started' }
<button on:click={handle_start_qr_scanning} class="btn btn-lg variant-soft-primary btn_start"><span class="fas fa-qrcode"></span> Start Scanning</button>
{:else if scanning_status == 'paused' && show_pause_btn}
<button on:click={handle_resume_qr_scanning} class="btn btn-lg variant-soft-primary btn_resume"><span class="fas fa-play"></span> Resume</button>
<button on:click={handle_resume_qr_scanning} class="btn btn-md variant-soft-primary btn_resume"><span class="fas fa-play"></span> Resume</button>
<span>Scanning paused</span>
{:else if scanning_status == 'scanning'}
<button on:click={handle_stop_qr_scanning} class="btn btn-lg variant-soft-secondary btn_stop"><span class="fas fa-stop-circle"></span> Stop</button>
<button on:click={handle_stop_qr_scanning} class="btn btn-md variant-soft-secondary btn_stop"><span class="fas fa-stop-circle m-1"></span> Stop</button>
{#if show_pause_btn}
<button on:click={handle_pause_qr_scanning} class="btn btn-lg variant-soft-secondary btn_pause"><span class="fas fa-pause-circle"></span> Pause</button>
{/if}
@@ -392,4 +392,55 @@ function handle_qr_manual_entry() {
background-color: hsla(120, 100%, 75%, 0.3);
border-color: hsla(120, 100%, 75%, 0.6);
}
.qr_scanner {
/* outline: solid thin pink; */
max-width: 100vw;
/* overflow-x: scroll; */
display: flex;
flex-direction: column;
/* flex-wrap: wrap; */
justify-content: flex-start;
align-items: center; /* center */
align-content: stretch;
}
.ae_element.qr_scanner div.qr_scanner_viewfinder {
/* max-width: 100vw; */
/* contain: content; */
/* contain: contain; */
}
.qr_scanner .qr_scanner_viewfinder {
/* outline: dashed medium blue; */
min-width: 400px;
width: 100%;
/* max-width: 100%; */
max-width: 500px;
/* max-width: 100vw; */
/* outline: solid thin red; */
contain: contain;
overflow-x: scroll;
}
@media (max-width: 767px) {
.qr_scanner .qr_scanner_viewfinder {
/* outline: dashed medium red; */
min-width: 80vw;
/* width: 100%; */
/* max-width: 100%; */
/* max-width: 450px; */
max-width: 100vw;
margin: 0;
padding: 0;
}
}
</style>

View File

@@ -13,7 +13,7 @@ onMount(() => {
// console.log('ae_ slct:', $slct);
console.log(window.location.href);
// console.log(window.location.href);
let href_url = window.location.href;
// $ae_loc.href_url = href_url;
// console.log(`$ae_loc.href_url = `, $ae_loc.href_url);

View File

@@ -4,13 +4,14 @@ console.log(`ae_events_leads +page data:`, data);
// console.log(`ae_events_leads Data Params:`, data.url.searchParams.get('event_id'));
import { onMount } from 'svelte';
import { goto, invalidate, pushState, replaceState } from '$app/navigation';
import { ae_util } from '$lib/ae_utils';
import { api } from '$lib/api';
import { liveQuery } from "dexie";
import { db_events } from "$lib/db_events";
import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/ae_stores';
import { events_loc, events_slct, events_trigger } from '$lib/ae_events_stores';
import { events_loc, events_sess, events_slct, events_trigger } from '$lib/ae_events_stores';
import Element_data_store from '$lib/element_data_store.svelte';
@@ -18,26 +19,30 @@ import Element_data_store from '$lib/element_data_store.svelte';
let event_exhibit_obj_li = liveQuery(
// () => db_events.exhibits.toArray()
() => db_events.exhibits
// .where('passcode')
.where('license_max')
// .aboveOrEqual(0)
// .equals('99999')
.orderBy('name')
.above(0)
.sortBy('name') // Use sortBy() instead of orderBy(). toArray() is also not needed???
// .orderBy('name')
// .offset(10).limit(5)
.toArray()
// .toArray()
);
// if (data.url.searchParams.get('event_id')) {
// $events_slct.event_id = data.url.searchParams.get('event_id');
// } else if (data.ae_loc.site_cfg_json.slct__event_id) {
// $events_slct.event_id = data.ae_loc.site_cfg_json.slct__event_id;
// } else if ($events_loc.default__event_id) {
// $events_slct.event_id = $events_loc.default__event_id;
// } else if ($events_slct.event_id) {
// console.log(`Event ID already set:`, $events_slct.event_id);
// } else {
// console.log(`No Event ID set.`);
// }
// This should probably be moved
if (data.url.searchParams.get('event_id')) {
$events_slct.event_id = data.url.searchParams.get('event_id');
} else if (data.ae_loc.site_cfg_json.slct__event_id) {
$events_slct.event_id = data.ae_loc.site_cfg_json.slct__event_id;
} else if ($events_loc.default__event_id) {
$events_slct.event_id = $events_loc.default__event_id;
} else if ($events_slct.event_id) {
console.log(`Event ID already set:`, $events_slct.event_id);
} else {
console.log(`No Event ID set.`);
}
export let event_exhibit_staff_passcode: string = '';
// export let event_exhibit_staff_passcode: string = '';
let disable_open_lead_retrieval_btn: boolean = true;
let disable_reset_passcode_btn: boolean = true;
let reset_passcode: string = '';
@@ -61,7 +66,7 @@ onMount(() => {
});
$: if (event_exhibit_staff_passcode.length >= 5) {
$: if ($events_sess.leads.entered_passcode && $events_sess.leads.entered_passcode >= 5) {
// disable_open_lead_retrieval_btn = false;
handle_check_event_exhibit_staff_passcode();
} else {
@@ -70,12 +75,27 @@ $: if (event_exhibit_staff_passcode.length >= 5) {
}
function handle_check_event_exhibit_staff_passcode() {
// console.log(`*** handle_check_event_exhibit_staff_passcode() *** $slct_event_exhibit_obj=`, $events_slct.exhibit_obj);
console.log(`*** handle_check_event_exhibit_staff_passcode() *** $events_slct.exhibit_obj=`, $events_slct.exhibit_obj);
if ($events_slct.exhibit_obj && event_exhibit_staff_passcode && event_exhibit_staff_passcode.length >= 4) {
if ($events_slct.exhibit_obj.staff_passcode == event_exhibit_staff_passcode) {
$events_sess.leads.open_href = '';
if ($events_slct.exhibit_obj && $events_sess.leads.entered_passcode && $events_sess.leads.entered_passcode.length >= 4) {
if ($events_slct.exhibit_obj.staff_passcode == $events_sess.leads.entered_passcode) {
console.log('Passcode matched');
disable_open_lead_retrieval_btn = false;
$events_sess.leads.entered_passcode = null;
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] = {
key: null,
updated_on: new Date().toISOString()
};
// console.log($events_slct);
$events_sess.leads.open_href = `/events_leads/exhibit/${$events_slct.exhibit_obj.id_random}?event_id=${$events_slct.event_id}`;
if ($events_loc.leads.auto_view) {
goto($events_sess.leads.open_href, {invalidateAll: true});
}
} else {
// console.log('Passcode does not match');
disable_open_lead_retrieval_btn = true;
@@ -88,7 +108,7 @@ function handle_check_event_exhibit_staff_passcode() {
}
if ($events_loc.leads.auto_view) {
open_exhibit_tracking($events_slct.exhibit_obj.event_exhibit_id_random, event_exhibit_staff_passcode)
// open_exhibit_tracking($events_slct.exhibit_obj.id_random)
} else {
// console.log(document.getElementById('open_lead_retrieval_btn'));
// document.getElementById('open_lead_retrieval_btn').focus();
@@ -96,22 +116,23 @@ function handle_check_event_exhibit_staff_passcode() {
}
function open_exhibit_tracking(event_exhibit_id_random, event_exhibit_staff_passcode) {
console.log(`open_exhibit_tracking() event_exhibit_id_random=${event_exhibit_id_random} event_exhibit_staff_passcode=${event_exhibit_staff_passcode}`);
// function open_exhibit_tracking(event_exhibit_id_random) {
// console.log(`open_exhibit_tracking() event_exhibit_id_random=${event_exhibit_id_random}`);
// let url = `/events_leads/exhibit/${event_exhibit_id_random}`;
// window.open(url, '_blank');
// window.focus();
// if (!event_exhibit_id_random) {
// console.log('No event exhibit ID provided.');
// return null;
// }
let url = `/events_leads/exhibit/${event_exhibit_id_random}`;
window.open(url);
// window.open(url, '_blank');
window.focus();
}
// if ($events_loc.leads.auto_view) {
// goto($events_sess.leads.open_href, {invalidateAll: true});
// } else {
// }
// }
</script>
<section class="ae_events_leads md:container h-full mx-auto">
<section class="ae_events_leads h-full w-full flex flex-col wrap align-begin justify-start space-y-4">
<h1 class="h2">Events - Leads</h1>
@@ -121,14 +142,14 @@ function open_exhibit_tracking(event_exhibit_id_random, event_exhibit_staff_pass
for_type="event"
for_id={$events_slct.event_id}
display="block"
class_li="variant-ghost-surface p-2"
class_li="variant-ghost-secondary p-2"
/>
<a href="/{$events_slct.event_id}">Event ID {$events_slct.event_id}</a>
<!-- <a href="/{$events_slct.event_id}">Event ID {$events_slct.event_id}</a> -->
{#if $event_exhibit_obj_li}
<h2>Exhibits</h2>
<h2 class="h3">Exhibits</h2>
<!-- <ul>
{#each $event_exhibit_obj_li as exhibit_obj}
<li>
@@ -139,51 +160,64 @@ function open_exhibit_tracking(event_exhibit_id_random, event_exhibit_staff_pass
<div class="event_exhibit_tracking_select_exhibit space-y-6">
<form on:submit|preventDefault={() => open_exhibit_tracking($events_slct.exhibit_obj, event_exhibit_staff_passcode)} class="form-floating">
<form
on:submit|preventDefault={() => {
$events_sess.leads.open_href = `/events_leads/exhibit/${$events_slct.exhibit_obj.id_random}?event_id=${$events_slct.event_id}`;
goto($events_sess.leads.open_href, {invalidateAll: true});
}}
class="form-floating">
<h2>Exhibitor Lead Retrieval</h2>
<div>Select your exhibit booth from the list and enter passcode you were given.</div>
<div class="form-floating mb-1 col-md-12 col-lg-12">
<label for="exhibit_list" class="label">
Exhibit List:<br>
<select bind:value={$events_slct.exhibit_obj} id="exhibit_list" class="select max-w-md">
<option value="">-- Nothing Selected --</option>
<option value="" selected>-- Nothing Selected --</option>
{#each $event_exhibit_obj_li as event_exhibit_obj, index}
<!-- <option value="{event_exhibit_obj.event_exhibit_id_random}">{event_exhibit_obj.name} (Booth # {event_exhibit_obj.code})</option> -->
<option value="{event_exhibit_obj}">{event_exhibit_obj.name} (Booth #{event_exhibit_obj.code})</option>
{/each}
<option value={event_exhibit_obj}>{event_exhibit_obj.name} (Booth #{event_exhibit_obj.code})</option>
{/each}
</select>
<label for="exhibit_list" class="label">
Exhibit List:
</label>
</div>
<div class="container_group">
<!-- <input bind:value={event_exhibit_staff_passcode} type="text" id="exhibit_passcode" placeholder="Exhibit passcode" /> -->
<!-- <input bind:value={$events_sess.leads.entered_passcode} type="text" id="exhibit_passcode" placeholder="Exhibit passcode" /> -->
<input
bind:value={event_exhibit_staff_passcode}
bind:value={$events_sess.leads.entered_passcode}
class="input max-w-40"
placeholder="Exhibit passcode"
/>
<!-- <button on:click={() => open_exhibit_tracking(exhibit_obj.event_exhibit_id_random, event_exhibit_staff_passcode)} id="open_lead_retrieval_btn" disabled={disable_open_lead_retrieval_btn} autofocus>Open Exhibitor Lead Retrieval</button> -->
<!-- <button on:click={() => open_exhibit_tracking(exhibit_obj.event_exhibit_id_random, $events_sess.leads.entered_passcode)} id="open_lead_retrieval_btn" disabled={disable_open_lead_retrieval_btn} autofocus>Open Exhibitor Lead Retrieval</button> -->
<button
type="submit"
disabled={disable_open_lead_retrieval_btn}
class="btn variant-filled-primary open_lead_retrieval_btn"
>
<span class="fas fa-arrow-right"></span> Open Exhibitor Lead Retrieval
<span class="fas fa-arrow-right mx-1"></span> Open Exhibitor Lead Retrieval
</button>
<!-- <a
on:click|preventDefault={() => goto($events_sess.leads.open_href, {invalidateAll: true})}
href={$events_sess.leads.open_href}
>
Open Exhibitor Lead Retrieval
</a> -->
</div>
</form>
{#if ($ae_loc.trusted_access)}
{#if ($ae_loc.administrator_access && !$events_loc.show_details)}
<div class="">
<!-- <input bind:value={reset_passcode} type="text" id="reset_exhibit_passcode" placeholder="Reset exhibit passcode" /> -->
<input bind:value={reset_passcode} placeholder="Reset passcode" title="Reset exhibit passcode" class="input max-w-40" />
<!-- <button on:click={() => open_exhibit_tracking(exhibit_obj.event_exhibit_id_random, event_exhibit_staff_passcode)} id="open_lead_retrieval_btn" disabled={disable_open_lead_retrieval_btn} autofocus>Open Exhibitor Lead Retrieval</button> -->
<!-- <button on:click={() => open_exhibit_tracking(exhibit_obj.event_exhibit_id_random, $events_sess.leads.entered_passcode)} id="open_lead_retrieval_btn" disabled={disable_open_lead_retrieval_btn} autofocus>Open Exhibitor Lead Retrieval</button> -->
<!-- <button type="button" id="reset_passcode_btn" disabled={disable_reset_passcode_btn} autofocus on:click={() => show_exhibit_tracking_add_modal=true}>Reset Passcode</button> -->
<button
@@ -194,7 +228,7 @@ function open_exhibit_tracking(event_exhibit_id_random, event_exhibit_staff_pass
}}
class="btn variant-filled-secondary reset_passcode_btn"
>
<span class="fas fa-undo"></span> Reset Passcode
<span class="fas fa-undo mx-1"></span> Reset Passcode
</button>
</div>
{/if}
@@ -203,7 +237,17 @@ function open_exhibit_tracking(event_exhibit_id_random, event_exhibit_staff_pass
</div>
<!-- <button
type="button"
on:click={() => {
console.log(`Goto Button Clicked`);
// goto($events_sess.leads.open_href, {invalidateAll: true});
goto('?key=value');
}}
class="btn variant-filled-secondary"
>
Test Goto Button
</button> -->
{/if}

View File

@@ -29,10 +29,10 @@ export async function load({ params, parent, url }) { // route
// Do not wait on these:
let event_id = url.searchParams.get('event_id');
let load_event_obj = events_func.handle_load_ae_obj_id__event({api_cfg: data.ae_api, event_id: event_id, try_cache: false});
console.log(`load_event_obj = `, load_event_obj);
// console.log(`load_event_obj = `, load_event_obj);
let load_event_exhibit_obj_li = events_func.handle_load_ae_obj_li__exhibit({api_cfg: data.ae_api, event_id: event_id, try_cache: false});
console.log(`load_event_exhibit_obj_li = `, load_event_exhibit_obj_li);
// console.log(`load_event_exhibit_obj_li = `, load_event_exhibit_obj_li);
// let exhibit_id = data.params.slug;
// let load_event_exhibit_obj = events_func.handle_load_ae_obj_id__exhibit({api_cfg: data.ae_api, exhibit_id: exhibit_id, try_cache: false});

View File

@@ -14,18 +14,13 @@ import { events_loc, events_sess, events_slct, events_trigger } from '$lib/ae_ev
import { events_func } from '$lib/ae_events_functions';
// This works and uses local storage:
// store_current_tab must be prefixed with $ to be reactive.
import { clipboard, FileDropzone, getModalStore, localStorageStore, ProgressRadial, RadioGroup, RadioItem, TabGroup, Tab, TabAnchor } from '@skeletonlabs/skeleton';
import type { Writable } from 'svelte/store';
// import type { Writable } from 'svelte/store';
import Element_data_store from '$lib/element_data_store.svelte';
import Element_qr_scanner from '$lib/element_qr_scanner.svelte';
const store_current_tab: Writable<string> = localStorageStore('ae_events_leads_current_tab', 'start');
console.log(`ae_events_leads exhibit +page.svelte [slug] store_current_tab:`, $store_current_tab);
let param_slug_event_exhibit_id = data.params.slug;
let event_exhibit_obj = liveQuery(
@@ -48,13 +43,30 @@ $events_trigger = 'load__event_exhibit_obj';
let license_submit_results: Promise<any>|key_val;
if ($events_loc.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]) {
console.log('Already logged in.');
} else {
console.log('Not logged in.');
$store_current_tab = 'start';
if (!$events_loc.leads.tab) {
$events_loc.leads.tab = {};
$events_loc.leads.tab[$events_slct.exhibit_id] = 'start';
}
if (!$events_loc.leads.auth_exhibit_kv) {
$events_loc.leads.auth_exhibit_kv = {};
}
if ($events_loc.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id]) {
console.log('Logged in using shared exhibit staff passcode.');
if ($events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key) {
console.log(`Using the license key: ${$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}`);
} else {
console.log('License key (email) not used.');
$events_loc.leads.tab[$events_slct.exhibit_id] = 'start';
}
} else {
console.log('Not logged in using shared exhibit staff passcode.');
$events_loc.leads.tab[$events_slct.exhibit_id] = 'start';
}
onMount(() => {
console.log('Events Leads Exhibit [slug]: +page.svelte');
@@ -69,7 +81,7 @@ onMount(() => {
});
// console.log(`$ae_loc = `, $ae_loc);
$: if ($slct.event_exhibit_obj && $events_sess.leads.entered_passcode) {
$: if ($events_slct.exhibit_obj && $events_sess.leads.entered_passcode) {
console.log('Check the passcode?');
if ($events_sess.leads.entered_passcode.length > 4) {
console.log('Check the passcode');
@@ -83,16 +95,24 @@ $: if ($slct.event_exhibit_obj && $events_sess.leads.entered_passcode) {
function handle_check_event_exhibit_staff_passcode() {
// console.log(`*** handle_check_event_exhibit_staff_passcode() *** $slct_event_exhibit_obj=`, $events_slct.exhibit_obj);
if (!$events_loc.leads.auth_exhibit_li) {
$events_loc.leads.auth_exhibit_li = {};
// if (!$events_loc.leads.auth_exhibit_li) {
// $events_loc.leads.auth_exhibit_li = {};
// }
if (!$events_loc.leads.auth_exhibit_kv) {
$events_loc.leads.auth_exhibit_kv = {};
}
if ($slct.event_exhibit_obj && $events_sess.leads.entered_passcode && $events_sess.leads.entered_passcode.length >= 4) {
if ($events_slct.exhibit_obj && $events_sess.leads.entered_passcode && $events_sess.leads.entered_passcode.length >= 4) {
if ($events_slct.exhibit_obj.staff_passcode == $events_sess.leads.entered_passcode) {
console.log('Passcode matched');
// disable_open_lead_retrieval_btn = false;
$events_sess.leads.entered_passcode = null;
$events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id] = new Date().toISOString();
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] = {
key: null,
updated_on: new Date().toISOString()
};
} else {
// console.log('Passcode does not match');
// disable_open_lead_retrieval_btn = true;
@@ -402,6 +422,107 @@ function send_init_confirm_email({to_email}) {
});
}
function handle_qr_scan_result(event) {
console.log('*** handle_qr_scan_result() ***');
let qr_scan_result = event.detail.result;
console.log(qr_scan_result);
let qr_scan_obj = ae_util.process_data_string(qr_scan_result);
if (qr_scan_obj.qr_type == 'OBJ') {
console.log(`Got a QR type of OBJ. Type ${qr_scan_obj.type}; ID ${qr_scan_obj.id}`);
if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_badge') {
console.log(`Found an Event Badge object type and ID.`);
let event_badge_id = qr_scan_obj.id
$events_sess.leads.qr_scan_result = `Found a badge type with ID: ${event_badge_id}`;
// event_exhibit_tracking_obj_create_promise = await handle_create_event_exhibit_tracking_obj($slct.event_exhibit_id, event_badge_id);
// console.log(event_exhibit_tracking_obj_create_promise);
// if (event_exhibit_tracking_obj_create_promise) {
// console.log('Created new log entry for this badge.');
// console.log(event_exhibit_tracking_obj_create_promise);
// handle_load_event_exhibit_obj({event_exhibit_id: $slct.event_exhibit_id, try_cache: false});
// $slct.event_exhibit_tracking_obj = event_exhibit_tracking_obj_create_promise;
// $slct.event_exhibit_tracking_id = $slct.event_exhibit_tracking_obj.event_exhibit_tracking_id_random;
// // $slct.event_badge_obj = $slct.event_exhibit_tracking_obj.event_badge;
// // $slct.event_badge_id = $slct.event_badge_obj.event_badge_id_random;
// show_add_qr = false;
// qr_scan_result = '';
// qr_scan_obj = {};
// show_tracking_entry = true;
// } else if (event_exhibit_tracking_obj_create_promise === null) {
// console.log('A matching log entry probably exists for this person!');
// } else {
// console.log('Something unexpected happened???');
// }
} else if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_exhibit') {
console.log(`Ignoring.`);
} else if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_person') {
console.log(`Ignoring.`);
} else if (qr_scan_obj.type && qr_scan_obj.id && qr_scan_obj.type == 'event_session') {
console.log(`Ignoring.`);
} else {
console.log(`Ignoring. The object returned was unexpected or not valid.`);
console.log(qr_scan_obj);
}
} else if (qr_scan_obj.qr_type == 'MECARD') {
console.log(`Got a QR type of MECARD. This was not expected, but we will at least display it???`);
// https://github.com/ertant/vCard
// vcard = vCardParser.parse(qr_scan_obj.str); // vCard
// console.log(vcard);
mecard = qr_scan_obj.str.split(';'); // vCard
// NOTE: Next we need to loop through the values and split each again on ":".
// NOTE: Then probably do a second check based on the known key values (N, EMAIL, ADR).
console.log(mecard);
show_mecard = true;
} else {
console.log(`Got a QR type of ${qr_scan_obj.qr_type}. Display warning to user, but otherwise ignoring.`);
console.log(qr_scan_obj);
}
}
function handle_qr_camera(event) {
console.log('*** handle_qr_camera() ***', event.detail);
if (!$ae_loc.hub.qr) {
$ae_loc.hub.qr = {};
}
if (event.detail.status == 'allowed') {
// console.log('Camera access allowed');
$ae_loc.hub.qr.camera_status = 'allowed';
} else if (event.detail.status == 'denied') {
console.log('Camera access denied!?');
$ae_loc.hub.qr.camera_status = 'denied';
}
}
// Updated 2022-04-22
export let get_event_exhibit_tracking_export = async function get_event_exhibit_tracking_export({event_exhibit_id, file_type='CSV', return_file=true, filename=null, auto_download=false, params={}, log_lvl=0}) {
console.log('*** stores_event_api.js: get_event_exhibit_tracking_export() ***');
const endpoint = `/event/exhibit/${event_exhibit_id}/tracking/export`;
if (file_type == 'CSV' || file_type == 'Excel') {
params['file_type'] = file_type;
}
params['return_file'] = true;
let event_exhibit_tracking_export_file_get_promise = await api.get_object({api_cfg: ae_api, endpoint: endpoint, params: params, return_blob: true, filename: filename, auto_download: auto_download, log_lvl: log_lvl});
// console.log(event_exhibit_tracking_export_file_get_promise);
return event_exhibit_tracking_export_file_get_promise;
}
</script>
@@ -421,7 +542,7 @@ function send_init_confirm_email({to_email}) {
<!-- <div
class="events__leads__exhibit_obj_main_about"
class:hidden={$store_current_tab !== 'start'}
class:hidden={$events_loc.leads.tab[$events_slct.exhibit_id] !== 'start'}
>
<Element_data_store
ds_code="events__leads__exhibit_obj_main_about"
@@ -434,16 +555,12 @@ function send_init_confirm_email({to_email}) {
</div> -->
{#if $events_slct.exhibit_id && $event_exhibit_obj}
<section class="ae_h_scrollfix"></section>
<!-- <section class="ae_h_scrollfix"> -->
<!-- <hr>
<p class="variant-soft-warning">Make logging in with shared exhibit passcode work first!</p>
<p>Mark as logged in by using: events_loc.leads.auth_exhibit_li. This is a key (exhibit ID) and value (started datetime) pair. They can be logged into more than one exhibit at a time. Warn about log out when using the "Use License" button. Avoid "accidental" clicks.</p>
<p>Check that the started datetime is still within X period and check against the tracked session timestamps. The table or object field is event_exhibit.license_sess_li.</p>
<p>Config option to show additional settings or information? Hide the Email and Copy buttons by default. Hide license input fields by default.</p>
<p class="variant-soft-warning">Tabs: Main (list of licenses to use, show started timestamps?, summary of counts per license), Manage (export, settings), Add/Scan, Leads</p>
<p>The tabs and everything is not visible until they enter the shared exhibit passcode. Or maybe just gray out tabs and hide any details under the active one.</p>
<p>Header, footer, etc can be shown/hidden</p>
<p>The header image can use md:hidden to hide when too small?</p>
<p class="variant-soft-warning">Only show exhibitors in the list that have licenses available.</p>
@@ -460,7 +577,7 @@ function send_init_confirm_email({to_email}) {
class="bg-surface-100-800-token w-full"
>
<Tab
bind:group={$store_current_tab}
bind:group={$events_loc.leads.tab[$events_slct.exhibit_id]}
name="tab_start"
value={'start'}>
<svelte:fragment slot="lead">
@@ -472,11 +589,11 @@ function send_init_confirm_email({to_email}) {
<!-- Manage - For changing the settings, exporting, and other. -->
<Tab
bind:group={$store_current_tab}
bind:group={$events_loc.leads.tab[$events_slct.exhibit_id]}
name="tab_manage"
value={'manage'}
disabled={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_li || !$events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]}
regionTab={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_li || !$events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id] ? 'text-slate-400' : ''}
disabled={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_kv || !$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
regionTab={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_kv || !$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] ? 'text-slate-400' : ''}
>
<svelte:fragment slot="lead">
<span class="fas fa-cogs"></span>
@@ -485,11 +602,11 @@ function send_init_confirm_email({to_email}) {
</Tab>
<Tab
bind:group={$store_current_tab}
bind:group={$events_loc.leads.tab[$events_slct.exhibit_id]}
name="tab_add_scan"
value={'add_scan'}
disabled={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_li || !$events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]}
regionTab={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_li || !$events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id] ? 'text-slate-400' : ''}
disabled={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_kv || !$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
regionTab={!$events_slct.exhibit_obj || !$events_loc?.leads.auth_exhibit_kv || !$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] ? 'text-slate-400' : ''}
>
<svelte:fragment slot="lead">
<span class="fas fa-qrcode"></span>
@@ -499,29 +616,44 @@ function send_init_confirm_email({to_email}) {
</TabGroup>
{#if $store_current_tab === 'start'}
<!-- BEGIN Tab: Main (start) -->
{#if $events_loc.leads.tab[$events_slct.exhibit_id] === 'start'}
<div class="text-center m-4">
<p>
<section class="tab__start flex flex-col wrap justify-center items-center space-y-4 ae_h_scrollfix">
<div class="flex flex-col wrap justify-center items-center">
<h2 class="h3">
<!-- {$events_slct.exhibit_obj.name} -->
<strong>{$event_exhibit_obj?.name ?? 'Welcome to Leads for Exhibits!'}</strong>
<strong>{$event_exhibit_obj?.code ?? ''}</strong>
</p>
</h2>
<h3 class="h4">
{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
<span class="fas fa-check text-green-500"></span>
{$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
<button
type="button"
class="btn btn-sm variant-soft-warning"
on:click={() => {
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key = null;
}}
>
<span class="fas fa-times mx-1"></span>
Clear License
</button>
{:else}
<span class="fas fa-times text-red-500"></span>
No license key selected.
{/if}
</h3>
</div>
{#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]}
<!-- <button
type="button"
on:click={() => {
console.log('Log Out');
$events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id] = null;
}}
title="Log out"
class="btn variant-soft-primary w-40"
>
<span class="fas fa-sign-out-alt mx-1"></span>
Log Out
</button> -->
{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
<p>
You are logged in using the shared exhibit staff passcode and are using the license key for {$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}. Any leads you collect will be associated with this license key (email address).
</p>
{:else if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
<p>To use the lead retrieval service, please select a license from the list below.</p>
{:else}
<p>To access this exhibit you must enter the shared staff passcode that you were given. You will then be able to select a license and use the lead retrieval service from your device.</p>
@@ -538,13 +670,13 @@ function send_init_confirm_email({to_email}) {
{/if}
{#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]}
{#if $events_loc?.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
<!-- Loop through the key value pairs. Each license key has a passcode, updated_on, etc -->
{#if $event_exhibit_obj?.license_max }
<h2 class="h3">License List (max {$event_exhibit_obj?.license_max})</h2>
<section class="ae_license_list">
{#if $event_exhibit_obj?.license_li_json && $event_exhibit_obj?.license_li_json.length < $event_exhibit_obj?.license_max}
<button
@@ -587,23 +719,26 @@ function send_init_confirm_email({to_email}) {
</button> -->
{/if} <!-- $event_exhibit_obj?.license_li_json.length < $event_exhibit_obj?.license_max -->
<div>Use one of the options below to log in using one of the licenses.</div>
<div>Use the "Sign In" or "Email" option buttons below to log in using one of the available licenses. If you select a license that is already in use on another device, it will be logged out. The "Sign In" option will use the license selected with your browser. The "Email" option will send an email with a link to log in.</div>
<section class="ae_license_list ae_h_scrollfix">
<form
on:submit|preventDefault={() => {
console.log('Save License List');
handle_submit_form(event);
}}
id="form__license_table"
class="flex flex-row items-center space-x-2 border border-ae-3 p-0 m-0"
class="p-0 m-0"
>
<input type="hidden" name="license_max" value={$event_exhibit_obj?.license_max} />
<!-- <div class="ae_h_scrollfix"> -->
<table class="table table-compact table-hover">
<thead>
<tr>
<th>Use License</th>
<th>License</th>
<th>Info</th>
<!-- <th>Email</th> -->
<!-- <th>Full Name</th> -->
@@ -648,7 +783,7 @@ function send_init_confirm_email({to_email}) {
<button
type="button"
on:click={() => {
console.log('Use License');
console.log(`Use license: ${license.email}`);
// Use the license key to sign in
// $events_slct.exhibit_obj.url = `${data.url.origin}/events_leads/exhibit/${$events_slct.exhibit_id}?license_key=${index}&event_id=${$events_slct.event_id}`;
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] = {
@@ -669,7 +804,9 @@ function send_init_confirm_email({to_email}) {
// Send an email with the login link
send_init_confirm_email({ to_email: license.email });
}}
disabled={!$ae_loc.trusted_access}
class="btn btn-sm text-sm variant-soft-secondary"
title={`TEMPORARILY DISABLED: Send an email with the license login link to ${license.email}`}
>
<span class="fas fa-envelope mx-1"></span>
Email
@@ -694,57 +831,25 @@ function send_init_confirm_email({to_email}) {
</td>
<td>
<div class="flex flex-row wrap gap-1 justify-between items-center">
<!-- All elements should be centered horizontally and vertically using flex. -->
<div class="
flex flex-row wrap gap-1
items-center justify-center
content-center
"
>
<!-- <td> -->
<div class="full_name_email">
{#if $events_loc.leads.edit_license_li}
<input
type="text"
name={`license_${index}_full_name`}
value={license.full_name ?? ''}
placeholder="Full Name"
required
class="input text-sm max-w-40 font-mono"
minlength="2"
/>
{:else}
<div class="flex flex-col gap-1 wrap full_name_email grow">
<span class="text-sm">{license.full_name}</span>
{/if}
<!-- </td> -->
<!-- <input type="email" value={key ?? ''} name="license_key" placeholder="Valid email" required class="input text-sm max-w-xs" /> -->
{#if $events_loc.leads.edit_license_li}
<input
type="text"
name={`license_${index}_email`}
required
value={license.email ?? ''}
placeholder="Valid email"
minlength="5"
class="input text-sm max-w-xs font-mono"
/>
{:else}
<span class="text-sm">{license.email}</span>
{/if}
<!-- </td> -->
</div>
<!-- <td> -->
{#if $events_loc.leads.edit_license_li}
<input
type="text"
name={`license_${index}_passcode`}
value={license.passcode ?? '987654'}
placeholder="Passcode"
disabled={index >= $event_exhibit_obj?.license_max}
required
class="input text-sm max-w-20 font-mono"
minlength="5"
/>
{:else}
<span class="font-bold text-sm">{license.passcode}</span>
{/if}
<span
class="font-bold text-sm"
class:hidden={!$events_loc.show_details}
>
{license.passcode}
</span>
</div>
</td>
@@ -781,6 +886,18 @@ function send_init_confirm_email({to_email}) {
type="button"
on:click={() => {
console.log('Remove License');
if (confirm('Are you sure you want to remove this license?')) {
// This still needs to be saved to the database.
// Signal that this license should be removed from the list.
// $events_sess.leads.tmp_license.index = -1;
$events_sess.leads.tmp_license.index = index;
$events_sess.leads.tmp_license.email = null;
$events_sess.leads.tmp_license.full_name = null;
handle_submit_form_license_update(event);
}
// let tmp_obj = $event_exhibit_obj;
// tmp_obj?.license_li_json.splice(index, 1);
// console.log('Remove License:', tmp_obj);
@@ -789,10 +906,10 @@ function send_init_confirm_email({to_email}) {
// This still needs to be saved to the database.
// $events_sess.leads.tmp_license.index = -1;
// Signal that this license should be removed from the list.
$events_sess.leads.tmp_license.index = index;
$events_sess.leads.tmp_license.email = null;
$events_sess.leads.tmp_license.full_name = null;
handle_submit_form_license_update(event);
// $events_sess.leads.tmp_license.index = index;
// $events_sess.leads.tmp_license.email = null;
// $events_sess.leads.tmp_license.full_name = null;
// handle_submit_form_license_update(event);
}}
class="btn btn-sm variant-soft-error">
<span class="fas fa-trash mx-1"></span>
@@ -826,16 +943,137 @@ function send_init_confirm_email({to_email}) {
</tbody>
</table>
<!-- </div> --> <!-- .ae_h_scrollfix -->
</form>
</section> <!-- .ae_license_list -->
{/if} <!-- $event_exhibit_obj?.license_max -->
{/if}
</section> <!-- .tab__start -->
{:else if $store_current_tab == 'manage'}
{#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]}
<div>Manage: Logged in. Nothing here yet</div>
<!-- BEGIN Tab: Manage -->
{:else if $events_loc.leads.tab[$events_slct.exhibit_id] == 'manage'}
<section class="tab__manage flex flex-col wrap justify-center items-center space-y-4 ae_h_scrollfix">
<h2 class="h3">
<!-- <span class="fas fa-download"></span> -->
Login and License
</h2>
{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
<div>
<strong>Logged in and using license for:</strong>
{#if $event_exhibit_obj?.license_li_json}
<!-- <div class="flex flex-row wrap gap-1"> -->
{#each $event_exhibit_obj?.license_li_json as license, index}
{#if license.email === $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
<div class="flex flex-row items-center space-x-2">
<span class="ae_label">Name:</span>
<span class="ae_value">{license.full_name}</span>
</div>
{/if}
{/each}
<!-- </div> -->
{/if}
<div class="flex flex-row items-center space-x-2">
<span class="ae_label">Email:</span>
<span class="ae_value">{$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
</div>
<div class="flex flex-row items-center space-x-2">
<span class="ae_label">Started:</span>
<span class="ae_value">{ae_util.iso_datetime_formatter($events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].updated_on, 'datetime_long')}</span>
</div>
<!-- Show the full_name of the person associated with that license key email address. The license information is stored in an array. The license key is not the index number value in the array. Ideally I was planning to make the key the email address, not an array index number. -->
<button
type="button"
class="btn btn-sm variant-soft-warning w-48"
on:click={() => {
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key = null;
}}
>
<span class="fas fa-times mx-1"></span>
Clear License
</button>
<button
type="button"
on:click={() => {
console.log('Log Out');
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] = null;
}}
title="Log out"
class="btn btn-sm variant-soft-warning w-48"
>
<span class="fas fa-sign-out-alt mx-1"></span>
Log Out
</button>
</div>
{:else if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
<div class="variant-soft-warning">You are logged in using the shared passcode for the exhibit. You will want to select a license to fully use this lead retrieval service. Please go to the Main tab and select a license to use.</div>
<button
type="button"
on:click={() => {
console.log('Log Out');
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] = null;
}}
title="Log out"
class="btn btn-sm variant-soft-warning w-48"
>
<span class="fas fa-sign-out-alt mx-1"></span>
Log Out
</button>
{:else}
<div class="variant-soft-warning">Please go to the Main tab to login using the shared staff passcode for this exhibit. Then select a license to use.</div>
{/if}
{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
<hr class="border w-full">
<h2 class="h3">
<!-- <span class="fas fa-download"></span> -->
Export Data
</h2>
<p>Use this to export the leads data for this exhibit to an Excel file format. The data can be downloaded at anytime using the export button below.</p>
<button
type="button"
on:click={() => {
if (!confirm('Download exported data Excel file?')) {
return false;
}
get_event_exhibit_tracking_export({ 'event_exhibit_id': $events_slct.exhibit_id, file_type: 'Excel', 'return_file': true, filename: `lead_retrieval_export_${$events_slct.exhibit_obj.name.replaceAll(' ', '_')}.xlsx`, auto_download: true, log_lvl: 2 });
// .replace(' ', '_')
}}
disabled={true}
class="btn btn-sm variant-soft-primary w-48 mb-1 export_data_btn"
title={`TEMPORARILY DISABLED: Download leads data for ${$events_slct.exhibit_obj.name}`}
>
<span class="fas fa-download mx-1"></span> Export Data
</button>
{/if} <!-- $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key -->
<hr class="border w-full">
<h2 class="h3">
<!-- <span class="fas fa-cogs"></span> -->
Additional Settings
</h2>
{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
<button
type="button"
@@ -843,18 +1081,18 @@ function send_init_confirm_email({to_email}) {
console.log('Show/Hide Details');
$events_loc.show_details = !$events_loc.show_details;
}}
class="btn variant-soft-primary w-48"
class="btn btn-sm variant-soft w-48"
>
<span class="fas fa-eye mx-1"></span>
Show/Hide Details
</button>
{#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]}
<!-- {#if $events_loc?.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
<button
type="button"
on:click={() => {
console.log('Log Out');
$events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id] = null;
$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] = null;
}}
title="Log out"
class="btn variant-soft-primary w-48"
@@ -863,39 +1101,49 @@ function send_init_confirm_email({to_email}) {
Log Out
</button>
<p>To use the lead retrieval service, please select a license from the list on the Main tab.</p>
{/if} -->
{:else}
<div>You must be logged in to view this tab.</div>
{/if} <!-- $events_loc?.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] -->
</section>
<!-- BEGIN Tab: Add/Scan -->
{:else if $events_loc.leads.tab[$events_slct.exhibit_id] == 'add_scan'}
<section class="tab__add_section min-w-full flex flex-col wrap justify-center items-center space-y-4 ae_h_scrollfix">
{#if $events_loc?.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id]}
{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
<div>Scanning for:
{$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key}
</div>
{:else}
<div class="variant-soft-warning">Please go to the Main tab and select a license to use.</div>
{/if}
{:else}
<div>Manage: Not logged in? Nothing here yet.</div>
{/if} <!-- $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id] -->
<!-- <div class=""> -->
<Element_qr_scanner show_qr_scan_result={true} show_qr_manual_badge_id_entry_option={true} on:qr_scan_result={handle_qr_scan_result} on:qr_camera={handle_qr_camera} />
<!-- </div> -->
{:else if $store_current_tab == 'add_scan'}
<div class="qr_quick_results variant-soft-secondary font-bold p-4">
{@html $events_sess.leads.qr_scan_result ?? 'No results yet'}
</div>
{#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]}
<div>Add/Scan: Logged in. Nothing here yet</div>
{:else}
<div class="variant-soft-error">Not logged in. Please log in and select a user license.</div>
{/if} <!-- $events_loc?.leads.auth_exhibit_kv && $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id] -->
<Element_qr_scanner show_qr_manual_badge_id_entry_option={true} />
</section>
{/if} <!-- $events_loc.leads.tab[$events_slct.exhibit_id] -->
{:else}
<div>Add/Scan: Not logged in? Nothing here yet.</div>
{/if} <!-- $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id] -->
{/if} <!-- $store_current_tab -->
<!-- {:else} -->
<!-- {/if} -->
<!-- </section> -->
{/if} <!-- $events_slct.exhibit_id && $event_exhibit_obj -->
</section>