From 1f7a38593dfc5335a3fcd3c556e4fff227e51ca7 Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Sat, 3 Aug 2024 21:07:12 +1000 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=84Cache=20+=20Settings=20work?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- front/deviceDetails.php | 2 +- front/devices.php | 30 +-- front/js/common.js | 237 ++++++++++++++-------- front/js/db_methods.js | 2 +- front/js/settings_utils.js | 31 +-- front/js/ui_components.js | 136 +++++-------- front/multiEditCore.php | 21 +- front/plugins/__template/config.json | 19 +- front/plugins/dhcp_leases/config.json | 19 +- front/plugins/newdev_template/config.json | 73 +++---- front/plugins/omada_sdn_imp/config.json | 19 +- front/plugins/snmp_discovery/config.json | 19 +- front/plugins/undiscoverables/config.json | 19 +- front/plugins/unifi_import/config.json | 20 +- front/plugins/website_monitor/config.json | 19 +- front/settings.php | 29 ++- server/initialise.py | 4 +- 17 files changed, 370 insertions(+), 329 deletions(-) diff --git a/front/deviceDetails.php b/front/deviceDetails.php index 03c44d92..2847d15f 100755 --- a/front/deviceDetails.php +++ b/front/deviceDetails.php @@ -1149,7 +1149,7 @@ function initializeCalendar () { } else { setTimeout(() => { updateIconPreview('#txtIcon') - }, 100); + }, 500); hideSpinner() } diff --git a/front/devices.php b/front/devices.php index f5e8001a..092a845b 100755 --- a/front/devices.php +++ b/front/devices.php @@ -143,9 +143,23 @@ var tableOrder = [[3,'desc'], [0,'asc']]; var tableColumnHide = []; + var tableColumnOrder = []; + var tableColumnVisible = []; - //initialize the table headers in the correct order - var headersDefaultOrder = [ + + + + // Read parameters & Initialize components + callAfterAppInitialized(main) + showSpinner(); + + + +// ----------------------------------------------------------------------------- +function main () { + + //initialize the table headers in the correct order + var headersDefaultOrder = [ getString('Device_TableHead_Name'), getString('Device_TableHead_Owner'), getString('Device_TableHead_Type'), @@ -173,16 +187,8 @@ // generate default order lists of given length var columnsStr = JSON.stringify(Array.from({ length: headersDefaultOrder.length }, (_, i) => i)); - var tableColumnOrder = Array.from({ length: headersDefaultOrder.length }, (_, i) => i); - var tableColumnVisible = tableColumnOrder; - - // Read parameters & Initialize components - showSpinner(); - main(); - - -// ----------------------------------------------------------------------------- -function main () { + tableColumnOrder = Array.from({ length: headersDefaultOrder.length }, (_, i) => i); + tableColumnVisible = tableColumnOrder; handleLoadingDialog() diff --git a/front/js/common.js b/front/js/common.js index d659ff71..20b5322b 100755 --- a/front/js/common.js +++ b/front/js/common.js @@ -10,9 +10,10 @@ // ----------------------------------------------------------------------------- var timerRefreshData = '' -var emptyArr = ['undefined', "", undefined, null, 'null']; -var UI_LANG = "English"; -var settingsJSON = {} +var emptyArr = ['undefined', "", undefined, null, 'null']; +var UI_LANG = "English"; +const allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "zh_cn"]; // needs to be same as in lang.php +var settingsJSON = {} // ----------------------------------------------------------------------------- @@ -207,98 +208,123 @@ function getSetting (key) { // ----------------------------------------------------------------------------- // Get language string // ----------------------------------------------------------------------------- -function cacheStrings() -{ +function cacheStrings() { return new Promise((resolve, reject) => { - if(!getCache('completedCalls').includes('cacheStrings')) - { - // handle core strings and translations - var allLanguages = ["en_us", "es_es", "de_de", "fr_fr", "it_it", "ru_ru", "nb_no", "pl_pl", "zh_cn"]; // needs to be same as in lang.php - - allLanguages.forEach(function (language_code) { - $.get(`php/templates/language/${language_code}.json?nocache=${Date.now()}`, function (res) { - // Iterate over each language - Object.entries(res).forEach(([key, value]) => { - // Store translations for each key-value pair - setCache(`pia_lang_${key}_${language_code}`, value) - }); - - // handle strings and translations from plugins - $.get(`api/table_plugins_language_strings.json?nocache=${Date.now()}`, function(res) { - - data = res["data"]; - - data.forEach((langString) => { - setCache(`pia_lang_${langString.String_Key}_${langString.Language_Code}`, langString.String_Value) - }); - }).then(() => handleSuccess('cacheStrings', resolve())).catch(() => handleFailure('cacheStrings', reject("cacheStrings already completed"))); // handle AJAX synchronization + + // Create a promise for each language + const languagePromises = allLanguages.map((language_code) => { + return new Promise((resolveLang, rejectLang) => { + // Fetch core strings and translations + $.get(`php/templates/language/${language_code}.json?nocache=${Date.now()}`) + .done((res) => { + // Iterate over each key-value pair and store the translations + Object.entries(res).forEach(([key, value]) => { + setCache(`pia_lang_${key}_${language_code}`, value); + }); + + // Fetch strings and translations from plugins + $.get(`api/table_plugins_language_strings.json?nocache=${Date.now()}`) + .done((pluginRes) => { + const data = pluginRes["data"]; + + // Store plugin translations + data.forEach((langString) => { + setCache(`pia_lang_${langString.String_Key}_${langString.Language_Code}`, langString.String_Value); + }); + + // Handle successful completion of language processing + handleSuccess(`cacheStrings[${language_code}]`, resolveLang); + }) + .fail((pluginError) => { + // Handle failure in plugin strings fetching + rejectLang(pluginError); + }); + }) + .fail((error) => { + // Handle failure in core strings fetching + rejectLang(error); + }); }); }); - } + + // Wait for all language promises to complete + Promise.all(languagePromises) + .then(() => { + // All languages processed successfully + resolve(); + }) + .catch((error) => { + // Handle failure in any of the language processing + handleFailure('cacheStrings', reject); + }); + }); } +// ----------------------------------------------------------------------------- // Get translated language string -function getString (key) { +function getString(key) { - // handle initial load to make sure everything is set-up and cached - handleFirstLoad(getString) - - UI_LANG = getSetting("UI_LANG"); + function fetchString(key) { + UI_LANG = getSetting("UI_LANG"); - lang_code = 'en_us'; + let lang_code = 'en_us'; - switch(UI_LANG) - { - case 'English': - lang_code = 'en_us'; - break; - case 'Spanish': - lang_code = 'es_es'; - break; - case 'German': - lang_code = 'de_de'; - break; - case 'French': - lang_code = 'fr_fr'; - break; - case 'Norwegian': - lang_code = 'nb_no'; - break; - case 'Polish (pl_pl)': - lang_code = 'pl_pl'; - break; - case 'Portuguese (pt_br)': - lang_code = 'pt_br'; - break; - case 'Turkish (tr_tr)': - lang_code = 'tr_tr'; - break; - case 'Italian (it_it)': - lang_code = 'it_it'; - break; - case 'Russian': - lang_code = 'ru_ru'; - break; - case 'Chinese (zh_cn)': - lang_code = 'zh_cn'; - break; - } - result = getCache(`pia_lang_${key}_${lang_code}`, true); + switch (UI_LANG) { + case 'English': + lang_code = 'en_us'; + break; + case 'Spanish': + lang_code = 'es_es'; + break; + case 'German': + lang_code = 'de_de'; + break; + case 'French': + lang_code = 'fr_fr'; + break; + case 'Norwegian': + lang_code = 'nb_no'; + break; + case 'Polish (pl_pl)': + lang_code = 'pl_pl'; + break; + case 'Portuguese (pt_br)': + lang_code = 'pt_br'; + break; + case 'Turkish (tr_tr)': + lang_code = 'tr_tr'; + break; + case 'Italian (it_it)': + lang_code = 'it_it'; + break; + case 'Russian': + lang_code = 'ru_ru'; + break; + case 'Chinese (zh_cn)': + lang_code = 'zh_cn'; + break; + } + let result = getCache(`pia_lang_${key}_${lang_code}`, true); - if(isEmpty(result)) - { - result = getCache(`pia_lang_${key}_en_us`, true); + if (isEmpty(result)) { + result = getCache(`pia_lang_${key}_en_us`, true); + } + + return result; } - return result; + if (isAppInitialized()) { + return fetchString(key); + } else { + callAfterAppInitialized(() => fetchString(key)); + } } - // ----------------------------------------------------------------------------- // String utilities // ----------------------------------------------------------------------------- @@ -334,6 +360,15 @@ function isValidBase64(str) { } +function isValidJSON(jsonString) { + try { + JSON.parse(jsonString); + return true; + } catch (e) { + return false; + } +} + // ----------------------------------------------------------------------------- // General utilities // ----------------------------------------------------------------------------- @@ -835,7 +870,7 @@ function getDeviceDataByMac(macAddress, dbColumn) { } // ----------------------------------------------------------------------------- -// Cache teh devices as one JSON +// Cache the devices as one JSON function cacheDevices() { @@ -918,6 +953,8 @@ function showSpinner(stringKey='Loading') text = getString(stringKey) } + text = isEmpty(text) ? "Loading" : text; + if($("#loadingSpinner").length) { $("#loadingSpinner").show(); @@ -1102,6 +1139,8 @@ function arraysContainSameValues(arr1, arr2) { const sessionStorageKey = "myScriptExecuted_common_js"; var completedCalls = [] var completedCalls_final = ['cacheSettings', 'cacheStrings', 'cacheDevices']; +var completedCallsCount = 0; +var completedCallsCount_final = allLanguages.length + 2; // number of language files + cacheDevices + cacheSettings // ----------------------------------------------------------------------------- // Clearing all the caches @@ -1139,10 +1178,24 @@ async function handleFirstLoad(callback) { } } +// ----------------------------------------------------------------------------- +// Execute callback once app initialized +function callAfterAppInitialized(callback) { + if (!isAppInitialized()) { + setTimeout(() => { + callAfterAppInitialized(callback) + }, 500); + } else + { + callback(); + } +} + // ----------------------------------------------------------------------------- // Check if the code has been executed before by checking sessionStorage function isAppInitialized() { - return arraysContainSameValues(getCache("completedCalls").split(',').filter(Boolean), completedCalls_final); + // return arraysContainSameValues(getCache("completedCalls").split(',').filter(Boolean), completedCalls_final); + return (parseInt(getCache("completedCallsCount")) == completedCallsCount_final); } // Define a function that will execute the code only once @@ -1151,9 +1204,10 @@ async function executeOnce() { if (!isAppInitialized()) { try { - await cacheStrings(); - await cacheSettings(); await cacheDevices(); + await cacheSettings(); + await cacheStrings(); + console.log("✅ All AJAX callbacks have completed"); onAllCallsComplete(); } catch (error) { @@ -1166,8 +1220,20 @@ async function executeOnce() { // Function to handle successful completion of an AJAX call const handleSuccess = (callName) => { console.log(`AJAX call successful: ${callName}`); - completedCalls.push(callName); - setCache('completedCalls', mergeUniqueArrays(getCache('completedCalls').split(','), [callName])); + // completedCalls.push(callName); + // setCache('completedCalls', mergeUniqueArrays(getCache('completedCalls').split(','), [callName])); + + val = getCache('completedCallsCount'); + + if(val == "") + { + val = 0; + } else + { + val = parseInt(val) + } + + setCache('completedCallsCount', val + 1) }; // ----------------------------------------------------------------------------- @@ -1190,6 +1256,10 @@ const onAllCallsComplete = () => { sessionStorage.setItem(sessionStorageKey + '_time', millisecondsNow); console.log('✔ Cache initialized'); + // setTimeout(() => { + // location.reload() + // }, 10); + } else { // If not all strings are initialized, retry initialization console.log('❌ Not all strings are initialized. Retrying...'); @@ -1199,14 +1269,13 @@ const onAllCallsComplete = () => { // Call any other initialization functions here if needed - // No need for location.reload() here }; // Function to check if all necessary strings are initialized const areAllStringsInitialized = () => { // Implement logic to check if all necessary strings are initialized // Return true if all strings are initialized, false otherwise - return getString('UI_LANG') != "" + return getString('UI_LANG_name') != "" }; // Call the function to execute the code diff --git a/front/js/db_methods.js b/front/js/db_methods.js index 363f273f..c0373a99 100755 --- a/front/js/db_methods.js +++ b/front/js/db_methods.js @@ -89,7 +89,7 @@ function checkDbLock() { type: "GET", success: function (response) { - console.log(response); + // console.log(response); if (response == 0) { // console.log('Database is not locked'); $(".header-status-locked-db").hide(); diff --git a/front/js/settings_utils.js b/front/js/settings_utils.js index a810e41f..52ae1b81 100755 --- a/front/js/settings_utils.js +++ b/front/js/settings_utils.js @@ -259,7 +259,8 @@ function addList(element, clearInput = true) { .attr("value", input) .text(input); - const el = $(`#${toId}`).append(newOption); + // add new option + $(`#${toId}`).append(newOption); // clear input if (clearInput) { @@ -269,6 +270,7 @@ function addList(element, clearInput = true) { // Initialize interaction options only for the newly added option initListInteractionOptions(newOption); + // flag something changes to prevent navigating from page settingsChanged(); } @@ -279,31 +281,6 @@ function removeFromList(element) { .find("option:last") .remove(); } -// --------------------------------------------------------- -function addInterface() { - ipMask = $("#ipMask").val(); - ipInterface = $("#ipInterface").val(); - - full = ipMask + " --interface=" + ipInterface; - - console.log(full); - - if (ipMask == "" || ipInterface == "") { - showModalOk( - "Validation error", - "Specify both, the network mask and the interface" - ); - } else { - $("#SCAN_SUBNETS").append( - $("").attr("value", full).text(full) - ); - - $("#ipMask").val(""); - $("#ipInterface").val(""); - - settingsChanged(); - } -} // ------------------------------------------------------------------- // Function to remove an item from the select element @@ -555,7 +532,7 @@ function generateOptionsOrSetOptions( transformers = [] // Transformers to be applied to the values ) { - console.log(codeName); + // console.log(codeName); // NOTE {value} options to replace with a setting or SQL value are handled in the cacheSettings() function options = arrayToObject(createArray(getSettingOptions(codeName))) diff --git a/front/js/ui_components.js b/front/js/ui_components.js index 9158b185..40a5f0fe 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -11,16 +11,7 @@ // ----------------------------------------------------------------------------- // Initialize device selectors / pickers fields // ----------------------------------------------------------------------------- -function initDeviceSelectors() { - - // console.log(devicesList) - // Retrieve device list from session variable - var devicesListAll_JSON = getCache('devicesListAll_JSON'); - - var devicesList = JSON.parse(devicesListAll_JSON); - - // console.log(devicesList); - +function initDeviceSelectors(devicesListAll_JSON) { // Check if both device list exists if (devicesListAll_JSON) { @@ -78,52 +69,6 @@ function initDeviceSelectors() { -// // ----------------------------------------------------------------------------- -// // (ASYNC) Initiate dropdown -// function generateSetOptions(settingKey, // Identifier for the setting -// valuesArray, // Array of values to be pre-selected in the dropdown -// targetLocation, // ID of the HTML element where dropdown should be rendered (will be replaced) -// callbackToGenerateEntries, // Callback function to generate entries based on options -// targetField, // Target field or element where selected value should be applied or updated -// nameTransformer) // callback to transform the name (e.g. base64) -// { - -// var optionsHtml = "" - -// // NOTE {value} options to replace with a setting or SQL value are handled in the cacheSettings() function -// optionsArray = createArray(getSettingOptions(settingKey)) - - -// // check if the result is a SQL query -// if(optionsArray.length > 0 && isSQLQuery(optionsArray[0])) -// { - -// if (settingKey == "NEWDEV_dev_Network_Node_MAC_ADDR") { -// console.log("isSQLQuery in generateSetOptions"); - -// } -// readData(optionsArray[0], callbackToGenerateEntries, valuesArray, targetLocation, targetField, nameTransformer); - -// } else // this should be already an array, e.g. from a setting or pre-defined -// { -// optionsArray.forEach(option => { -// let selected = valuesArray.includes(option) ? 'selected' : ''; -// optionsHtml += ``; -// }); - -// // Replace the specified placeholder div with the resulting HTML -// setTimeout(() => { - -// $("#" + targetLocation).replaceWith(optionsHtml); - -// }, 50); -// } - - - -// } - - // ----------------------------------------------------------------------------- // Hide elements on the page based on the supplied setting function hideUIelements(settingKey) { @@ -290,42 +235,57 @@ function getCellValue(row, index) { // initialize // ----------------------------------------------------------------------------- +function initSelect2() { -setTimeout(() => { + // Retrieve device list from session variable + var devicesListAll_JSON = getCache('devicesListAll_JSON'); - initDeviceSelectors(); + // check if cache ready + if(isValidJSON(devicesListAll_JSON)) + { + // prepare HTML DOM before initializing the frotend + initDeviceSelectors(devicesListAll_JSON) - - // -------------------------------------------------------- - //Initialize Select2 Elements and make them sortable - - $(function () { - // Iterate over each Select2 dropdown - $('.select2').each(function() { - var selectEl = $(this).select2(); - - // Apply sortable functionality to the dropdown's dropdown-container - selectEl.next().children().children().children().sortable({ - containment: 'parent', - update: function () { - var sortedValues = $(this).children().map(function() { - return $(this).attr('title'); - }).get(); - - var sortedOptions = selectEl.find('option').sort(function(a, b) { - return sortedValues.indexOf($(a).text()) - sortedValues.indexOf($(b).text()); - }); - - // Replace all options in selectEl - selectEl.empty().append(sortedOptions); - - // Trigger change event on Select2 - selectEl.trigger('change'); - } - }); + + // -------------------------------------------------------- + //Initialize Select2 Elements and make them sortable + $(function () { + // Iterate over each Select2 dropdown + $('.select2').each(function() { + var selectEl = $(this).select2(); + + // Apply sortable functionality to the dropdown's dropdown-container + selectEl.next().children().children().children().sortable({ + containment: 'parent', + update: function () { + var sortedValues = $(this).children().map(function() { + return $(this).attr('title'); + }).get(); + + var sortedOptions = selectEl.find('option').sort(function(a, b) { + return sortedValues.indexOf($(a).text()) - sortedValues.indexOf($(b).text()); + }); + + // Replace all options in selectEl + selectEl.empty().append(sortedOptions); + + // Trigger change event on Select2 + selectEl.trigger('change'); + } + }); + }); }); - }); - + } else // cache not ready try later + { + setTimeout(() => { + initSelect2() + }, 1000); + } +} + +// try to initialize select2 +setTimeout(() => { + initSelect2() }, 500); diff --git a/front/multiEditCore.php b/front/multiEditCore.php index c8f6bb38..987327ab 100755 --- a/front/multiEditCore.php +++ b/front/multiEditCore.php @@ -101,10 +101,19 @@ for (let j = i * elementsPerColumn; j < Math.min((i + 1) * elementsPerColumn, columns.length); j++) { const setTypeObject = JSON.parse(columns[j].Type.replace(/'/g, '"')); - // console.log(setTypeObject); - const lastElementObj = setTypeObject.elements[setTypeObject.elements.length - 1] + // console.log(setTypeObject); 🔽 + // const lastElementObj = setTypeObject.elements[setTypeObject.elements.length - 1] - const { elementType, elementOptions = [], transformers = [] } = lastElementObj; + // get the element with the input value(s) + let elementsWithInputValue = setTypeObject.elements.filter(element => element.elementHasInputValue === 1); + + // if none found, take last + if(elementsWithInputValue.length == 0) + { + elementsWithInputValue = setTypeObject.elements[setTypeObject.elements.length - 1] + } + + const { elementType, elementOptions = [], transformers = [] } = elementsWithInputValue; const { inputType, readOnly, @@ -123,8 +132,8 @@ // console.log(setTypeObject); // console.log(inputType); - // render based on element type - if (lastElementObj.elementType === 'select') { + // render based on element type + if (elementsWithInputValue.elementType === 'select') { targetLocation = columns[j].Code_Name + "_generateSetOptions" @@ -154,7 +163,7 @@ } - } else if (lastElementObj.elementType === 'input'){ + } else if (elementsWithInputValue.elementType === 'input'){ // Add classes specifically for checkboxes inputType === 'checkbox' ? inputClass = 'checkbox' : inputClass = 'form-control'; diff --git a/front/plugins/__template/config.json b/front/plugins/__template/config.json index dafc1986..639bb89f 100755 --- a/front/plugins/__template/config.json +++ b/front/plugins/__template/config.json @@ -173,6 +173,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -194,15 +204,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, diff --git a/front/plugins/dhcp_leases/config.json b/front/plugins/dhcp_leases/config.json index 4900929b..996d7e92 100755 --- a/front/plugins/dhcp_leases/config.json +++ b/front/plugins/dhcp_leases/config.json @@ -525,6 +525,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -546,15 +556,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, diff --git a/front/plugins/newdev_template/config.json b/front/plugins/newdev_template/config.json index 1d2b0357..c61653e3 100755 --- a/front/plugins/newdev_template/config.json +++ b/front/plugins/newdev_template/config.json @@ -52,6 +52,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -73,15 +83,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, @@ -127,6 +128,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -148,15 +159,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, @@ -194,14 +196,24 @@ { "elementType": "button", "elementOptions": [ - { "sourceSuffixes": [] }, + { "sourceSuffixes": ["_in"] }, { "separator": "" }, - { "cssClasses": "col-sm-3" }, - { "onClick": "removeAllOptions(this)" }, - { "getStringKey": "Gen_Remove_All" } + { "cssClasses": "col-sm-2" }, + { "onClick": "addList(this, false)" }, + { "getStringKey": "Gen_Add" } ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": ["base64"] + }, { "elementType": "button", "elementOptions": [ @@ -216,22 +228,13 @@ { "elementType": "button", "elementOptions": [ - { "sourceSuffixes": ["_in"] }, + { "sourceSuffixes": [] }, { "separator": "" }, - { "cssClasses": "col-sm-2" }, - { "onClick": "addList(this, false)" }, - { "getStringKey": "Gen_Add" } + { "cssClasses": "col-sm-3" }, + { "onClick": "removeAllOptions(this)" }, + { "getStringKey": "Gen_Remove_All" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": ["base64"] } ] }, diff --git a/front/plugins/omada_sdn_imp/config.json b/front/plugins/omada_sdn_imp/config.json index 3aff59b6..31fc14d0 100755 --- a/front/plugins/omada_sdn_imp/config.json +++ b/front/plugins/omada_sdn_imp/config.json @@ -155,6 +155,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -176,15 +186,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, diff --git a/front/plugins/snmp_discovery/config.json b/front/plugins/snmp_discovery/config.json index 67f72466..7c58372f 100755 --- a/front/plugins/snmp_discovery/config.json +++ b/front/plugins/snmp_discovery/config.json @@ -434,6 +434,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -455,15 +465,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, diff --git a/front/plugins/undiscoverables/config.json b/front/plugins/undiscoverables/config.json index 106e252a..a9be9fef 100755 --- a/front/plugins/undiscoverables/config.json +++ b/front/plugins/undiscoverables/config.json @@ -301,6 +301,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -322,15 +332,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, diff --git a/front/plugins/unifi_import/config.json b/front/plugins/unifi_import/config.json index 85d7763e..2336d062 100755 --- a/front/plugins/unifi_import/config.json +++ b/front/plugins/unifi_import/config.json @@ -271,6 +271,7 @@ }, { "column": "Watched_Value3", + "mapped_to_column": "cur_Type", "css_classes": "col-sm-2", "default_value": "", "localized": ["name"], @@ -776,6 +777,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -797,15 +808,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] } diff --git a/front/plugins/website_monitor/config.json b/front/plugins/website_monitor/config.json index f151bc10..23e7ea9f 100755 --- a/front/plugins/website_monitor/config.json +++ b/front/plugins/website_monitor/config.json @@ -624,6 +624,16 @@ ], "transformers": [] }, + { + "elementType": "select", + "elementHasInputValue": 1, + "elementOptions": [ + { "multiple": "true" }, + { "readonly": "true" }, + { "editable": "true" } + ], + "transformers": [] + }, { "elementType": "button", "elementOptions": [ @@ -645,15 +655,6 @@ { "getStringKey": "Gen_Remove_Last" } ], "transformers": [] - }, - { - "elementType": "select", - "elementOptions": [ - { "multiple": "true" }, - { "readonly": "true" }, - { "editable": "true" } - ], - "transformers": [] } ] }, diff --git a/front/settings.php b/front/settings.php index 7fbae9e4..12fbe9b2 100755 --- a/front/settings.php +++ b/front/settings.php @@ -219,7 +219,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX try { const isMetadata = codeName.includes('__metadata'); - // is this isn't a metadata entry, get corresponding metadata object from the dummy setting + // if this isn't a metadata entry, get corresponding metadata object from the dummy setting const setObj = isMetadata ? {} : JSON.parse(getSetting(`${codeName}__metadata`)); } catch (error) { @@ -459,6 +459,8 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX } // INPUT + + console.log(codeName); // Parse the setType JSON string into an object let inputHtml = ''; @@ -614,8 +616,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX clearCache() }, 1500); - } else - { + } else { var settingsArray = []; // collect values for each of the different input form controls @@ -628,12 +629,18 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX setType = set["Type"] setCodeName = set["Code_Name"] + console.log(prefix); + const setTypeObject = JSON.parse(setType.replace(/'/g, '"')); // console.log(setTypeObject); const dataType = setTypeObject.dataType; - const lastElementObj = setTypeObject.elements[setTypeObject.elements.length - 1]; - const { elementType, elementOptions = [], transformers = [] } = lastElementObj; + // const lastElementObj = setTypeObject.elements[setTypeObject.elements.length - 1]; //🔽 + + // get the element with the input value(s) + const elementsWithInputValue = setTypeObject.elements.filter(element => element.elementHasInputValue === 1); + + const { elementType, elementOptions = [], transformers = [] } = elementsWithInputValue; const { inputType, readOnly, @@ -714,13 +721,15 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX success: function(data, textStatus) { if(data == "OK") - { - showMessage (getString("settings_saved"), 5000, "modal_grey"); + { + // showMessage (getString("settings_saved"), 5000, "modal_grey"); // Remove navigation prompt "Are you sure you want to leave..." window.onbeforeunload = null; // Reloads the current page - setTimeout("clearCache()", 5000); + // setTimeout("clearCache()", 5000); + + clearCache() } else{ // something went wrong // write_notification(data, 'interrupt') @@ -746,7 +755,7 @@ $settingsJSON_DB = json_encode($settings, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX