diff --git a/package-lock.json b/package-lock.json index d62aaed0..eb74e4f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/src/app.postcss b/src/app.postcss index f193a108..5e9f3630 100644 --- a/src/app.postcss +++ b/src/app.postcss @@ -215,4 +215,24 @@ input:required { div.btn-group button:last-child { border-top-right-radius: .25rem; border-bottom-right-radius: .25rem; -} */ \ No newline at end of file +} */ + + +.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; + } +} \ No newline at end of file diff --git a/src/lib/ae_events_functions.ts b/src/lib/ae_events_functions.ts index f0ed221d..d8dba0c6 100644 --- a/src/lib/ae_events_functions.ts +++ b/src/lib/ae_events_functions.ts @@ -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 }) diff --git a/src/lib/ae_events_stores.ts b/src/lib/ae_events_stores.ts index 72c84305..326b57b7 100644 --- a/src/lib/ae_events_stores.ts +++ b/src/lib/ae_events_stores.ts @@ -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 = localStorageStore('ae_events_slct', events_slct_obj_template); +// export let events_slct: Writable = 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); diff --git a/src/lib/ae_stores.ts b/src/lib/ae_stores.ts index 1c1941b5..f671abaa 100644 --- a/src/lib/ae_stores.ts +++ b/src/lib/ae_stores.ts @@ -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 = localStorageStore('ae_slct', slct_obj_template); +// This works and uses *local* storage: +// export let slct: Writable = 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); diff --git a/src/lib/ae_utils.ts b/src/lib/ae_utils.ts index e9fb0342..392628f2 100644 --- a/src/lib/ae_utils.ts +++ b/src/lib/ae_utils.ts @@ -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, diff --git a/src/lib/api.js b/src/lib/api.js index b9697609..76dd87a7 100644 --- a/src/lib/api.js +++ b/src/lib/api.js @@ -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) { diff --git a/src/lib/db_events.ts b/src/lib/db_events.ts index be7a1831..bce33df5 100644 --- a/src/lib/db_events.ts +++ b/src/lib/db_events.ts @@ -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; } diff --git a/src/lib/element_qr_scanner.svelte b/src/lib/element_qr_scanner.svelte index d4e285e2..f1574ca1 100644 --- a/src/lib/element_qr_scanner.svelte +++ b/src/lib/element_qr_scanner.svelte @@ -278,7 +278,7 @@ function handle_qr_manual_entry() {
QR Scanner: -->
Start Scanning {:else if scanning_status == 'paused' && show_pause_btn} - + Scanning paused {:else if scanning_status == 'scanning'} - + {#if show_pause_btn} {/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; + } +} diff --git a/src/routes/events_leads/+layout.svelte b/src/routes/events_leads/+layout.svelte index 7ae2ec27..942b58b4 100644 --- a/src/routes/events_leads/+layout.svelte +++ b/src/routes/events_leads/+layout.svelte @@ -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); diff --git a/src/routes/events_leads/+page.svelte b/src/routes/events_leads/+page.svelte index 54fcc77b..f1184550 100644 --- a/src/routes/events_leads/+page.svelte +++ b/src/routes/events_leads/+page.svelte @@ -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 { +// } +// } -
+

Events - Leads

@@ -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" /> -Event ID {$events_slct.event_id} + {#if $event_exhibit_obj_li} -

Exhibits

+

Exhibits

- - {/each} + + {/each} -
- + - + + +
- {#if ($ae_loc.trusted_access)} + {#if ($ae_loc.administrator_access && !$events_loc.show_details)}
- +
{/if} @@ -203,7 +237,17 @@ function open_exhibit_tracking(event_exhibit_id_random, event_exhibit_staff_pass
- + {/if} diff --git a/src/routes/events_leads/+page.ts b/src/routes/events_leads/+page.ts index 9fea2547..25b9b2cc 100644 --- a/src/routes/events_leads/+page.ts +++ b/src/routes/events_leads/+page.ts @@ -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}); diff --git a/src/routes/events_leads/exhibit/[slug]/+page.svelte b/src/routes/events_leads/exhibit/[slug]/+page.svelte index 55db101f..77a73ec3 100644 --- a/src/routes/events_leads/exhibit/[slug]/+page.svelte +++ b/src/routes/events_leads/exhibit/[slug]/+page.svelte @@ -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 = 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|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; +} + + @@ -421,7 +542,7 @@ function send_init_confirm_email({to_email}) { {#if $events_slct.exhibit_id && $event_exhibit_obj} -
+ @@ -485,11 +602,11 @@ function send_init_confirm_email({to_email}) { @@ -499,29 +616,44 @@ function send_init_confirm_email({to_email}) { -{#if $store_current_tab === 'start'} + +{#if $events_loc.leads.tab[$events_slct.exhibit_id] === 'start'} -
-

+ +

+ +
+

{$event_exhibit_obj?.name ?? 'Welcome to Leads for Exhibits!'} {$event_exhibit_obj?.code ?? ''} -

+

+

+ {#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key} + + {$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key} + + {:else} + + No license key selected. + {/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_slct.exhibit_id].key} +

+ 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). +

+{:else if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id]}

To use the lead retrieval service, please select a license from the list below.

{:else}

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.

@@ -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]} {#if $event_exhibit_obj?.license_max }

License List (max {$event_exhibit_obj?.license_max})

-
+ {#if $event_exhibit_obj?.license_li_json && $event_exhibit_obj?.license_li_json.length < $event_exhibit_obj?.license_max}
-{:else if $store_current_tab == 'manage'} - {#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]} -
Manage: Logged in. Nothing here yet
+ +{:else if $events_loc.leads.tab[$events_slct.exhibit_id] == 'manage'} + + +
+ +

+ + Login and License +

+ +{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key} + +
+ Logged in and using license for: + {#if $event_exhibit_obj?.license_li_json} + + {#each $event_exhibit_obj?.license_li_json as license, index} + {#if license.email === $events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key} +
+ Name: + {license.full_name} +
+ {/if} + {/each} + + {/if} +
+ Email: + {$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key} +
+
+ Started: + {ae_util.iso_datetime_formatter($events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].updated_on, 'datetime_long')} +
+ + + + +
+ +{:else if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id]} +
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.
+ + +{:else} +
Please go to the Main tab to login using the shared staff passcode for this exhibit. Then select a license to use.
+{/if} + + +{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id].key} + + +
+ +

+ + Export Data +

+ +

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.

+ + +{/if} + + +
+ +

+ + Additional Settings +

+ +{#if $events_loc?.leads.auth_exhibit_kv[$events_slct.exhibit_id]} - {#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]} + + +{:else} +
You must be logged in to view this tab.
+{/if} + +
+ + + +{:else if $events_loc.leads.tab[$events_slct.exhibit_id] == 'add_scan'} + + +
+ +{#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} +
Scanning for: + {$events_loc.leads.auth_exhibit_kv[$events_slct.exhibit_id].key} +
+ {:else} +
Please go to the Main tab and select a license to use.
{/if} - {:else} -
Manage: Not logged in? Nothing here yet.
- {/if} + + + -{:else if $store_current_tab == 'add_scan'} +
+ {@html $events_sess.leads.qr_scan_result ?? 'No results yet'} +
- {#if $events_loc?.leads.auth_exhibit_li && $events_loc.leads.auth_exhibit_li[$events_slct.exhibit_id]} -
Add/Scan: Logged in. Nothing here yet
+{:else} +
Not logged in. Please log in and select a user license.
+{/if} - +
+ +{/if} - - {:else} -
Add/Scan: Not logged in? Nothing here yet.
- {/if} - -{/if} - - - - - - - - - - {/if} -