// ------------------------------------------------------------------- // Get all plugin prefixes of a given type function getPluginsByType(pluginsData, pluginType, onlyEnabled) { var result = []; pluginsData.forEach((plug) => { if (plug.plugin_type == pluginType) { // collect all, or if only enabled, check if NOT disabled if ( onlyEnabled == false || (onlyEnabled && getSetting(plug.unique_prefix + "_RUN") != "disabled") ) { result.push(plug.unique_prefix); } } }); return result; } // ------------------------------------------------------------------- // Get plugin code name base on prefix function getPluginCodeName(pluginsData, prefix) { var result = ""; pluginsData.forEach((plug) => { if (plug.unique_prefix == prefix) { id = plug.code_name; // console.log(id) result = plug.code_name; } }); return result; } // ------------------------------------------------------------------- // Get plugin type base on prefix function getPluginType(pluginsData, prefix) { var result = "core"; pluginsData.forEach((plug) => { if (plug.unique_prefix == prefix) { id = plug.plugin_type; // console.log(id) result = plug.plugin_type; } }); return result; } // ------------------------------------------------------------------- // Get plugin config based on prefix function getPluginConfig(pluginsData, prefix) { result = ""; pluginsData.forEach((plug) => { if (plug.unique_prefix == prefix) { // console.log(id) result = plug; } }); return result; } // ------------------------------------------------------------------- // Generate plugin HTML card based on prefixes in an array function pluginCards(prefixesOfEnabledPlugins, includeSettings) { html = ""; prefixesOfEnabledPlugins.forEach((prefix) => { includeSettings_html = ""; includeSettings.forEach((set) => { includeSettings_html += `
${getSetting(prefix + "_" + set)}
`; }); html += `
${getString(prefix + "_icon")}
`; }); return html; } // ----------------------------------------------------------------------------- // Open or close all settings // ----------------------------------------------------------------------------- function toggleAllSettings(openOrClose = "") { inStr = " in"; allOpen = true; openIcon = "fa-angle-double-down"; closeIcon = "fa-angle-double-up"; $(".panel-collapse").each(function () { if ($(this).attr("class").indexOf(inStr) == -1) { allOpen = false; } }); if (allOpen == false || openOrClose == "open") { // open all openAllSettings(); $("#toggleSettings").attr( "class", $("#toggleSettings").attr("class").replace(openIcon, closeIcon) ); } else { // close all $('div[data-myid="collapsible"]').each(function () { $(this).attr("class", "panel-collapse collapse "); }); $("#toggleSettings").attr( "class", $("#toggleSettings").attr("class").replace(closeIcon, openIcon) ); } } function openAllSettings() { $('div[data-myid="collapsible"]').each(function () { $(this).attr("class", "panel-collapse collapse in"); }); $('div[data-myid="collapsible"]').each(function () { $(this).attr("style", "height:inherit"); }); } // ------------------------------------------------------------------- // Checks if all schedules are the same function schedulesAreSynchronized(prefixesOfEnabledPlugins, pluginsData) { plug_schedules = []; prefixesOfEnabledPlugins.forEach((prefix) => { pluginsData.forEach((plug) => { if (plug.unique_prefix == prefix) { plug_schedules.push( getSetting(prefix + "_RUN_SCHD").replace(/\s/g, "") ); // replace all white characters to compare them easier } }); }); // Check if all plug_schedules are the same if (plug_schedules.length > 0) { const firstSchedule = plug_schedules[0]; return plug_schedules.every((schedule) => schedule === firstSchedule); } return true; // Return true if no schedules are found } // ------------------------------------------------------------------- // Checks if value is already encoded function isSHA256(value) { // Check if the value is a string and has a length of 64 characters if (typeof value === "string" && value.length === 64) { // Check if the value contains only hexadecimal characters return /^[0-9a-fA-F]+$/.test(value); } else { return false; } } // ------------------------------------------------------------------- // Validation // ------------------------------------------------------------------- function settingsCollectedCorrectly(settingsArray, settingsJSON_DB) { // check if the required UI_LANG setting is in the array - if not something went wrong $.each(settingsArray, function (index, value) { if (value[1] == "UI_LANG") { if (isEmpty(value[3]) == true) { console.log(`⚠ Error: Required setting UI_LANG not found`); showModalOk("ERROR", getString("settings_missing_block")); return false; } } }); const settingsCodeNames = settingsJSON_DB.map((setting) => setting.setKey); const detailedCodeNames = settingsArray.map((item) => item[1]); const missingCodeNamesOnPage = detailedCodeNames.filter( (setKey) => !settingsCodeNames.includes(setKey) ); const missingCodeNamesInDB = settingsCodeNames.filter( (setKey) => !detailedCodeNames.includes(setKey) ); // check if the number of settings on the page and in the DB are the same if (missingCodeNamesOnPage.length !== missingCodeNamesInDB.length) { console.log( `⚠ Error: The following settings are missing in the DB or on the page (Reload page to fix):` ); console.log(missingCodeNamesOnPage); console.log(missingCodeNamesInDB); showModalOk("ERROR", getString("settings_missing_block")); return false; } // all OK return true; } // ------------------------------------------------------------------- // Manipulating Editable List options // ------------------------------------------------------------------- // --------------------------------------------------------- // Add row to datatable function addDataTableRow(el) { alert("a") } // --------------------------------------------------------- // Clone datatable row function cloneDataTableRow(el){ console.log(el); const id = "NEWDEV_devCustomProps_table"; // Your table ID const table = $('#'+id).DataTable(); // Get the 'my-index' attribute from the closest tr element const myIndex = parseInt($(el).closest("tr").attr("my-index")); // Find the row in the table with the matching 'my-index' const row = table.rows().nodes().to$().filter(`[my-index="${myIndex}"]`).first().get(0); // Clone the row (including its data and controls) let clonedRow = $(row).clone(true, true); // The true arguments copy the data and event handlers $(clonedRow).attr("my-index",table.rows().count()) console.log(clonedRow); // Add the cloned row to the DataTable table.row.add(clonedRow[0]).draw(); } // --------------------------------------------------------- // Remove current datatable row function removeDataTableRow(el) { console.log(el); const id = "NEWDEV_devCustomProps_table"; // Your table ID const table = $('#'+id).DataTable(); if(table.rows().count() > 1) { // Get the 'my-index' attribute from the closest tr element const myIndex = parseInt($(el).closest("tr").attr("my-index")); // Find the row in the table with the matching 'my-index' const row = table.rows().nodes().to$().filter(`[my-index="${myIndex}"]`).first().get(0); // Remove the row from the DataTable table.row(row).remove().draw(); } else { showMessage (getString("CustProps_cant_remove"), 3000, "modal_red"); } } // --------------------------------------------------------- // Add item to list function addList(element, clearInput = true) { const fromId = $(element).attr("my-input-from"); const toId = $(element).attr("my-input-to"); const input = $(`#${fromId}`).val(); console.log(`fromId | toId | input : ${fromId} | ${toId} | ${input}`); const newOption = $("") .attr("value", input) .text(input); // add new option $(`#${toId}`).append(newOption); // clear input if (clearInput) { $(`#${fromId}`).val(""); } // Initialize interaction options only for the newly added option initListInteractionOptions(newOption); // flag something changes to prevent navigating from page settingsChanged(); } // --------------------------------------------------------- function removeFromList(element) { settingsChanged(); $(`#${$(element).attr("my-input-to")}`) .find("option:last") .remove(); } // ------------------------------------------------------------------- // Function to remove an item from the select element function removeOptionItem(option) { settingsChanged(); option.remove(); } // ------------------------------------------------------------------- // Update value of an item from the select element function updateOptionItem(option, value) { settingsChanged(); option.html(value); option.val(value); } // ------------------------------------------------------------------- // Remove all options function removeAllOptions(element) { settingsChanged(); $(`#${$(element).attr("my-input-to")}`).empty(); } // ------------------------------------------------------------------- // Add all options function selectAll(element) { settingsChanged(); // Get the element with the class 'deviceSelector' // var selectElement = $('.deviceSelector select'); var selectElement = $(`#${$(element).attr("my-input-to")}`); // Iterate over each option within the select element selectElement.find('option').each(function() { // Unselect each option $(this).prop('selected', false); }); // Trigger the 'change' event to notify Bootstrap Select of the changes selectElement.trigger('change'); } // ----------------------------------------------------------------------------- // Trigger change to open up the dropdown filed function selectChange(element) { settingsChanged(); // Get the `; generateOptionsOrSetOptions(setKey, createArray(val), `${setKey}_temp_`, generateOptions, null, transformers, overrideOptions); break; case 'input': const checked = val === 'True' || val === 'true' || val === '1' ? 'checked' : ''; const inputClass = inputType === 'checkbox' ? 'checkbox' : 'form-control'; inputHtml += ``; break; case 'button': inputHtml += ``; break; case 'textarea': inputHtml += ``; break; case 'span': inputHtml += ` ${getString(getStringKey)}${placeholder} `; break; case 'datatable': const tableId = `${setKey}_table`; let datatableHtml = ``; // Dynamic array creation let emptyVal = []; let columnSettings = []; // Generate table headers datatableHtml += ''; columns.forEach(column => { let columnSetting = getSetObject(settingsData, column.settingKey) || {}; datatableHtml += ``; if(column.typeOverride) { columnSetting["setType"] = JSON.stringify(column.typeOverride); } if(column.optionsOverride) { if (column.optionsOverride.startsWith("setting.")) { columnSetting["setOptions"] = getSetting(column.optionsOverride.replace("setting.","")); } else { columnSetting["setOptions"] = column.optionsOverride; } } columnSettings.push(columnSetting) // helper for if val is empty emptyVal.push(''); }); datatableHtml += ''; // Generate table body datatableHtml += ''; if(val.length > 0 && isBase64(val)) { val = atob(val) // console.log(val); val = JSON.parse(val) }else{ // init empty val = [emptyVal] } let index = 0; val.forEach(rowData => { datatableHtml += ``; let j = 0; columnSettings.forEach(set => { // Extract the value for the current column based on the new structure let columnOverrideValue = rowData[j] && Object.values(rowData[j])[0]; if(columnOverrideValue == undefined) { columnOverrideValue = "" } // Create unique key to prevent dropdown data duplication const oldKey = set["setKey"]; set["setKey"] = oldKey + "_" + index; // Generate the cell HTML using the extracted value const cellHtml = generateFormHtml( settingsData, set, columnOverrideValue.toString(), set["setOptions"], oldKey ); datatableHtml += ``; // Restore the original key set["setKey"] = oldKey; j++; }); datatableHtml += ''; index++; }); datatableHtml += '
${columnSetting.setName}
${cellHtml}
'; inputHtml += datatableHtml; // Initialize DataTable with jQuery $(document).ready(() => { $(`#${tableId}`).DataTable({ ordering: false, // Disables sorting on all columns searching: false, // Disables the search box dom: "<'top'rt><'bottom'ipl>", // Move length dropdown to the bottom }); }); break; default: console.warn(`🟥 Unknown element type: ${elementType}`); } }); // Generate event HTML if applicable let eventsHtml = ''; const eventsList = createArray(set['setEvents']); // inline buttons events if (eventsList.length > 0) { eventsList.forEach(event => { eventsHtml += ` `; }); } // Combine and return the final HTML return inputHtml + eventsHtml; } // ----------------------------------------------------- // Return the setting object by setKey function getSetObject(settingsData, setKey) { found = false; result = "" settingsData.forEach(function(set) { if (set.setKey == setKey) { // console.log(set); result = set; return; } }); if(result == "") { console.error(settingsData); console.error(`Setting not found: ${setKey}`); } return result; } // --------------------------------------- // Collect DataTable data function collectTableData(tableSelector) { const table = $(tableSelector).DataTable(); let tableData = []; table.rows().every(function () { const rowData = []; const cells = $(this.node()).find('td'); cells.each((index, cell) => { const input = $(cell).find('input, select, textarea'); if (input.length) { if (input.attr('type') === 'checkbox') { // For checkboxes, check if they are checked rowData[index] = { [input.attr("my-originalsetkey")] : input.prop('checked') }; } else { // Generic sync for other inputs (text, select, textarea) rowData[index] = { [input.attr("my-originalsetkey")] : input.val().replace(/'/g, "").replace(/"/g, "") }; } } else { // Handle plain text // rowData[index] = { [input.attr("my-originalsetkey")] : $(cell).text()}; console.log(`Nothig to collect: ${$(cell).html()}`) } }); tableData.push(rowData); }); return tableData; }