nics work 724
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run

This commit is contained in:
jokob-sk
2025-07-13 09:02:21 +10:00
parent 0e53aef9ea
commit 393c3fd3b6
7 changed files with 120 additions and 42 deletions

View File

@@ -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 #deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice
{ {
height: 30px; height: 20px;
background-color: #606060; background-color: #606060;
} }
#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice span #deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice span
{ {
font-size: 15px; font-size: 14px;
} }
#deviceDetailsEdit .select2-selection #deviceDetailsEdit .select2-selection

View File

@@ -85,7 +85,7 @@
}, },
// Group for event and alert settings // Group for event and alert settings
DevDetail_EveandAl_Title: { 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", docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NOTIFICATIONS.md",
iconClass: "fa fa-bell", iconClass: "fa fa-bell",
inputGroupClasses: "field-group alert-group col-lg-4 col-sm-6 col-xs-12", inputGroupClasses: "field-group alert-group col-lg-4 col-sm-6 col-xs-12",
@@ -218,8 +218,13 @@
</span>`; </span>`;
} }
// handle devChildrenDynamic - selected values and options are the same // handle devChildrenDynamic or NEWDEV_devChildrenNicsDynamic - selected values and options are the same
if (setting.setKey == "NEWDEV_devChildrenDynamic" && Array.isArray(fieldData)) { if (
Array.isArray(fieldData) &&
(setting.setKey == "NEWDEV_devChildrenDynamic" ||
setting.setKey == "NEWDEV_devChildrenNicsDynamic" )
)
{
fieldDataNew = [] fieldDataNew = []
fieldData.forEach(child => { fieldData.forEach(child => {
fieldDataNew.push(child.devMac) fieldDataNew.push(child.devMac)
@@ -383,7 +388,7 @@
mac: $('#NEWDEV_devMac').val(), mac: $('#NEWDEV_devMac').val(),
name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "")), name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "")),
owner: encodeURIComponent($('#NEWDEV_devOwner').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, "")), vendor: encodeURIComponent($('#NEWDEV_devVendor').val().replace(/'/g, "")),
icon: encodeURIComponent($('#NEWDEV_devIcon').val()), icon: encodeURIComponent($('#NEWDEV_devIcon').val()),
favorite: ($('#NEWDEV_devFavorite')[0].checked * 1), favorite: ($('#NEWDEV_devFavorite')[0].checked * 1),
@@ -399,6 +404,8 @@
alertevents: ($('#NEWDEV_devAlertEvents')[0].checked * 1), alertevents: ($('#NEWDEV_devAlertEvents')[0].checked * 1),
alertdown: ($('#NEWDEV_devAlertDown')[0].checked * 1), alertdown: ($('#NEWDEV_devAlertDown')[0].checked * 1),
skiprepeated: $('#NEWDEV_devSkipRepeated').val().split(' ')[0], skiprepeated: $('#NEWDEV_devSkipRepeated').val().split(' ')[0],
relType: $('#NEWDEV_devParentRelType').val().replace(/'/g, ""),
reqNics: ($('#NEWDEV_devReqNicsOnline')[0].checked * 1),
newdevice: ($('#NEWDEV_devIsNew')[0].checked * 1), newdevice: ($('#NEWDEV_devIsNew')[0].checked * 1),
archived: ($('#NEWDEV_devIsArchived')[0].checked * 1), archived: ($('#NEWDEV_devIsArchived')[0].checked * 1),
devFirstConnection: ($('#NEWDEV_devFirstConnection').val()), devFirstConnection: ($('#NEWDEV_devFirstConnection').val()),

View File

@@ -899,14 +899,14 @@ function initializeDatatable (status) {
tmp_devPresentLastScan = rowData[mapIndx(24)] tmp_devPresentLastScan = rowData[mapIndx(24)]
tmp_devAlertDown = rowData[mapIndx(25)] tmp_devAlertDown = rowData[mapIndx(25)]
const badgeHtml = getStatusBadgeHtml( const badge = getStatusBadgeParts(
rowData[mapIndx(24)], // tmp_devPresentLastScan rowData[mapIndx(24)], // tmp_devPresentLastScan
rowData[mapIndx(25)], // tmp_devAlertDown rowData[mapIndx(25)], // tmp_devAlertDown
rowData[mapIndx(11)], // MAC rowData[mapIndx(11)], // MAC
cellData // optional text cellData // optional text
); );
$(td).html (badgeHtml); $(td).html (`<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.text}</a>`);
} }, } },
], ],

View File

@@ -609,25 +609,36 @@ function getColumnNameFromLangString(headStringKey) {
} }
// Generating the device status chip // Generating the device status chip
function getStatusBadgeHtml(tmp_devPresentLastScan, tmp_devAlertDown, macAddress, statusText = '') { function getStatusBadgeParts(tmp_devPresentLastScan, tmp_devAlertDown, macAddress, statusText = '') {
let css = 'gray text-white statusUnknown'; let css = 'bg-gray text-white statusUnknown';
let icon = '<i class="fa-solid fa-question"></i>'; let icon = '<i class="fa-solid fa-question"></i>';
let status = 'unknown';
if (tmp_devPresentLastScan == 1) { if (tmp_devPresentLastScan == 1) {
css = 'green text-white statusOnline'; css = 'bg-green text-white statusOnline';
icon = '<i class="fa-solid fa-plug"></i>'; icon = '<i class="fa-solid fa-plug"></i>';
status = 'online';
} else if (tmp_devAlertDown == 1) { } else if (tmp_devAlertDown == 1) {
css = 'red text-white statusDown'; css = 'bg-red text-white statusDown';
icon = '<i class="fa-solid fa-triangle-exclamation"></i>'; icon = '<i class="fa-solid fa-triangle-exclamation"></i>';
status = 'down';
} else if (tmp_devPresentLastScan != 1) { } else if (tmp_devPresentLastScan != 1) {
css = 'gray text-white statusOffline'; css = 'bg-gray text-white statusOffline';
icon = '<i class="fa-solid fa-xmark"></i>'; icon = '<i class="fa-solid fa-xmark"></i>';
status = 'offline';
} }
// Remove dashes from statusText
const cleanedText = statusText.replace(/-/g, ''); const cleanedText = statusText.replace(/-/g, '');
const url = `deviceDetails.php?mac=${encodeURIComponent(macAddress)}`;
return `<a href="deviceDetails.php?mac=${macAddress}" class="badge bg-${css}">${icon} ${cleanedText}</a>`; return {
cssClass: css,
iconHtml: icon,
mac: macAddress,
text: cleanedText,
status: status,
url: url
};
} }
@@ -651,35 +662,38 @@ function initSelect2() {
$(function () { $(function () {
// Iterate over each Select2 dropdown // Iterate over each Select2 dropdown
$('.select2').each(function() { $('.select2').each(function() {
// handle Device chips, if my-transformers="deviceChip"
if($(this).attr("my-transformers") == "deviceChip") if($(this).attr("my-transformers") == "deviceChip")
{ {
var selectEl = $(this).select2({ var selectEl = $(this).select2({
templateSelection: function (data, container) { templateSelection: function (data, container) {
if (!data.id) return data.text; // default for placeholder etc. 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 // Custom HTML
const html = $(` const html = $(`
<span class="custom-chip"> <a href="${badge.url}" target="_blank">
<span class="iconPreview">${atob(getDevDataByMac(data.id, "devIcon"))}</span> <span class="custom-chip" >
${data.text} <span class="iconPreview">${atob(getDevDataByMac(data.id, "devIcon"))}</span>
<span> ${data.text}
${getStatusBadgeHtml( <span>
getDevDataByMac(data.id, "devPresentLastScan"), (${badge.iconHtml})
getDevDataByMac(data.id, "devAlertDown"), </span
data.id </span>
)} </a>
</span
</span>
`); `);
// 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; return html;
}, },
@@ -688,7 +702,7 @@ function initSelect2() {
} }
}); });
} else } else // default handling - default template
{ {
var selectEl = $(this).select2(); var selectEl = $(this).select2();
} }

View File

@@ -92,6 +92,8 @@ function getServerDeviceData() {
"devLogEvents" => 0, "devLogEvents" => 0,
"devAlertEvents" => 0, "devAlertEvents" => 0,
"devAlertDown" => 0, "devAlertDown" => 0,
"devParentRelType" => "default",
"devReqNicsOnline" => 0,
"devSkipRepeated" => 0, "devSkipRepeated" => 0,
"devLastNotification" => "", "devLastNotification" => "",
"devPresentLastScan" => 0, "devPresentLastScan" => 0,
@@ -113,9 +115,7 @@ function getServerDeviceData() {
"devEvents" => 0, "devEvents" => 0,
"devDownAlerts" => 0, "devDownAlerts" => 0,
"devPresenceHours" => 0, "devPresenceHours" => 0,
"devFQDN" => "", "devFQDN" => ""
"devParentRelType" => "default",
"devReqNicsOnline" => 0
]; ];
echo json_encode($deviceData); echo json_encode($deviceData);
return; return;
@@ -142,7 +142,7 @@ function getServerDeviceData() {
$deviceData['devIsRandomMAC'] = isRandomMAC($mac); $deviceData['devIsRandomMAC'] = isRandomMAC($mac);
// devChildrenDynamic // 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); $result = $db->query($sql);
$children = []; $children = [];
@@ -153,6 +153,17 @@ function getServerDeviceData() {
} }
$deviceData['devChildrenDynamic'] = $children; $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 // Count Totals
$condition = ' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate; $condition = ' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate;
@@ -226,6 +237,8 @@ function setDeviceData() {
$scancycle = quotes($_POST['scancycle']); $scancycle = quotes($_POST['scancycle']);
$alertevents = quotes($_POST['alertevents']); $alertevents = quotes($_POST['alertevents']);
$alertdown = quotes($_POST['alertdown']); $alertdown = quotes($_POST['alertdown']);
$relType = quotes($_POST['relType']);
$reqNics = quotes($_POST['reqNics']);
$skiprepeated = quotes($_POST['skiprepeated']); $skiprepeated = quotes($_POST['skiprepeated']);
$newdevice = quotes($_POST['newdevice']); $newdevice = quotes($_POST['newdevice']);
$archived = quotes($_POST['archived']); $archived = quotes($_POST['archived']);
@@ -257,6 +270,8 @@ function setDeviceData() {
devScan = '$scancycle', devScan = '$scancycle',
devAlertEvents = '$alertevents', devAlertEvents = '$alertevents',
devAlertDown = '$alertdown', devAlertDown = '$alertdown',
devParentRelType = '$relType',
devReqNicsOnline = '$reqNics',
devSkipRepeated = '$skiprepeated', devSkipRepeated = '$skiprepeated',
devIsNew = '$newdevice', devIsNew = '$newdevice',
devIsArchived = '$archived', devIsArchived = '$archived',
@@ -282,6 +297,8 @@ function setDeviceData() {
devScan, devScan,
devAlertEvents, devAlertEvents,
devAlertDown, devAlertDown,
devParentRelType,
devReqNicsOnline,
devSkipRepeated, devSkipRepeated,
devIsNew, devIsNew,
devIsArchived, devIsArchived,
@@ -310,6 +327,8 @@ function setDeviceData() {
'$scancycle', '$scancycle',
'$alertevents', '$alertevents',
'$alertdown', '$alertdown',
'$relType',
'$reqNics',
'$skiprepeated', '$skiprepeated',
'$newdevice', '$newdevice',
'$archived', '$archived',

View File

@@ -540,7 +540,7 @@
} }
] ]
}, },
"default_value": false, "default_value": true,
"options": [], "options": [],
"localized": ["name", "description"], "localized": ["name", "description"],
"name": [ "name": [

View File

@@ -1758,6 +1758,34 @@
"string": "Indicates whether this device should be considered online only if all associated NICs (devices with the <code>nic</code> relationship type) are online. If disabled, the device is considered online if any NIC is online." "string": "Indicates whether this device should be considered online only if all associated NICs (devices with the <code>nic</code> 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 <code>nic</code> Relationship Type. Navigate to the child device directly to edit the relationship and details."
}
]
} }
], ],
"required": [], "required": [],