mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 01:26:11 -08:00
The "saveSettings" function is corrected by changing the relative url to an absolute url so that it works correctly with reverse proxies.
728 lines
25 KiB
PHP
Executable File
728 lines
25 KiB
PHP
Executable File
<?php
|
|
|
|
require 'php/templates/header.php';
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Action selector
|
|
//------------------------------------------------------------------------------
|
|
// Set maximum execution time to 15 seconds
|
|
ini_set ('max_execution_time','30');
|
|
|
|
// check permissions
|
|
$dbPath = "../db/pialert.db";
|
|
$confPath = "../config/pialert.conf";
|
|
|
|
checkPermissions([$dbPath, $confPath]);
|
|
|
|
// get settings from the API json file
|
|
|
|
// path to your JSON file
|
|
$file = '../front/api/table_settings.json';
|
|
// put the content of the file in a variable
|
|
$data = file_get_contents($file);
|
|
// JSON decode
|
|
$settingsJson = json_decode($data);
|
|
|
|
// get settings from the DB
|
|
|
|
global $db;
|
|
global $settingKeyOfLists;
|
|
|
|
$result = $db->query("SELECT * FROM Settings");
|
|
|
|
// array
|
|
$settingKeyOfLists = array();
|
|
|
|
$settings = array();
|
|
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
|
|
// Push row data
|
|
$settings[] = array( 'Code_Name' => $row['Code_Name'],
|
|
'Display_Name' => $row['Display_Name'],
|
|
'Description' => $row['Description'],
|
|
'Type' => $row['Type'],
|
|
'Options' => $row['Options'],
|
|
'RegEx' => $row['RegEx'],
|
|
'Value' => $row['Value'],
|
|
'Group' => $row['Group'],
|
|
'Events' => $row['Events']
|
|
);
|
|
}
|
|
|
|
|
|
?>
|
|
<!-- Page ------------------------------------------------------------------ -->
|
|
<!-- Page ------------------------------------------------------------------ -->
|
|
|
|
<script src="js/pialert_common.js"></script>
|
|
|
|
|
|
<div id="settingsPage" class="content-wrapper">
|
|
|
|
<!-- Content header--------------------------------------------------------- -->
|
|
<section class="content-header">
|
|
<?php require 'php/templates/notification.php'; ?>
|
|
<h1 id="pageTitle">
|
|
<i class="fa fa-cog"></i>
|
|
<?= lang('Navigation_Settings');?>
|
|
<a style="cursor:pointer">
|
|
<span>
|
|
<i id='toggleSettings' onclick="toggleAllSettings()" class="settings-expand-icon fa fa-angle-double-down"></i>
|
|
</span>
|
|
</a>
|
|
</h1>
|
|
<div class="settingsImported"><?= lang("settings_imported");?> <span id="lastImportedTime"></span></div>
|
|
</section>
|
|
<div class="content settingswrap" id='accordion_gen'>
|
|
<!-- PLACEHOLDER -->
|
|
</div>
|
|
|
|
<!-- /.content -->
|
|
<div class="row" >
|
|
<div class="row">
|
|
<button type="button" class="center top-margin btn btn-primary btn-default pa-btn bg-green dbtools-button" id="save" onclick="saveSettings()"><?= lang('DevDetail_button_Save');?></button>
|
|
</div>
|
|
<div id="result"></div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- /.content-wrapper -->
|
|
|
|
<!-- ----------------------------------------------------------------------- -->
|
|
<?php
|
|
require 'php/templates/footer.php';
|
|
?>
|
|
|
|
|
|
<script>
|
|
|
|
|
|
function getData(){
|
|
|
|
$.get('api/table_settings.json?nocache=' + Date.now(), function(res) {
|
|
|
|
settingsData = res["data"];
|
|
|
|
initSettingsPage(settingsData);
|
|
})
|
|
}
|
|
|
|
function initSettingsPage(settingsData){
|
|
|
|
const settingGroups = [];
|
|
const settingKeyOfLists = [];
|
|
// core groups are the ones not generated by plugins
|
|
const settingCoreGroups = ['General', 'Email', 'Webhooks', 'Apprise', 'NTFY', 'PUSHSAFER', 'MQTT', 'DynDNS', 'API'];
|
|
|
|
|
|
// Loop through the settingsArray and collect unique settingGroups
|
|
settingsData.forEach((set) => {
|
|
if (!settingGroups.includes(set.Group)) {
|
|
settingGroups.push(set.Group);
|
|
}
|
|
});
|
|
|
|
|
|
console.log(settingGroups);
|
|
|
|
let headersHtml = '';
|
|
let pluginHtml = `
|
|
<div class="row table_row">
|
|
<div class="table_cell bold">
|
|
<i class="fa-regular fa-book fa-sm"></i>
|
|
<a href="https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins" target="_blank">
|
|
<?= lang('Gen_ReadDocs');?>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
`;
|
|
let isIn = ' in '; // to open the active panel in AdminLTE
|
|
|
|
for (const group of settingGroups) {
|
|
let isPlugin = false;
|
|
let settingGroupTypeHtml = '';
|
|
|
|
if (settingCoreGroups.includes(group)) {
|
|
settingGroupTypeHtml = '';
|
|
} else {
|
|
settingGroupTypeHtml = ' (<i class="fa-regular fa-plug fa-sm"></i>) ';
|
|
isPlugin = true;
|
|
}
|
|
|
|
headersHtml += `<div class="box panel panel-default">
|
|
<a data-toggle="collapse" data-parent="#accordion_gen" href="#${group}">
|
|
<div class="panel-heading">
|
|
<h4 class="panel-title">${getString(group+"_icon")} ${getString(group+"_display_name")} ${settingGroupTypeHtml}</h4>
|
|
</div>
|
|
</a>
|
|
<div id="${group}" data-myid="collapsible" class="panel-collapse collapse ${isIn}">
|
|
<div class="panel-body">
|
|
${isPlugin ? pluginHtml: ""}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
isIn = ' '; // open the first panel only by default on page load
|
|
}
|
|
|
|
// generate headers/sections
|
|
$('#accordion_gen').html(headersHtml);
|
|
|
|
// generate panel content
|
|
for (const group of settingGroups) {
|
|
|
|
// go thru all settings and collect settings per settings group
|
|
settingsData.forEach((set) => {
|
|
|
|
let val = set['Value'];
|
|
const codeName = set['Code_Name'];
|
|
const setType = set['Type'].toLowerCase();
|
|
const isMetadata = codeName.includes('__metadata');
|
|
// is this isn't a metadata entry, get corresponding metadata object from the dummy setting
|
|
const setObj = isMetadata ? {} : JSON.parse(getSetting(`${codeName}__metadata`));
|
|
|
|
// constructing final HTML for the setting
|
|
setHtml = ""
|
|
|
|
if(set["Group"] == group)
|
|
{
|
|
// hide metadata by default by assigning it a special class
|
|
isMetadata ? metadataClass = 'metadata' : metadataClass = '';
|
|
isMetadata ? infoIcon = '' : infoIcon = `<i
|
|
my-to-toggle="row_${codeName}__metadata"
|
|
title="${getString("Settings_Metadata_Toggle")}"
|
|
class="fa fa-circle-question pointer"
|
|
onclick="toggleMetadata(this)">
|
|
</i>` ;
|
|
|
|
// NAME & DESCRIPTION columns
|
|
setHtml += `
|
|
<div class="row table_row ${metadataClass}" id="row_${codeName}">
|
|
<div class="table_cell setting_name bold">
|
|
<label>${getString(codeName + '_name', set['Display_Name'])}</label>
|
|
<div class="small">
|
|
<code>${codeName}</code>${infoIcon}
|
|
</div>
|
|
</div>
|
|
<div class="table_cell setting_description">
|
|
${getString(codeName + '_description', set['Description'])}
|
|
</div>
|
|
<div class="table_cell setting_input input-group">
|
|
`;
|
|
|
|
// OVERRIDE
|
|
// surface settings override functionality if the setting is a template that can be overriden with user defined values
|
|
// if the setting is a json of the correct structure, handle like a template setting
|
|
|
|
let overrideHtml = "";
|
|
|
|
//pre-check if this is a json object that needs value extraction
|
|
|
|
let overridable = false; // indicates if the setting is overridable
|
|
let override = false; // If the setting is set to be overriden by the user or by default
|
|
let readonly = ""; // helper variable to make text input readonly
|
|
let disabled = ""; // helper variable to make checkbox input readonly
|
|
|
|
// TODO finish
|
|
if ('override_value' in setObj) {
|
|
overridable = true;
|
|
overrideObj = setObj["override_value"]
|
|
override = overrideObj["override"];
|
|
|
|
console.log(setObj)
|
|
console.log(group)
|
|
}
|
|
|
|
// prepare override checkbox and HTML
|
|
if(overridable)
|
|
{
|
|
let checked = override ? 'checked' : '';
|
|
|
|
overrideHtml = `<div class="override col-xs-12">
|
|
<div class="override-check col-xs-1">
|
|
<input onChange="overrideToggle(this)" my-data-type="${setType}" my-input-toggle-readonly="${codeName}" class="checkbox" id="${codeName}_override" type="checkbox" ${checked} />
|
|
</div>
|
|
<div class="override-text col-xs-11" title="${getString("Setting_Override_Description")}">
|
|
${getString("Setting_Override")}
|
|
</div>
|
|
</div>`;
|
|
|
|
}
|
|
|
|
|
|
// INPUT
|
|
// pre-processing done, render setting based on type
|
|
|
|
let inputHtml = "";
|
|
if (setType.startsWith('text') || setType.startsWith('string') || setType.startsWith('date-time') ) {
|
|
|
|
if(setType.includes(".select"))
|
|
{
|
|
inputHtml = generateInputOptions(set, inputHtml, isMultiSelect = false)
|
|
|
|
} else if(setType.includes(".multiselect"))
|
|
{
|
|
inputHtml = generateInputOptions(set, inputHtml, isMultiSelect = true)
|
|
} else{
|
|
|
|
// if it's overridable set readonly accordingly
|
|
if(overridable)
|
|
{
|
|
override ? readonly = "" : readonly = " readonly" ;
|
|
}
|
|
|
|
inputHtml = `<input class="form-control" onChange="settingsChanged()" my-data-type="${setType}" id="${codeName}" value="${val}" ${readonly}/>`;
|
|
}
|
|
} else if (setType === 'integer') {
|
|
inputHtml = `<input onChange="settingsChanged()" my-data-type="${setType}" class="form-control" id="${codeName}" type="number" value="${val}"/>`;
|
|
} else if (setType === 'password') {
|
|
inputHtml = `<input onChange="settingsChanged()" my-data-type="${setType}" class="form-control input" id="${codeName}" type="password" value="${val}"/>`;
|
|
} else if (setType === 'readonly') {
|
|
inputHtml = `<input class="form-control input" my-data-type="${setType}" id="${codeName}" value="${val}" readonly/>`;
|
|
} else if (setType === 'boolean' || setType === 'integer.checkbox') {
|
|
let checked = val === 'True' || val === '1' ? 'checked' : '';
|
|
|
|
// if it's overridable set readonly accordingly
|
|
if(overridable)
|
|
{
|
|
override ? disabled = "" : disabled = " disabled" ;
|
|
}
|
|
|
|
inputHtml = `<input onChange="settingsChanged()" my-data-type="${setType}" class="checkbox" id="${codeName}" type="checkbox" value="${val}" ${checked} ${disabled}/>`;
|
|
} else if (setType === 'integer.select') {
|
|
|
|
inputHtml = generateInputOptions(set, inputHtml)
|
|
|
|
} else if (setType === 'subnets') {
|
|
inputHtml = `
|
|
<div class="row form-group">
|
|
<div class="col-xs-5">
|
|
<input class="form-control" id="ipMask" type="text" placeholder="192.168.1.0/24"/>
|
|
</div>
|
|
<div class="col-xs-4">
|
|
<input class="form-control" id="ipInterface" type="text" placeholder="eth0" />
|
|
</div>
|
|
<div class="col-xs-3">
|
|
<button class="btn btn-primary" onclick="addInterface()">Add</button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<select class="form-control" my-data-type="${setType}" name="${codeName}" id="${codeName}" multiple readonly>`;
|
|
|
|
|
|
options = createArray(val);
|
|
|
|
options.forEach(option => {
|
|
inputHtml += `<option value="${option}" disabled>${option}</option>`;
|
|
});
|
|
|
|
inputHtml += '</select></div>' +
|
|
'<div><button class="btn btn-primary" onclick="removeInterfaces()">Remove all</button></div>';
|
|
} else if (setType === 'list' || setType === 'list.readonly') {
|
|
|
|
settingKeyOfLists.push(codeName);
|
|
|
|
inputHtml = `
|
|
<div class="row form-group">
|
|
<div class="col-xs-9">
|
|
<input class="form-control" type="text" id="${codeName}_input" placeholder="Enter value"/>
|
|
</div>
|
|
<div class="col-xs-3">
|
|
<button class="btn btn-primary" my-input-from="${codeName}_input" my-input-to="${codeName}" onclick="addList(this)">Add</button>
|
|
</div>
|
|
</div>
|
|
<div class="form-group">
|
|
<select class="form-control" my-data-type="${setType}" name="${codeName}" id="${codeName}" multiple readonly>`;
|
|
|
|
let options = createArray(val);
|
|
|
|
options.forEach(option => {
|
|
inputHtml += `<option value="${option}" disabled>${option}</option>`;
|
|
});
|
|
|
|
inputHtml += '</select></div>' +
|
|
`<div><button class="btn btn-primary" my-input="${codeName}" onclick="removeFromList(this)">Remove last</button></div>`;
|
|
} else if (setType === 'json') {
|
|
inputHtml = `<textarea class="form-control input" my-data-type="${setType}" id="${codeName}" readonly>${JSON.stringify(val, null, 2)}</textarea>`;
|
|
}
|
|
|
|
// EVENTS
|
|
// process events (e.g. run ascan, or test a notification) if associated with the setting
|
|
let eventsHtml = "";
|
|
|
|
const eventsList = createArray(set['Events']);
|
|
|
|
if (eventsList.length > 0) {
|
|
console.log(eventsList)
|
|
eventsList.forEach(event => {
|
|
eventsHtml += `<span class="input-group-addon pointer"
|
|
data-myparam="${codeName}"
|
|
data-myparam-plugin="${group}"
|
|
data-myevent="${event}"
|
|
onclick="handleEvent(this)"
|
|
>
|
|
<i title="${getString(event + "_event_tooltip")}" class="fa ${getString(event + "_event_icon")}">
|
|
</i>
|
|
</span>`;
|
|
});
|
|
}
|
|
|
|
// construct final HTML for the setting
|
|
setHtml += inputHtml + eventsHtml + overrideHtml + `
|
|
</div>
|
|
</div>
|
|
`
|
|
|
|
// generate settings in the correct group section
|
|
$(`#${group} .panel-body`).append(setHtml);
|
|
|
|
}
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// generate a list of options for a input select
|
|
function generateInputOptions(set, input, isMultiSelect = false)
|
|
{
|
|
|
|
multi = isMultiSelect ? "multiple" : "";
|
|
input = `<select onChange="settingsChanged()" my-data-type="${set['Type']}" class="form-control" name="${set['Code_Name']}" id="${set['Code_Name']}" ${multi}>`;
|
|
|
|
values = createArray(set['Value']);
|
|
options = createArray(set['Options']);
|
|
|
|
options.forEach(option => {
|
|
let selected = values.includes(option) ? 'selected' : '';
|
|
input += `<option value="${option}" ${selected}>${option}</option>`;
|
|
});
|
|
|
|
input += '</select>';
|
|
|
|
return input;
|
|
}
|
|
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// Helper methods
|
|
// ---------------------------------------------------------
|
|
// Toggle readonly mode of teh target element specified by the id in the "my-input-toggle-readonly" attribute
|
|
function overrideToggle(element) {
|
|
settingsChanged();
|
|
|
|
targetId = $(element).attr("my-input-toggle-readonly");
|
|
|
|
inputElement = $(`#${targetId}`)[0];
|
|
|
|
if (!inputElement) {
|
|
console.error("Input element not found!");
|
|
return;
|
|
}
|
|
|
|
if (inputElement.type === "text" || inputElement.type === "password") {
|
|
inputElement.readOnly = !inputElement.readOnly;
|
|
} else if (inputElement.type === "checkbox") {
|
|
inputElement.disabled = !inputElement.disabled;
|
|
} else {
|
|
console.warn("Unsupported input type. Only text, password, and checkbox inputs are supported.");
|
|
}
|
|
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
// Generate an array object from a string representation of an array
|
|
function createArray(input) {
|
|
// Empty array
|
|
if (input === '[]') {
|
|
return [];
|
|
}
|
|
|
|
// Regex patterns
|
|
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)];
|
|
}
|
|
|
|
// Remove quotes
|
|
optionsTmp.forEach(item => {
|
|
options.push(item.replace(patternQuotes, replacement).trim());
|
|
});
|
|
|
|
return options;
|
|
}
|
|
|
|
// number of settings has to be equal to
|
|
|
|
// display the name of the first person
|
|
// echo $settingsJson[0]->name;
|
|
var settingsNumber = <?php echo count($settingsJson->data)?>;
|
|
|
|
// Wrong number of settings processing
|
|
if(<?php echo count($settings)?> != settingsNumber)
|
|
{
|
|
showModalOk('WARNING', "<?= lang("settings_missing")?>");
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
function addList(element)
|
|
{
|
|
|
|
const fromId = $(element).attr('my-input-from');
|
|
const toId = $(element).attr('my-input-to');
|
|
|
|
input = $(`#${fromId}`).val();
|
|
$(`#${toId}`).append($("<option disabled></option>").attr("value", input).text(input));
|
|
|
|
// clear input
|
|
$(`#${fromId}`).val("");
|
|
|
|
settingsChanged();
|
|
}
|
|
// ---------------------------------------------------------
|
|
function removeFromList(element)
|
|
{
|
|
settingsChanged();
|
|
$(`#${$(element).attr('my-input')}`).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($('<option disabled></option>').attr('value', full).text(full));
|
|
|
|
$('#ipMask').val('');
|
|
$('#ipInterface').val('');
|
|
|
|
settingsChanged();
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
function removeInterfaces()
|
|
{
|
|
settingsChanged();
|
|
$('#SCAN_SUBNETS').empty();
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
function collectSettings()
|
|
{
|
|
var settingsArray = [];
|
|
|
|
// collect values for each of the different input form controls
|
|
const noConversion = ['text', 'integer', 'string', 'password', 'readonly', 'text.select', 'integer.select', 'text.multiselect'];
|
|
|
|
settingsJSON["data"].forEach(set => {
|
|
if (noConversion.includes(set['Type'])) {
|
|
|
|
settingsArray.push([set["Group"], set["Code_Name"], set["Type"], $('#'+set["Code_Name"]).val()]);
|
|
|
|
} else if (set['Type'] === 'boolean' || set['Type'] === 'integer.checkbox') {
|
|
|
|
const temp = $(`#${set["Code_Name"]}`).is(':checked') ? 1 : 0;
|
|
settingsArray.push([set["Group"], set["Code_Name"], set["Type"], temp]);
|
|
|
|
} else if (set['Type'] === 'list' || set['Type'] === 'subnets') {
|
|
const temps = [];
|
|
$(`#${set["Code_Name"]} option`).each(function (i, selected) {
|
|
const vl = $(selected).val();
|
|
if (vl !== '') {
|
|
temps.push(vl);
|
|
}
|
|
});
|
|
settingsArray.push([set["Group"], set["Code_Name"], set["Type"], JSON.stringify(temps)]);
|
|
} else if (set['Type'] === 'json') {
|
|
const temps = $('#'+set["Code_Name"]).val();
|
|
settingsArray.push([set["Group"], set["Code_Name"], set["Type"], temps]);
|
|
}
|
|
});
|
|
|
|
return settingsArray;
|
|
}
|
|
|
|
// ---------------------------------------------------------
|
|
function saveSettings() {
|
|
if(<?php echo count($settings)?> != settingsNumber)
|
|
{
|
|
showModalOk('WARNING', "<?= lang("settings_missing_block")?>");
|
|
} else
|
|
{
|
|
$.ajax({
|
|
method: "POST",
|
|
url: "php/server/util.php",
|
|
data: {
|
|
function: 'savesettings',
|
|
settings: JSON.stringify(collectSettings()) },
|
|
success: function(data, textStatus) {
|
|
showModalOk ('Result', data );
|
|
// Remove navigation prompt "Are you sure you want to leave..."
|
|
window.onbeforeunload = null;
|
|
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
function getParam(targetId, key, skipCache = false) {
|
|
|
|
skipCacheQuery = "";
|
|
|
|
if(skipCache)
|
|
{
|
|
skipCacheQuery = "&skipcache";
|
|
}
|
|
|
|
// get parameter value
|
|
$.get('php/server/parameters.php?action=get&defaultValue=0¶meter='+ key + skipCacheQuery, function(data) {
|
|
|
|
var result = data;
|
|
|
|
if(key == "Back_Settings_Imported")
|
|
{
|
|
fileModificationTime = <?php echo filemtime($confPath)*1000;?>;
|
|
importedMiliseconds = parseInt(result.match( /\d+/g ).join('')); // sanitize the string and get only the numbers
|
|
|
|
result = (new Date(importedMiliseconds)).toLocaleString("en-UK", { timeZone: "<?php echo $timeZone?>" }); //.toDateString("");
|
|
|
|
// check if displayed settings are outdated
|
|
if(fileModificationTime > importedMiliseconds)
|
|
{
|
|
showModalOk('WARNING: Outdated settings displayed', "<?= lang("settings_old")?>");
|
|
}
|
|
} else{
|
|
result = result.replaceAll('"', '');
|
|
}
|
|
|
|
document.getElementById(targetId).innerHTML = result.replaceAll('"', '');
|
|
});
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
function toggleAllSettings()
|
|
{
|
|
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)
|
|
{
|
|
// close all
|
|
$('div[data-myid="collapsible"]').each(function(){$(this).attr('class', 'panel-collapse collapse ')})
|
|
$('#toggleSettings').attr('class', $('#toggleSettings').attr('class').replace(closeIcon, openIcon))
|
|
}
|
|
else{
|
|
// open all
|
|
$('div[data-myid="collapsible"]').each(function(){$(this).attr('class', 'panel-collapse collapse in')})
|
|
$('div[data-myid="collapsible"]').each(function(){$(this).attr('style', 'height:inherit')})
|
|
$('#toggleSettings').attr('class', $('#toggleSettings').attr('class').replace(openIcon, closeIcon))
|
|
}
|
|
|
|
}
|
|
|
|
getData()
|
|
|
|
</script>
|
|
|
|
<script defer>
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// handling events on the backend initiated by the front end START
|
|
// -----------------------------------------------------------------------------
|
|
function toggleMetadata(element)
|
|
{
|
|
const id = $(element).attr('my-to-toggle');
|
|
|
|
$(`#${id}`).toggle();
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// handling events on the backend initiated by the front end START
|
|
// -----------------------------------------------------------------------------
|
|
|
|
modalEventStatusId = 'modal-message-front-event'
|
|
|
|
function handleEvent (element){
|
|
|
|
// value has to be in format event|param. e.g. run|ARPSCAN
|
|
value = $(element).attr('data-myevent') + '|'+ $(element).attr('data-myparam-plugin')
|
|
|
|
setParameter ('Front_Event', value)
|
|
|
|
// show message
|
|
showModalOk("<?= lang("general_event_title")?>", "<?= lang("general_event_description")?> <code id='"+modalEventStatusId+"'></code>");
|
|
|
|
// Periodically update state of the requested action
|
|
getParam(modalEventStatusId,"Front_Event", true, updateModalState)
|
|
|
|
updateModalState()
|
|
}
|
|
|
|
|
|
function updateModalState(){
|
|
|
|
setTimeout(function(){
|
|
displayedEvent = $('#'+modalEventStatusId).html()
|
|
|
|
// loop until finished
|
|
if(displayedEvent.indexOf('finished') == -1) // if the message is different from finished, check again in 2s
|
|
{
|
|
|
|
getParam(modalEventStatusId,"Front_Event", true)
|
|
|
|
updateModalState()
|
|
|
|
}
|
|
}, 2000);
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// handling events on the backend initiated by the front end END
|
|
// -----------------------------------------------------------------------------
|
|
|
|
// ---------------------------------------------------------
|
|
// Show last time settings have been imported
|
|
getParam("lastImportedTime", "Back_Settings_Imported", skipCache = true);
|
|
|
|
</script>
|