mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-03-03 14:46:29 -05:00
Add next scan ETA display and update app state with scan timing information
This commit is contained in:
@@ -87,6 +87,8 @@
|
||||
<div class="box-header">
|
||||
<div class=" col-sm-8 ">
|
||||
<h3 id="tableDevicesTitle" class="box-title text-gray "></h3>
|
||||
<!-- Next scan ETA — populated by sse_manager.js via nax:scanEtaUpdate -->
|
||||
<small id="nextScanEta" class="text-muted" style="display:none;margin-left:8px;font-weight:normal;font-size:0.75em;"></small>
|
||||
</div>
|
||||
<div class="dummyDevice col-sm-4 ">
|
||||
<span id="multiEditPlc">
|
||||
@@ -536,6 +538,95 @@ function badgeFromRowData(rowData) {
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Build the rich empty-table onboarding message (HTML).
|
||||
// Used as the DataTables 'emptyTable' language option.
|
||||
function buildEmptyDeviceTableMessage(nextScanLabel) {
|
||||
var etaLine = nextScanLabel
|
||||
? '<small class="text-muted" style="margin-top:6px;display:block;">' + nextScanLabel + '</small>'
|
||||
: '';
|
||||
return '<div class="text-center" style="padding:20px;">' +
|
||||
'<i class="fa fa-search fa-2x text-muted" style="margin-bottom:10px;"></i><br>' +
|
||||
'<strong>' + getString('Device_NoData_Title') + '</strong><br>' +
|
||||
'<span class="text-muted">' + getString('Device_NoData_Scanning') + '</span><br>' +
|
||||
etaLine +
|
||||
'<small style="margin-top:6px;display:block;">' + getString('Device_NoData_Help') + '</small>' +
|
||||
'</div>';
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Compute a live countdown label from an ISO next_scan_time string.
|
||||
// next_scan_time is the earliest scheduled run time across enabled device_scanner plugins,
|
||||
// computed by the backend and broadcast via SSE — no guesswork needed on the frontend.
|
||||
function computeNextScanLabel(nextScanTime) {
|
||||
if (!nextScanTime) return getString('Device_NextScan_Imminent');
|
||||
// Append Z if no UTC offset marker present — backend may emit naive UTC ISO strings.
|
||||
var isoStr = /Z$|[+-]\d{2}:?\d{2}$/.test(nextScanTime.trim()) ? nextScanTime : nextScanTime + 'Z';
|
||||
var secsLeft = Math.round((new Date(isoStr).getTime() - Date.now()) / 1000);
|
||||
if (secsLeft <= 0) return getString('Device_NextScan_Imminent');
|
||||
if (secsLeft >= 60) {
|
||||
var m = Math.floor(secsLeft / 60);
|
||||
var s = secsLeft % 60;
|
||||
return getString('Device_NextScan_In') + m + 'm ' + s + 's';
|
||||
}
|
||||
return getString('Device_NextScan_In') + secsLeft + 's';
|
||||
}
|
||||
|
||||
// Anchor for next scheduled scan time, ticker handle, and plugins data — module-level.
|
||||
var _nextScanTimeAnchor = null;
|
||||
var _scanEtaTickerId = null;
|
||||
var _pluginsData = null;
|
||||
|
||||
// Fetch plugins.json once on page load so we can guard ETA display to device_scanner plugins only.
|
||||
$.get('php/server/query_json.php', { file: 'plugins.json', nocache: Date.now() }, function(res) {
|
||||
_pluginsData = res['data'] || [];
|
||||
});
|
||||
|
||||
// Returns true only when at least one device_scanner plugin is loaded and not disabled.
|
||||
function hasEnabledDeviceScanners() {
|
||||
if (!_pluginsData || !_pluginsData.length) return false;
|
||||
return getPluginsByType(_pluginsData, 'device_scanner', true).length > 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Update the title-bar ETA subtitle and the DataTables empty-state message.
|
||||
// Called on every nax:scanEtaUpdate; the inner ticker keeps the title bar live between events.
|
||||
function updateScanEtaDisplay(nextScanTime) {
|
||||
// Prefer the backend-computed next_scan_time; keep previous anchor if not yet received.
|
||||
_nextScanTimeAnchor = nextScanTime || _nextScanTimeAnchor;
|
||||
|
||||
// Restart the per-second title-bar ticker
|
||||
if (_scanEtaTickerId !== null) { clearInterval(_scanEtaTickerId); }
|
||||
|
||||
function tickTitleBar() {
|
||||
var eta = document.getElementById('nextScanEta');
|
||||
if (!eta) return;
|
||||
if (!hasEnabledDeviceScanners()) {
|
||||
eta.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
eta.textContent = computeNextScanLabel(_nextScanTimeAnchor);
|
||||
eta.style.display = '';
|
||||
}
|
||||
|
||||
// Update DataTables empty message once per SSE event — avoids AJAX spam on server-side tables.
|
||||
// Only show the next-scan ETA line when device_scanner plugins are actually enabled.
|
||||
var label = hasEnabledDeviceScanners() ? computeNextScanLabel(_nextScanTimeAnchor) : '';
|
||||
if ($.fn.DataTable.isDataTable('#tableDevices')) {
|
||||
var dt = $('#tableDevices').DataTable();
|
||||
dt.settings()[0].oLanguage.sEmptyTable = buildEmptyDeviceTableMessage(label);
|
||||
if (dt.page.info().recordsTotal === 0) { dt.draw(false); }
|
||||
}
|
||||
|
||||
tickTitleBar();
|
||||
_scanEtaTickerId = setInterval(tickTitleBar, 1000);
|
||||
}
|
||||
|
||||
// Listen for scan ETA updates dispatched by sse_manager.js (SSE push or poll fallback)
|
||||
document.addEventListener('nax:scanEtaUpdate', function(e) {
|
||||
updateScanEtaDisplay(e.detail.nextScanTime);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Initializes the main devices list datatable
|
||||
function initializeDatatable (status) {
|
||||
@@ -893,7 +984,7 @@ function initializeDatatable (status) {
|
||||
// Processing
|
||||
'processing' : true,
|
||||
'language' : {
|
||||
emptyTable: 'No data',
|
||||
emptyTable: buildEmptyDeviceTableMessage(getString('Device_NextScan_Imminent')),
|
||||
"lengthMenu": "<?= lang('Device_Tablelenght');?>",
|
||||
"search": "<?= lang('Device_Searchbox');?>: ",
|
||||
"paginate": {
|
||||
|
||||
@@ -175,6 +175,16 @@ class NetAlertXStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Dispatch scan ETA update for pages that display next-scan timing
|
||||
if (appState["last_scan_run"] !== undefined || appState["next_scan_time"] !== undefined) {
|
||||
document.dispatchEvent(new CustomEvent('nax:scanEtaUpdate', {
|
||||
detail: {
|
||||
lastScanRun: appState["last_scan_run"],
|
||||
nextScanTime: appState["next_scan_time"]
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// console.log("[NetAlertX State] UI updated via jQuery");
|
||||
} catch (e) {
|
||||
console.error("[NetAlertX State] Failed to update state display:", e);
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "إجراءات جماعية",
|
||||
"Device_MultiEdit_No_Devices": "لم يتم تحديد أي أجهزة.",
|
||||
"Device_MultiEdit_Tooltip": "تعديل الأجهزة المحددة",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "تم إدخال قيمة غير صالحة",
|
||||
"Gen_LockedDB": "قاعدة البيانات مقفلة",
|
||||
"Gen_NetworkMask": "قناع الشبكة",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "غير متصل",
|
||||
"Gen_Okay": "موافق",
|
||||
"Gen_Online": "متصل",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Accions massives:",
|
||||
"Device_MultiEdit_No_Devices": "Cap dispositiu seleccionat.",
|
||||
"Device_MultiEdit_Tooltip": "Atenció. Si feu clic a això s'aplicarà el valor de l'esquerra a tots els dispositius seleccionats a dalt.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "Problemes guardant el dispositiu",
|
||||
"Device_Save_Unauthorized": "Token invàlid - No autoritzat",
|
||||
"Device_Saved_Success": "S'ha guardat el dispositiu",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "S'ha introduït un valor incorrecte",
|
||||
"Gen_LockedDB": "ERROR - DB podria estar bloquejada - Fes servir F12 Eines desenvolupament -> Consola o provar-ho més tard.",
|
||||
"Gen_NetworkMask": "Màscara de xarxa",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Fora de línia",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "En línia",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "CHYBA - Databáze je možná zamčená - Zkontrolujte F12 -> Nástroje pro vývojáře -> Konzole. nebo to zkuste později.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
|
||||
@@ -207,6 +207,11 @@
|
||||
"Device_MultiEdit_MassActions": "Massen aktionen:",
|
||||
"Device_MultiEdit_No_Devices": "Keine Geräte ausgewählt.",
|
||||
"Device_MultiEdit_Tooltip": "Achtung! Beim Drücken werden alle Werte auf die oben ausgewählten Geräte übertragen.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "Gerät erfolgreich gespeichert",
|
||||
@@ -340,6 +345,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "ERROR - DB eventuell gesperrt - Nutze die Konsole in den Entwickler Werkzeugen (F12) zur Überprüfung oder probiere es später erneut.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Mass actions:",
|
||||
"Device_MultiEdit_No_Devices": "No devices selected.",
|
||||
"Device_MultiEdit_Tooltip": "Careful. Clicking this will apply the value on the left to all devices selected above.",
|
||||
"Device_NextScan_Imminent": "imminent",
|
||||
"Device_NextScan_In": "Next scan in ",
|
||||
"Device_NoData_Help": "If devices don't appear after the scan, check your SCAN_SUBNETS setting and <a href=\"https://docs.netalertx.com/SUBNETS\" target=\"_blank\">documentation</a>.",
|
||||
"Device_NoData_Scanning": "Waiting for the first scan - this may take several minutes after the initial setup.",
|
||||
"Device_NoData_Title": "No devices found yet",
|
||||
"Device_Save_Failed": "Failed to save device",
|
||||
"Device_Save_Unauthorized": "Unauthorized - invalid API token",
|
||||
"Device_Saved_Success": "Device saved successfully",
|
||||
|
||||
@@ -205,6 +205,11 @@
|
||||
"Device_MultiEdit_MassActions": "Acciones masivas:",
|
||||
"Device_MultiEdit_No_Devices": "Sin dispositivo seleccionado.",
|
||||
"Device_MultiEdit_Tooltip": "Cuidado. Al hacer clic se aplicará el valor de la izquierda a todos los dispositivos seleccionados anteriormente.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "Fallo al guardar el dispositivo",
|
||||
"Device_Save_Unauthorized": "No autorizado - Token de API inválido",
|
||||
"Device_Saved_Success": "Dispositivo guardado exitósamente",
|
||||
@@ -338,6 +343,7 @@
|
||||
"Gen_Invalid_Value": "Un valor inválido fue ingresado",
|
||||
"Gen_LockedDB": "Fallo - La base de datos puede estar bloqueada - Pulsa F1 -> Ajustes de desarrolladores -> Consola o prueba más tarde.",
|
||||
"Gen_NetworkMask": "Máscara de red",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Desconectado",
|
||||
"Gen_Okay": "Aceptar",
|
||||
"Gen_Online": "En linea",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "",
|
||||
"Gen_Okay": "",
|
||||
"Gen_Online": "",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Actions en masse :",
|
||||
"Device_MultiEdit_No_Devices": "Aucun appareil sélectionné.",
|
||||
"Device_MultiEdit_Tooltip": "Attention. Ceci va appliquer la valeur de gauche à tous les appareils sélectionnés au-dessus.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "Erreur à l'enregistrement de l'appareil",
|
||||
"Device_Save_Unauthorized": "Non autorisé - Jeton d'API invalide",
|
||||
"Device_Saved_Success": "Appareil enregistré avec succès",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "Une valeur invalide a été renseignée",
|
||||
"Gen_LockedDB": "Erreur - La base de données est peut-être verrouillée - Vérifier avec les outils de dév via F12 -> Console ou essayer plus tard.",
|
||||
"Gen_NetworkMask": "Masque réseau",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Hors ligne",
|
||||
"Gen_Okay": "OK",
|
||||
"Gen_Online": "En ligne",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Azioni di massa:",
|
||||
"Device_MultiEdit_No_Devices": "Nessun dispositivo selezionato.",
|
||||
"Device_MultiEdit_Tooltip": "Attento. Facendo clic verrà applicato il valore sulla sinistra a tutti i dispositivi selezionati sopra.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "Impossibile salvare il dispositivo",
|
||||
"Device_Save_Unauthorized": "Non autorizzato: token API non valido",
|
||||
"Device_Saved_Success": "Dispositivo salvato correttamente",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "È stato inserito un valore non valido",
|
||||
"Gen_LockedDB": "ERRORE: il DB potrebbe essere bloccato, controlla F12 Strumenti di sviluppo -> Console o riprova più tardi.",
|
||||
"Gen_NetworkMask": "Maschera di rete",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
@@ -797,4 +803,4 @@
|
||||
"settings_system_label": "Sistema",
|
||||
"settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>",
|
||||
"test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni."
|
||||
}
|
||||
}
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "大量のアクション:",
|
||||
"Device_MultiEdit_No_Devices": "デバイスが選択されていません。",
|
||||
"Device_MultiEdit_Tooltip": "注意。これをクリックすると、左側の値が上記で選択したすべてのデバイスに適用されます。",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "デバイスの保存に失敗しました",
|
||||
"Device_Save_Unauthorized": "許可されていない - 無効なAPIトークン",
|
||||
"Device_Saved_Success": "デバイスが正常に保存されました",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "無効な値が入力されました",
|
||||
"Gen_LockedDB": "エラー - DBがロックされている可能性があります - F12で開発者ツール→コンソールを確認するか、後で試してください。",
|
||||
"Gen_NetworkMask": "ネットワークマスク",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "オフライン",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "オンライン",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Flerhandlinger:",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "Forsiktig. Ved å klikke på denne vil verdien til venstre brukes på alle enhetene som er valgt ovenfor.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "FEIL - DB kan være låst - Sjekk F12 Dev tools -> Konsoll eller prøv senere.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Frakoblet",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Operacje zbiorcze:",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "Uwaga. Kliknięcie tego spowoduje zastosowanie wartości po lewej stronie do wszystkich wybranych powyżej urządzeń.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "Błąd - Baza danych może być zablokowana - Sprawdź narzędzia deweloperskie F12 -> Konsola lub spróbuj później.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Niedostępne",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Dostępne",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Ações em massa:",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "Cuidadoso. Clicar aqui aplicará o valor à esquerda a todos os dispositivos selecionados acima.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "ERRO - O banco de dados pode estar bloqueado - Verifique F12 Ferramentas de desenvolvimento -> Console ou tente mais tarde.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Ações em massa:",
|
||||
"Device_MultiEdit_No_Devices": "Nenhum dispositivo selecionado.",
|
||||
"Device_MultiEdit_Tooltip": "Cuidadoso. Clicar aqui aplicará o valor à esquerda a todos os dispositivos selecionados acima.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "ERRO - A base de dados pode estar bloqueada - Verifique F12 Ferramentas de desenvolvimento -> Console ou tente mais tarde.",
|
||||
"Gen_NetworkMask": "Máscara de Rede",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Offline",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "Online",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Массовые действия:",
|
||||
"Device_MultiEdit_No_Devices": "Устройства не выбраны.",
|
||||
"Device_MultiEdit_Tooltip": "Осторожно. При нажатии на эту кнопку значение слева будет применено ко всем устройствам, выбранным выше.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "Не удалось сохранить устройство",
|
||||
"Device_Save_Unauthorized": "Не авторизован - недействительный токен API",
|
||||
"Device_Saved_Success": "Устройство успешно сохранено",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "Введено некорректное значение",
|
||||
"Gen_LockedDB": "ОШИБКА - Возможно, база данных заблокирована. Проверьте инструменты разработчика F12 -> Консоль или повторите попытку позже.",
|
||||
"Gen_NetworkMask": "Маска сети",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Оффлайн",
|
||||
"Gen_Okay": "OK",
|
||||
"Gen_Online": "Онлайн",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "",
|
||||
"Gen_Okay": "",
|
||||
"Gen_Online": "",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Toplu komutlar:",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "Dikkat. Buna tıklamak, soldaki değeri yukarıda seçilen tüm cihazlara uygulayacaktır.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "HATA - Veritabanı kilitlenmiş olabilir - F12 Geliştirici araçlarını -> Konsol kısmını kontrol edin veya daha sonra tekrar deneyin.",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Çevrimdışı",
|
||||
"Gen_Okay": "Tamam",
|
||||
"Gen_Online": "Çevrimiçi",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "Масові акції:",
|
||||
"Device_MultiEdit_No_Devices": "Не вибрано жодного пристрою.",
|
||||
"Device_MultiEdit_Tooltip": "Обережно. Якщо натиснути це, значення зліва буде застосовано до всіх пристроїв, вибраних вище.",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "Не вдалося зберегти пристрій",
|
||||
"Device_Save_Unauthorized": "Неавторизовано – недійсний токен API",
|
||||
"Device_Saved_Success": "Пристрій успішно збережено",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "Введено недійсне значення",
|
||||
"Gen_LockedDB": "ПОМИЛКА – БД може бути заблоковано – перевірте F12 Інструменти розробника -> Консоль або спробуйте пізніше.",
|
||||
"Gen_NetworkMask": "Маска мережі",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "Офлайн",
|
||||
"Gen_Okay": "Гаразд",
|
||||
"Gen_Online": "Онлайн",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "",
|
||||
"Device_MultiEdit_No_Devices": "",
|
||||
"Device_MultiEdit_Tooltip": "",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "",
|
||||
"Device_Save_Unauthorized": "",
|
||||
"Device_Saved_Success": "",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "",
|
||||
"Gen_LockedDB": "",
|
||||
"Gen_NetworkMask": "",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "",
|
||||
"Gen_Okay": "",
|
||||
"Gen_Online": "",
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
"Device_MultiEdit_MassActions": "谨慎操作:",
|
||||
"Device_MultiEdit_No_Devices": "未选择设备。",
|
||||
"Device_MultiEdit_Tooltip": "小心。 单击此按钮会将左侧的值应用到上面选择的所有设备。",
|
||||
"Device_NextScan_Imminent": "",
|
||||
"Device_NextScan_In": "",
|
||||
"Device_NoData_Help": "",
|
||||
"Device_NoData_Scanning": "",
|
||||
"Device_NoData_Title": "",
|
||||
"Device_Save_Failed": "保存设备失败",
|
||||
"Device_Save_Unauthorized": "未授权 - API 令牌无效",
|
||||
"Device_Saved_Success": "设备保存成功",
|
||||
@@ -336,6 +341,7 @@
|
||||
"Gen_Invalid_Value": "输入了无效的值",
|
||||
"Gen_LockedDB": "错误 - DB 可能被锁定 - 检查 F12 开发工具 -> 控制台或稍后重试。",
|
||||
"Gen_NetworkMask": "网络掩码",
|
||||
"Gen_New": "",
|
||||
"Gen_Offline": "离线",
|
||||
"Gen_Okay": "Ok",
|
||||
"Gen_Online": "在线",
|
||||
|
||||
@@ -124,8 +124,16 @@ def main():
|
||||
# last time any scan or maintenance/upkeep was run
|
||||
conf.last_scan_run = loop_start_time
|
||||
|
||||
# Header
|
||||
updateState("Process: Start")
|
||||
# Compute the next scheduled run time across enabled device_scanner plugins
|
||||
scanner_prefixes = {p["unique_prefix"] for p in all_plugins if p.get("plugin_type") == "device_scanner"}
|
||||
scanner_next = [s.last_next_schedule for s in conf.mySchedules if s.service in scanner_prefixes]
|
||||
next_scan_dt = min(scanner_next, default=None)
|
||||
next_scan_time_iso = next_scan_dt.replace(microsecond=0).isoformat() if next_scan_dt else ""
|
||||
|
||||
# Header (also broadcasts last_scan_run + next_scan_time to frontend via SSE / app_state.json)
|
||||
updateState("Process: Start",
|
||||
last_scan_run=loop_start_time.replace(microsecond=0).isoformat(),
|
||||
next_scan_time=next_scan_time_iso)
|
||||
|
||||
# Timestamp
|
||||
startTime = loop_start_time
|
||||
|
||||
@@ -43,7 +43,9 @@ class app_state_class:
|
||||
processScan=False,
|
||||
pluginsStates=None,
|
||||
appVersion=None,
|
||||
buildTimestamp=None
|
||||
buildTimestamp=None,
|
||||
last_scan_run=None,
|
||||
next_scan_time=None
|
||||
):
|
||||
"""
|
||||
Initialize the application state, optionally overwriting previous values.
|
||||
@@ -89,6 +91,8 @@ class app_state_class:
|
||||
self.pluginsStates = previousState.get("pluginsStates", {})
|
||||
self.appVersion = previousState.get("appVersion", "")
|
||||
self.buildTimestamp = previousState.get("buildTimestamp", "")
|
||||
self.last_scan_run = previousState.get("last_scan_run", "")
|
||||
self.next_scan_time = previousState.get("next_scan_time", "")
|
||||
else: # init first time values
|
||||
self.settingsSaved = 0
|
||||
self.settingsImported = 0
|
||||
@@ -101,6 +105,8 @@ class app_state_class:
|
||||
self.pluginsStates = {}
|
||||
self.appVersion = ""
|
||||
self.buildTimestamp = ""
|
||||
self.last_scan_run = ""
|
||||
self.next_scan_time = ""
|
||||
|
||||
# Overwrite with provided parameters if supplied
|
||||
if settingsSaved is not None:
|
||||
@@ -133,6 +139,10 @@ class app_state_class:
|
||||
self.appVersion = appVersion
|
||||
if buildTimestamp is not None:
|
||||
self.buildTimestamp = buildTimestamp
|
||||
if last_scan_run is not None:
|
||||
self.last_scan_run = last_scan_run
|
||||
if next_scan_time is not None:
|
||||
self.next_scan_time = next_scan_time
|
||||
# check for new version every hour and if currently not running new version
|
||||
if self.isNewVersion is False and self.isNewVersionChecked + 3600 < int(
|
||||
timeNowUTC(as_string=False).timestamp()
|
||||
@@ -165,7 +175,9 @@ class app_state_class:
|
||||
self.settingsImported,
|
||||
timestamp=self.lastUpdated,
|
||||
appVersion=self.appVersion,
|
||||
buildTimestamp=self.buildTimestamp
|
||||
buildTimestamp=self.buildTimestamp,
|
||||
last_scan_run=self.last_scan_run,
|
||||
next_scan_time=self.next_scan_time
|
||||
)
|
||||
except Exception as e:
|
||||
mylog("none", [f"[app_state] SSE broadcast: {e}"])
|
||||
@@ -183,7 +195,9 @@ def updateState(newState = None,
|
||||
processScan = None,
|
||||
pluginsStates=None,
|
||||
appVersion=None,
|
||||
buildTimestamp=None):
|
||||
buildTimestamp=None,
|
||||
last_scan_run=None,
|
||||
next_scan_time=None):
|
||||
"""
|
||||
Convenience method to create or update the app state.
|
||||
|
||||
@@ -197,6 +211,8 @@ def updateState(newState = None,
|
||||
pluginsStates (dict, optional): Plugin state updates.
|
||||
appVersion (str, optional): Application version.
|
||||
buildTimestamp (str, optional): Build timestamp.
|
||||
last_scan_run (str, optional): ISO timestamp of last backend scan run.
|
||||
next_scan_time (str, optional): ISO timestamp of next scheduled device_scanner run.
|
||||
|
||||
Returns:
|
||||
app_state_class: Updated state object.
|
||||
@@ -210,7 +226,9 @@ def updateState(newState = None,
|
||||
processScan,
|
||||
pluginsStates,
|
||||
appVersion,
|
||||
buildTimestamp
|
||||
buildTimestamp,
|
||||
last_scan_run,
|
||||
next_scan_time
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user