- 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.
352 lines
11 KiB
TypeScript
352 lines
11 KiB
TypeScript
// Import external files first. Eventually this will be broken up in to smaller files.
|
|
import {
|
|
clean_filename,
|
|
format_bytes,
|
|
guess_file_name,
|
|
guess_file_extension,
|
|
get_file_hash
|
|
} 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';
|
|
import { extract_prefixed_form_data } from './ae_utils__extract_prefixed_form_data';
|
|
import { to_title_case } from './ae_utils__to_title_case';
|
|
import { process_data_string } from './ae_utils__process_data_string';
|
|
import { set_obj_prop_display_name } from './ae_utils__set_obj_prop_display_name';
|
|
import { return_obj_type_path } from './ae_utils__return_obj_type_path';
|
|
import { format_html } from './ae_utils__format_html';
|
|
import {
|
|
combine_iv_and_base64,
|
|
encrypt_content,
|
|
encrypt_wrapper,
|
|
decrypt_content,
|
|
decrypt_wrapper
|
|
} from './ae_utils__crypto';
|
|
|
|
export type key_str = {
|
|
[key: string]: string;
|
|
};
|
|
|
|
export type key_val = {
|
|
[key: string]: any;
|
|
};
|
|
|
|
/* This utility function will add commas to a number. */
|
|
function number_w_commas(x: number | string) {
|
|
if (!x) return '0';
|
|
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
}
|
|
|
|
// This function will update the URL and send a message to the parent window (iframe).
|
|
// The name should be something like "example_id".
|
|
// Svelte specific:
|
|
// WARNING: Avoid using `history.pushState(...)` and `history.replaceState(...)` as these will conflict with SvelteKit's router. Use the `pushState` and `replaceState` imports from `$app/navigation` instead.
|
|
// Updated 2024-03-02
|
|
// import { pushState, replaceState } from '$app/navigation';
|
|
|
|
function handle_url_and_message(name: string, value: null | string) {
|
|
console.log(`*** handle_url_and_message() *** name=${name} value=${value}`);
|
|
|
|
const location = window.location.href;
|
|
// console.log('location:', location);
|
|
const url = new URL(location);
|
|
// console.log('url:', url);
|
|
|
|
if (value) {
|
|
url.searchParams.set(name, value);
|
|
history.pushState({}, '', url);
|
|
|
|
// console.log('url:', url);
|
|
// pushState(url.href, {});
|
|
// pushState(url.search, {});
|
|
// replaceState(url.href, {});
|
|
|
|
const message = { name: value };
|
|
window.parent.postMessage(message, '*');
|
|
} else {
|
|
url.searchParams.delete(name);
|
|
history.pushState({}, '', url);
|
|
|
|
// console.log('url:', url);
|
|
// pushState({}, '', url.search);
|
|
// pushState(url.href, {});
|
|
// replaceState(url.href, {});
|
|
|
|
const message = { name: null };
|
|
window.parent.postMessage(message, '*');
|
|
}
|
|
// console.log('Message sent to parent (iframe):', message);
|
|
}
|
|
|
|
function create_a_element({
|
|
account_id,
|
|
base_url,
|
|
hosted_file_id,
|
|
filename = null,
|
|
extension = null,
|
|
text = 'Download',
|
|
class_li = 'text-blue-500'
|
|
}: {
|
|
account_id: string;
|
|
base_url: string;
|
|
hosted_file_id: string;
|
|
filename?: string | null;
|
|
extension?: string | null;
|
|
text?: string;
|
|
class_li?: string;
|
|
}) {
|
|
return `<a href="${base_url}/hosted_file/${hosted_file_id}/download?x_no_account_id_token=${account_id}&filename=${filename}" class="${class_li}">${text}</a>`;
|
|
}
|
|
|
|
function create_img_element({
|
|
account_id,
|
|
base_url,
|
|
hosted_file_id,
|
|
filename = null,
|
|
extension = null,
|
|
class_li = 'max-w-64',
|
|
style = '',
|
|
inc_link = false
|
|
}: {
|
|
account_id: string;
|
|
base_url: string;
|
|
hosted_file_id: string;
|
|
filename?: string | null;
|
|
extension?: string | null;
|
|
class_li?: string;
|
|
style?: string;
|
|
inc_link?: boolean;
|
|
}) {
|
|
let img_html = '';
|
|
if (filename) {
|
|
img_html = `<img src="${base_url}/hosted_file/${hosted_file_id}/download?x_no_account_id_token=${account_id}&filename=${filename}" class="${class_li}" style="${style}" />`;
|
|
} else {
|
|
img_html = `<img src="${base_url}/hosted_file/${hosted_file_id}/download?x_no_account_id_token=${account_id}" class="${class_li}" style="${style}" />`;
|
|
}
|
|
|
|
if (inc_link) {
|
|
const a_html = create_a_element({
|
|
account_id: account_id,
|
|
base_url: base_url,
|
|
hosted_file_id: hosted_file_id,
|
|
filename: filename,
|
|
extension: extension
|
|
});
|
|
img_html = `<div class="ae_img ae_a">${img_html}${a_html}</div>`;
|
|
}
|
|
|
|
return img_html;
|
|
}
|
|
|
|
function create_video_element({
|
|
account_id,
|
|
base_url,
|
|
hosted_file_id,
|
|
filename = null,
|
|
extension = null,
|
|
class_li = 'max-w-64',
|
|
inc_link = false
|
|
}: {
|
|
account_id: string;
|
|
base_url: string;
|
|
hosted_file_id: string;
|
|
filename?: string | null;
|
|
extension?: string | null;
|
|
class_li?: string;
|
|
inc_link?: boolean;
|
|
}) {
|
|
let video_html = '';
|
|
if (filename) {
|
|
video_html = `<video src="${base_url}/hosted_file/${hosted_file_id}/download?x_no_account_id_token=${account_id}&filename=${filename}" controls class="${class_li}"></video>`;
|
|
} else {
|
|
video_html = `<video src="${base_url}/hosted_file/${hosted_file_id}/download?x_no_account_id_token=${account_id}" controls class="${class_li}"></video>`;
|
|
}
|
|
|
|
if (inc_link) {
|
|
const a_html = create_a_element({
|
|
account_id: account_id,
|
|
base_url: base_url,
|
|
hosted_file_id: hosted_file_id,
|
|
filename: filename,
|
|
extension: extension
|
|
});
|
|
video_html = `<div class="ae_video ae_a">${video_html}${a_html}</div>`;
|
|
}
|
|
|
|
return video_html;
|
|
}
|
|
|
|
// // Clear the quick access type
|
|
// function clear_access_type() {
|
|
// // NOTE: I think it makes since to reset this to anonymous even if logged in as an admin or similar.
|
|
// window.localStorage.setItem('access_type', 'anonymous');
|
|
|
|
// // $ae_loc.access_type = null; // 'anonymous';
|
|
// $ae_loc.access_type = 'anonymous';
|
|
// trigger = 'process_permission_check';
|
|
|
|
// show_passcode_input = false;
|
|
|
|
// // $ae_loc = $ae_loc; // Trigger Svelte just in case
|
|
// // ae_loc.set($ae_loc);
|
|
// // console.log($ae_loc);
|
|
|
|
// return true;
|
|
// }
|
|
|
|
// This function will take a long string (sentences or paragraphs) of text and return an estimated number of words.
|
|
function count_words(text: string) {
|
|
if (!text || text.length < 1) {
|
|
return false;
|
|
}
|
|
const count = text.trim().split(/\s+/).length;
|
|
|
|
return count;
|
|
}
|
|
|
|
// Updated 2024-06-19
|
|
// This function behaves weirdly. It needs to be reviewed and updated.
|
|
export const shorten_string = function shorten_string({
|
|
string,
|
|
max_length = 45,
|
|
begin_length = 15,
|
|
end_length = 5,
|
|
wildcard_length = 3
|
|
}: {
|
|
string: undefined | string;
|
|
max_length?: number;
|
|
begin_length?: number;
|
|
end_length?: number;
|
|
wildcard_length?: number;
|
|
}) {
|
|
// console.log('*** shorten_filename() ***');
|
|
|
|
if (!string || typeof string != 'string') {
|
|
// console.log('Invalid string value passed');
|
|
// return false;
|
|
return '';
|
|
}
|
|
|
|
// NOTE: max_length is not the actual end result length. The actual max will be 45 characters.
|
|
// 20 part 1 characters, 5 part 2 characters, 20 part 3 characters
|
|
|
|
// let length = string.length;
|
|
const char_over = string.length - max_length;
|
|
let new_string = null;
|
|
let wildcards = char_over;
|
|
if (char_over > 0) {
|
|
const part1 = string.slice(0, begin_length);
|
|
|
|
let part2 = '';
|
|
if (char_over > 5) {
|
|
wildcards = 5;
|
|
} else {
|
|
}
|
|
|
|
if (wildcard_length) {
|
|
part2 = '.'.repeat(wildcard_length);
|
|
} else {
|
|
part2 = '.'.repeat(wildcards);
|
|
}
|
|
|
|
const part3 = string.slice(end_length * -1);
|
|
|
|
new_string = part1 + part2 + part3;
|
|
} else {
|
|
new_string = string;
|
|
}
|
|
return new_string;
|
|
};
|
|
|
|
// Svelte action to set focus on an element
|
|
function set_focus(node: HTMLElement, focus: boolean) {
|
|
if (focus) {
|
|
node.focus();
|
|
}
|
|
return {
|
|
update(new_focus: boolean) {
|
|
if (new_focus) {
|
|
node.focus();
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
// Updated 2024-06-19
|
|
// This function should return a shorted version of a filename if over the max length. It should always contain at least the first character of the original filename and the complete extension.
|
|
// Example 1: The Original Long File Name.pdf -> The Orig....pdf
|
|
// Example 2: The Original Long File Name.html -> The Ori....html
|
|
function shorten_filename({
|
|
filename,
|
|
max_length = 20,
|
|
slice_end_at = 15,
|
|
max_end_length = 5
|
|
}: {
|
|
filename: string;
|
|
max_length?: number;
|
|
slice_end_at?: number;
|
|
max_end_length?: number;
|
|
}) {
|
|
// console.log('*** shorten_filename() ***');
|
|
|
|
if (typeof filename !== 'string' || filename.length <= max_length) {
|
|
return filename;
|
|
}
|
|
|
|
let new_filename = null;
|
|
const char_over = filename.length - max_length;
|
|
let wildcards = char_over - 4; // The number of characters over the max length
|
|
if (wildcards < 1) {
|
|
return filename; // No point in changing the filename?
|
|
}
|
|
|
|
const part_1 = filename.slice(0, slice_end_at);
|
|
if (wildcards > 3) {
|
|
wildcards = 3;
|
|
} else {
|
|
}
|
|
const part_2 = '.'.repeat(wildcards);
|
|
const part_3 = filename.slice(max_end_length * -1);
|
|
|
|
new_filename = part_1 + part_2 + part_3;
|
|
|
|
return new_filename;
|
|
}
|
|
|
|
export const ae_util = {
|
|
is_datetime_recent: is_datetime_recent,
|
|
process_permission_checks: process_permission_checks,
|
|
iso_datetime_formatter: iso_datetime_formatter,
|
|
clean_filename: clean_filename,
|
|
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,
|
|
get_obj_li_w_match_prop: get_obj_li_w_match_prop,
|
|
extract_prefixed_form_data: extract_prefixed_form_data,
|
|
process_data_string: process_data_string,
|
|
handle_url_and_message: handle_url_and_message,
|
|
create_a_element: create_a_element,
|
|
create_img_element: create_img_element,
|
|
create_video_element: create_video_element,
|
|
count_words: count_words,
|
|
to_title_case: to_title_case,
|
|
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,
|
|
combine_iv_and_base64: combine_iv_and_base64,
|
|
encrypt_content: encrypt_content,
|
|
encrypt_wrapper: encrypt_wrapper,
|
|
decrypt_content: decrypt_content,
|
|
decrypt_wrapper: decrypt_wrapper,
|
|
set_focus: set_focus
|
|
};
|