diff --git a/ae_app_svelte_tailwind_skeleton.code-workspace b/ae_app_svelte_tailwind_skeleton.code-workspace index 876a1499..eabf0eb6 100644 --- a/ae_app_svelte_tailwind_skeleton.code-workspace +++ b/ae_app_svelte_tailwind_skeleton.code-workspace @@ -4,5 +4,9 @@ "path": "." } ], - "settings": {} + "settings": { + "cSpell.words": [ + "filelist" + ] + } } \ No newline at end of file diff --git a/src/lib/ae_core_functions.ts b/src/lib/ae_core_functions.ts index d024b745..4244948d 100644 --- a/src/lib/ae_core_functions.ts +++ b/src/lib/ae_core_functions.ts @@ -19,6 +19,41 @@ import { let ae_promises: key_val = {}; // Promise; +// Updated 2024-08-12 +async function check_hosted_file_obj_w_hash( + { + api_cfg, + hosted_file_hash, + check_for_local=true, + params={}, + return_meta=false, + log_lvl=0 + } : { + api_cfg: any, + hosted_file_hash: string, + check_for_local?: boolean, + params?: key_val, + return_meta?: boolean, + log_lvl?: number + } + ) { + console.log('*** stores_event_api.js: check_hosted_file_obj_w_hash() ***'); + + const endpoint = `/hosted_file/hash/${hosted_file_hash}`; + if (check_for_local) { + params['check_for_local'] = true; + } + let check_hosted_file_obj_w_hash_get_promise = await api.get_object({ + api_cfg: api_cfg, + endpoint: endpoint, + params: params, + return_meta: return_meta, + log_lvl: log_lvl + }); + return check_hosted_file_obj_w_hash_get_promise; +} + + // Updated 2024-03-29 async function handle_load_ae_obj_id__site_domain( { @@ -364,6 +399,7 @@ async function handle_download_export__obj_type( let export_obj = { + check_hosted_file_obj_w_hash: check_hosted_file_obj_w_hash, handle_load_ae_obj_id__site_domain: handle_load_ae_obj_id__site_domain, handle_load_ae_obj_code__data_store: handle_load_ae_obj_code__data_store, handle_load_ae_obj_id__person: handle_load_ae_obj_id__person, diff --git a/src/lib/ae_events_stores.ts b/src/lib/ae_events_stores.ts index 73d9abf9..68f85f80 100644 --- a/src/lib/ae_events_stores.ts +++ b/src/lib/ae_events_stores.ts @@ -89,6 +89,10 @@ let events_local_data_struct: key_val = { 'classes__form': 'border border-surface-200 p-4 space-y-4 rounded-container-token', }, + // Event Files - uploads for sessions, presenters, etc + 'files': { + }, + // Event Presentation Launcher 'launcher': { qry_max__sessions: 75, @@ -241,6 +245,15 @@ let events_session_data_struct: key_val = { qr_scan_result: null, }, + // Event Files - uploads for sessions, presenters, etc + 'files': { + disable_submit__event_file_obj: null, + status__submit: null, + status__file_list: null, // processing, complete + + processed_file_list: [], + }, + // Event Presentation Launcher 'launcher': { }, diff --git a/src/lib/ae_utils.ts b/src/lib/ae_utils.ts index 3388b9de..f0ed9011 100644 --- a/src/lib/ae_utils.ts +++ b/src/lib/ae_utils.ts @@ -33,6 +33,63 @@ function number_w_commas(x) { } +// Updated 2024-08-12 +function guess_file_name(filename_string: string) { + // console.log('*** guess_file_name() ***'); + if (!filename_string) { + return ''; + } + + if (filename_string.includes('.')) { + let file_name = filename_string.substring(0, filename_string.lastIndexOf('.')); + // console.log(file_name); + return file_name; + } else { + return filename_string; + } +} + + +// Updated 2024-08-12 +function guess_file_extension(filename_string: string) { + // console.log('*** guess_file_extension() ***'); + if (!filename_string) { + return ''; + } + + if (!filename_string.includes('.')) { + return ''; + } + + let file_extension = filename_string.substring(filename_string.lastIndexOf('.') + 1, filename_string.length) || filename_string; + // console.log(file_extension); + return file_extension; +} + + +// Updated 2024-08-12 +async function get_file_hash(file) { + return new Promise((resolve, reject) => { + let file_reader = new FileReader(); + + file_reader.onload = async function() { + if (file_reader.result.byteLength !== file.size) { + console.log('File was not read completely'); + reject("Error reading the file"); + } + + const hash_buffer = await crypto.subtle.digest('SHA-256', file_reader.result); + const hash_array = Array.from(new Uint8Array(hash_buffer)); + const hash_hex = hash_array.map(b => b.toString(16).padStart(2, '0')).join(''); + + resolve(hash_hex); + }; + + file_reader.readAsArrayBuffer(file); + }); +} + + /* This utility function looks for any form data with the prefixed name passed and returns a new object. * This function is used heavily! Be very careful making changes!!! * If rm_empty_id then it will remove/ignore fields matching. This helps with the API and new records/objects @@ -726,6 +783,9 @@ export let ae_util = { iso_datetime_formatter: iso_datetime_formatter, format_bytes: format_bytes, number_w_commas: number_w_commas, + guess_file_name: guess_file_name, + guess_file_extension: guess_file_extension, + get_file_hash: get_file_hash, extract_prefixed_form_data: extract_prefixed_form_data, process_data_string: process_data_string, handle_url_and_message: handle_url_and_message, diff --git a/src/lib/element_input_file.svelte b/src/lib/element_input_file.svelte new file mode 100644 index 00000000..88766500 --- /dev/null +++ b/src/lib/element_input_file.svelte @@ -0,0 +1,413 @@ + + + +
+ + + + + {#if file_list_status == 'processing'} +
+ Processing selected file list... +
+ {/if} + + + + {#if use_selected_file_table && input_file_list_processed && input_file_list_processed.length} + Files selected for upload + + + + + + + + + + + + + {#each input_file_list_processed as file_list_item, file_index} + + + + + + + + + + + + {/each} + +
RemoveFilenameModifiedSizeExtHash
+ + {file_list_item.filename}{file_list_item.modified_datetime_string} + {file_list_item.file_size_string} + + + {file_list_item.guessed_extension} + + {ae_util.shorten_string({string: file_list_item.hash_sha256, begin_length: 5, end_length: 4, wildcard_length: 2})} +
+ {/if} + +
+ + + diff --git a/src/routes/events_pres_mgmt/(launcher)/launcher/[slug]/element_input_file.svelte b/src/lib/element_input_files_tbl.svelte similarity index 61% rename from src/routes/events_pres_mgmt/(launcher)/launcher/[slug]/element_input_file.svelte rename to src/lib/element_input_files_tbl.svelte index d1c70b00..662a8159 100644 --- a/src/routes/events_pres_mgmt/(launcher)/launcher/[slug]/element_input_file.svelte +++ b/src/lib/element_input_files_tbl.svelte @@ -1,25 +1,28 @@ -
- +
+ + + {#if file_list_status == 'processing'} +
+ Processing selected file list... +
+ {/if} {#if use_selected_file_table && input_file_list_processed && input_file_list_processed.length} Files selected for upload - +
@@ -267,17 +318,37 @@ function remove_file_from_filelist(index) { - + - - + @@ -285,42 +356,26 @@ function remove_file_from_filelist(index) {
Remove
- {file_list_item.filename} {file_list_item.modified_datetime_string}{file_list_item.file_size_string} + {file_list_item.file_size_string} + + {file_list_item.guessed_extension} - {ae.util.shorten_string({string: file_list_item.hash_sha256, begin_length: 5, end_length: 4, wildcard_length: 2})} + + {file_list_item.guessed_extension} + + {ae_util.shorten_string({string: file_list_item.hash_sha256, begin_length: 5, end_length: 4, wildcard_length: 2})}
{/if} - -