diff --git a/front/css/app.css b/front/css/app.css index 74b404a5..a33e8d0b 100755 --- a/front/css/app.css +++ b/front/css/app.css @@ -1547,15 +1547,25 @@ input[readonly] { } +#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice a +{ + color: #FFF0E0; +} + +#deviceDetailsEdit .iconPreview svg +{ + height: 14px; +} + #deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice { - height: 30px; - background-color: #606060; + height: 20px; + background-color: #606060; } #deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice span { - font-size: 15px; + font-size: 14px; } #deviceDetailsEdit .select2-selection diff --git a/front/deviceDetailsEdit.php b/front/deviceDetailsEdit.php index c4d806b3..4c446db2 100755 --- a/front/deviceDetailsEdit.php +++ b/front/deviceDetailsEdit.php @@ -85,7 +85,7 @@ }, // Group for event and alert settings DevDetail_EveandAl_Title: { - data: ["devAlertEvents", "devAlertDown", "devSkipRepeated", "devReqNicsOnline"], + data: ["devAlertEvents", "devAlertDown", "devSkipRepeated", "devReqNicsOnline", "devChildrenNicsDynamic"], docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NOTIFICATIONS.md", iconClass: "fa fa-bell", inputGroupClasses: "field-group alert-group col-lg-4 col-sm-6 col-xs-12", @@ -218,8 +218,13 @@ `; } - // handle devChildrenDynamic - selected values and options are the same - if (setting.setKey == "NEWDEV_devChildrenDynamic" && Array.isArray(fieldData)) { + // handle devChildrenDynamic or NEWDEV_devChildrenNicsDynamic - selected values and options are the same + if ( + Array.isArray(fieldData) && + (setting.setKey == "NEWDEV_devChildrenDynamic" || + setting.setKey == "NEWDEV_devChildrenNicsDynamic" ) + ) + { fieldDataNew = [] fieldData.forEach(child => { fieldDataNew.push(child.devMac) @@ -383,7 +388,7 @@ mac: $('#NEWDEV_devMac').val(), name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "’")), owner: encodeURIComponent($('#NEWDEV_devOwner').val().replace(/'/g, "’")), - type: $('#NEWDEV_devType').val().replace(/'/g, ""), + type: $('#NEWDEV_devType').val().replace(/'/g, ""), vendor: encodeURIComponent($('#NEWDEV_devVendor').val().replace(/'/g, "’")), icon: encodeURIComponent($('#NEWDEV_devIcon').val()), favorite: ($('#NEWDEV_devFavorite')[0].checked * 1), @@ -399,6 +404,8 @@ alertevents: ($('#NEWDEV_devAlertEvents')[0].checked * 1), alertdown: ($('#NEWDEV_devAlertDown')[0].checked * 1), skiprepeated: $('#NEWDEV_devSkipRepeated').val().split(' ')[0], + relType: $('#NEWDEV_devParentRelType').val().replace(/'/g, ""), + reqNics: ($('#NEWDEV_devReqNicsOnline')[0].checked * 1), newdevice: ($('#NEWDEV_devIsNew')[0].checked * 1), archived: ($('#NEWDEV_devIsArchived')[0].checked * 1), devFirstConnection: ($('#NEWDEV_devFirstConnection').val()), diff --git a/front/devices.php b/front/devices.php index 91367ca9..0738ce29 100755 --- a/front/devices.php +++ b/front/devices.php @@ -899,14 +899,14 @@ function initializeDatatable (status) { tmp_devPresentLastScan = rowData[mapIndx(24)] tmp_devAlertDown = rowData[mapIndx(25)] - const badgeHtml = getStatusBadgeHtml( + const badge = getStatusBadgeParts( rowData[mapIndx(24)], // tmp_devPresentLastScan rowData[mapIndx(25)], // tmp_devAlertDown rowData[mapIndx(11)], // MAC cellData // optional text ); - $(td).html (badgeHtml); + $(td).html (`${badge.iconHtml} ${badge.text}`); } }, ], diff --git a/front/js/ui_components.js b/front/js/ui_components.js index d5f5b45e..d541fadc 100755 --- a/front/js/ui_components.js +++ b/front/js/ui_components.js @@ -609,25 +609,36 @@ function getColumnNameFromLangString(headStringKey) { } // Generating the device status chip -function getStatusBadgeHtml(tmp_devPresentLastScan, tmp_devAlertDown, macAddress, statusText = '') { - let css = 'gray text-white statusUnknown'; +function getStatusBadgeParts(tmp_devPresentLastScan, tmp_devAlertDown, macAddress, statusText = '') { + let css = 'bg-gray text-white statusUnknown'; let icon = ''; + let status = 'unknown'; if (tmp_devPresentLastScan == 1) { - css = 'green text-white statusOnline'; + css = 'bg-green text-white statusOnline'; icon = ''; + status = 'online'; } else if (tmp_devAlertDown == 1) { - css = 'red text-white statusDown'; + css = 'bg-red text-white statusDown'; icon = ''; + status = 'down'; } else if (tmp_devPresentLastScan != 1) { - css = 'gray text-white statusOffline'; + css = 'bg-gray text-white statusOffline'; icon = ''; + status = 'offline'; } - // Remove dashes from statusText const cleanedText = statusText.replace(/-/g, ''); + const url = `deviceDetails.php?mac=${encodeURIComponent(macAddress)}`; - return `${icon} ${cleanedText}`; + return { + cssClass: css, + iconHtml: icon, + mac: macAddress, + text: cleanedText, + status: status, + url: url + }; } @@ -651,35 +662,38 @@ function initSelect2() { $(function () { // Iterate over each Select2 dropdown - $('.select2').each(function() { - - + $('.select2').each(function() { + // handle Device chips, if my-transformers="deviceChip" if($(this).attr("my-transformers") == "deviceChip") { var selectEl = $(this).select2({ templateSelection: function (data, container) { if (!data.id) return data.text; // default for placeholder etc. + + const badge = getStatusBadgeParts( + getDevDataByMac(data.id, "devPresentLastScan"), + getDevDataByMac(data.id, "devAlertDown"), + data.id + ) + + $(container).addClass(badge.cssClass); + + + // Custom HTML const html = $(` - - ${atob(getDevDataByMac(data.id, "devIcon"))} - ${data.text} - - ${getStatusBadgeHtml( - getDevDataByMac(data.id, "devPresentLastScan"), - getDevDataByMac(data.id, "devAlertDown"), - data.id - )} - + + + ${atob(getDevDataByMac(data.id, "devIcon"))} + ${data.text} + + (${badge.iconHtml}) + + `); - - // Attach click listener (you can also use event delegation outside) - html.find('.chip-btn').on('click', function (e) { - // e.stopPropagation(); // prevent dropdown toggle - alert('Button clicked for ID: ' + data.id); - }); + return html; }, @@ -688,7 +702,7 @@ function initSelect2() { } }); - } else + } else // default handling - default template { var selectEl = $(this).select2(); } diff --git a/front/php/server/devices.php b/front/php/server/devices.php index cccebc93..3ba70519 100755 --- a/front/php/server/devices.php +++ b/front/php/server/devices.php @@ -92,6 +92,8 @@ function getServerDeviceData() { "devLogEvents" => 0, "devAlertEvents" => 0, "devAlertDown" => 0, + "devParentRelType" => "default", + "devReqNicsOnline" => 0, "devSkipRepeated" => 0, "devLastNotification" => "", "devPresentLastScan" => 0, @@ -113,9 +115,7 @@ function getServerDeviceData() { "devEvents" => 0, "devDownAlerts" => 0, "devPresenceHours" => 0, - "devFQDN" => "", - "devParentRelType" => "default", - "devReqNicsOnline" => 0 + "devFQDN" => "" ]; echo json_encode($deviceData); return; @@ -142,7 +142,7 @@ function getServerDeviceData() { $deviceData['devIsRandomMAC'] = isRandomMAC($mac); // devChildrenDynamic - $sql = 'SELECT rowid, * FROM Devices WHERE devParentMAC = "' . $mac . '"'; + $sql = 'SELECT rowid, * FROM Devices WHERE devParentMAC = "' . $mac . '" order by devPresentLastScan DESC'; $result = $db->query($sql); $children = []; @@ -153,6 +153,17 @@ function getServerDeviceData() { } $deviceData['devChildrenDynamic'] = $children; + // devChildrenNicsDynamic + $sql = 'SELECT rowid, * FROM Devices WHERE devParentMAC = "' . $mac . '" and devParentRelType = "nic" order by devPresentLastScan DESC'; + $result = $db->query($sql); + + $childrenNics = []; + if ($result) { + while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $childrenNics[] = $row; + } + } + $deviceData['devChildrenNicsDynamic'] = $childrenNics; // Count Totals $condition = ' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate; @@ -226,6 +237,8 @@ function setDeviceData() { $scancycle = quotes($_POST['scancycle']); $alertevents = quotes($_POST['alertevents']); $alertdown = quotes($_POST['alertdown']); + $relType = quotes($_POST['relType']); + $reqNics = quotes($_POST['reqNics']); $skiprepeated = quotes($_POST['skiprepeated']); $newdevice = quotes($_POST['newdevice']); $archived = quotes($_POST['archived']); @@ -257,6 +270,8 @@ function setDeviceData() { devScan = '$scancycle', devAlertEvents = '$alertevents', devAlertDown = '$alertdown', + devParentRelType = '$relType', + devReqNicsOnline = '$reqNics', devSkipRepeated = '$skiprepeated', devIsNew = '$newdevice', devIsArchived = '$archived', @@ -282,6 +297,8 @@ function setDeviceData() { devScan, devAlertEvents, devAlertDown, + devParentRelType, + devReqNicsOnline, devSkipRepeated, devIsNew, devIsArchived, @@ -310,6 +327,8 @@ function setDeviceData() { '$scancycle', '$alertevents', '$alertdown', + '$relType', + '$reqNics', '$skiprepeated', '$newdevice', '$archived', diff --git a/front/plugins/_publisher_ntfy/config.json b/front/plugins/_publisher_ntfy/config.json index 28cfdfc3..317300cc 100755 --- a/front/plugins/_publisher_ntfy/config.json +++ b/front/plugins/_publisher_ntfy/config.json @@ -540,7 +540,7 @@ } ] }, - "default_value": false, + "default_value": true, "options": [], "localized": ["name", "description"], "name": [ diff --git a/front/plugins/newdev_template/config.json b/front/plugins/newdev_template/config.json index 3988e105..e7de1534 100755 --- a/front/plugins/newdev_template/config.json +++ b/front/plugins/newdev_template/config.json @@ -1758,6 +1758,34 @@ "string": "Indicates whether this device should be considered online only if all associated NICs (devices with the nic relationship type) are online. If disabled, the device is considered online if any NIC is online." } ] + }, + { + "function": "devChildrenNicsDynamic", + "type": { + "dataType": "array", + "elements": [ + { + "elementType": "select", + "elementOptions": [{ "multiple": "true", "ordeable": "true", "readonly": "true" }], + "transformers": ["deviceChip"] + } + ] + }, + "default_value": [], + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "NICs" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Children nodes with the nic Relationship Type. Navigate to the child device directly to edit the relationship and details." + } + ] } ], "required": [],