From f8e88b03551e17e7afc1354cc810f22c20355937 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 7 Jan 2025 20:22:44 -0500 Subject: [PATCH] Trying to improve the hosted file manage. --- .../ae_comp__hosted_files_clip_video.svelte | 565 ++++++------------ ...ae_comp__hosted_files_clip_video_li.svelte | 75 +++ .../ae_comp__hosted_files_upload.svelte | 4 + src/lib/ae_core/ae_core_functions.ts | 10 +- src/lib/ae_core/core__hosted_files.ts | 279 ++++++++- src/lib/ae_core/db_core.ts | 47 +- src/lib/ae_stores.ts | 11 + src/lib/element_manage_hosted_file_li.svelte | 142 +++++ .../element_manage_hosted_file_li_all.svelte | 88 +++ src/routes/hosted_files/+layout.ts | 47 ++ src/routes/hosted_files/+page.svelte | 153 ++++- 11 files changed, 1027 insertions(+), 394 deletions(-) create mode 100644 src/lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte create mode 100644 src/lib/element_manage_hosted_file_li.svelte create mode 100644 src/lib/element_manage_hosted_file_li_all.svelte create mode 100644 src/routes/hosted_files/+layout.ts diff --git a/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte b/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte index 6fa15692..6fac23d0 100644 --- a/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte +++ b/src/lib/ae_core/ae_comp__hosted_files_clip_video.svelte @@ -9,6 +9,7 @@ import Element_input_files_tbl from '$lib/element_input_files_tbl.svelte'; import type { key_val } from '$lib/ae_stores'; import { api } from '$lib/api'; +import { ae_util } from '$lib/ae_utils/ae_utils'; import { ae_snip, ae_loc, ae_sess, ae_api, ae_trig, slct, slct_trigger } from '$lib/ae_stores'; // Exports @@ -26,281 +27,72 @@ export let class_li: string = ''; export let input_class_li: string[] = ['file_drop_area']; export let table_class_li: string[] = ['table', 'table-sm', 'table-striped', 'table-hover' , 'text-sm']; -export let upload_complete: boolean = false; +export let clip_complete: boolean = false; +// export let upload_complete: boolean = false; export let submit_status: null|string = null; export let hosted_file_id_li: string[] = []; export let hosted_file_obj_li: any[] = []; +export let hosted_file_obj_kv: key_val = {}; +export let video_clip_file_kv: key_val = {}; // Local Variables let task_id = link_to_id; -let input_file_list: any = null; -let ae_promises: key_val = {}; // Promise; -let ae_triggers: key_val = {}; +// let input_file_list: any = null; +let ae_promises: key_val = {}; +// let ae_promises_clipping: key_val = {}; +// let ae_triggers: key_val = {}; -let input_element_id = 'ae_comp__hosted_files_upload__input'; +// let input_element_id = 'ae_comp__hosted_files_upload__input'; -let form_kv: key_val = { - start_time: null, - end_time: null, - reencode: null, - video_file: null, -}; -let download_clip_src: string; -let download_clip_filename: string; +// let form_kv: key_val = { +// start_time: null, +// end_time: null, +// reencode: null, +// video_file: null, +// }; +// let download_clip_src: string; +// let download_clip_filename: string; $ae_sess.files.obj = { obj: null, }; + // Functions and Logic -async function handle_submit_form_files(event) { - console.log('*** handle_submit_form() ***'); - - $ae_sess.files.disable_submit__hosted_file_obj = true; - $ae_sess.files.submit_status = 'saving'; - submit_status = 'saving'; - upload_complete = false; - - hosted_file_id_li = []; - hosted_file_obj_li = []; - - let hosted_file_results; - - form_kv = { - start_time: event.target.start_time.value, - end_time: event.target.end_time.value, - reencode: event.target.reencode.value, - video_file: event.target.file_list.files[0], - }; - - - // const form_data = new FormData(); - - // form_data.append('start_time', event.target.start_time.value); - // form_data.append('end_time', event.target.end_time.value); - - // if (event.target.reencode.value == '1' || event.target.reencode.value == 'true') { - // form_data.append('reencode', 'true'); - // } else { - // form_data.append('reencode', 'false'); - // } - // form_data.append('reencode', event.target.reencode.value); - - // form_data.append(`video_file`, event.target.video_file.files[0]); - - // let download_filename = `clipped_file_test.mp4`; - - // let params = null; - - // let endpoint = '/hosted_file/clip_video'; - - // console.log(form_data); - - // params = null; - - - if (event.target[input_element_id].files.length > 0) { - task_id = link_to_id; // Ideally this should be the file hash, but we may be uploading multiple files at once. This should be done with a loop instead? - - // Loop through each file and upload them individually in event.target[input_element_id].files - // The task_id should be the file hash. - // processed_file_list[i] has the file hash_sha256, hash_sha256_match, warnings, uploaded, uploaded_bytes, filename, and file_size_bytes. - for (let i = 0; i < event.target[input_element_id].files.length; i++) { - let tmp_file = event.target[input_element_id].files[i]; - - task_id = $ae_sess.files.processed_file_list[i].hash_sha256; - - hosted_file_results = await handle_input_upload_files([tmp_file], form_kv, task_id); - - if (hosted_file_results) { - console.log(`hosted_file_results:`, hosted_file_results); - } else { - console.log(`hosted_file_results:`, hosted_file_results); - } - } - // hosted_file_results = await handle_input_upload_files(event.target[input_element_id].files, task_id); - $ae_sess.files.processed_file_list = []; - $ae_sess = $ae_sess; - event.target.reset(); - // await tick(); - - if (log_lvl) { - console.log(`hosted_file_id_li: ${hosted_file_id_li}`, hosted_file_id_li); - } else if (log_lvl > 1) { - console.log('hosted_file_results:', hosted_file_results); - } - - // db_events.files.clear(); - - // let params = { - // qry__enabled: 'all', - // qry__hidden: 'all', - // } - - // events_func.load_ae_obj_li__event_file({ - // api_cfg: $ae_api, - // for_obj_type: link_to_type, - // for_obj_id: link_to_id, - // params: params, - // try_cache: true - // }); - } - - $ae_sess.files.disable_submit__hosted_file_obj = false; - $ae_sess.files.submit_status = 'saved'; - submit_status = 'saved'; - upload_complete = true; -} - - -async function handle_input_upload_files(input_upload_files, form_kv, task_id) { - console.log('*** handle_input_upload_files() ***'); - console.log(input_upload_files); - console.log(form_kv); - - const form_data = new FormData(); - - // form_data.append('account_id', $ae_loc.account_id); - // form_data.append('link_to_type', link_to_type); - // form_data.append('link_to_id', link_to_id); - - form_data.append('start_time', form_kv.start_time); - form_data.append('end_time', form_kv.end_time); - - if (form_kv.reencode == '1' || form_kv.reencode == 'true') { - form_data.append('reencode', 'true'); - } else { - form_data.append('reencode', 'false'); - } - - // There should really only be one file uploaded at a time for now. - for (let i = 0; i < input_upload_files.length; i++) { - form_data.append(`video_file`, input_upload_files[i]); - } - - // hash_sha256, uploaded, uploaded_bytes - // $ae_sess.files.processed_file_list[i] = { - // ...$ae_sess.files.processed_file_list[i], - // uploaded: $ae_sess.api_upload_kv[link_to_id].percent_completed, - // uploaded_bytes: $ae_sess.api_upload_kv[link_to_id].uploaded_bytes, - // }; - - let params = null; - - let endpoint = '/hosted_file/clip_video'; - - console.log(form_data); - - params = null; - - // Uncomment and the post_promise is not seen by the "await" below - // post_promise = await api.post_object({api_cfg: $cfg.api, endpoint: endpoint, params: params, data:form_data}); - // Uncomment so that the post_promise is not seen by the "await" below - ae_promises.upload__hosted_file_obj = api.post_object({ - api_cfg: $ae_api, - endpoint: endpoint, - params: params, - form_data: form_data, - return_blob: true, - filename: 'clipped_video_test.mp4', - auto_download: false, - task_id: task_id, - log_lvl: log_lvl - }) - .then(async function (result) { - console.log(result); - - let file_blob = new Blob([result.data]); - // console.log(file_blob); - let file_obj_url = window.URL.createObjectURL(file_blob); // The img src - // const url = window.URL.createObjectURL(new Blob([result.data])); - download_clip_src = file_obj_url; - // download_filename = file_obj_url; - - return true; - - - // // WARNING!!!! ONLY ONE FILE IS EXPECTED TO BE UPLOADED AT A TIME!!! - // // NOTE: The /hosted_file/upload_files endpoint will always return a list of successful files uploaded. In this case we are only uploading one file and expecting a list of one item. - // let x = 0; - // console.log(result[x]); - // let hosted_file_obj = result[x]; - - // let hosted_file_id = hosted_file_obj.hosted_file_id_random; - - // hosted_file_id_li.push(hosted_file_id); - // hosted_file_obj_li.push(hosted_file_obj); - - // let hosted_file_data: key_val = {}; - // hosted_file_data['hosted_file_id_random'] = hosted_file_id; - // hosted_file_data['for_type'] = link_to_type; - // hosted_file_data['for_id_random'] = link_to_id; - // hosted_file_data['filename'] = hosted_file_obj.filename; - // hosted_file_data['extension'] = hosted_file_obj.extension; - // hosted_file_data['enable'] = true; - // console.log(hosted_file_data); - - // return hosted_file_data; - - // $ae_sess.files.new_upload_list[i].uploaded_bytes = 10; // fake 10 bytes at least... - - // let event_file_id = await events_func.create_hosted_file_obj_from_hosted_file_async({ - // api_cfg: $ae_api, - // hosted_file_id: hosted_file_id, - // data: event_file_data, - // log_lvl: log_lvl - // }) - // .then(function (create_result) { - // console.log(create_result); // NOTE: This should be the event_file_id string - // // let event_file_id = create_result; - // return create_result; - // }); - - // return event_file_id; - }) - // .then(function (hosted_file_data) { - // return hosted_file_data; - // }) - .catch(function (error) { - console.log('Something went wrong.'); - console.log(error); - return false; - }) - .finally( function () { - // $slct_trigger = 'load__hosted_file_obj_li'; - }); - - console.log(ae_promises.upload__hosted_file_obj); - let hosted_file_result = ae_promises.upload__hosted_file_obj; - - return hosted_file_result; -} - function handle_clip_video(event) { console.log('*** handle_clip_video() ***'); + submit_status = 'clipping'; + clip_complete = false; + let hosted_file_id = event.target.hosted_file_id.value; - // $ae_sess.files.disable_submit__hosted_file_obj = true; - $ae_sess.files[hosted_file_id] = {}; - $ae_sess.files[hosted_file_id].submit_status = 'saving'; - $ae_sess.files[hosted_file_id].start_time = event.target.start_time.value; - $ae_sess.files[hosted_file_id].end_time = event.target.end_time.value; - $ae_sess.files[hosted_file_id].reencode = event.target.reencode.value; - $ae_sess.files[hosted_file_id].new_filename = event.target.new_filename.value; - $ae_sess.files[hosted_file_id].upload_complete = false; + $ae_sess.files.processed_file_kv[hosted_file_id] = {}; + $ae_sess.files.processed_file_kv[hosted_file_id].submit_status = 'clipping'; + $ae_sess.files.processed_file_kv[hosted_file_id].clip_complete = false; - let endpoint = `/${hosted_file_id}/clip_video`; + // $ae_sess.files.disable_submit__hosted_file_obj = true; + $ae_loc.files.processed_file_kv[hosted_file_id] = {}; + $ae_loc.files.processed_file_kv[hosted_file_id].submit_status = 'clipping'; + $ae_loc.files.processed_file_kv[hosted_file_id].start_time = event.target.start_time.value; + $ae_loc.files.processed_file_kv[hosted_file_id].end_time = event.target.end_time.value; + $ae_loc.files.processed_file_kv[hosted_file_id].reencode = event.target.reencode.value; + $ae_loc.files.processed_file_kv[hosted_file_id].new_filename = event.target.new_filename.value; + $ae_loc.files.processed_file_kv[hosted_file_id].clip_complete = false; + + let endpoint = `/hosted_file/${hosted_file_id}/clip_video`; let params = { + link_to_type: link_to_type, + link_to_id: link_to_id, + filename_no_ext: event.target.new_filename.value.replace('.mp4', ''), + from_type: 'mp4', // Video file type being converted + to_type: 'mp4', // Video file type to convert to start_time: event.target.start_time.value, end_time: event.target.end_time.value, reencode: event.target.reencode.value, - filename_no_ext: event.target.new_filename.value, - from_type: 'mp4', // Video file type being converted - to_type: 'mp4', // Video file type to convert to }; ae_promises[hosted_file_id] = {}; @@ -309,13 +101,36 @@ function handle_clip_video(event) { api_cfg: $ae_api, endpoint: endpoint, params: params, + // return_blob: true, + // filename: event.target.new_filename.value, + // auto_download: false, + task_id: task_id, log_lvl: log_lvl }) .then(function (result) { console.log(result); - $ae_sess.files[hosted_file_id].submit_status = 'saved'; - $ae_sess.files[hosted_file_id].upload_complete = true; + video_clip_file_kv[result.hosted_file_id_random] = {}; + video_clip_file_kv[result.hosted_file_id_random] = result; + + // $ae_loc.files.video_clip_file_kv[result.hosted_file_id_random] = {}; + // $ae_loc.files.video_clip_file_kv[result.hosted_file_id_random] = result; + + $ae_sess.files.processed_file_kv[hosted_file_id].submit_status = 'clipped'; + $ae_sess.files.processed_file_kv[hosted_file_id].clip_complete = true; + + $ae_loc.files.processed_file_kv[hosted_file_id].submit_status = 'clipped'; + $ae_loc.files.processed_file_kv[hosted_file_id].clip_complete = true; + + submit_status = 'clipped'; + clip_complete = true; + + // let file_blob = new Blob([result.data]); + // // console.log(file_blob); + // let file_obj_url = window.URL.createObjectURL(file_blob); // The img src + // // const url = window.URL.createObjectURL(new Blob([result.data])); + // download_clip_src = file_obj_url; + // // download_filename = file_obj_url; return true; }); @@ -326,153 +141,153 @@ function handle_clip_video(event) {
-

{hosted_file_obj_li.length}× files uploaded

-{#each hosted_file_obj_li as hosted_file_obj, i} -
- {hosted_file_obj.hosted_file_id_random} - {hosted_file_obj.filename} - {hosted_file_obj.extension} + + +

{Object.entries(hosted_file_obj_kv).length}× files uploaded

+{#each Object.entries(hosted_file_obj_kv) as [hosted_file_id, hosted_file_obj]} +
+ + +
+ + {ae_util.shorten_filename({filename: hosted_file_obj?.filename, max_length: 30})} + + + File ID: + + {hosted_file_obj.hosted_file_id_random} + + + Type: + + {hosted_file_obj.extension} +
+
- - +
+ New Filename: + +
- +
+ - + - -{/each} - - -
- - - - - - - {#await ae_promises.upload__hosted_file_obj} -
+ {#await ae_promises[hosted_file_id]} - - Uploading - {#if $ae_sess.api_upload_kv[task_id]} - {$ae_sess.api_upload_kv[task_id].percent_completed}% - {/if} - -
+ Processing... This may take a few minutes. + {:then} + {#if ae_promises[hosted_file_id]} + Ready to download below! + {:else} + + {/if} {/await} - +
+{/each} - - - - - - - - -
+
\ No newline at end of file diff --git a/src/lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte b/src/lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte new file mode 100644 index 00000000..db9a95d9 --- /dev/null +++ b/src/lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte @@ -0,0 +1,75 @@ + + + +

{Object.entries($ae_loc.files).length}× files clipped

+
+ + {#each Object.entries($ae_loc.files.video_clip_file_kv) as [hosted_file_id, hosted_file_obj]} + + {/each} +
\ No newline at end of file diff --git a/src/lib/ae_core/ae_comp__hosted_files_upload.svelte b/src/lib/ae_core/ae_comp__hosted_files_upload.svelte index 752b4cc0..170355b1 100644 --- a/src/lib/ae_core/ae_comp__hosted_files_upload.svelte +++ b/src/lib/ae_core/ae_comp__hosted_files_upload.svelte @@ -31,6 +31,7 @@ export let submit_status: null|string = null; export let hosted_file_id_li: string[] = []; export let hosted_file_obj_li: any[] = []; +export let hosted_file_obj_kv: key_val = {}; // Local Variables @@ -52,6 +53,7 @@ async function handle_submit_form_files(event) { hosted_file_id_li = []; hosted_file_obj_li = []; + hosted_file_obj_kv = {}; let hosted_file_results; @@ -169,6 +171,8 @@ async function handle_input_upload_files(input_upload_files, task_id) { hosted_file_data['enable'] = true; console.log(hosted_file_data); + hosted_file_obj_kv[hosted_file_id] = hosted_file_data; + return hosted_file_data; // $ae_sess.files.new_upload_list[i].uploaded_bytes = 10; // fake 10 bytes at least... diff --git a/src/lib/ae_core/ae_core_functions.ts b/src/lib/ae_core/ae_core_functions.ts index 9f608bcf..954ab2f8 100644 --- a/src/lib/ae_core/ae_core_functions.ts +++ b/src/lib/ae_core/ae_core_functions.ts @@ -39,7 +39,11 @@ import { } from "$lib/ae_core/core__country_subdivisions"; import { - delete_ae_obj_id__hosted_file + load_ae_obj_id__hosted_file, + load_ae_obj_li__hosted_file, + delete_ae_obj_id__hosted_file, + db_save_ae_obj_li__hosted_file, + db_update_ae_obj_id__hosted_file } from "$lib/ae_core/core__hosted_files"; let ae_promises: key_val = {}; // Promise; @@ -403,7 +407,11 @@ let export_obj = { load_ae_obj_li__time_zone: load_ae_obj_li__time_zone, load_ae_obj_li__country: load_ae_obj_li__country, load_ae_obj_li__country_subdivision: load_ae_obj_li__country_subdivision, + load_ae_obj_id__hosted_file: load_ae_obj_id__hosted_file, + load_ae_obj_li__hosted_file: load_ae_obj_li__hosted_file, delete_ae_obj_id__hosted_file: delete_ae_obj_id__hosted_file, + db_save_ae_obj_li__hosted_file: db_save_ae_obj_li__hosted_file, + db_update_ae_obj_id__hosted_file: db_update_ae_obj_id__hosted_file, 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, load_ae_obj_id__activity_log: load_ae_obj_id__activity_log, diff --git a/src/lib/ae_core/core__hosted_files.ts b/src/lib/ae_core/core__hosted_files.ts index 61e160c4..1eec7abc 100644 --- a/src/lib/ae_core/core__hosted_files.ts +++ b/src/lib/ae_core/core__hosted_files.ts @@ -1,11 +1,149 @@ import type { key_val } from '$lib/ae_stores'; import { api } from '$lib/api'; -// import { db_events } from "$lib/db_events"; +import { db_core } from "$lib/ae_core/db_core"; let ae_promises: key_val = {}; +// Updated 2024-06-14 +export async function load_ae_obj_id__hosted_file( + { + api_cfg, + hosted_file_id, + try_cache = false, + log_lvl = 0 + }: { + api_cfg: any, + hosted_file_id: string, + try_cache?: boolean, + log_lvl?: number + } + ) { + if (log_lvl) { + console.log(`*** load_ae_obj_id__hosted_file() *** hosted_file_id=${hosted_file_id}`); + } + + let params = {}; + + ae_promises.load__hosted_file_obj = await api.get_ae_obj_id_crud({ + api_cfg: api_cfg, + obj_type: 'hosted_file', + obj_id: hosted_file_id, // NOTE: This is the FQDN, not normally the ID. + use_alt_table: false, // NOTE: This will use the table_name_alt value instead of the table_name value in the API config. + use_alt_base: false, // NOTE: This will use the base_name_alt value instead of the base_name value + params: params, + log_lvl: log_lvl + }) + .then(function (hosted_file_obj_get_result) { + if (hosted_file_obj_get_result) { + // This is expecting a list + db_save_ae_obj_li__hosted_file({obj_type: 'hosted_file', obj_li: [hosted_file_obj_get_result]}); + return hosted_file_obj_get_result; + } else { + console.log('No results returned.'); + return null; + } + }) + .catch(function (error) { + console.log('No results returned or failed.', error); + }); + + return ae_promises.load__hosted_file_obj; +} + + +// Updated 2024-07-03 +export async function load_ae_obj_li__hosted_file( + { + api_cfg, + for_obj_type, + for_obj_id, + enabled = 'enabled', + hidden = 'not_hidden', + limit = 99, + offset = 0, + order_by_li = {'priority': 'DESC', 'sort': 'DESC', 'updated_on': 'DESC', 'created_on': 'DESC'}, + params = {}, + try_cache = true, + log_lvl = 0 + }: { + api_cfg: any, + for_obj_type: string, + for_obj_id: string, + enabled?: string, + hidden?: string, + limit?: number, + offset?: number, + order_by_li?: key_val, + params?: key_val, + try_cache?: boolean, + log_lvl?: number + } + ) { + if (log_lvl) { + console.log(`*** load_ae_obj_li__hosted_file() *** for_obj_type=${for_obj_type} for_obj_id=${for_obj_id}`); + } + + // Check if for_obj_type is in the list of valid Aether object types: + let valid_for_obj_types = ['account', 'archive', 'archive_content', 'event', 'event_session', 'event_presentation', 'event_presenter', 'event_location', 'post', 'post_comment']; + if (!valid_for_obj_types.includes(for_obj_type)) { + console.log(`Invalid for_obj_type: ${for_obj_type}`); + return []; + } + + // let enabled: string = (params.qry__enabled ?? 'enabled'); // all, disabled, enabled + // let hidden: string = (params.qry__hidden ?? 'all'); // all, hidden, not_hidden + // let limit: number = (params.qry__limit ?? 99); // 99 + // let offset: number = (params.qry__offset ?? 0); // 0 + + let params_json: key_val = {}; + + // console.log('params_json:', params_json); + + ae_promises.load__hosted_file_obj_li = await api.get_ae_obj_li_for_obj_id_crud_v2({ + api_cfg: api_cfg, + obj_type: 'hosted_file', + for_obj_type: for_obj_type, + for_obj_id: for_obj_id, + use_alt_tbl: false, + use_alt_mdl: false, + use_alt_exp: false, + enabled: enabled, + hidden: hidden, + order_by_li: order_by_li, + limit: limit, + offset: offset, + params_json: params_json, + params: params, + log_lvl: log_lvl + }) + .then(function (hosted_file_obj_li_get_result) { + if (hosted_file_obj_li_get_result) { + if (try_cache) { + db_save_ae_obj_li__hosted_file({ + obj_type: 'hosted_file', + obj_li: hosted_file_obj_li_get_result, + log_lvl: log_lvl + }); + } + return hosted_file_obj_li_get_result; + } else { + console.log('No results returned.'); + return []; + } + }) + .catch(function (error) { + console.log('No results returned or failed.', error); + }); + + if (log_lvl) { + console.log('ae_promises.load__hosted_file_obj_li:', ae_promises.load__hosted_file_obj_li); + } + return ae_promises.load__hosted_file_obj_li; +} + + // Updated 2024-11-07 export async function delete_ae_obj_id__hosted_file( { @@ -56,4 +194,141 @@ export async function delete_ae_obj_id__hosted_file( }); return ae_promises.delete__hosted_file_obj; -} \ No newline at end of file +} + + + +// This function will loop through the hosted_file_obj_li and save each one to the DB. +// Updated 2025-01-07 +export function db_save_ae_obj_li__hosted_file( + { + obj_type, + obj_li, + log_lvl = 0 + }: { + obj_type: string, + obj_li: any, + log_lvl?: number + } + ) { + if (log_lvl) { + console.log(`*** db_save_ae_obj_li__hosted_file() ***`); + } + + if (obj_li && obj_li.length) { + obj_li.forEach(async function (obj: any) { + if (log_lvl) { + console.log(`ae_obj ${obj_type}:`, obj); + } + + try { + const id_random = await db_core.file.put({ + id: obj.hosted_file_id_random, + id_random: obj.hosted_file_id_random, + hosted_file_id: obj.hosted_file_id_random, + hosted_file_id_random: obj.hosted_file_id_random, + + hash_sha256: obj.hash_sha256, // Renamed with alias in FastAPI model + + for_type: obj.for_type, + for_id: obj.for_id_id_random, + for_id_random: obj.for_id_random, + + account_id: obj.account_id_random, + + filename: obj.filename, + extension: obj.extension, + content_type: obj.content_type, + size: obj.size, + + enable: obj.enable, + hide: obj.hide, + // priority: obj.priority, + // sort: obj.sort, + group: obj.group, + notes: obj.notes, + created_on: obj.created_on, + updated_on: obj.updated_on, + + filename_no_ext: obj.filename_no_ext, + filename_w_ext: obj.filename_w_ext, + }); + // console.log(`Put obj with ID: ${obj.hosted_file_id_random} or ${id_random}`); + } catch (error) { + let status = `Failed to put ${obj.hosted_file_id_random}: ${error}`; + console.log(status); + } + + // const id_random = await db_core.file.put(obj); + // console.log(`Put obj with ID: ${obj.hosted_file_id_random}`); + }); + + return true; + } + return false; +} + + +// Updated 2025-01-07 +export function db_update_ae_obj_id__hosted_file( + { + obj_type, + obj_id, + data_kv, + log_lvl = 0 + }: { + obj_type: string, + obj_id: string, + data_kv: key_val, + log_lvl?: number + } + ) { + if (log_lvl) { + console.log(`*** db_update_ae_obj_id__hosted_file() ***`); + } + + if (obj_id) { + console.log(`ae_obj ${obj_type}:`, obj_id); + + try { + // db_core.file.update(obj_id, data_kv); + db_core.file.update(obj_id, + { + // for_type: data_kv.for_type, + // for_id: data_kv.for_id_id_random, + // for_id_random: data_kv.for_id_random, + + filename: data_kv.filename, + extension: data_kv.extension, + content_type: data_kv.content_type, + size: data_kv.size, + + // enable: data_kv.enable, + // hide: data_kv.hide, + // priority: data_kv.priority, + // sort: data_kv.sort, + // group: data_kv.group, + // notes: data_kv.notes, + // created_on: data_kv.created_on, + // updated_on: data_kv.updated_on, + + filename_no_ext: data_kv.filename_no_ext, + filename_w_ext: data_kv.filename_w_ext, + // hosted_file_content_type: data_kv.hosted_file_content_type, + // file_size: data_kv.file_size, + // hosted_file_size: data_kv.hosted_file_size, + } + ); + + console.log(`Update obj with ID: ${obj_id}`); + } catch (error) { + let status = `Failed to update ${obj_id}: ${error}`; + console.log(status); + } + + // const id_random = await db_core.file.put(obj); + // console.log(`Put obj with ID: ${data_kv.hosted_file_id_random}`); + return true; + } + return false; +} diff --git a/src/lib/ae_core/db_core.ts b/src/lib/ae_core/db_core.ts index 2052d8b4..47a61c59 100644 --- a/src/lib/ae_core/db_core.ts +++ b/src/lib/ae_core/db_core.ts @@ -3,6 +3,41 @@ import Dexie, { type Table } from 'dexie'; // li = list // kv = key value list +// Updated 2025-01-07 +export interface File { + id: string; + id_random: string; + hosted_file_id: string; + hosted_file_id_random: string; + + hash_sha256: string; + + for_type?: string; + for_id?: string; + for_id_random?: string; + + account_id: string; + + filename: string; + extension: string; + content_type: string; + size: number; // In bytes + + enable: null|boolean; + hide?: null|boolean; + priority?: null|boolean + sort?: null|number; + group?: null|string; + notes?: null|string; + created_on: Date; + updated_on?: null|Date; + + // Additional fields for convenience (database views) + filename_no_ext: string; + filename_w_ext: string; +} + + // Updated 2024-07-17 export interface Person { id: string; @@ -71,14 +106,24 @@ export interface Person { } -// Updated 2024-06-24 +// Updated 2025-01-07 export class MySubClassedDexie extends Dexie { + file!: Table; person!: Table; // user!: Table; constructor() { super('ae_core_db'); this.version(1).stores({ + file: ` + id, id_random, hosted_file_id, hosted_file_id_random, + hash_sha256, + account_id, + for_type, for_id, for_id_random, + filename, extension, + content_type, size, + enable, hide, priority, sort, group, created_on, updated_on`, + person: ` id, person_id, person_id_random, external_id, code, diff --git a/src/lib/ae_stores.ts b/src/lib/ae_stores.ts index 944ba935..0d486693 100644 --- a/src/lib/ae_stores.ts +++ b/src/lib/ae_stores.ts @@ -112,6 +112,12 @@ export let ae_app_local_data_struct: key_val = { show_element__sql_qry_results: false, }, + files: { + processed_file_kv: {}, + uploaded_file_kv: {}, + video_clip_file_kv: {}, + }, + 'ds': {}, 'hub': { 'show_element__cfg': true, @@ -214,7 +220,12 @@ export let ae_app_session_data_struct: key_val = { 'files': { disable_submit__hosted_file_obj: false, + processed_file_kv: {}, + uploaded_file_kv: {}, + video_clip_file_kv: {}, processed_file_list: [], + // uploaded_file_list: [], + video_clip_file_list: [], submit_status: null, // 'saving', 'created', 'updated', 'saved' }, diff --git a/src/lib/element_manage_hosted_file_li.svelte b/src/lib/element_manage_hosted_file_li.svelte new file mode 100644 index 00000000..b0fa4bea --- /dev/null +++ b/src/lib/element_manage_hosted_file_li.svelte @@ -0,0 +1,142 @@ + + + +
+ + + +
+ + +
+ + +

+ Manage Files: + + + {@html $lq__hosted_file_obj_li ? `${$lq__hosted_file_obj_li.length}×` : '-- none --'} + +

+ +{#if $lq__hosted_file_obj_li && $lq__hosted_file_obj_li.length} +
+ + +
    +{#each $lq__hosted_file_obj_li as hosted_file_obj} +
  1. + {hosted_file_obj.filename} +
  2. +{/each} +
+ +
+ +{:else} + +

+ No files available to display +

+ +{/if} + +
+ + + \ No newline at end of file diff --git a/src/lib/element_manage_hosted_file_li_all.svelte b/src/lib/element_manage_hosted_file_li_all.svelte new file mode 100644 index 00000000..95ca98b7 --- /dev/null +++ b/src/lib/element_manage_hosted_file_li_all.svelte @@ -0,0 +1,88 @@ + + + + + + +{#if lq__hosted_file_obj_li} + +{:else} +

No files found

+{/if} diff --git a/src/routes/hosted_files/+layout.ts b/src/routes/hosted_files/+layout.ts new file mode 100644 index 00000000..d190b998 --- /dev/null +++ b/src/routes/hosted_files/+layout.ts @@ -0,0 +1,47 @@ +/** @type {import('./$types').LayoutLoad} */ +console.log(`IDAA BB - [account_id] +layout.ts start`); + +import { error } from '@sveltejs/kit'; +import { browser } from '$app/environment'; +import { core_func } from '$lib/ae_core/ae_core_functions'; + +export async function load({ params, parent }) { // route + let log_lvl: number = 0; + + let data = await parent(); + data.log_lvl = log_lvl; + + let account_id = data.account_id; + let ae_acct = data[account_id]; + // console.log(`ae_acct = `, ae_acct); + + if (!account_id) { + console.log(`ae Core - [account_id] +page.ts: The account_id was not found!!!`); + error(404, { + message: 'Account ID not found' + }); + } + + ae_acct.slct.account_id = account_id; + + if (browser) { + let load_hosted_file_obj_li = core_func.load_ae_obj_li__hosted_file({ + api_cfg: ae_acct.api, + for_obj_type: 'account', + for_obj_id: account_id, + enabled: 'enabled', + hidden: 'not_hidden', + limit: 99, + order_by_li: {'priority': 'DESC', 'sort': 'DESC', 'updated_on': 'DESC', 'created_on': 'DESC', 'title': 'ASC'}, + try_cache: true, + log_lvl: log_lvl + }); + console.log(`load_hosted_file_obj_li = `, load_hosted_file_obj_li); + ae_acct.slct.hosted_file_obj_li = load_hosted_file_obj_li; + } + + // WARNING: Precaution against shared data between sites and sessions. + data[account_id] = ae_acct; + + return data; +} diff --git a/src/routes/hosted_files/+page.svelte b/src/routes/hosted_files/+page.svelte index 0eba1171..b9869554 100644 --- a/src/routes/hosted_files/+page.svelte +++ b/src/routes/hosted_files/+page.svelte @@ -12,9 +12,14 @@ import type { key_val } from '$lib/ae_stores'; import Comp_hosted_files_upload from '$lib/ae_core/ae_comp__hosted_files_upload.svelte'; import Comp_hosted_files_clip_video from '$lib/ae_core/ae_comp__hosted_files_clip_video.svelte'; +import Comp_hosted_files_clip_video_li from '$lib/ae_core/ae_comp__hosted_files_clip_video_li.svelte'; + +import Element_manage_hosted_file_li_wrap from '$lib/element_manage_hosted_file_li_all.svelte'; let log_lvl = 1; +let ae_promises: key_val = {}; + // export let container_class_li = []; let file_uploads_post_promise; @@ -31,9 +36,53 @@ let hosted_file_upload: key_val = { // link_to_id: ae_loc.account_id, hosted_file_id_li: [], hosted_file_obj_li: [], + clip_complete: false, upload_complete: false, + submit_status: null, }; +let hosted_file_clip: key_val = { + video_clip_file_kv: {}, + clip_complete: false, + submit_status: null, +}; + +if (!$ae_loc.files) { + $ae_loc.files = {}; + $ae_loc.files.processed_file_kv = {}; + $ae_loc.files.uploaded_file_kv = {}; + $ae_loc.files.video_clip_file_kv = {}; + // $ae_loc.files.uploaded_file_list = []; + // $ae_loc.files.video_clip_file_list = []; +} +if (!$ae_loc.files.processed_file_kv) { + $ae_loc.files.processed_file_kv = {}; +} + +$: if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_li) { + // Append this list to the $ae_loc.files.uploaded_file_li list + $ae_loc.files.uploaded_file_li = [ + ...$ae_loc.files.uploaded_file_li, + ...$ae_sess.files.uploaded_file_li + ]; +} + +$: if ($ae_sess.files.upload_complete && $ae_sess.files.uploaded_file_kv) { + // Add this key-value pair to the $ae_loc.files.uploaded_file_kv object + $ae_loc.files.uploaded_file_kv = { + ...$ae_loc.files.uploaded_file_kv, + ...$ae_sess.files.uploaded_file_kv + }; +} + +$: if ($ae_sess.files.clip_complete && $ae_sess.files.video_clip_file_kv) { + // Add this key-value pair to the $ae_loc.files.video_clip_file_kv object + $ae_loc.files.video_clip_file_kv = { + ...$ae_loc.files.video_clip_file_kv, + ...$ae_sess.files.video_clip_file_kv + }; +} + onMount(() => { console.log('Hosted Files: AV Utilities +page.svelte'); }); @@ -170,7 +219,7 @@ function handle_submit_form(event) {
@@ -184,7 +233,8 @@ function handle_submit_form(event) { link_to_id={$ae_loc.account_id} bind:hosted_file_id_li={hosted_file_upload.hosted_file_id_li} bind:hosted_file_obj_li={hosted_file_upload.hosted_file_obj_li} - bind:upload_complete={hosted_file_upload.upload_complete} + bind:hosted_file_obj_kv={$ae_sess.files.uploaded_file_kv} + bind:upload_complete={$ae_sess.files.upload_complete} log_lvl={log_lvl} > @@ -199,22 +249,80 @@ function handle_submit_form(event) { +

Step 2: Clip Video

- {#if hosted_file_upload.upload_complete} - - + {#if $ae_loc.files.uploaded_file_kv && Object.entries($ae_loc.files.uploaded_file_kv).length > 0} + + + {:else} -

Upload a video file to clip.

+

Upload a video file to clip first.

{/if} + +

Step 3: Download Video Clips

+ {#if $ae_loc.files.video_clip_file_kv && Object.entries($ae_loc.files.video_clip_file_kv).length > 0} + + + + {:else} +

Clip a video file first.

+ {/if} + + + + + + + + + +The end +