UI auto-refresh #614 Schedule for undiscoverable devices to mark ONLINE work #617

This commit is contained in:
Jokob-sk
2024-04-03 23:01:36 +11:00
parent 69450c5885
commit 1367649554
18 changed files with 125 additions and 28 deletions

View File

@@ -197,7 +197,7 @@
</label> </label>
<div class="col-sm-9"> <div class="col-sm-9">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon"><i class="fa" id="txtIconFA" onclick="editDrp('txtIcon');"></i></span> <span class="input-group-addon" id="txtIconFA"></span>
<input class="form-control" id="txtIcon" type="text" value="--"> <input class="form-control" id="txtIcon" type="text" value="--">
<span class="input-group-addon" title='<?= lang('DevDetail_button_OverwriteIcons_Tooltip');?>'><i class="fa fa-copy pointer" onclick="askOverwriteIconType();"></i></span> <span class="input-group-addon" title='<?= lang('DevDetail_button_OverwriteIcons_Tooltip');?>'><i class="fa fa-copy pointer" onclick="askOverwriteIconType();"></i></span>
<div class="input-group-btn"> <div class="input-group-btn">
@@ -205,6 +205,7 @@
<span class="fa fa-caret-down"></span> <span class="fa fa-caret-down"></span>
</button> </button>
<ul id="dropdownIcon" class="dropdown-menu dropdown-menu-right"> <ul id="dropdownIcon" class="dropdown-menu dropdown-menu-right">
<li id="dropdownIcon_tmp"></li>
</ul> </ul>
</div> </div>
</div> </div>
@@ -734,7 +735,7 @@ function main () {
// Show device icon as it changes // Show device icon as it changes
$('#txtIcon').on('change input', function() { $('#txtIcon').on('change input', function() {
$('#txtIconFA').removeClass().addClass(`fa fa-${$(this).val()} pointer`) $('#txtIconFA').html(atob($(this).val()))
}); });
@@ -799,8 +800,6 @@ function initializeiCheck () {
function initializeCombos () { function initializeCombos () {
// Initialize combos with queries // Initialize combos with queries
initializeCombo ( '#dropdownIcon', 'getIcons', 'txtIcon', false);
initializeCombo ( '#dropdownAction', 'getActions', 'txtAction', false); initializeCombo ( '#dropdownAction', 'getActions', 'txtAction', false);
initializeCombo ( '#dropdownDevices', 'getDevices', 'txtFromDevice', false); initializeCombo ( '#dropdownDevices', 'getDevices', 'txtFromDevice', false);
@@ -809,9 +808,11 @@ function initializeCombos () {
// valuesArray, // Array of values to be pre-selected in the dropdown // 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) // targetLocation, // ID of the HTML element where dropdown should be rendered (will be replaced)
// callbackToGenerateEntries, // Callback function to generate entries based on options // callbackToGenerateEntries, // Callback function to generate entries based on options
// targetField) // Target field or element where selected value should be applied or updated // targetField, // Target field or element where selected value should be applied or updated
// nameTransformer) // callback to transform name
initSettingDropdown("NEWDEV_dev_Icon", [], "dropdownIcon_tmp", genDevDetailsList, 'txtIcon', atob )
initSettingDropdown("NEWDEV_dev_DeviceType", [], "dropdownDeviceType_tmp", genDevDetailsList, 'txtDeviceType' ) initSettingDropdown("NEWDEV_dev_DeviceType", [], "dropdownDeviceType_tmp", genDevDetailsList, 'txtDeviceType' )
initSettingDropdown("NEWDEV_dev_Owner", [], "dropdownOwner_tmp", genDevDetailsList, 'txtOwner' ) initSettingDropdown("NEWDEV_dev_Owner", [], "dropdownOwner_tmp", genDevDetailsList, 'txtOwner' )
initSettingDropdown("NEWDEV_dev_Group", [], "dropdownGroup_tmp", genDevDetailsList, 'txtGroup' ) initSettingDropdown("NEWDEV_dev_Group", [], "dropdownGroup_tmp", genDevDetailsList, 'txtGroup' )

View File

@@ -582,7 +582,7 @@ function initializeDatatable (status) {
{targets: [mapIndx(3)], {targets: [mapIndx(3)],
'createdCell': function (td, cellData, rowData, row, col) { 'createdCell': function (td, cellData, rowData, row, col) {
if (!emptyArr.includes(cellData)){ if (!emptyArr.includes(cellData)){
$(td).html (cellData); $(td).html (atob(cellData));
} else { } else {
$(td).html (''); $(td).html ('');
} }

View File

@@ -3,14 +3,14 @@
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Read data and place intotarget location, callback processies the results // Read data and place intotarget location, callback processies the results
function readData(sqlQuery, processDataCallback, valuesArray, targetLocation, targetField) { function readData(sqlQuery, processDataCallback, valuesArray, targetLocation, targetField, nameTransformer) {
var apiUrl = `php/server/dbHelper.php?action=read&rawSql=${encodeURIComponent(sqlQuery)}`; var apiUrl = `php/server/dbHelper.php?action=read&rawSql=${encodeURIComponent(sqlQuery)}`;
$.get(apiUrl, function(data) { $.get(apiUrl, function(data) {
// Process the JSON data using the provided callback function // Process the JSON data using the provided callback function
data = JSON.parse(data) data = JSON.parse(data)
var htmlResult = processDataCallback(data, valuesArray, targetField); var htmlResult = processDataCallback(data, valuesArray, targetField, nameTransformer);
// Place the resulting HTML into the specified placeholder div // Place the resulting HTML into the specified placeholder div
$("#" + targetLocation).replaceWith(htmlResult); $("#" + targetLocation).replaceWith(htmlResult);

View File

@@ -628,10 +628,19 @@ function stopTimerRefreshData () {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
function newTimerRefreshData (refeshFunction) { function newTimerRefreshData (refeshFunction, timeToRefresh) {
if(timeToRefresh && (timeToRefresh != 0 || timeToRefresh != ""))
{
time = parseInt(timeToRefresh)
} else
{
time = 60000
}
timerRefreshData = setTimeout (function() { timerRefreshData = setTimeout (function() {
refeshFunction(); refeshFunction();
}, 60000); }, time);
} }
@@ -1247,6 +1256,16 @@ const onAllCallsComplete = () => {
// Call the function to execute the code // Call the function to execute the code
executeOnce(); executeOnce();
// Set timer for page refresh if configured
setTimeout(() => {
const refreshTime = getSetting("UI_REFRESH");
if (refreshTime && refreshTime !== "0" && refreshTime !== "") {
newTimerRefreshData(clearCache, refreshTime);
}
}, 10000);
console.log("init pialert_common.js"); console.log("init pialert_common.js");

View File

@@ -117,7 +117,8 @@ function initSettingDropdown(settingKey, // Identifier for the setting
valuesArray, // Array of values to be pre-selected in the dropdown 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) targetLocation, // ID of the HTML element where dropdown should be rendered (will be replaced)
callbackToGenerateEntries, // Callback function to generate entries based on options callbackToGenerateEntries, // Callback function to generate entries based on options
targetField) // Target field or element where selected value should be applied or updated targetField, // Target field or element where selected value should be applied or updated
nameTransformer) // callback to transform the name (e.g. base64)
{ {
var optionsHtml = "" var optionsHtml = ""
@@ -127,7 +128,7 @@ function initSettingDropdown(settingKey, // Identifier for the setting
// check if the result is a SQL query // check if the result is a SQL query
if(isSQLQuery(optionsArray[0])) if(isSQLQuery(optionsArray[0]))
{ {
readData(optionsArray[0], callbackToGenerateEntries, valuesArray, targetLocation, targetField); readData(optionsArray[0], callbackToGenerateEntries, valuesArray, targetLocation, targetField, nameTransformer);
} else // this should be already an array, e.g. from a setting or pre-defined } else // this should be already an array, e.g. from a setting or pre-defined
{ {
@@ -212,8 +213,8 @@ function generateList(data, valuesArray) {
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Processor to generate a list // Processor to generate a list in teh deviceDetails page
function genDevDetailsList(data, valuesArray, targetField) { function genDevDetailsList(data, valuesArray, targetField, nameTransformer) {
var listHtml = ""; var listHtml = "";
@@ -222,12 +223,17 @@ function genDevDetailsList(data, valuesArray, targetField) {
let selected = valuesArray.includes(item.id) ? 'selected' : ''; let selected = valuesArray.includes(item.id) ? 'selected' : '';
console.log(item); console.log(item);
// listHtml += `<li ${selected}>${item.name}</li>`; labelName = item.name
if(nameTransformer && labelName != '❌None')
{
labelName = nameTransformer(labelName)
}
listHtml += `<li ${selected}> listHtml += `<li ${selected}>
<a href="javascript:void(0)" onclick="setTextValue('${targetField}','${item.id}')">${item.name}</a> <a href="javascript:void(0)" onclick="setTextValue('${targetField}','${item.id}')">${labelName}</a>
</li>`; </li>`;
}); });
@@ -236,6 +242,8 @@ function genDevDetailsList(data, valuesArray, targetField) {
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// initialize // initialize
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@@ -107,7 +107,7 @@
break; break;
} }
// Add classes specifically for checkboxes
if (inputType === 'text.select') { if (inputType === 'text.select') {
targetLocation = columns[j].Code_Name + "_initSettingDropdown" targetLocation = columns[j].Code_Name + "_initSettingDropdown"
@@ -122,6 +122,7 @@
</select>` </select>`
} else { } else {
// Add classes specifically for checkboxes
if (inputType === 'checkbox') { if (inputType === 'checkbox') {
inputClass = 'checkbox'; inputClass = 'checkbox';

View File

@@ -47,10 +47,11 @@
$node_badge = circle_offline; $node_badge = circle_offline;
} }
$decoded_icon = base64_decode($icon);
$idFromMac = str_replace(":", "_", $node_mac); $idFromMac = str_replace(":", "_", $node_mac);
$str_tab_header = '<li class="'.$activetab.'"> $str_tab_header = '<li class="'.$activetab.'">
<a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" >' // _id is added so it doesn't conflict with AdminLTE tab behavior <a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" >' // _id is added so it doesn't conflict with AdminLTE tab behavior
.$icon.$node_name.' ' .$str_port.$node_badge. .$decoded_icon.$node_name.' ' .$str_port.$node_badge.
'</a> '</a>
</li>'; </li>';
@@ -655,7 +656,7 @@
// Build HTML for individual nodes in the network diagram // Build HTML for individual nodes in the network diagram
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ? deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ?
`<div class="netIcon"> `<div class="netIcon">
${nodeData.data.icon} ${atob(nodeData.data.icon)}
</div>` : ""; </div>` : "";
devicePort = `<div class="netPort" devicePort = `<div class="netPort"
style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em"> style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em">

View File

@@ -645,7 +645,7 @@ function getDevicesList() {
$row['dev_Name'], $row['dev_Name'],
$row['dev_Owner'], $row['dev_Owner'],
handleNull($row['dev_DeviceType']), handleNull($row['dev_DeviceType']),
handleNull($row['dev_Icon'], "laptop"), handleNull($row['dev_Icon'], "<i class='fa fa-laptop'></i>"),
$row['dev_Favorite'], $row['dev_Favorite'],
$row['dev_Group'], $row['dev_Group'],
// ---- // ----
@@ -754,10 +754,10 @@ function getIcons() {
// arrays of rows // arrays of rows
$tableData = array(); $tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) { while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$icon = handleNull($row['dev_Icon'], "laptop"); $icon = handleNull($row['dev_Icon'], "<i class='fa fa-laptop'></i>");
// Push row data // Push row data
$tableData[] = array('id' => $icon, $tableData[] = array('id' => $icon,
'name' => '<i class="fa fa-'.$icon.'"></i> - '.$icon ); 'name' => $icon );
} }
// Control no rows // Control no rows

View File

@@ -685,6 +685,8 @@
"UI_NOT_RANDOM_MAC_name": "", "UI_NOT_RANDOM_MAC_name": "",
"UI_PRESENCE_description": "Ausw\u00e4hlen, welche Status im <b>Ger\u00e4tepr\u00e4senz im Laufe der Zeit</b>-Diagramm in der <a href=\"/devices.php\" target=\"_blank\">Ger\u00e4te</a>-Seite angzeigt werden sollen. (<code>STRG + klicken</code> zum aus-/abw\u00e4hlen).", "UI_PRESENCE_description": "Ausw\u00e4hlen, welche Status im <b>Ger\u00e4tepr\u00e4senz im Laufe der Zeit</b>-Diagramm in der <a href=\"/devices.php\" target=\"_blank\">Ger\u00e4te</a>-Seite angzeigt werden sollen. (<code>STRG + klicken</code> zum aus-/abw\u00e4hlen).",
"UI_PRESENCE_name": "Anzeige im Pr\u00e4senzdiagramm", "UI_PRESENCE_name": "Anzeige im Pr\u00e4senzdiagramm",
"UI_REFRESH_description": "",
"UI_REFRESH_name": "",
"WEBHOOK_PAYLOAD_description": "The Webhook payload data format for the <code>body</code> > <code>attachments</code> > <code>text</code> attribute in the payload json. See an example of the payload <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">here</a>. (e.g.: for discord use <code>text</code>)", "WEBHOOK_PAYLOAD_description": "The Webhook payload data format for the <code>body</code> > <code>attachments</code> > <code>text</code> attribute in the payload json. See an example of the payload <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">here</a>. (e.g.: for discord use <code>text</code>)",
"WEBHOOK_PAYLOAD_name": "Payload type", "WEBHOOK_PAYLOAD_name": "Payload type",
"WEBHOOK_REQUEST_METHOD_description": "The HTTP request method to be used for the webhook call.", "WEBHOOK_REQUEST_METHOD_description": "The HTTP request method to be used for the webhook call.",

View File

@@ -616,6 +616,8 @@
"UI_NOT_RANDOM_MAC_name": "Don't mark as Random", "UI_NOT_RANDOM_MAC_name": "Don't mark as Random",
"UI_PRESENCE_description": "Select what statuses should be shown in the <b>Device presence</b> chart in the <a href=\"/devices.php\" target=\"_blank\">Devices</a> page. (<code>CTRL + Click</code> to select/deselect)", "UI_PRESENCE_description": "Select what statuses should be shown in the <b>Device presence</b> chart in the <a href=\"/devices.php\" target=\"_blank\">Devices</a> page. (<code>CTRL + Click</code> to select/deselect)",
"UI_PRESENCE_name": "Show in presence chart", "UI_PRESENCE_name": "Show in presence chart",
"UI_REFRESH_description": "Enter number of seconds after which the UI reloads. Set to <code>0</code> to disable.",
"UI_REFRESH_name": "Auto-refresh UI",
"devices_old": "Refreshing...", "devices_old": "Refreshing...",
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:", "general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
"general_event_title": "Executing an ad-hoc event", "general_event_title": "Executing an ad-hoc event",

View File

@@ -685,6 +685,8 @@
"UI_NOT_RANDOM_MAC_name": "No marcar como aleatoria", "UI_NOT_RANDOM_MAC_name": "No marcar como aleatoria",
"UI_PRESENCE_description": "Elige que estados del dispositivo deben mostrarse en la gr\u00e1fica de <b>Presencia del dispositivo a lo largo del tiempo</b> de la p\u00e1gina de <a href=\"/devices.php\" target=\"_blank\">Dispositivos</a>. (<code>CTRL + Clic</code> para seleccionar / deseleccionar)", "UI_PRESENCE_description": "Elige que estados del dispositivo deben mostrarse en la gr\u00e1fica de <b>Presencia del dispositivo a lo largo del tiempo</b> de la p\u00e1gina de <a href=\"/devices.php\" target=\"_blank\">Dispositivos</a>. (<code>CTRL + Clic</code> para seleccionar / deseleccionar)",
"UI_PRESENCE_name": "Mostrar en el gr\u00e1fico de presencia", "UI_PRESENCE_name": "Mostrar en el gr\u00e1fico de presencia",
"UI_REFRESH_description": "",
"UI_REFRESH_name": "",
"WEBHOOK_PAYLOAD_description": "El formato de datos de carga de Webhook para el atributo <code>body</code> > <code>attachments</code> > <code>text</code> en el json de carga. Vea un ejemplo de la carga <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">aqu\u00ed</a>. (por ejemplo: para discord use <code>text</code>)", "WEBHOOK_PAYLOAD_description": "El formato de datos de carga de Webhook para el atributo <code>body</code> > <code>attachments</code> > <code>text</code> en el json de carga. Vea un ejemplo de la carga <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">aqu\u00ed</a>. (por ejemplo: para discord use <code>text</code>)",
"WEBHOOK_PAYLOAD_name": "Tipo de carga", "WEBHOOK_PAYLOAD_name": "Tipo de carga",
"WEBHOOK_REQUEST_METHOD_description": "El m\u00e9todo de solicitud HTTP que se utilizar\u00e1 para la llamada de webhook.", "WEBHOOK_REQUEST_METHOD_description": "El m\u00e9todo de solicitud HTTP que se utilizar\u00e1 para la llamada de webhook.",

View File

@@ -616,6 +616,8 @@
"UI_NOT_RANDOM_MAC_name": "", "UI_NOT_RANDOM_MAC_name": "",
"UI_PRESENCE_description": "", "UI_PRESENCE_description": "",
"UI_PRESENCE_name": "", "UI_PRESENCE_name": "",
"UI_REFRESH_description": "",
"UI_REFRESH_name": "",
"devices_old": "", "devices_old": "",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",

View File

@@ -616,6 +616,8 @@
"UI_NOT_RANDOM_MAC_name": "", "UI_NOT_RANDOM_MAC_name": "",
"UI_PRESENCE_description": "", "UI_PRESENCE_description": "",
"UI_PRESENCE_name": "", "UI_PRESENCE_name": "",
"UI_REFRESH_description": "",
"UI_REFRESH_name": "",
"devices_old": "", "devices_old": "",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",

View File

@@ -616,6 +616,8 @@
"UI_NOT_RANDOM_MAC_name": "\u041d\u0435 \u043e\u0442\u043c\u0435\u0447\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0435", "UI_NOT_RANDOM_MAC_name": "\u041d\u0435 \u043e\u0442\u043c\u0435\u0447\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0435",
"UI_PRESENCE_description": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043a\u0430\u043a\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 <b>\u041f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430</b> \u00b7 \u00b7 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <a href=\"/devices.php\" target=\"_blank\">\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430</a>. (<code>CTRL + Click</code>, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c/\u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440)", "UI_PRESENCE_description": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043a\u0430\u043a\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 <b>\u041f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430</b> \u00b7 \u00b7 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435 <a href=\"/devices.php\" target=\"_blank\">\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430</a>. (<code>CTRL + Click</code>, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0431\u0440\u0430\u0442\u044c/\u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0432\u044b\u0431\u043e\u0440)",
"UI_PRESENCE_name": "\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f", "UI_PRESENCE_name": "\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f",
"UI_REFRESH_description": "",
"UI_REFRESH_name": "",
"devices_old": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f...", "devices_old": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f...",
"general_event_description": "\u0421\u043e\u0431\u044b\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043b\u0438, \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0444\u043e\u043d\u043e\u0432\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u0441\u044f. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0430\u044f \u043d\u0438\u0436\u0435, \u043e\u043f\u0443\u0441\u0442\u0435\u0435\u0442 (\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 <a href='/maintenance.php#tab_Logging'>\u0436\u0443\u0440\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a</a> \u043f\u0440\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c). <br/> <br/>\u00b7 \u00b7 \u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:", "general_event_description": "\u0421\u043e\u0431\u044b\u0442\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u044b \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043b\u0438, \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043d\u044f\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0444\u043e\u043d\u043e\u0432\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u0441\u044f. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044f, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0430\u044f \u043d\u0438\u0436\u0435, \u043e\u043f\u0443\u0441\u0442\u0435\u0435\u0442 (\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 <a href='/maintenance.php#tab_Logging'>\u0436\u0443\u0440\u043d\u0430\u043b \u043e\u0448\u0438\u0431\u043e\u043a</a> \u043f\u0440\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c). <br/> <br/>\u00b7 \u00b7 \u041e\u0447\u0435\u0440\u0435\u0434\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:",
"general_event_title": "\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f", "general_event_title": "\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f",

View File

@@ -582,9 +582,16 @@
}, },
{ {
"function": "dev_Icon", "function": "dev_Icon",
"type": "string", "type": "text.select",
"default_value": "", "default_value": "",
"options": [], "options": ["{value}"],
"options_params" : [
{
"name" : "value",
"type" : "sql",
"value" : "SELECT DISTINCT '❌None' AS name, '' AS id UNION SELECT Dev_Icon AS name, Dev_Icon AS id FROM Devices WHERE Dev_Icon <> '';"
}
],
"localized": ["name", "description"], "localized": ["name", "description"],
"name": [ "name": [
{ {

View File

@@ -71,6 +71,7 @@
"options": [ "options": [
"disabled", "disabled",
"once", "once",
"schedule",
"always_after_scan" "always_after_scan"
], ],
"localized": [ "localized": [
@@ -94,11 +95,11 @@
"description": [ "description": [
{ {
"language_code": "en_us", "language_code": "en_us",
"string": "When enabled, ONCE is the preferred option. It runs at startup and after every save of the config here.<br> Changes will only show in the devices <b> after the next scan!</b>" "string": "When enabled, <code>once</code> is the preferred option, or set to <code>schedule</code> and align the <code>UNDIS_RUN_SCHD</code> setting with the other scanners if you want the devices to show up as ONLINE. It runs at startup and after every save of the config here.<br> Changes will only show in the devices <b> after the next scan!</b>"
}, },
{ {
"language_code": "es_es", "language_code": "es_es",
"string": "Cuando está habilitado, ONCE es la opción preferida. Se ejecuta al inicio y después de cada guardado de la configuración aquí.<br> ¡Los cambios solo se mostrarán en los dispositivos <b> después del próximo escaneo!</b>" "string": "Cuando está habilitado, <code>once</code> es la opción preferida. Se ejecuta al inicio y después de cada guardado de la configuración aquí.<br> ¡Los cambios solo se mostrarán en los dispositivos <b> después del próximo escaneo!</b>"
}, },
{ {
"language_code": "de_de", "language_code": "de_de",
@@ -302,6 +303,29 @@
"string": "Geräte, welche der Geräteliste hinzugefügt werden." "string": "Geräte, welche der Geräteliste hinzugefügt werden."
} }
] ]
},
{
"function": "RUN_SCHD",
"type": "text",
"default_value":"*/5 * * * *",
"options": [],
"localized": ["name", "description"],
"name" : [{
"language_code":"en_us",
"string" : "Schedule"
},
{
"language_code":"es_es",
"string" : "Schedule"
}],
"description": [{
"language_code":"en_us",
"string" : "Only enabled if you select <code>schedule</code> in the <a href=\"#UNDIS_RUN\"><code>UNDIS_RUN</code> setting</a>. Make sure you enter the schedule in the correct cron-like format (e.g. validate at <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). For example entering <code>0 4 * * *</code> will run the scan after 4 am in the <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</code> you set above</a>. Will be run NEXT time the time passes. <br/> It's recommended to use the same schedule interval for all plugins responsible for discovering new devices. "
},
{
"language_code":"es_es",
"string" : "Solo está habilitado si selecciona <code>schedule</code> en la configuración <a href=\"#UNDIS_RUN\"><code>UNDIS_RUN</code></a>. Asegúrese de ingresar la programación en el formato similar a cron correcto (por ejemplo, valide en <a href=\"https://crontab.guru/\" target=\"_blank\">crontab.guru</a>). Por ejemplo, ingresar <code>0 4 * * *</code> ejecutará el escaneo después de las 4 a.m. en el <a onclick=\"toggleAllSettings()\" href=\"#TIMEZONE\"><code>TIMEZONE</ código> que configuró arriba</a>. Se ejecutará la PRÓXIMA vez que pase el tiempo."
}]
} }
], ],
"database_column_definitions": [ "database_column_definitions": [

View File

@@ -1,6 +1,7 @@
""" all things database to support Pi.Alert """ """ all things database to support Pi.Alert """
import sqlite3 import sqlite3
import base64
# pialert modules # pialert modules
from const import fullDbPath, sql_devices_stats, sql_devices_all from const import fullDbPath, sql_devices_stats, sql_devices_all
@@ -269,10 +270,32 @@ class DB():
sql_Icons = """ UPDATE Devices SET dev_Icon = '<i class="fa fa-' || dev_Icon || '"></i>' sql_Icons = """ UPDATE Devices SET dev_Icon = '<i class="fa fa-' || dev_Icon || '"></i>'
WHERE dev_Icon NOT LIKE '<i class="fa fa-%' WHERE dev_Icon NOT LIKE '<i class="fa fa-%'
AND dev_Icon NOT LIKE '<svg%' AND dev_Icon NOT LIKE '<svg%'
AND dev_Icon NOT LIKE 'PGkg%'
AND dev_Icon NOT IN ('', 'null') AND dev_Icon NOT IN ('', 'null')
""" """
self.sql.execute(sql_Icons) self.sql.execute(sql_Icons)
self.commitDB()
# Base64 conversion
self.sql.execute("SELECT dev_MAC, dev_Icon FROM Devices WHERE dev_Icon like '<%' ")
icons = self.sql.fetchall()
# Loop through the icons, encode them, and update the database
for icon_tuple in icons:
icon = icon_tuple[1]
# Encode the icon as base64
encoded_icon = base64.b64encode(icon.encode('utf-8')).decode('ascii')
# Update the database with the encoded icon
sql_update = f"""
UPDATE Devices
SET dev_Icon = '{encoded_icon}'
WHERE dev_MAC = '{icon_tuple[0]}'
"""
self.sql.execute(sql_update)
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Icon format migration table setup DEPRECATED after 9/9/2024 cleanup above # Icon format migration table setup DEPRECATED after 9/9/2024 cleanup above

View File

@@ -110,6 +110,7 @@ def importConfigs (db):
conf.UI_DEV_SECTIONS = ccd('UI_DEV_SECTIONS', [] , c_d, 'Show sections', 'text.multiselect', "['Tile Cards', 'Device Presence']", 'General') conf.UI_DEV_SECTIONS = ccd('UI_DEV_SECTIONS', [] , c_d, 'Show sections', 'text.multiselect', "['Tile Cards', 'Device Presence']", 'General')
conf.UI_MY_DEVICES = ccd('UI_MY_DEVICES', ['online', 'offline', 'archived', 'new', 'down'] , c_d, 'Include in My Devices', 'text.multiselect', "['online', 'offline', 'archived', 'new', 'down']", 'General') conf.UI_MY_DEVICES = ccd('UI_MY_DEVICES', ['online', 'offline', 'archived', 'new', 'down'] , c_d, 'Include in My Devices', 'text.multiselect', "['online', 'offline', 'archived', 'new', 'down']", 'General')
conf.UI_NOT_RANDOM_MAC = ccd('UI_NOT_RANDOM_MAC', [] , c_d, 'Exlude from Random Prefix', 'list', "", 'General') conf.UI_NOT_RANDOM_MAC = ccd('UI_NOT_RANDOM_MAC', [] , c_d, 'Exlude from Random Prefix', 'list', "", 'General')
conf.UI_REFRESH = ccd('UI_REFRESH', 0 , c_d, 'Refresh interval', 'integer', "", 'General')
conf.DAYS_TO_KEEP_EVENTS = ccd('DAYS_TO_KEEP_EVENTS', 90 , c_d, 'Delete events days', 'integer', '', 'General') conf.DAYS_TO_KEEP_EVENTS = ccd('DAYS_TO_KEEP_EVENTS', 90 , c_d, 'Delete events days', 'integer', '', 'General')
conf.HRS_TO_KEEP_NEWDEV = ccd('HRS_TO_KEEP_NEWDEV', 0 , c_d, 'Keep new devices for', 'integer', "0", 'General') conf.HRS_TO_KEEP_NEWDEV = ccd('HRS_TO_KEEP_NEWDEV', 0 , c_d, 'Keep new devices for', 'integer', "0", 'General')
conf.API_CUSTOM_SQL = ccd('API_CUSTOM_SQL', 'SELECT * FROM Devices WHERE dev_PresentLastScan = 0' , c_d, 'Custom endpoint', 'text', '', 'General') conf.API_CUSTOM_SQL = ccd('API_CUSTOM_SQL', 'SELECT * FROM Devices WHERE dev_PresentLastScan = 0' , c_d, 'Custom endpoint', 'text', '', 'General')