mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2026-04-02 08:12:21 -07:00
feat: Add devFlapping attribute to device management and update related UI components
This commit is contained in:
@@ -23,9 +23,10 @@ function loadNetworkNodes() {
|
||||
LOWER(parent.devParentMAC) AS parent_mac,
|
||||
parent.devIcon AS node_icon,
|
||||
parent.devAlertDown AS node_alert,
|
||||
parent.devFlapping AS node_flapping,
|
||||
COUNT(child.devMac) AS node_ports_count
|
||||
FROM Devices AS parent
|
||||
LEFT JOIN Devices AS child
|
||||
FROM DevicesView AS parent
|
||||
LEFT JOIN DevicesView AS child
|
||||
/* CRITICAL FIX: COLLATE NOCASE ensures the join works
|
||||
even if devParentMAC is uppercase and devMac is lowercase
|
||||
*/
|
||||
@@ -33,7 +34,7 @@ function loadNetworkNodes() {
|
||||
WHERE parent.devType IN (${networkDeviceTypes})
|
||||
AND parent.devIsArchived = 0
|
||||
GROUP BY parent.devMac, parent.devName, parent.devPresentLastScan,
|
||||
parent.devType, parent.devParentMAC, parent.devIcon, parent.devAlertDown
|
||||
parent.devType, parent.devParentMAC, parent.devIcon, parent.devAlertDown, parent.devFlapping
|
||||
ORDER BY parent.devName;
|
||||
`;
|
||||
|
||||
@@ -143,6 +144,7 @@ function loadDeviceTable({ sql, containerSelector, tableId, wrapperHtml = null,
|
||||
const badge = getStatusBadgeParts(
|
||||
device.devPresentLastScan,
|
||||
device.devAlertDown,
|
||||
device.devFlapping,
|
||||
device.devMac,
|
||||
device.devStatus
|
||||
);
|
||||
@@ -202,8 +204,8 @@ function loadDeviceTable({ sql, containerSelector, tableId, wrapperHtml = null,
|
||||
*/
|
||||
function loadUnassignedDevices() {
|
||||
const sql = `
|
||||
SELECT devMac, devPresentLastScan, devName, devLastIP, devVendor, devAlertDown, devParentPort
|
||||
FROM Devices
|
||||
SELECT devMac, devPresentLastScan, devName, devLastIP, devVendor, devAlertDown, devParentPort, devFlapping, devStatus
|
||||
FROM DevicesView
|
||||
WHERE (devParentMAC IS NULL OR devParentMAC IN ("", " ", "undefined", "null"))
|
||||
AND LOWER(devMac) NOT LIKE "%internet%"
|
||||
AND devIsArchived = 0
|
||||
@@ -237,7 +239,7 @@ function loadConnectedDevices(node_mac) {
|
||||
const normalized_mac = node_mac.toLowerCase();
|
||||
|
||||
const sql = `
|
||||
SELECT devName, devMac, devLastIP, devVendor, devPresentLastScan, devAlertDown, devParentPort, devVlan,
|
||||
SELECT devName, devMac, devLastIP, devVendor, devPresentLastScan, devAlertDown, devParentPort, devVlan, devFlapping,
|
||||
CASE
|
||||
WHEN devIsNew = 1 THEN 'New'
|
||||
WHEN devPresentLastScan = 1 THEN 'On-line'
|
||||
@@ -246,7 +248,7 @@ function loadConnectedDevices(node_mac) {
|
||||
WHEN devPresentLastScan = 0 THEN 'Off-line'
|
||||
ELSE 'Unknown status'
|
||||
END AS devStatus
|
||||
FROM Devices
|
||||
FROM DevicesView
|
||||
/* Using COLLATE NOCASE here solves the 'TEXT' vs 'NOCASE' mismatch */
|
||||
WHERE devParentMac = '${normalized_mac}' COLLATE NOCASE`;
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ function initNetworkTopology() {
|
||||
WHEN devType IN (${networkDeviceTypes}) THEN 1
|
||||
ELSE 0
|
||||
END AS devIsNetworkNodeDynamic
|
||||
FROM Devices a
|
||||
FROM DevicesView a
|
||||
`;
|
||||
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ function renderNetworkTabContent(nodes) {
|
||||
const badge = getStatusBadgeParts(
|
||||
node.online,
|
||||
node.node_alert,
|
||||
node.node_flapping,
|
||||
node.node_mac
|
||||
);
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ function getChildren(node, list, path, visited = [])
|
||||
ip: node.devLastIP,
|
||||
status: node.devStatus,
|
||||
presentLastScan: node.devPresentLastScan,
|
||||
flapping: node.devFlapping,
|
||||
alertDown: node.devAlertDown,
|
||||
hasChildren: children.length > 0 || hiddenMacs.includes(node.devMac),
|
||||
relType: node.devParentRelType,
|
||||
@@ -266,7 +267,13 @@ function initTree(myHierarchy)
|
||||
<i class="fa-solid fa-hard-drive"></i>
|
||||
</span>` : "";
|
||||
|
||||
const badgeConf = getStatusBadgeParts(nodeData.data.presentLastScan, nodeData.data.alertDown, nodeData.data.mac, statusText = '')
|
||||
const badgeConf = getStatusBadgeParts(
|
||||
nodeData.data.presentLastScan,
|
||||
nodeData.data.alertDown,
|
||||
nodeData.data.flapping,
|
||||
nodeData.data.mac,
|
||||
statusText = ''
|
||||
);
|
||||
|
||||
return result = `<div
|
||||
class="node-inner hover-node-info box pointer ${highlightedCss} ${cssNodeType}"
|
||||
@@ -283,6 +290,7 @@ function initTree(myHierarchy)
|
||||
data-lastseen="${nodeData.data.lastseen}"
|
||||
data-firstseen="${nodeData.data.firstseen}"
|
||||
data-relationship="${nodeData.data.relType}"
|
||||
data-flapping="${nodeData.data.flapping}"
|
||||
data-status="${nodeData.data.status}"
|
||||
data-present="${nodeData.data.presentLastScan}"
|
||||
data-alert="${nodeData.data.alertDown}"
|
||||
|
||||
@@ -765,7 +765,8 @@ function getColumnNameFromLangString(headStringKey) {
|
||||
"Device_TableHead_ReqNicsOnline": "devReqNicsOnline",
|
||||
"Device_TableHead_Vlan": "devVlan",
|
||||
"Device_TableHead_IPv4": "devPrimaryIPv4",
|
||||
"Device_TableHead_IPv6": "devPrimaryIPv6"
|
||||
"Device_TableHead_IPv6": "devPrimaryIPv6",
|
||||
"Device_TableHead_Flapping": "devFlapping"
|
||||
};
|
||||
|
||||
return columnNameMap[headStringKey] || "";
|
||||
@@ -773,17 +774,25 @@ function getColumnNameFromLangString(headStringKey) {
|
||||
|
||||
//--------------------------------------------------------------
|
||||
// Generating the device status chip
|
||||
function getStatusBadgeParts(devPresentLastScan, devAlertDown, devMac, statusText = '') {
|
||||
function getStatusBadgeParts(devPresentLastScan, devAlertDown, devFlapping, devMac, statusText = '') {
|
||||
let css = 'bg-gray text-white statusUnknown';
|
||||
let icon = '<i class="fa-solid fa-question"></i>';
|
||||
let status = 'unknown';
|
||||
let cssText = '';
|
||||
|
||||
if (devPresentLastScan == 1) {
|
||||
console.log(devFlapping);
|
||||
|
||||
|
||||
if (devPresentLastScan == 1 && devFlapping == 0) {
|
||||
css = 'bg-green text-white statusOnline';
|
||||
cssText = 'text-green';
|
||||
icon = '<i class="fa-solid fa-plug"></i>';
|
||||
status = 'online';
|
||||
} else if (devPresentLastScan == 1 && devFlapping == 1) {
|
||||
css = 'bg-yellow text-white statusFlapping';
|
||||
cssText = 'text-yellow';
|
||||
icon = '<i class="fa-solid fa-plug-circle-exclamation"></i>';
|
||||
status = 'online';
|
||||
} else if (devAlertDown == 1) {
|
||||
css = 'bg-red text-white statusDown';
|
||||
cssText = 'text-red';
|
||||
@@ -958,6 +967,7 @@ function renderDeviceLink(data, container, useName = false) {
|
||||
const badge = getStatusBadgeParts(
|
||||
device.devPresentLastScan,
|
||||
device.devAlertDown,
|
||||
device.devFlapping,
|
||||
device.devMac
|
||||
);
|
||||
|
||||
@@ -974,6 +984,7 @@ function renderDeviceLink(data, container, useName = false) {
|
||||
'data-firstseen': device.devFirstConnection,
|
||||
'data-relationship': device.devParentRelType,
|
||||
'data-status': device.devStatus,
|
||||
'data-flapping': device.devFlapping,
|
||||
'data-present': device.devPresentLastScan,
|
||||
'data-alert': device.devAlertDown,
|
||||
'data-icon': device.devIcon
|
||||
@@ -1044,7 +1055,8 @@ function initHoverNodeInfo() {
|
||||
const lastseen = $el.data('lastseen') || 'Unknown';
|
||||
const firstseen = $el.data('firstseen') || 'Unknown';
|
||||
const relationship = $el.data('relationship') || 'Unknown';
|
||||
const badge = getStatusBadgeParts( $el.data('present'), $el.data('alert'), $el.data('mac'))
|
||||
const flapping = $el.data('flapping') || 0;
|
||||
const badge = getStatusBadgeParts( $el.data('present'), $el.data('alert'), flapping, $el.data('mac'))
|
||||
const status =`<span class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.status}</span>`
|
||||
|
||||
const html = `
|
||||
|
||||
Reference in New Issue
Block a user