diff --git a/front/devices.php b/front/devices.php index 329cbf97..86d3a063 100755 --- a/front/devices.php +++ b/front/devices.php @@ -810,4 +810,3 @@ function multiEditDevices() - diff --git a/front/donations.php b/front/donations.php index f7ee5623..0d4d428c 100755 --- a/front/donations.php +++ b/front/donations.php @@ -1,7 +1,7 @@ - +
diff --git a/front/js/db_methods.js b/front/js/db_methods.js index 9293b114..08606167 100755 --- a/front/js/db_methods.js +++ b/front/js/db_methods.js @@ -3,14 +3,14 @@ // ----------------------------------------------------------------------------- // Read data and place intotarget location, callback processies the results -function readData(sqlQuery, processDataCallback, targetLocation) { +function readData(sqlQuery, processDataCallback, valuesArray, targetLocation) { var apiUrl = `php/server/dbHelper.php?action=read&rawSql=${encodeURIComponent(sqlQuery)}`; $.get(apiUrl, function(data) { // Process the JSON data using the provided callback function data = JSON.parse(data) - var htmlResult = processDataCallback(data); + var htmlResult = processDataCallback(data, valuesArray); // Place the resulting HTML into the specified placeholder div $("#" + targetLocation).replaceWith(htmlResult); diff --git a/front/js/pialert_common.js b/front/js/pialert_common.js index 8f476344..aa0fe143 100755 --- a/front/js/pialert_common.js +++ b/front/js/pialert_common.js @@ -26,12 +26,12 @@ var settingsJSON = {} function getCache(key, noCookie = false) { // check cache - if(sessionStorage.getItem(key)) + if(localStorage.getItem(key)) { // check if not expired if(noCookie || getCookie(key + '_session_expiry') != "") { - return sessionStorage.getItem(key); + return localStorage.getItem(key); } } @@ -41,7 +41,7 @@ function getCache(key, noCookie = false) // ----------------------------------------------------------------------------- function setCache(key, data, expirationMinutes='') { - sessionStorage.setItem(key, data); + localStorage.setItem(key, data); // create cookie if expiration set to handle refresh of data if (expirationMinutes != '') @@ -107,55 +107,77 @@ function deleteAllCookies() { // ----------------------------------------------------------------------------- -// Get settings from the .json file generated by the python backend +// Get settings from the .json file generated by the python backend +// and cache them, if available, with options // ----------------------------------------------------------------------------- function cacheSettings() { $.get('api/table_settings.json?nocache=' + Date.now(), function(resSet) { - $.get('api/plugins.json?nocache=' + Date.now(), function(resPlug) { + $.get('api/plugins.json?nocache=' + Date.now(), function(resPlug) { pluginsData = resPlug["data"]; - settingsData = resSet["data"]; + settingsData = resSet["data"]; settingsData.forEach((set) => { - resolvedValue = set.Value; + resolvedOptions = createArray(set.Options) setPlugObj = {}; options_params = []; - - setPlugObj = getPluginSettingObject(pluginsData, set.Code_Name) - - - if(setPlugObj != {} && setPlugObj["options_params"]) + // proceed only if first option item contains something to resolve + if( !set.Code_Name.includes("__metadata") && + resolvedOptions.length != 0 && + resolvedOptions[0].includes("{value}")) { - options_params = setPlugObj["options_params"] + // get setting definition from the plugin config if available + setPlugObj = getPluginSettingObject(pluginsData, set.Code_Name) + + // check if options contains parameters and resolve + if(setPlugObj != {} && setPlugObj["options_params"]) + { + // get option_params for {value} resolution + options_params = setPlugObj["options_params"] + + if(options_params != []) + { + // handles only strings of length == 1 + resolvedOptions = `["${resolveParams(options_params, resolvedOptions[0])}"]` + } + } } - - // check if options contains parameters and resolve - if(set.Value.includes("{value}")) - { - resolvedValue = resolveParams(options_params, set.Value) - - console.log(resolvedValue) - } - - setCache(`pia_set_${set.Code_Name}`, resolvedValue) + setCache(`pia_set_${set.Code_Name}`, set.Value) + setCache(`pia_set_opt_${set.Code_Name}`, resolvedOptions) }); - - - }); + }).then(() => handleSuccess('cacheSettings')).catch(() => handleFailure('cacheSettings')); // handle AJAX synchronization }) } +// ----------------------------------------------------------------------------- +// Get a setting value by key +function getSettingOptions (key) { + + // handle initial load to make sure everything is set-up and cached + // handleFirstLoad() + + result = getCache(`pia_set_opt_${key}`, true); + + if (result == "") + { + console.log(`Setting options with key "${key}" not found`) + } + + return result; +} + +// ----------------------------------------------------------------------------- // Get a setting value by key function getSetting (key) { // handle initial load to make sure everything is set-up and cached - handleFirstLoad() + // handleFirstLoad() result = getCache(`pia_set_${key}`, true); @@ -195,7 +217,7 @@ function cacheStrings() data.forEach((langString) => { setCache(`pia_lang_${langString.String_Key}_${langString.Language_Code}`, langString.String_Value) }); - }) + }).then(() => handleSuccess('cacheStrings')).catch(() => handleFailure('cacheStrings')); // handle AJAX synchronization } @@ -203,7 +225,7 @@ function cacheStrings() function getString (key) { // handle initial laod to make sure everything is set-up and cached - handleFirstLoad() + // handleFirstLoad() UI_LANG = getSetting("UI_LANG"); @@ -759,30 +781,51 @@ function isRandomMAC(mac) if (input === '[]') { return []; } - - // Regex patterns + + // Regex pattern for brackets const patternBrackets = /(^\s*\[)|(\]\s*$)/g; - const patternQuotes = /(^\s*')|('\s*$)/g; const replacement = ''; - + // Remove brackets const noBrackets = input.replace(patternBrackets, replacement); - + const options = []; - - // Create array - const optionsTmp = noBrackets.split(','); - - // Handle only one item in array - if (optionsTmp.length === 0) { - return [noBrackets.replace(patternQuotes, replacement)]; + + // Detect the type of quote used after the opening bracket + const firstChar = noBrackets.trim()[0]; + const isDoubleQuoted = firstChar === '"'; + const isSingleQuoted = firstChar === "'"; + + // Create array while handling commas within quoted segments + let currentSegment = ''; + let withinQuotes = false; + for (let i = 0; i < noBrackets.length; i++) { + const char = noBrackets[i]; + if ((char === '"' && !isSingleQuoted) || (char === "'" && !isDoubleQuoted)) { + withinQuotes = !withinQuotes; + } + if (char === ',' && !withinQuotes) { + options.push(currentSegment.trim()); + currentSegment = ''; + } else { + currentSegment += char; + } } - - // Remove quotes - optionsTmp.forEach(item => { - options.push(item.replace(patternQuotes, replacement).trim()); + // Push the last segment + options.push(currentSegment.trim()); + + // Remove quotes based on detected type + options.forEach((item, index) => { + let trimmedItem = item.trim(); + // Check if the string starts and ends with the same type of quote + if ((isDoubleQuoted && trimmedItem.startsWith('"') && trimmedItem.endsWith('"')) || + (isSingleQuoted && trimmedItem.startsWith("'") && trimmedItem.endsWith("'"))) { + // Remove the quotes + trimmedItem = trimmedItem.substring(1, trimmedItem.length - 1); + } + options[index] = trimmedItem; }); - + return options; } @@ -832,7 +875,7 @@ function initDeviceListAll_JSON() } setCache('devicesListAll_JSON', devicesListAll_JSON_str) - }); + }).then(() => handleSuccess('initDeviceListAll_JSON')).catch(() => handleFailure('initDeviceListAll_JSON')); // handle AJAX synchronization } @@ -1009,7 +1052,7 @@ function resolveParams(params, template) { }); // Log the resolved template - console.log(template); + // console.log(template); // Return the resolved template return template; @@ -1021,12 +1064,14 @@ function resolveParams(params, template) { // Define a unique key for storing the flag in sessionStorage var sessionStorageKey = "myScriptExecuted_pialert_common"; +// ----------------------------------------------------------------------------- function resetInitializedFlag() { // Set the flag in sessionStorage to indicate that the code and cahce needs to be reloaded sessionStorage.setItem(sessionStorageKey, "false"); } +// ----------------------------------------------------------------------------- // check if cache needs to be refreshed because of setting changes $.get('api/app_state.json?nocache=' + Date.now(), function(appState) { @@ -1038,12 +1083,18 @@ $.get('api/app_state.json?nocache=' + Date.now(), function(appState) { if(importedMiliseconds > lastReloaded) { - resetInitializedFlag() - location.reload(); + console.log("Cache needs to be refreshed because of setting changes"); + setTimeout(() => { + resetInitializedFlag() + location.reload(); + + }, 500); + } }); +// ----------------------------------------------------------------------------- // Display spinner and reload page if not yet initialized function handleFirstLoad() { @@ -1056,6 +1107,7 @@ function handleFirstLoad() } } +// ----------------------------------------------------------------------------- // Check if the code has been executed before by checking sessionStorage var pialert_common_init = sessionStorage.getItem(sessionStorageKey) === "true"; @@ -1066,20 +1118,46 @@ function executeOnce() { showSpinner() + // Counter to keep track of completed AJAX calls + completedCalls = 0; + // Your initialization code here cacheSettings(); cacheStrings(); initDeviceListAll_JSON(); + } +} + +// ----------------------------------------------------------------------------- +// Function to handle successful completion of an AJAX call +const handleSuccess = (callName) => { + console.log(`AJAX call ${callName} successful`); + completedCalls++; + onAllCallsComplete(); +}; + +// ----------------------------------------------------------------------------- +// Function to handle failure of an AJAX call +const handleFailure = (callName) => { + // Handle AJAX call failure here + console.error(`AJAX call ${callName} failed`); +}; + +// ----------------------------------------------------------------------------- +// Function to execute when all AJAX calls have completed +const onAllCallsComplete = () => { + // Check if all three AJAX calls have completed + if (completedCalls === 3) { // Set the flag in sessionStorage to indicate that the code has been executed - // and save time when last time the page for initialized + // and save time when last time the page was initialized sessionStorage.setItem(sessionStorageKey, "true"); const millisecondsNow = Date.now(); sessionStorage.setItem(sessionStorageKey + '_time', millisecondsNow); console.log("init pialert_common.js"); } -} +}; // Call the function to execute the code executeOnce(); diff --git a/front/js/ui_components.js b/front/js/ui_components.js index c1b15716..18de6b46 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -111,40 +111,40 @@ $(function () { // ----------------------------------------------------------------------------- // Initiate dropdown -function initSettingDropdown(settingKey, targetLocation) +function initSettingDropdown(settingKey, valuesArray, targetLocation) { var optionsHtml = "" var targetLocation_options = settingKey + "_initSettingDropdown" - setVal = getSetting(settingKey) - - console.log(setVal); + optionsArray = createArray(getSettingOptions(settingKey)) // check if the result is a SQL query - if(isSQLQuery(setVal)) + if(isSQLQuery(optionsArray[0])) { optionsHtml += ``; - readData(setVal, generateDropdownOptions, targetLocation_options); + readData(optionsArray[0], generateDropdownOptions, valuesArray, targetLocation_options); } else // this should be already an array, e.g. from a setting or pre-defined { - options = createArray(setVal); - values = createArray(setVal); - - - options.forEach(option => { - let selected = values.includes(option) ? 'selected' : ''; + optionsArray.forEach(option => { + let selected = valuesArray.includes(option) ? 'selected' : ''; optionsHtml += ``; - }); + }); - // Place the resulting HTML into the specified placeholder div - $("#" + targetLocation).replaceWith(optionsHtml); + // Replace the specified placeholder div with the resulting HTML + setTimeout(() => { + + $("#" + targetLocation).replaceWith(optionsHtml); + + }, 50); } + + } @@ -156,10 +156,13 @@ function initSettingDropdown(settingKey, targetLocation) // ----------------------------------------------------------------------------- // Processor to generate options for a dropdown menu -function generateDropdownOptions(data) { +function generateDropdownOptions(data, valuesArray) { var optionsHtml = ""; data.forEach(function(item) { - optionsHtml += ``; + + let selected = valuesArray.includes(item.id) ? 'selected' : ''; + + optionsHtml += ``; }); return `${optionsHtml}`; } @@ -167,10 +170,13 @@ function generateDropdownOptions(data) { // ----------------------------------------------------------------------------- // Processor to generate a list -function generateList(data) { +function generateList(data, valuesArray) { var listHtml = ""; data.forEach(function(item) { - listHtml += `
  • ${item.name}
  • `; + + let selected = valuesArray.includes(item.id) ? 'selected' : ''; + + listHtml += `
  • ${item.name}
  • `; }); listHtml += ""; return listHtml; diff --git a/front/maintenance.php b/front/maintenance.php index 2f6747ae..14edef2e 100755 --- a/front/maintenance.php +++ b/front/maintenance.php @@ -807,7 +807,7 @@ function scrollDown() } } - }, 100); + }, 200); } @@ -946,6 +946,3 @@ window.onload = function asyncFooter() - - - diff --git a/front/multiEditCore.php b/front/multiEditCore.php index be6545e8..2a2f45ca 100755 --- a/front/multiEditCore.php +++ b/front/multiEditCore.php @@ -110,7 +110,7 @@ targetLocation = columns[j].Code_Name + "_initSettingDropdown" - initSettingDropdown(columns[j].Code_Name, targetLocation) + initSettingDropdown(columns[j].Code_Name, [], targetLocation) input = ` -