let Utils = {}; let locale; let format; Utils.translate = function (key) { if (!Lang.hasOwnProperty(locale)) { console.warn(`Language '${locale}' is not available. Using default 'en'.`); locale = "en"; } let langObj = Lang[locale]; const keys = key.split("."); for (const k of keys) { if (!langObj.hasOwnProperty(k)) { console.warn(`Translation key '${key}' not found for language '${locale}'.`); return "missing_translation"; } langObj = langObj[k]; } return langObj; }; Utils.setLocale = function (current_locale) { locale = current_locale; }; Utils.setFormat = function (current_format) { format = current_format; }; Utils.loadLanguageFile = async function () { try { await new Promise((resolve, reject) => { let fileUrl = `lang/${locale}.js`; const script = document.createElement("script"); script.src = fileUrl; script.onload = () => { resolve(); }; script.onerror = (event) => { reject(new Error("Failed to load language file: " + fileUrl)); }; document.body.appendChild(script); const timeoutDuration = 10000; // 10 seconds setTimeout(() => { reject(new Error("Timeout: The script took too long to load the language file: " + fileUrl)); }, timeoutDuration); }); } catch (error) { if (locale !== "en") { console.warn(`Language '${locale}' is not available. Using default 'en'.`); Utils.setLocale("en"); await Utils.loadLanguageFile(); } else { throw error; } } }; Utils.loadLanguageModules = async function (utils_module) { Utils.setLocale(utils_module.config.locale); Utils.setFormat(utils_module.config.format); await Utils.loadLanguageFile(); Utils.deepMerge(Lang,utils_module.lang); }; Utils.timeConverter = function (UNIX_timestamp, options = {}) { const timestampMillis = UNIX_timestamp * 1000; const formattedTime = new Date(timestampMillis).toLocaleString(locale, options); return formattedTime; }; Utils.currencyFormat = function (number, decimalPlaces = null) { const options = { style: "currency", currency: format.currency, }; if (decimalPlaces != null) { options.minimumFractionDigits = decimalPlaces; options.maximumFractionDigits = decimalPlaces; } return new Intl.NumberFormat(format.location, options).format(number); }; Utils.numberFormat = function (number, decimalPlaces = null) { const options = {}; if (decimalPlaces != null) { options.minimumFractionDigits = decimalPlaces; options.maximumFractionDigits = decimalPlaces; } return new Intl.NumberFormat(format.location, options).format(number); }; Utils.getCurrencySymbol = function () { const options = { style: "currency", currency: format.currency, minimumFractionDigits: 0, maximumFractionDigits: 0, }; return new Intl.NumberFormat(locale, options).format(0).replace(/\d/g, "").trim(); }; const requestQueue = []; let isProcessing = false; const processQueue = async () => { if (!isProcessing && requestQueue.length > 0) { isProcessing = true; const { event, data, route, cb } = requestQueue.shift(); try { const response = await fetch(Utils.getRoute(route), { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ event, data }), }); if (!response.ok) { throw new Error(`Request failed with status: ${response.status}`); } const responseData = await response.json(); if (cb) { cb(responseData); } else { if (responseData !== 200) { console.log(responseData); } } } catch (error) { console.error(`Error occurred while making a POST request with event: "${event}", data: "${JSON.stringify(data)}", and route: "${Utils.getRoute(route)}": ${error.message}`); } finally { isProcessing = false; setTimeout(function() { processQueue(); }, 200); } } }; Utils.post = function (event, data, route = "post", cb) { requestQueue.push({ event, data, route, cb }); processQueue(); }; let resource_name; Utils.getRoute = function (name) { return `https://${resource_name}/${name}`; }; Utils.setResourceName = function (current_resource_name) { resource_name = current_resource_name; }; const modalTemplate = ` `; Utils.showDefaultModal = function (action, body = Utils.translate("confirmation_modal_body")) { Utils.showCustomModal({ title: Utils.translate("confirmation_modal_title"), body, buttons: [ { text: Utils.translate("confirmation_modal_cancel_button"), class: "btn btn-outline-primary", dismiss: true }, { text: Utils.translate("confirmation_modal_confirm_button"), class: "btn btn-primary", dismiss: true, action }, ], }); }; Utils.showDefaultDangerModal = function (action, body = Utils.translate("confirmation_modal_body")) { Utils.showCustomModal({ title: Utils.translate("confirmation_modal_title"), body, buttons: [ { text: Utils.translate("confirmation_modal_cancel_button"), class: "btn btn-outline-danger", dismiss: true }, { text: Utils.translate("confirmation_modal_confirm_button"), class: "btn btn-danger", dismiss: true, action }, ], }); }; /* const exampleConfig = { title: 'Custom Modal Title', body: 'Custom Modal Body Text', bodyHtml: '

Custom Modal Body Text that accept HTML

', bodyImage: "https://shuffle.dev/randomizer/saas/bootstrap-pstls/1.0.0/static_elements/footer/10_awz.jpg", footerText: "Custom Footer Text", buttons: [ { text: Utils.translate('confirmation_modal_cancel_button'), class: 'btn btn-outline-primary', dismiss: true }, { text: Utils.translate('confirmation_modal_confirm_button'), class: 'btn btn-primary', dismiss: false, action: () => console.log('Confirmed') } { text: 'Submit', class: 'btn btn-primary', dismiss: false, type: 'submit' } ], inputs: [ { type: 'text', // Input type: text label: 'Text Input:', small: 'Small text', id: 'text-input-id', name: 'text-input-name', value: 'xxxx', required: true, placeholder: 'Enter text here' }, { type: 'number', // Input type: number label: 'Number Input:', small: 'Small text', id: 'number-input-id', name: 'number-input-name', value: 10, min: 0, max: 10, required: true, placeholder: 'Enter a number' }, { type: 'custom', html: `
0) { return; } const modalConfig = { title: Utils.translate("confirmation_modal_title"), buttons: [], inputs: [], }; // Merge the provided config with the default modalConfig const mergedConfig = { ...modalConfig }; Utils.deepMerge(mergedConfig, config); // Append the modal HTML to the body $("body").append(modalTemplate); // Cache the modal element const $modal = $("#confirmation-modal"); const $modalBody = $modal.find(".modal-body"); // Set modal content $modal.find(".modal-title").text(mergedConfig.title); if (mergedConfig.bodyImage) { const $imageContainer = $("
", { class: "d-flex justify-content-center m-2" }); const $image = $("", { src: mergedConfig.bodyImage, class: "w-50" }); $imageContainer.append($image); $modalBody.append($imageContainer); } if (mergedConfig.body) { const $p = $("

", { id: "modal-body-text", text: mergedConfig.body }); $modalBody.append($p); } if (mergedConfig.bodyHtml) { $modalBody.append(mergedConfig.bodyHtml); } // Set modal inputs const $form = $modal.find("#form-confirmation-modal"); mergedConfig.inputs.forEach(inputConfig => { const $inputContainer = $("

", { class: "form-group mx-2" }); if (inputConfig.type === "select") { const $label = $("