From aaead82c1af51ebbf22cc8d10960b404534c8aec Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 3 Feb 2026 11:19:23 -0500 Subject: [PATCH] feat(hosted-files): introduce standardized download component and V3 action support - Created AE_Comp_Hosted_Files_Download_Button using Svelte 5 and Lucide icons. - Added file_extension_icon_lucide utility for direct Lucide icon mapping. - Refactored download logic to core__hosted_files.ts using V3 Action endpoint (/v3/action/hosted_file/.../download). - Integrated new component into Event File Object Table. - Cleaned up legacy window.postMessage calls in several file management views. NOTE: The new download component is currently in development and may not be fully functional. --- .../ae_comp__hosted_files_clip_video.svelte | 1 - ...ae_comp__hosted_files_clip_video_li.svelte | 1 - ..._comp__hosted_files_download_button.svelte | 141 ++++++++++++++++++ src/lib/ae_core/core__hosted_files.ts | 47 ++++++ src/lib/ae_utils/ae_utils.ts | 2 + .../ae_utils__file_extension_icon_lucide.ts | 66 ++++++++ .../element_manage_event_file_li.svelte | 1 - .../events/ae_comp__event_file_obj_tbl.svelte | 74 +++------ ...e_idaa_comp__archive_content_obj_li.svelte | 1 - .../bb/ae_idaa_comp__post_obj_id_edit.svelte | 1 - .../bb/ae_idaa_comp__post_obj_id_view.svelte | 1 - 11 files changed, 275 insertions(+), 61 deletions(-) create mode 100644 src/lib/ae_core/ae_comp__hosted_files_download_button.svelte create mode 100644 src/lib/ae_utils/ae_utils__file_extension_icon_lucide.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 ef4ab864..11f94d02 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 @@ -224,7 +224,6 @@ log_lvl: 0 }); - // window.postMessage({ type: 'download_event_file', hosted_file_id: idaa_archive_content_obj.hosted_file_id, filename: idaa_archive_content_obj.filename, auto_download: true }, '*'); }} class:hidden={!$ae_loc.edit_mode} class="novi_btn btn btn-sm lg:btn-md preset-tonal-primary hover:preset-filled-primary-500 min-w-72 lg:min-w-96" 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 index 5692f766..b0a0fe33 100644 --- 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 @@ -60,7 +60,6 @@ log_lvl: log_lvl }); - // window.postMessage({ type: 'download_event_file', hosted_file_id: idaa_archive_content_obj.hosted_file_id, filename: idaa_archive_content_obj.filename, auto_download: true }, '*'); }} class="novi_btn btn btn-sm lg:btn-md preset-tonal-primary hover:preset-filled-primary-500 min-w-72 lg:min-w-96" title={`Download this file:\n${hosted_file_obj.filename}\n[API] SHA256: ${hosted_file_obj?.hash_sha256?.slice(0, 10)}... Hosted ID: ${hosted_file_obj.hosted_file_id}`} diff --git a/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte b/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte new file mode 100644 index 00000000..62f6a795 --- /dev/null +++ b/src/lib/ae_core/ae_comp__hosted_files_download_button.svelte @@ -0,0 +1,141 @@ + + +{#if hosted_file_id && hosted_file_obj} + {@const file_id = hosted_file_obj.id || hosted_file_obj.hosted_file_id || hosted_file_id} + +{:else} + +{/if} diff --git a/src/lib/ae_core/core__hosted_files.ts b/src/lib/ae_core/core__hosted_files.ts index de719244..fcdeb946 100644 --- a/src/lib/ae_core/core__hosted_files.ts +++ b/src/lib/ae_core/core__hosted_files.ts @@ -180,6 +180,53 @@ export async function delete_ae_obj_id__hosted_file({ return result; } +/** + * Download a hosted file (V3 Action) + * Uses the new /v3/action/... standard. + * Updated 2026-02-03 + */ +export async function download_ae_obj_id__hosted_file({ + api_cfg, + hosted_file_id, + return_file = true, + filename, + auto_download = false, + params = {}, + log_lvl = 0 +}: { + api_cfg: any; + hosted_file_id: string; + return_file?: boolean; + filename?: string; + auto_download?: boolean; + params?: key_val; + log_lvl?: number; +}) { + if (log_lvl) { + console.log(`*** download_ae_obj_id__hosted_file() *** id=${hosted_file_id}`); + } + + const task_id = hosted_file_id; + const endpoint = `/v3/action/hosted_file/${hosted_file_id}/download`; + + const query_params: key_val = { ...params }; + if (filename) { + query_params['filename'] = filename; + } + query_params['return_file'] = 'true'; // V3 prefers string 'true' for bool flags in query + + return await api.get_object({ + api_cfg, + endpoint, + params: query_params, + return_blob: return_file, + filename, + auto_download, + task_id, + log_lvl + }); +} + export const properties_to_save = [ 'id', 'hosted_file_id', diff --git a/src/lib/ae_utils/ae_utils.ts b/src/lib/ae_utils/ae_utils.ts index 6f241ac4..83c3088a 100644 --- a/src/lib/ae_utils/ae_utils.ts +++ b/src/lib/ae_utils/ae_utils.ts @@ -8,6 +8,7 @@ import { } from './ae_utils__files'; import { get_obj_li_w_match_prop } from './ae_utils__get_obj_li_w_match_prop'; import { file_extension_icon } from './ae_utils__file_extension_icon'; +import { file_extension_icon_lucide } from './ae_utils__file_extension_icon_lucide'; import { process_permission_checks } from './ae_utils__perm_checks'; import { iso_datetime_formatter } from './ae_utils__datetime_format'; import { is_datetime_recent } from './ae_utils__is_datetime_recent'; @@ -337,6 +338,7 @@ export const ae_util = { shorten_string: shorten_string, shorten_filename: shorten_filename, file_extension_icon: file_extension_icon, + file_extension_icon_lucide: file_extension_icon_lucide, format_html: format_html, set_obj_prop_display_name: set_obj_prop_display_name, return_obj_type_path: return_obj_type_path, diff --git a/src/lib/ae_utils/ae_utils__file_extension_icon_lucide.ts b/src/lib/ae_utils/ae_utils__file_extension_icon_lucide.ts new file mode 100644 index 00000000..a78566be --- /dev/null +++ b/src/lib/ae_utils/ae_utils__file_extension_icon_lucide.ts @@ -0,0 +1,66 @@ +import * as Lucide from 'lucide-svelte'; + +/** + * Returns a Lucide icon component based on the provided file extension. + * @param extension The file extension (e.g., 'pdf', 'jpg'). + * @returns The Lucide icon component. + */ +export function file_extension_icon_lucide(extension: string | undefined | null): any { + const ext = extension?.toLowerCase() || ''; + + const icon_map: Record = { + 'pdf': Lucide.FileText, + 'doc': Lucide.FileText, + 'docx': Lucide.FileText, + 'txt': Lucide.FileText, + 'rtf': Lucide.FileText, + + 'xls': Lucide.FileSpreadsheet, + 'xlsx': Lucide.FileSpreadsheet, + 'csv': Lucide.FileSpreadsheet, + + 'png': Lucide.FileImage, + 'jpg': Lucide.FileImage, + 'jpeg': Lucide.FileImage, + 'gif': Lucide.FileImage, + 'webp': Lucide.FileImage, + 'bmp': Lucide.FileImage, + 'svg': Lucide.FileImage, + + 'mp3': Lucide.FileAudio, + 'wav': Lucide.FileAudio, + 'm4a': Lucide.FileAudio, + 'flac': Lucide.FileAudio, + 'aac': Lucide.FileAudio, + 'aif': Lucide.FileAudio, + 'aiff': Lucide.FileAudio, + + 'mp4': Lucide.FileVideo, + 'mkv': Lucide.FileVideo, + 'mov': Lucide.FileVideo, + 'avi': Lucide.FileVideo, + '3gp': Lucide.FileVideo, + + 'ppt': Lucide.Presentation, + 'pptx': Lucide.Presentation, + 'key': Lucide.Presentation, + 'odp': Lucide.Presentation, + + 'zip': Lucide.FileArchive, + '7z': Lucide.FileArchive, + 'rar': Lucide.FileArchive, + 'tar': Lucide.FileArchive, + 'gz': Lucide.FileArchive, + + 'json': Lucide.FileJson, + + 'html': Lucide.FileCode, + 'htm': Lucide.FileCode, + 'js': Lucide.FileCode, + 'ts': Lucide.FileCode, + 'css': Lucide.FileCode, + 'php': Lucide.FileCode + }; + + return icon_map[ext] || Lucide.File; +} diff --git a/src/lib/elements/element_manage_event_file_li.svelte b/src/lib/elements/element_manage_event_file_li.svelte index 5b99a2b7..cf05d373 100644 --- a/src/lib/elements/element_manage_event_file_li.svelte +++ b/src/lib/elements/element_manage_event_file_li.svelte @@ -183,7 +183,6 @@ log_lvl: 0 }); - // window.postMessage({ type: 'download_event_file', event_file_id: event_file_obj.event_file_id, filename: event_file_obj.filename, auto_download: true }, '*'); }} class="btn btn-sm lg:btn-md preset-tonal-primary hover:preset-filled-primary-500 min-w-72 lg:min-w-96" title={`Download this file:\n${event_file_obj.filename}\n[API] SHA256: ${event_file_obj.hash_sha256.slice(0, 10)}... Hosted ID: ${event_file_obj.hosted_file_id} Event File ID: ${event_file_obj.event_file_id}`} diff --git a/src/routes/events/ae_comp__event_file_obj_tbl.svelte b/src/routes/events/ae_comp__event_file_obj_tbl.svelte index 06952d1b..720d1263 100644 --- a/src/routes/events/ae_comp__event_file_obj_tbl.svelte +++ b/src/routes/events/ae_comp__event_file_obj_tbl.svelte @@ -50,6 +50,7 @@ // import { events_loc, events_sess, events_slct, events_trigger, events_trig_kv } from '$lib/stores/ae_events_stores'; // import { events_func } from '$lib/ae_events_functions'; import MyClipboard from '$lib/app_components/e_app_clipboard.svelte'; + import AE_Comp_Hosted_Files_Download_Button from '$lib/ae_core/ae_comp__hosted_files_download_button.svelte'; // export let display_mode: string = 'default'; // 'default', 'compact', 'minimal', 'launcher' @@ -371,64 +372,27 @@ {#each $lq__event_file_obj_li as event_file_obj} - + class="badge preset-filled-success-600-400 hover:preset-filled-success-700-300 text-xs" + class:hidden={!event_file_obj?.file_purpose} + > + {event_file_obj?.file_purpose} + + {/snippet} + ${ log_lvl: 0 }); - // window.postMessage({ type: 'download_event_file', hosted_file_id: linked_obj.hosted_file_id_random, filename: linked_obj.filename, auto_download: true }, '*'); }} class="novi_btn btn btn-sm lg:btn-md preset-tonal-tertiary border border-tertiary-500 hover:preset-filled-tertiary-500 min-w-48" title={`Download this file:\n${linked_obj.filename}\n[API] SHA256: ${linked_obj?.hash_sha256.slice(0, 10)}... Hosted ID: ${linked_obj.hosted_file_id_random} Archive Content ID: ${linked_obj.archive_content_id}`} diff --git a/src/routes/idaa/(idaa)/bb/ae_idaa_comp__post_obj_id_view.svelte b/src/routes/idaa/(idaa)/bb/ae_idaa_comp__post_obj_id_view.svelte index 022416f2..b2afe0c7 100644 --- a/src/routes/idaa/(idaa)/bb/ae_idaa_comp__post_obj_id_view.svelte +++ b/src/routes/idaa/(idaa)/bb/ae_idaa_comp__post_obj_id_view.svelte @@ -179,7 +179,6 @@ log_lvl: 0 }); - // window.postMessage({ type: 'download_event_file', hosted_file_id: linked_obj.hosted_file_id_random, filename: linked_obj.filename, auto_download: true }, '*'); }} class="novi_btn btn btn-sm lg:btn-md preset-tonal-tertiary border border-tertiary-500 hover:preset-filled-tertiary-500 min-w-48" title={`Download this file:\n${linked_obj.filename}\n[API] SHA256: ${linked_obj?.hash_sha256.slice(0, 10)}... Hosted ID: ${linked_obj.hosted_file_id_random} Archive Content ID: ${linked_obj.archive_content_id}`}