From 9b3947cc9024937b8a54116b19929b813dc5ccdb Mon Sep 17 00:00:00 2001 From: jokob-sk Date: Tue, 5 Aug 2025 08:06:42 +1000 Subject: [PATCH] device tools init loading #1130 --- docs/API.md | 4 + docs/samples/API/Grafana_Dashboard.json | 1162 +++++++++++++++++++++++ front/deviceDetailsTools.php | 35 +- 3 files changed, 1199 insertions(+), 2 deletions(-) create mode 100755 docs/samples/API/Grafana_Dashboard.json diff --git a/docs/API.md b/docs/API.md index 986a316d..ceb0da00 100755 --- a/docs/API.md +++ b/docs/API.md @@ -323,6 +323,10 @@ scrape_configs: credentials: ``` +### Grafana template + +Grafana template sample: [Download json](./samples/API/Grafana_Dashboard.json) + ## API Endpoint: /log files This API endpoint retrieves files from the `/app/log` folder. diff --git a/docs/samples/API/Grafana_Dashboard.json b/docs/samples/API/Grafana_Dashboard.json new file mode 100755 index 00000000..211084b2 --- /dev/null +++ b/docs/samples/API/Grafana_Dashboard.json @@ -0,0 +1,1162 @@ +{ + "__inputs": [ + { + "name": "DS_PROMETHEUS", + "label": "Prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__elements": {}, + "__requires": [ + { + "type": "panel", + "id": "barchart", + "name": "Bar chart", + "version": "" + }, + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "12.0.0" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "stat", + "name": "Stat", + "version": "" + }, + { + "type": "panel", + "id": "table", + "name": "Table", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": null, + "links": [], + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "#00a3cc", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [], + "max": 105, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "expr": "netalertx_total_devices", + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Total Devices", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "#159d60", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 4, + "y": 0 + }, + "id": 2, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "expr": "netalertx_connected_devices", + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Connected", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "#b1720c", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 8, + "y": 0 + }, + "id": 3, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "expr": "netalertx_favorite_devices", + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Favorites", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "#F59E42", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 12, + "y": 0 + }, + "id": 4, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "expr": "netalertx_new_devices", + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "New Devices", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "#EF4444", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 16, + "y": 0 + }, + "id": 5, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "expr": "netalertx_down_devices", + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Down", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "#6B7280", + "mode": "fixed" + }, + "decimals": 0, + "mappings": [], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 0 + }, + "id": 6, + "options": { + "colorMode": "background", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "expr": "netalertx_archived_devices", + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Archived", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Connected" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#107648", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Offline" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#888888", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Down Devices" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "#913225", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 3 + }, + "id": 7, + "options": { + "barRadius": 0, + "barWidth": 0.9, + "displayMode": "stacked", + "fullHighlight": false, + "groupWidth": 0.7, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "minInterval": "1m", + "orientation": "vertical", + "showValue": "never", + "stacking": "normal", + "text": { + "valueSize": 10 + }, + "tooltip": { + "hideZeros": false, + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": -45, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "expr": "netalertx_connected_devices", + "legendFormat": "Connected", + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + }, + { + "expr": "netalertx_total_devices - (netalertx_connected_devices + netalertx_down_devices)", + "legendFormat": "Offline", + "refId": "B", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + }, + { + "expr": "netalertx_down_devices", + "legendFormat": "Down Devices", + "refId": "C", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Device Presence", + "type": "barchart" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Connected (Online) Devices", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "color-text" + }, + "filterable": true, + "inspect": false, + "minWidth": 120 + }, + "fieldMinMax": false, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-green" + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Status" + }, + "properties": [ + { + "id": "custom.width", + "value": 70 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "IP" + }, + "properties": [ + { + "id": "custom.width", + "value": 100 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "MAC" + }, + "properties": [ + { + "id": "custom.width", + "value": 134 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": 188 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Device" + }, + "properties": [ + { + "id": "custom.width", + "value": 300 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Vendor" + }, + "properties": [ + { + "id": "custom.width", + "value": 300 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "First Connect" + }, + "properties": [ + { + "id": "custom.width", + "value": 221 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Last Connect" + }, + "properties": [ + { + "id": "custom.width", + "value": 200 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 1001, + "options": { + "cellHeight": "sm", + "columns": [ + { + "text": "Time" + }, + { + "text": "device" + }, + { + "text": "ip" + }, + { + "text": "mac" + }, + { + "text": "vendor" + }, + { + "text": "dev_type" + }, + { + "text": "first_connection" + }, + { + "text": "last_connection" + } + ], + "footer": { + "countRows": false, + "enablePagination": true, + "fields": "", + "reducer": [], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "editorMode": "code", + "expr": "netalertx_device_status{device_status=\"Online\"}", + "format": "table", + "range": true, + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Connected Devices", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Value": true, + "__name__": true, + "device_status": false, + "instance": true, + "job": true + }, + "includeByName": {}, + "indexByName": { + "Time": 0, + "Value": 9, + "__name__": 12, + "dev_type": 5, + "device": 2, + "device_status": 6, + "first_connection": 7, + "instance": 11, + "ip": 1, + "job": 10, + "last_connection": 8, + "mac": 3, + "vendor": 4 + }, + "renameByName": { + "Time": "", + "dev_type": "Type", + "device": "Device", + "device_status": "Status", + "first_connection": "First Connect", + "ip": "IP", + "job": "", + "last_connection": "Last Connect", + "mac": "MAC", + "vendor": "Vendor" + } + } + }, + { + "id": "limit", + "options": { + "limitField": "100" + } + } + ], + "transparent": true, + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + }, + "description": "Disconnected(Offline) Devices", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "color-text" + }, + "filterable": true, + "inspect": false, + "minWidth": 120 + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "#ad2030" + } + ] + }, + "unit": "short" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Type" + }, + "properties": [ + { + "id": "custom.width", + "value": 94 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Status" + }, + "properties": [ + { + "id": "custom.width", + "value": 70 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "IP" + }, + "properties": [ + { + "id": "custom.width", + "value": 100 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "MAC" + }, + "properties": [ + { + "id": "custom.width", + "value": 134 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": 188 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Device" + }, + "properties": [ + { + "id": "custom.width", + "value": 300 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Vendor" + }, + "properties": [ + { + "id": "custom.width", + "value": 300 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "First Connect" + }, + "properties": [ + { + "id": "custom.width", + "value": 221 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Last Connect" + }, + "properties": [ + { + "id": "custom.width", + "value": 200 + } + ] + } + ] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 22 + }, + "id": 1002, + "options": { + "cellHeight": "sm", + "columns": [ + { + "text": "Time" + }, + { + "text": "device" + }, + { + "text": "ip" + }, + { + "text": "mac" + }, + { + "text": "vendor" + }, + { + "text": "dev_type" + }, + { + "text": "first_connection" + }, + { + "text": "last_connection" + } + ], + "footer": { + "countRows": false, + "enablePagination": true, + "fields": "", + "reducer": [], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "12.0.0", + "targets": [ + { + "editorMode": "code", + "expr": "netalertx_device_status{device_status=\"Offline\"}", + "format": "table", + "range": true, + "refId": "A", + "datasource": { + "type": "prometheus", + "uid": "${DS_PROMETHEUS}" + } + } + ], + "title": "Disconnected Devices", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Value": true, + "__name__": true, + "device_status": false, + "instance": true, + "job": true + }, + "includeByName": {}, + "indexByName": { + "Time": 0, + "Value": 9, + "__name__": 12, + "dev_type": 5, + "device": 2, + "device_status": 6, + "first_connection": 7, + "instance": 11, + "ip": 1, + "job": 10, + "last_connection": 8, + "mac": 3, + "vendor": 4 + }, + "renameByName": { + "Time": "", + "dev_type": "Type", + "device": "Device", + "device_status": "Status", + "first_connection": "First Connect", + "ip": "IP", + "job": "", + "last_connection": "Last Connect", + "mac": "MAC", + "vendor": "Vendor" + } + } + }, + { + "id": "limit", + "options": { + "limitField": "100" + } + } + ], + "transparent": true, + "type": "table" + } + ], + "refresh": "30s", + "schemaVersion": 41, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "NetAlertX Overview", + "uid": "netalertx-overview_7_26_2025", + "version": 7, + "weekStart": "" +} \ No newline at end of file diff --git a/front/deviceDetailsTools.php b/front/deviceDetailsTools.php index e93ad674..45d030db 100755 --- a/front/deviceDetailsTools.php +++ b/front/deviceDetailsTools.php @@ -443,6 +443,37 @@ } // init first time - initNmapButtons(); - initCopyFromDevice(); + // ----------------------------------------------------------- + var toolsPageInitialized = false; + + function initDeviceToolsPage() + { + // Only proceed if .panTools is visible + if (!$('#panTools:visible').length) { + return; // exit early if nothing is visible + } + + // init page once + if (toolsPageInitialized) return; + toolsPageInitialized = true; + + initNmapButtons(); + initCopyFromDevice(); + + hideSpinner(); + + } + + // ----------------------------------------------------------------------------- + // Recurring function to monitor the URL and reinitialize if needed + function deviceToolsPageUpdater() { + initDeviceToolsPage(); + + // Run updater again after delay + setTimeout(deviceToolsPageUpdater, 200); + } + + // start updater + deviceToolsPageUpdater(); +