// Import external files first. Eventually this will be broken up in to smaller files. import { process_permission_checks } from './ae_utils__perm_checks'; import { iso_datetime_formatter } from './ae_utils__datetime_format'; type key_str = { [key: string]: string; }; type key_val = { [key: string]: any; }; function format_bytes( bytes: number, decimals: number = 2 ) { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; } /* This utility function will add commas to a number. */ function number_w_commas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } /* 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 * If rm_empty then it will remove/ignore fields matching. Sometimes this is needed. * If trim_values then it will trim string values. * If bool_tf_str then it will convert string values of true/false (case insensitive) to boolean values. * Updated 2023-12-22 */ export let extract_prefixed_form_data = function extract_prefixed_form_data({prefix=null, form_data={}, rm_empty_id=true, rm_empty=false, trim_values=false, bool_tf_str=false, log_lvl=0}) { if (log_lvl) { console.log('*** extract_prefixed_form_data() ***'); if (prefix) { console.log(`Looking for prefixed fields: ${prefix}; Removing emptry ID fields: ${rm_empty_id}; Removing empty fields: ${rm_empty}; Trim string values: ${trim_values}; Convert true/false string values to boolean: ${bool_tf_str}`); } else { console.log(`No prefix set. Looking at all fields. Removing emptry ID fields: ${rm_empty_id}; Removing empty fields: ${rm_empty}; Trim string values: ${trim_values}; Convert true/false string values to boolean: ${bool_tf_str}`); } } if (log_lvl > 1) { console.log('Form Data:'); console.log(form_data); } // const data_obj: any = {}; // future TS let data_obj = {}; for (let field of form_data) { let [obj_prop_name, obj_prop_value] = field; if (log_lvl > 1) { console.log(`${obj_prop_name}: ${obj_prop_value} type=${typeof obj_prop_value}`); } // Trim string values if needed if (trim_values && typeof obj_prop_value === 'string') { if (log_lvl && obj_prop_value.trim() != obj_prop_value) { console.log('Trimming string value!'); obj_prop_value = obj_prop_value.trim(); } } // Convert string to boolean if needed if (bool_tf_str && typeof obj_prop_value === 'string') { // console.log('Flag set for converting true/false string values to boolean!'); if (obj_prop_value.toLowerCase() === 'true') { if (log_lvl) { console.log('Converting string to boolean value: true'); } obj_prop_value = true; } else if (obj_prop_value.toLowerCase() === 'false') { if (log_lvl) { console.log('Converting string to boolean value: false'); } obj_prop_value = false; } } if (prefix && obj_prop_name.startsWith(prefix)) { // Prefix set // if (obj_prop_name.startsWith(prefix)) { obj_prop_name = obj_prop_name.replace(prefix, ''); if (log_lvl) { console.log(`Checking: (${prefix})${obj_prop_name} value=${obj_prop_value}`); } if (rm_empty_id && obj_prop_name.endsWith('id_random') && !obj_prop_value) { if (log_lvl) { console.log(`Match but empty *_id_random. Ignoring/removing: ${obj_prop_name}`); } } else if (rm_empty && !obj_prop_value) { if (log_lvl) { console.log(`Match but empty. Ignoring/removing: ${obj_prop_name}`); } } else { if (log_lvl) { console.log(`Match: ${prefix})${obj_prop_name} value=${obj_prop_value}`); } data_obj[obj_prop_name] = obj_prop_value; } } else if (prefix && !obj_prop_name.startsWith(prefix)) { // Prefix set if (log_lvl > 1) { console.log('Did not start with prefix. Ignoring'); } } else { // No prefix set if (log_lvl) { console.log(`Checking: ${obj_prop_name} value=${obj_prop_value}`); } if (rm_empty_id && obj_prop_name.endsWith('id_random') && !obj_prop_value) { if (log_lvl > 1) { console.log(`Match but empty *_id_random. Ignoring/removing: ${obj_prop_name}`); } } else if (rm_empty && !obj_prop_value) { if (log_lvl > 1) { console.log(`Match but empty. Ignoring/removing: ${obj_prop_name}`); } } else { if (log_lvl > 1) { console.log(`Match: ${obj_prop_name} value=${obj_prop_value}`); } data_obj[obj_prop_name] = obj_prop_value; } } } if (log_lvl > 1) { console.log(data_obj); } return data_obj; } /* This utility function processes specific data string. * MECARD * OBJ = OBJ:ot:example,oi:asdf1234 * ot = Aether object type; oi = Aether object ID random * KV = KV:"key":"value" * JS = {"id":123,"name":"example name"} * http or https? * Common short keys used: * bdg: Badge ID Random * reg: Registration ID Random * exid: External ID * gn: Given First Name * fn: Family Last Name * em: Email Address */ // Updated 2022-02-11 export let process_data_string = function process_data_string(data_string: string) { console.log('*** process_data_string() ***'); // console.log(data_string); if (!data_string || data_string.length < 1) { console.log('No data string found.'); return false; } let obj: key_val = {}; let colon_index = data_string.indexOf(':') if (colon_index) { let data_string_type = data_string.slice(0, colon_index); console.log(data_string_type); obj['qr_type'] = data_string_type; if (data_string_type == 'MECARD') { let mecard_str = data_string.slice(colon_index+1); console.log(mecard_str); obj['str'] = mecard_str; } else if (data_string_type == 'OBJ') { let key_value_str = data_string.slice(colon_index+1); console.log(key_value_str); let key_value_array = key_value_str.split(','); // console.log(key_value_array); let ot_colon_index = key_value_array[0].indexOf(':') let obj_type = key_value_array[0].slice(ot_colon_index+1); // console.log(obj_type); let oi_colon_index = key_value_array[1].indexOf(':') let obj_id = key_value_array[1].slice(oi_colon_index+1); // console.log(obj_id); obj['type'] = obj_type; obj['id'] = obj_id; } else if (data_string_type == 'JSON') { let partial_json_str = data_string.slice(colon_index+1); console.log(partial_json_str); let json_str = `{${partial_json_str}}`; console.log(json_str); obj['json'] = JSON.parse(json_str); } else if (data_string_type == 'STR') { let str = data_string.slice(colon_index+1); console.log(str); obj['str'] = str; } else if (data_string_type == 'http' || data_string_type == 'https') { console.log(`http or https: ${data_string}`); obj['type'] = 'url'; obj['url'] = data_string; } else { console.log('The unknown data string type was found. Returning the string part.') let unknown_str = data_string.slice(colon_index+1); console.log(unknown_str); obj['str'] = unknown_str; } } else { console.log('The data string type was not found. Returning the entire string.') console.log(data_string); obj['qr_type'] = 'UNKNOWN'; obj['str'] = data_string; // return false; } console.log(obj); return obj; // Returns an object } // 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}`); let 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, {}); let 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, {}); let 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'}) { return `${text}`; } function create_img_element({account_id, base_url, hosted_file_id, filename=null, extension=null, class_li='max-w-64', style="", inc_link=false}) { let img_html = ''; if (filename) { img_html = ``; } else { img_html = ``; } if (inc_link) { let 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 = `
${img_html}${a_html}
`; } 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}) { let video_html = ''; if (filename) { video_html = ``; } else { video_html = ``; } if (inc_link) { let 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 = `
${video_html}${a_html}
`; } 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 paraghraphs) of text and return an estimated number of words. function count_words(text: string) { if (!text && text.length < 1) { return false; } let count = text.trim().split(/\s+/).length; return count; } /* Adapted from: To Title Case © 2018 David Gouch | https://github.com/gouch/to-title-case */ // eslint-disable-next-line no-extend-native function to_title_case (text_string) { // console.log('*** to_title_case() ***'); let smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|v.?|vs.?|via)$/i let alphanumericPattern = /([A-Za-z0-9\u00C0-\u00FF])/ let wordSeparators = /([ :–—-])/ return text_string.split(wordSeparators) .map(function (current, index, array) { if ( /* Check for small words */ current.search(smallWords) > -1 && /* Skip first and last word */ index !== 0 && index !== array.length - 1 && /* Ignore title end and subtitle start */ array[index - 3] !== ':' && array[index + 1] !== ':' && /* Ignore small words that start a hyphenated phrase */ (array[index + 1] !== '-' || (array[index - 1] === '-' && array[index + 1] === '-')) ) { return current.toLowerCase() } /* Ignore intentional capitalization */ if (current.substr(1).search(/[A-Z]|\../) > -1) { return current } /* Ignore URLs */ if (array[index + 1] === ':' && array[index + 2] !== '') { return current } /* Capitalize the first letter */ return current.replace(alphanumericPattern, function (match) { return match.toUpperCase() }) }) .join('') } // Updated 2024-06-19 export let shorten_string = function shorten_string( { string, max_length=45, begin_length=15, end_length=5, wildcard_length=3 }: { string: 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; } // 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; let char_over = string.length-max_length; let new_string = null; let wildcards = char_over; if (char_over > 0) { let 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); } let part3 = string.slice(end_length*-1); new_string = part1+part2+part3; } else { new_string = string; } return new_string; } // 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; let 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? } let part_1 = filename.slice(0, slice_end_at); if (wildcards > 3) { wildcards = 3; } else { } let part_2 = '.'.repeat(wildcards); let part_3 = filename.slice(max_end_length*-1); new_filename = part_1+part_2+part_3; return new_filename; } // Updated 2024-6-19 function file_extension_icon( extension: string ) { // console.log('*** file_extension_icon() ***'); let file_icons: key_str = { 'file': 'file', '3gp': 'file-video', '7z': 'file-archive', 'aac': 'file-audio', 'ac3': 'file-audio', 'aif': 'file-audio', 'aiff': 'file-audio', 'avi': 'file-video', 'bmp': 'file-image', 'csv': 'file-csv', 'doc': 'file-word', 'docx': 'file-word', 'eps': 'file-image', 'flac': 'file-audio', 'gif': 'file-image', 'htm': 'file-code', 'html': 'file-code', 'jpeg': 'file-image', 'jpg': 'file-image', 'key': 'file-powerpoint', 'mkv': 'file-video', 'mov': 'file-video', 'mp3': 'file-audio', 'mp4': 'file-video', 'odp': 'file-powerpoint', 'pdf': 'file-pdf', 'png': 'file-image', 'ppt': 'file-powerpoint', 'pptx': 'file-powerpoint', 'txt': 'file-alt', 'wav': 'file-audio', 'webp': 'file-image', 'xls': 'file-excel', 'xlsx': 'file-excel', 'zip': 'file-archive' }; if (file_icons[extension]) { return file_icons[extension]; } else { // return null; return file_icons['file']; } } // Updated 2023-08-18 function set_obj_prop_display_name({prop_name, obj_type=null, prefix_w_obj_type=true, prefix_all_w_obj_type=false, replace_underscores=true, title_case=true, override=null}) { console.log('*** set_obj_prop_display_name() ***'); if (override) { return override; } let known_obj_type_li = ['account', 'address', 'contact', 'event_badge', 'event_exhibit', 'event_file', 'event_location', 'event_person', 'event_presentation', 'event_presenter', 'event_registration', 'event_session', 'event', 'hosted_file', 'order_line', 'order', 'person', 'user']; let known_obj_type_li_dict = [ {name: 'account', display: 'Account'}, {name: 'address', display: 'Address'}, {name: 'contact', display: 'Contact'}, {name: 'event_badge', display: 'Event Badge'}, {name: 'event_exhibit', display: 'Event Exhibit'}, {name: 'event_file', display: 'Event File'}, {name: 'event_location', display: 'Event Location'}, {name: 'event_person', display: 'Event Person'}, {name: 'event_presentation', display: 'Event Presentation'}, {name: 'event_presenter', display: 'Event Presenter'}, {name: 'event_registration', display: 'Event Registration'}, {name: 'event_session', display: 'Event Session'}, {name: 'event', display: 'Event'}, {name: 'hosted_file', display: 'Hosted File'}, {name: 'order_line', display: 'Order Line'}, {name: 'order', display: 'Order'}, {name: 'person', display: 'Person'}, {name: 'user', display: 'User'}, ]; let prop_display_name = prop_name; if (!prefix_w_obj_type) { if (obj_type) { prop_display_name = prop_name.replace(obj_type, ''); } else { for (let i = 0; i < known_obj_type_li_dict.length; i++) { // console.log(known_obj_type_li_dict[i]); if (prop_name.startsWith(known_obj_type_li_dict[i].name)) { // console.log(`Found ${known_obj_type_li_dict[i].name}`); prop_display_name = prop_name.replace(known_obj_type_li_dict[i].name, ''); break; } } // for (let i = 0; i < known_obj_type_li.length; i++) { // // console.log(known_obj_type_li[i]); // if (prop_name.startsWith(known_obj_type_li[i])) { // console.log(`Found ${known_obj_type_li[i]}`); // prop_display_name = prop_name.replace(known_obj_type_li[i], ''); // break; // } // } } } else { if (!prefix_all_w_obj_type) { for (let i = 0; i < known_obj_type_li.length; i++) { // console.log(known_obj_type_li[i]); let found_obj_type = null; if (prop_name.startsWith(known_obj_type_li_dict[i].name)) { // if (prop_name.startsWith(known_obj_type_li[i])) { // console.log(`Found ${known_obj_type_li_dict[i].name}`); found_obj_type = known_obj_type_li_dict[i].name; if (found_obj_type == obj_type) { prop_display_name = prop_name.replace(known_obj_type_li_dict[i].name, ''); } break; } } // if (obj_type) { // prop_display_name = prop_name.replace(obj_type, ''); // } else { } } // console.log(prop_display_name); if (prop_display_name.search('ID')) { } prop_display_name = prop_display_name.replace('id_random', 'ID'); if (replace_underscores) { prop_display_name = prop_display_name.replaceAll('_', ' '); } if (title_case) { prop_display_name = to_title_case(prop_display_name); } // console.log(prop_display_name); return prop_display_name; } function return_obj_type_path({obj_type=null, obj_type_prop_name=null}) { console.log('*** set_obj_prop_display_name() ***'); let obj_type_path = null; let known_obj_type_li = ['account', 'address', 'archive', 'archive_content', 'contact', 'event_badge', 'event_exhibit', 'event_file', 'event_location', 'event_person', 'event_presentation', 'event_presenter', 'event_registration', 'event_session', 'event', 'hosted_file', 'order_line', 'order', 'person', 'post', 'post_comment', 'user']; let known_obj_type_li_dict = [ {name: 'account', display: 'Account', path: 'account'}, {name: 'archive', display: 'Archive', path: 'archive'}, {name: 'address', display: 'Address', path: 'address'}, {name: 'archive', display: 'Archive', path: 'archive'}, {name: 'archive_content', display: 'Archive Content', path: 'archive/content'}, {name: 'contact', display: 'Contact', path: 'contact'}, {name: 'data_store', display: 'Data Store', path: 'data_store'}, {name: 'event_abstract', display: 'Event Abstract', path: 'event/abstract'}, {name: 'event_badge', display: 'Event Badge', path: 'event/badge'}, {name: 'event_device', display: 'Event Device', path: 'event/device'}, {name: 'event_exhibit', display: 'Event Exhibit', path: 'event/exhibit'}, {name: 'event_file', display: 'Event File', path: 'event/file'}, {name: 'event_location', display: 'Event Location', path: 'event/location'}, {name: 'event_person', display: 'Event Person', path: 'event/person'}, {name: 'event_presentation', display: 'Event Presentation', path: 'event/'}, {name: 'event_presenter', display: 'Event Presenter', path: 'event/presenter'}, {name: 'event_registration', display: 'Event Registration', path: 'event/registration'}, {name: 'event_session', display: 'Event Session', path: 'event/session'}, {name: 'event', display: 'Event', path: 'event'}, {name: 'hosted_file', display: 'Hosted File', path: 'hosted_file'}, {name: 'journal', display: 'Journal', path: 'journal'}, {name: 'journal_entry', display: 'Journal Entry', path: 'journal/entry'}, {name: 'order_line', display: 'Order Line', path: 'order/line'}, {name: 'order', display: 'Order', path: 'order'}, {name: 'person', display: 'Person', path: 'person'}, {name: 'post', display: 'Archive', path: 'post'}, {name: 'post_comment', display: 'Archive Content', path: 'post/comment'}, {name: 'user', display: 'User', path: 'user'}, ]; if (obj_type) { // Need to loop through known for safety? obj_type_path = obj_type_prop_name.replaceAll('_', '/'); } else if (obj_type_prop_name) { let found_obj_type_name = null; let found_obj_type_path = null; for (let i = 0; i < known_obj_type_li_dict.length; i++) { // console.log(known_obj_type_li_dict[i]); // let guessed_obj_type = prop_name.startsWith(known_obj_type_li_dict[i] if (obj_type_prop_name.startsWith(known_obj_type_li_dict[i].name)) { console.log(`Found ${known_obj_type_li_dict[i].name}`); found_obj_type_name = known_obj_type_li_dict[i].name; found_obj_type_path = known_obj_type_li_dict[i].path; // obj_type_path = obj_type_prop_name.replaceAll('_', '/'); obj_type_path = found_obj_type_path; break; } } } else { console.log('Missing required parameters'); return false; } return obj_type_path; } export let ae_util = { process_permission_checks: process_permission_checks, iso_datetime_formatter: iso_datetime_formatter, format_bytes: format_bytes, number_w_commas: number_w_commas, 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, set_obj_prop_display_name: set_obj_prop_display_name, return_obj_type_path: return_obj_type_path, };