From 2552e1a839da88682f2e0eb105b4aabbc00d0503 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Fri, 21 Jun 2024 12:25:36 -0400 Subject: [PATCH] Now with upload and download percent! Also better editing for session POC. --- src/lib/ae_core_functions.ts | 57 ++++--- src/lib/ae_stores.ts | 5 +- src/lib/api.ts | 13 +- src/lib/api_get_object.ts | 54 +++++- src/lib/api_post_object.ts | 20 +++ src/routes/+layout.svelte | 45 +++-- src/routes/events_pres_mgmt/+page.svelte | 8 +- .../event/[slug]/+page.svelte | 161 ++++++++++++++++-- .../session/[slug]/+page.svelte | 92 +++++++++- .../session/[slug]/presenter_view.svelte | 36 +++- src/routes/sponsorships/+page.svelte | 6 +- 11 files changed, 433 insertions(+), 64 deletions(-) diff --git a/src/lib/ae_core_functions.ts b/src/lib/ae_core_functions.ts index 97e2244e..cbbd4b31 100644 --- a/src/lib/ae_core_functions.ts +++ b/src/lib/ae_core_functions.ts @@ -355,33 +355,35 @@ async function handle_update_ae_obj_id_crud( async function handle_download_export__obj_type( { - api_cfg, - get_obj_type, // The type of object to return: event_badge, event_presenter, sponsorship, etc. - for_obj_type, // Usually for an account, event, event_exhibit, or sponsorship_cfg - for_obj_id, // The ID of the object - file_type='CSV', // 'CSV' or 'Excel' - return_file=true, - filename='no_filename.csv', - auto_download=false, - limit=5000, - params={}, // key value object is expected - log_lvl=0 + api_cfg, + get_obj_type, // The type of object to return: event_badge, event_presenter, sponsorship, etc. + for_obj_type, // Usually for an account, event, event_exhibit, or sponsorship_cfg + for_obj_id, // The ID of the object + file_type='CSV', // 'CSV' or 'Excel' + return_file=true, + filename='no_filename.csv', + auto_download=false, + limit=5000, + params={}, // key value object is expected + log_lvl=0 } : { - api_cfg: any, - get_obj_type: string, - for_obj_type: string, - for_obj_id: string, - file_type?: string, - return_file?: boolean, - filename?: string, - auto_download?: boolean, - limit?: number, - params?: key_val, - log_lvl?: number + api_cfg: any, + get_obj_type: string, + for_obj_type: string, + for_obj_id: string, + file_type?: string, + return_file?: boolean, + filename?: string, + auto_download?: boolean, + limit?: number, + params?: key_val, + log_lvl?: number } ) { console.log('*** ae_core_functions.js: handle_download_export__obj_type() ***'); + let task_id = for_obj_id; + const endpoint = `/v2/crud/${get_obj_type}/list`; params['for_obj_type'] = for_obj_type; params['for_obj_id'] = for_obj_id; @@ -402,7 +404,16 @@ async function handle_download_export__obj_type( params['limit'] = limit; } - ae_promises.download__sponsorship_export_file = await api.get_object({api_cfg: api_cfg, endpoint: endpoint, params: params, return_blob: return_file, filename: clean_filename, auto_download: auto_download, log_lvl: log_lvl}); + ae_promises.download__sponsorship_export_file = await api.get_object({ + api_cfg: api_cfg, + endpoint: endpoint, + params: params, + return_blob: return_file, + filename: clean_filename, + auto_download: auto_download, + task_id: task_id, + log_lvl: log_lvl + }); console.log('ae_promises.download__sponsorship_export_file:', ae_promises.download__sponsorship_export_file); return ae_promises.download__sponsorship_export_file; diff --git a/src/lib/ae_stores.ts b/src/lib/ae_stores.ts index dec4ebd8..04ab4a61 100644 --- a/src/lib/ae_stores.ts +++ b/src/lib/ae_stores.ts @@ -198,7 +198,10 @@ export let ae_app_session_data_struct: key_val = { }, 'download': {}, - 'download_li': {}, + // For API download and upload progress status per file. + 'api_download_kv': {}, + // Example: {example_file_id: {status: 'downloading', endpoint: '/event/file/abc123/download', filename: 'example_file_name.ext', size_total: 0, size_loaded: 0, percent_completed: 0}} + 'api_upload_kv': {}, // {example_temp_id: {status: 'uploading', endpoint: '/event/file/abc123/upload', filename: 'example_file_name.ext', size_total: 0, size_loaded: 0, percent_completed: 0}} }; // console.log(`AE Stores - App Session Storage Data:`, ae_app_session_data_struct); export let ae_sess = writable(ae_app_session_data_struct); diff --git a/src/lib/api.ts b/src/lib/api.ts index 809bfab2..de2649b5 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -841,13 +841,24 @@ export let download_hosted_file = async function download_hosted_file({ }) { console.log('*** stores_hosted_api.js: download_hosted_file() ***'); + let task_id = hosted_file_id; + const endpoint = `/hosted_file/${hosted_file_id}/download`; if (filename) { params['filename'] = filename; } params['return_file'] = true; - let hosted_file_download_get_promise = await api.get_object({api_cfg: api_cfg, endpoint: endpoint, params: params, return_blob: true, filename: filename, auto_download: auto_download, log_lvl: log_lvl}); + let hosted_file_download_get_promise = await api.get_object({ + api_cfg: api_cfg, + endpoint: endpoint, + params: params, + return_blob: true, + filename: filename, + auto_download: auto_download, + task_id: task_id, + log_lvl: log_lvl + }); // console.log(hosted_file_download_get_promise); return hosted_file_download_get_promise; } diff --git a/src/lib/api_get_object.ts b/src/lib/api_get_object.ts index 3861fe99..a91616bc 100644 --- a/src/lib/api_get_object.ts +++ b/src/lib/api_get_object.ts @@ -36,7 +36,7 @@ export let get_object = async function get_object( timeout?: number, return_meta?: boolean, return_blob?: boolean, - filename?: string, + filename?: null|string, auto_download?: boolean, as_list?: boolean, task_id?: string, @@ -119,9 +119,27 @@ export let get_object = async function get_object( let percent_completed = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); - // console.log('GET Data Timestamp:', progressEvent.timeStamp, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed); + console.log('GET Data Progress:', progressEvent.progress, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed); temp_get_object_percent_completed = percent_completed; + + // WARNING: This needs to be tied to an object type and ID. This is a temporary solution. + try { + window.postMessage({ + type: 'api_download_data', + status: 'downloading', + task_id: task_id, + endpoint: endpoint, + filename: filename, + size_total: progressEvent.total, + size_loaded: progressEvent.loaded, + percent_completed: percent_completed, + }, + '*' + ); + } catch (error) { + console.log('Error posting message to window:', error); + } } } ) @@ -132,6 +150,25 @@ export let get_object = async function get_object( if (log_lvl > 1) { console.log('GET Response:', response); } + + // Post file download message + try { + window.postMessage({ + type: 'api_download_data', + status: 'complete', + task_id: task_id, + endpoint: endpoint, + filename: filename, + size_total: 0, + size_loaded: 0, + percent_completed: 100, + }, + '*' + ); + } catch (error) { + console.log('Error posting message to window:', error); + } + if (!Array.isArray(response.data['data']) && as_list) { if (log_lvl) { console.log('Data result is a dictionary/object, not an array/list. Forcing return as an array/list'); @@ -252,11 +289,13 @@ export let get_object = async function get_object( try { window.postMessage({ type: 'api_download_blob', + status: 'downloading', + task_id: task_id, endpoint: endpoint, filename: filename, size_total: progressEvent.total, size_loaded: progressEvent.loaded, - percent_completed: percent_completed + percent_completed: percent_completed, }, '*' ); @@ -287,7 +326,14 @@ export let get_object = async function get_object( // WARNING: This needs to be tied to an object type and ID. This is a temporary solution. try { window.postMessage({ - type: 'api_download_blob', endpoint: endpoint, filename: filename, size_total: 0, size_loaded: 0, percent_completed: 100 + type: 'api_download_blob', + status: 'complete', + task_id: task_id, + endpoint: endpoint, + filename: filename, + size_total: 0, + size_loaded: 0, + percent_completed: 100, }, '*' ); diff --git a/src/lib/api_post_object.ts b/src/lib/api_post_object.ts index 6b713764..ab9ea44a 100644 --- a/src/lib/api_post_object.ts +++ b/src/lib/api_post_object.ts @@ -87,6 +87,8 @@ export let post_object = async function post_object( try { window.postMessage({ type: 'api_post_json_form', + status: 'uploading', + task_id: task_id, endpoint: endpoint, size_total: progressEvent.total, size_loaded: progressEvent.loaded, @@ -104,6 +106,24 @@ export let post_object = async function post_object( ) .then(function (response) { console.log('POST Response Data:', response.data); + try { + window.postMessage({ + type: 'api_post_json_form', + status: 'complete', + task_id: task_id, + endpoint: endpoint, + size_total: 0, + size_loaded: 0, + percent_completed: 100, + progress: 100, + rate: 0, + }, + '*' + ); + } catch (error) { + console.log('Error posting message to window:', error); + } + if (response.data['data'].result === null) { // This should mean that the request was successful, but a result of None/null was returned from Aether API. // console.log('Returning null after POST'); diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index f12eae11..438a64e4 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -210,6 +210,9 @@ onMount(() => { 'size_loaded': 0, 'percent_completed': 0, }; + + + window.addEventListener('message', function(event) { console.log('Message received in root +layout.svelte:'); console.log(event); @@ -220,26 +223,48 @@ onMount(() => { // Get the event_file_id from the event.data.endpoint value. // Example: /event/file/abc123/download - let endpoint = event.data.endpoint; + // let endpoint = event.data.endpoint; // let event_file_id = endpoint.split('/')[3]; - // ae_downloads[event_file_id] = { + let task_id = event.data.task_id; - // $ae_sess.download = { - $ae_sess.download[endpoint] = { - 'endpoint': endpoint, + $ae_sess.download[event.data.endpoint] = { + 'status': event.data.status, + 'task_id': task_id, + 'endpoint': event.data.endpoint, 'filename': event.data.filename, 'size_total': event.data.size_total, 'size_loaded': event.data.size_loaded, 'percent_completed': event.data.percent_completed, }; - // let event_file_id = event.data.event_file_id; - // let filename = event.data.filename; - // let auto_download = event.data.auto_download; + $ae_sess.api_download_kv[task_id] = + { + 'status': event.data.status, + 'task_id': task_id, + 'endpoint': event.data.endpoint, + 'filename': event.data.filename, + 'size_total': event.data.size_total, + 'size_loaded': event.data.size_loaded, + 'percent_completed': event.data.percent_completed, + }; + } else if (event.data.type == 'api_post_json_form') { + console.log('Post JSON form message received:', event.data); - // ae_promises[event_file_id] - // ae_promises[event_file_id] = download_event_file({ 'event_file_id': event_file_id, 'return_file': true, filename: filename, auto_download: auto_download, log_lvl: 1 }); + let task_id = event.data.task_id; + + $ae_sess.api_upload_kv[task_id] = + { + 'status': event.data.status, + 'task_id': task_id, + 'endpoint': event.data.endpoint, + 'filename': event.data.filename, + 'size_total': event.data.size_total, + 'size_loaded': event.data.size_loaded, + 'percent_completed': event.data.percent_completed, + 'progress': event.data.progress, + 'rate': event.data.rate, + }; } }); diff --git a/src/routes/events_pres_mgmt/+page.svelte b/src/routes/events_pres_mgmt/+page.svelte index cb93d0d9..79b25674 100644 --- a/src/routes/events_pres_mgmt/+page.svelte +++ b/src/routes/events_pres_mgmt/+page.svelte @@ -120,13 +120,13 @@ onMount(() => { || $ae_loc.trusted_access } - + { // When the cursor is hovering we want to set the event_id and event_obj - // $events_slct.event_id = event_obj.id_random; + // $events_slct.event_id = event_obj.event_id_random; // $events_slct.event_obj = event_obj; }} > @@ -148,7 +148,7 @@ onMount(() => { {#if $ae_loc.trusted_access} Manage diff --git a/src/routes/events_pres_mgmt/event/[slug]/+page.svelte b/src/routes/events_pres_mgmt/event/[slug]/+page.svelte index 9b7d2a13..677d9a19 100644 --- a/src/routes/events_pres_mgmt/event/[slug]/+page.svelte +++ b/src/routes/events_pres_mgmt/event/[slug]/+page.svelte @@ -11,7 +11,10 @@ import { clipboard, FileDropzone, getModalStore, localStorageStore, ProgressRadi import type { key_val } from '$lib/ae_stores'; import { ae_util } from '$lib/ae_utils'; import { api } from '$lib/api'; +import Element_ae_crud from '$lib/element_ae_crud.svelte'; + import { liveQuery } from "dexie"; +import { core_func } from '$lib/ae_core_functions'; import { db_events } from "$lib/db_events"; import { ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger } from '$lib/ae_stores'; import { events_loc, events_sess, events_slct, events_trigger } from '$lib/ae_events_stores'; @@ -52,7 +55,7 @@ let event_obj_v2 = db_events.events.get($events_slct.event_id); let load_obj_li_results: Promise|key_val; let search_submit_results: Promise|key_val; -// These will likely be used for patch/update triggers. Maybe delete? +let ae_tmp: key_val = {}; let ae_triggers: key_val = {}; let ae_event_session_get_promise: Promise; @@ -294,7 +297,7 @@ $: if ($events_trigger == 'load__event_session_obj_li' && $events_slct.event_id) Date Start/End Location - + POC @@ -330,15 +333,153 @@ $: if ($events_trigger == 'load__event_session_obj_li' && $events_slct.event_id) {/if} {session_obj.event_location_name ?? '-- not set --'} - + {#if $ae_loc.trusted_access} + + + + {session_obj.poc_person_primary_email} + + + {/if} + {:else} + -- not set -- + {/if} + + {#if $ae_loc.trusted_access} + + {#if session_obj.event_session_id_random == $events_slct.event_session_id && ae_tmp[$events_slct.event_session_id] && ae_tmp[$events_slct.event_session_id].show__edit_poc_person} + { + console.log(`ae_crud_updated:`, e.detail); + + events_func.handle_load_ae_obj_id__event_session({api_cfg: $ae_api, event_session_id: $events_slct?.event_session_id, log_lvl: 1}) + .then(function (load_results) { + ae_tmp[$events_slct.event_session_id].poc_person_id = null; + ae_tmp[$events_slct.event_session_id].show__edit_poc_person = false; + + $events_slct.event_session_id = null; + $events_slct.event_obj = null; + + // Careful with the trigger_patch. It will keep firing if not reset. + ae_triggers.update_person_poc = false; + + // Maybe reload page? + // window.location.reload(); + }); + }} > - - View - - --> + {#await $slct.person_obj_li} + + {:then person_obj_li} + {#if person_obj_li && person_obj_li.length > 0} + + + + {/if} + {/await} + + {/if} + + {#if ae_tmp[$events_slct.event_session_id] && ae_tmp[$events_slct.event_session_id].show__edit_poc_person} + + {:else} + + {/if} + + {/if} + {/each} diff --git a/src/routes/events_pres_mgmt/session/[slug]/+page.svelte b/src/routes/events_pres_mgmt/session/[slug]/+page.svelte index 4c689254..250880e9 100644 --- a/src/routes/events_pres_mgmt/session/[slug]/+page.svelte +++ b/src/routes/events_pres_mgmt/session/[slug]/+page.svelte @@ -436,6 +436,90 @@ function send_sign_in_poc_email( {$lq__event_session_obj.code} + + {#if $ae_loc.trusted_access} + { + console.log(`ae_crud_updated:`, e.detail); + + events_func.handle_load_ae_obj_id__event_session({api_cfg: $ae_api, event_session_id: $lq__event_session_obj?.event_session_id_random, log_lvl: 1}) + .then(function (load_results) { + ae_tmp.name = null; + ae_tmp.show__edit_name = false; + + // Maybe reload page? + // window.location.reload(); + }); + }} + > + {#if ae_tmp?.show__edit_name} + + + {/if} + + {#if ae_tmp.show__edit_name} + + {:else} + + {/if} + + {/if}
  • Date time: {ae_util.iso_datetime_formatter($lq__event_session_obj.start_datetime, 'datetime_long')} - {ae_util.iso_datetime_formatter($lq__event_session_obj.end_datetime, 'datetime_long')} @@ -548,7 +632,8 @@ function send_sign_in_poc_email( $slct.person_obj_li = core_func.handle_load_ae_obj_li__person({api_cfg: $ae_api, account_id: $slct.account_id, params: params}); - ae_tmp.poc_person_id = $lq__event_session_obj?.poc_person_id_random;ae_tmp.show__edit_poc_person = true; + ae_tmp.poc_person_id = $lq__event_session_obj?.poc_person_id_random; + ae_tmp.show__edit_poc_person = true; }} class="btn btn-sm variant-soft-warning hover:variant-ghost-warning" > @@ -917,6 +1002,7 @@ function send_sign_in_poc_email( class="input min-w-96 max-w-96 text-sm" /> + @@ -482,8 +508,8 @@ WARNING: The file upload and management is a work in progress. You can upload an Downloading - {#if $ae_sess.download[`/hosted_file/${event_file_obj.hosted_file_id_random}/download`]} - {$ae_sess.download[`/hosted_file/${event_file_obj.hosted_file_id_random}/download`].percent_completed}% + {#if $ae_sess.api_download_kv[event_file_obj.hosted_file_id_random]} + {$ae_sess.api_download_kv[event_file_obj.hosted_file_id_random].percent_completed}% {/if} : diff --git a/src/routes/sponsorships/+page.svelte b/src/routes/sponsorships/+page.svelte index 46cf27c1..fbe89de7 100644 --- a/src/routes/sponsorships/+page.svelte +++ b/src/routes/sponsorships/+page.svelte @@ -509,7 +509,7 @@ function generate_guest_list_csv(ae_obj_li) { {:else}
    - The CHOW 2024 sponsor Hub has closed. If you have changes to your gala RSVP list please email Laurie VanBenschoten, lvanbenschoten@marinesanctuary.org, AND Erin Quigg, erinq@preconevents.com. + The CHOW 2024 sponsor Hub has closed. If you have changes to your gala RSVP list please email Laurie VanBenschoten, lvanbenschoten@marinesanctuary.org, AND Erin Quigg, erinq@preconevents.com.
    {/if} @@ -545,8 +545,8 @@ function generate_guest_list_csv(ae_obj_li) { {/await} Export All Data - {#if $ae_sess.download && $ae_sess.download.size_total > $ae_sess.download.size_loaded} - {$ae_sess.download.percent_completed}% + {#if $ae_sess.api_download_kv[$slct.account_id] && $ae_sess.api_download_kv[$slct.account_id].status == 'downloading'} + {$ae_sess.api_download_kv[$slct.account_id].percent_completed}% {/if}