Refactor network tree data structure and improve device status handling

- Updated the network tree data structure to use consistent naming conventions for device properties (e.g., devName, devMac).
- Enhanced the initTree function to utilize the new property names and improved the rendering of device nodes.
- Refactored the getStatusBadgeParts function to include additional parameters for archived and new device statuses.
- Introduced convenience functions (badgeFromDevice and badgeFromDataAttrs) to streamline badge generation from device objects and data attributes.
- Updated various language files to include new status labels and ensure consistency across translations.
- Modified the renderSmallBox function to allow for custom icon HTML, improving flexibility in UI components.
This commit is contained in:
Jokob @NetAlertX
2026-03-02 09:35:42 +00:00
parent 3e237bb452
commit 6724d250d4
28 changed files with 280 additions and 156 deletions

View File

@@ -425,17 +425,22 @@ async function renderSmallBoxes() {
const deviceData = await response.json();
// Derive status card appearance from shared getStatusBadgeParts —
// ensures icon, color, label and lang key are always in sync with the rest of the UI.
const statusBadge = badgeFromDevice(deviceData);
const statusText = statusBadge.label;
// Prepare custom data
const customData = [
{
"onclickEvent": "$('#tabDetails').trigger('click')",
"color": "bg-aqua",
"color": statusBadge.cssClass,
"headerId": "deviceStatus",
"headerStyle": "margin-left: 0em",
"labelLang": "DevDetail_Shortcut_CurrentStatus",
"iconId": "deviceStatusIcon",
"iconClass": deviceData.devPresentLastScan == 1 ? "fa fa-check text-green" : "fa fa-xmark text-red",
"dataValue": deviceData.devPresentLastScan == 1 ? getString("Gen_Online") : getString("Gen_Offline")
"iconHtml": statusBadge.iconHtml,
"dataValue": statusText
},
{
"onclickEvent": "$('#tabSessions').trigger('click');",

View File

@@ -520,6 +520,22 @@ function mapColumnIndexToFieldName(index, tableColumnVisible) {
}
// ---------------------------------------------------------
// Status badge helper for DataTables rowData (positional array).
// Uses mapIndx(COL.*) for reordered display fields and COL_EXTRA.* for extra fields.
function badgeFromRowData(rowData) {
return getStatusBadgeParts(
rowData[mapIndx(COL.devPresentLastScan)],
rowData[mapIndx(COL.devAlertDown)],
rowData[mapIndx(COL.devFlapping)],
rowData[mapIndx(COL.devMac)],
'',
rowData[COL_EXTRA.devIsSleeping] || 0,
rowData[COL_EXTRA.devIsArchived] || 0,
rowData[COL_EXTRA.devIsNew] || 0
);
}
// ---------------------------------------------------------
// Initializes the main devices list datatable
function initializeDatatable (status) {
@@ -657,6 +673,11 @@ function initializeDatatable (status) {
for (let index = 0; index < tableColumnOrder.length; index++) {
newRow.push(originalRow[tableColumnOrder[index]]);
}
// Append extra (non-display) fields after the display columns so
// they are accessible in createdCell via COL_EXTRA.*
GRAPHQL_EXTRA_FIELDS.forEach(field => {
newRow.push(device[field] ?? (NUMERIC_DEFAULTS.has(field) ? 0 : ""));
});
return newRow;
});
}
@@ -717,8 +738,11 @@ function initializeDatatable (status) {
data-relationship="${rowData[mapIndx(COL.devParentRelType)]}"
data-status="${rowData[mapIndx(COL.devStatus)]}"
data-present="${rowData[mapIndx(COL.devPresentLastScan)]}"
data-alert="${rowData[mapIndx(COL.devAlertDown)]}"
data-alertdown="${rowData[mapIndx(COL.devAlertDown)]}"
data-flapping="${rowData[mapIndx(COL.devFlapping)]}"
data-sleeping="${rowData[COL_EXTRA.devIsSleeping] || 0}"
data-archived="${rowData[COL_EXTRA.devIsArchived] || 0}"
data-isnew="${rowData[COL_EXTRA.devIsNew] || 0}"
data-icon="${rowData[mapIndx(COL.devIcon)]}">
${displayedValue}
</a>
@@ -860,20 +884,9 @@ function initializeDatatable (status) {
{targets: [mapIndx(COL.devStatus)],
'createdCell': function (td, cellData, rowData, row, col) {
tmp_devPresentLastScan = rowData[mapIndx(COL.devPresentLastScan)]
tmp_devAlertDown = rowData[mapIndx(COL.devAlertDown)]
tmp_devMac = rowData[mapIndx(COL.devMac)]
tmp_devFlapping = rowData[mapIndx(COL.devFlapping)]
const badge = badgeFromRowData(rowData);
const badge = getStatusBadgeParts(
tmp_devPresentLastScan, // tmp_devPresentLastScan
tmp_devAlertDown, // tmp_devAlertDown
tmp_devFlapping, // tmp_devFlapping
tmp_devMac, // MAC
cellData // optional text
);
$(td).html (`<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.text}</a>`);
$(td).html(`<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.label}</a>`);
} },
],

View File

@@ -75,8 +75,17 @@ const GRAPHQL_EXTRA_FIELDS = [
"devLastNotification",
"devIsNew",
"devIsArchived",
"devIsSleeping",
];
// Row positions for extra (non-display) fields.
// In dataSrc, extra fields are appended AFTER the display columns in each row,
// so their position = DEVICE_COLUMN_FIELDS.length + their index in GRAPHQL_EXTRA_FIELDS.
// Use COL_EXTRA.fieldName to access them in createdCell rowData.
const COL_EXTRA = Object.fromEntries(
GRAPHQL_EXTRA_FIELDS.map((name, i) => [name, DEVICE_COLUMN_FIELDS.length + i])
);
// Maps Device_TableHead_* language keys to their GraphQL/DB field names.
// Used by getColumnNameFromLangString() in ui_components.js and by
// column filter logic in devices.php.

View File

@@ -16,15 +16,16 @@ function loadNetworkNodes() {
// PC (leaf) <------- leafs are not included in this SQL query
const rawSql = `
SELECT
parent.devName AS node_name,
LOWER(parent.devMac) AS node_mac,
parent.devPresentLastScan AS online,
parent.devType AS node_type,
LOWER(parent.devParentMAC) AS parent_mac,
parent.devIcon AS node_icon,
parent.devAlertDown AS node_alert,
parent.devFlapping AS node_flapping,
parent.devIsSleeping AS node_sleeping,
parent.devName,
LOWER(parent.devMac) AS devMac,
parent.devPresentLastScan,
parent.devType,
LOWER(parent.devParentMAC) AS devParentMAC,
parent.devIcon,
parent.devAlertDown,
parent.devFlapping,
parent.devIsSleeping,
parent.devIsNew,
COUNT(child.devMac) AS node_ports_count
FROM DevicesView AS parent
LEFT JOIN DevicesView AS child
@@ -35,7 +36,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.devFlapping, parent.devIsSleeping
parent.devType, parent.devParentMAC, parent.devIcon, parent.devAlertDown, parent.devFlapping, parent.devIsSleeping, parent.devIsNew
ORDER BY parent.devName;
`;
@@ -142,15 +143,8 @@ function loadDeviceTable({ sql, containerSelector, tableId, wrapperHtml = null,
data: 'devStatus',
width: '15%',
render: function (_, type, device) {
const badge = getStatusBadgeParts(
device.devPresentLastScan,
device.devAlertDown,
device.devFlapping,
device.devMac,
device.devStatus,
device.devIsSleeping || 0
);
return `<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.text}</a>`;
const badge = badgeFromDevice(device);
return `<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.label}</a>`;
}
},
{
@@ -206,7 +200,7 @@ function loadDeviceTable({ sql, containerSelector, tableId, wrapperHtml = null,
*/
function loadUnassignedDevices() {
const sql = `
SELECT devMac, devPresentLastScan, devName, devLastIP, devVendor, devAlertDown, devParentPort, devFlapping, devIsSleeping, devStatus
SELECT devMac, devPresentLastScan, devName, devLastIP, devVendor, devAlertDown, devParentPort, devFlapping, devIsSleeping, devIsNew, devStatus
FROM DevicesView
WHERE (devParentMAC IS NULL OR devParentMAC IN ("", " ", "undefined", "null"))
AND LOWER(devMac) NOT LIKE "%internet%"
@@ -241,7 +235,7 @@ function loadConnectedDevices(node_mac) {
const normalized_mac = node_mac.toLowerCase();
const sql = `
SELECT devName, devMac, devLastIP, devVendor, devPresentLastScan, devAlertDown, devParentPort, devVlan, devFlapping, devIsSleeping,
SELECT devName, devMac, devLastIP, devVendor, devPresentLastScan, devAlertDown, devParentPort, devVlan, devFlapping, devIsSleeping, devIsNew, devIsArchived,
CASE
WHEN devIsNew = 1 THEN 'New'
WHEN devPresentLastScan = 1 THEN 'On-line'

View File

@@ -8,19 +8,19 @@
function renderNetworkTabs(nodes) {
let html = '';
nodes.forEach((node, i) => {
const iconClass = node.online == 1 ? "text-green" :
(node.node_sleeping == 1 ? "text-aqua" :
(node.node_alert == 1 ? "text-red" : "text-gray50"));
const iconClass = node.devPresentLastScan == 1 ? "text-green" :
(node.devIsSleeping == 1 ? "text-aqua" :
(node.devAlertDown == 1 ? "text-red" : "text-gray50"));
const portLabel = node.node_ports_count ? ` (${node.node_ports_count})` : '';
const icon = atob(node.node_icon);
const id = node.node_mac.replace(/:/g, '_');
const icon = atob(node.devIcon);
const id = node.devMac.replace(/:/g, '_');
html += `
<li class="networkNodeTabHeaders ${i === 0 ? 'active' : ''}">
<a href="#${id}" data-mytabmac="${node.node_mac}" id="${id}_id" data-toggle="tab" title="${node.node_name}">
<a href="#${id}" data-mytabmac="${node.devMac}" id="${id}_id" data-toggle="tab" title="${node.devName}">
<div class="icon ${iconClass}">${icon}</div>
<span class="node-name">${node.node_name}</span>${portLabel}
<span class="node-name">${node.devName}</span>${portLabel}
</a>
</li>`;
});
@@ -50,21 +50,14 @@ function renderNetworkTabContent(nodes) {
$('.tab-content').empty();
nodes.forEach((node, i) => {
const id = node.node_mac.replace(/:/g, '_').toLowerCase();
const id = node.devMac.replace(/:/g, '_').toLowerCase();
const badge = getStatusBadgeParts(
node.online,
node.node_alert,
node.node_flapping,
node.node_mac,
'',
node.node_sleeping || 0
);
const badge = badgeFromDevice(node);
const badgeHtml = `<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.status}</a>`;
const parentId = node.parent_mac.replace(/:/g, '_');
const badgeHtml = `<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.label}</a>`;
const parentId = node.devParentMAC.replace(/:/g, '_');
isRootNode = node.parent_mac == "";
isRootNode = node.devParentMAC == "";
const paneHtml = `
<div class="tab-pane box box-aqua box-body ${i === 0 ? 'active' : ''}" id="${id}">
@@ -73,18 +66,18 @@ function renderNetworkTabContent(nodes) {
<div class="mb-3 row">
<label class="col-sm-3 col-form-label fw-bold">${getString('DevDetail_Tab_Details')}</label>
<div class="col-sm-9">
<a href="./deviceDetails.php?mac=${node.node_mac}" target="_blank" class="anonymize">${node.node_name}</a>
<a href="./deviceDetails.php?mac=${node.devMac}" target="_blank" class="anonymize">${node.devName}</a>
</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label fw-bold">MAC</label>
<div class="col-sm-9 anonymize">${node.node_mac}</div>
<div class="col-sm-9 anonymize">${node.devMac}</div>
</div>
<div class="mb-3 row">
<label class="col-sm-3 col-form-label fw-bold">${getString('Device_TableHead_Type')}</label>
<div class="col-sm-9">${node.node_type}</div>
<div class="col-sm-9">${node.devType}</div>
</div>
<div class="mb-3 row">
@@ -96,8 +89,8 @@ function renderNetworkTabContent(nodes) {
<label class="col-sm-3 col-form-label fw-bold">${getString('Network_Parent')}</label>
<div class="col-sm-9">
${isRootNode ? '' : `<a class="anonymize" href="#">`}
<span my-data-mac="${node.parent_mac}" data-mac="${node.parent_mac}" data-devIsNetworkNodeDynamic="1" onclick="handleNodeClick(this)">
${isRootNode ? getString('Network_Root') : getDevDataByMac(node.parent_mac, "devName")}
<span my-data-mac="${node.devParentMAC}" data-mac="${node.devParentMAC}" data-devIsNetworkNodeDynamic="1" onclick="handleNodeClick(this)">
${isRootNode ? getString('Network_Root') : getDevDataByMac(node.devParentMAC, "devName")}
</span>
${isRootNode ? '' : `</a>`}
</div>
@@ -115,7 +108,7 @@ function renderNetworkTabContent(nodes) {
`;
$('.tab-content').append(paneHtml);
loadConnectedDevices(node.node_mac);
loadConnectedDevices(node.devMac);
});
}

View File

@@ -57,26 +57,28 @@ function getChildren(node, list, path, visited = [])
// console.log(node);
return {
name: node.devName,
devName: node.devName,
path: path,
mac: node.devMac,
port: node.devParentPort,
devMac: node.devMac,
devParentPort: node.devParentPort,
id: node.devMac,
parentMac: node.devParentMAC,
icon: node.devIcon,
type: node.devType,
devParentMAC: node.devParentMAC,
devIcon: node.devIcon,
devType: node.devType,
devIsNetworkNodeDynamic: node.devIsNetworkNodeDynamic,
vendor: node.devVendor,
lastseen: node.devLastConnection,
firstseen: node.devFirstConnection,
ip: node.devLastIP,
status: node.devStatus,
presentLastScan: node.devPresentLastScan,
flapping: node.devFlapping,
alertDown: node.devAlertDown,
sleeping: node.devIsSleeping || 0,
devVendor: node.devVendor,
devLastConnection: node.devLastConnection,
devFirstConnection: node.devFirstConnection,
devLastIP: node.devLastIP,
devStatus: node.devStatus,
devPresentLastScan: node.devPresentLastScan,
devFlapping: node.devFlapping,
devAlertDown: node.devAlertDown,
devIsSleeping: node.devIsSleeping || 0,
devIsArchived: node.devIsArchived || 0,
devIsNew: node.devIsNew || 0,
hasChildren: children.length > 0 || hiddenMacs.includes(node.devMac),
relType: node.devParentRelType,
devParentRelType: node.devParentRelType,
devVlan: node.devVlan,
devSSID: node.devSSID,
hiddenChildren: hiddenMacs.includes(node.devMac),
@@ -227,16 +229,16 @@ function initTree(myHierarchy)
htmlId: "networkTree",
renderNode: nodeData => {
(!emptyArr.includes(nodeData.data.port )) ? port = nodeData.data.port : port = "";
(!emptyArr.includes(nodeData.data.devParentPort)) ? port = nodeData.data.devParentPort : port = "";
(port == "" || port == 0 || port == 'None' ) ? portBckgIcon = `<i class="fa fa-wifi"></i>` : portBckgIcon = `<i class="fa fa-ethernet"></i>`;
portHtml = (port == "" || port == 0 || port == 'None' ) ? " &nbsp " : port;
// Build HTML for individual nodes in the network diagram
deviceIcon = (!emptyArr.includes(nodeData.data.icon )) ?
deviceIcon = (!emptyArr.includes(nodeData.data.devIcon)) ?
`<div class="netIcon">
${atob(nodeData.data.icon)}
${atob(nodeData.data.devIcon)}
</div>` : "";
devicePort = `<div class="netPort"
style="width:${emSize}em;height:${emSize}em">
@@ -253,13 +255,13 @@ function initTree(myHierarchy)
`<div class="netCollapse"
style="font-size:${nodeHeightPx/2}px;top:${Math.floor(nodeHeightPx / 4)}px"
data-mytreepath="${nodeData.data.path}"
data-mytreemac="${nodeData.data.mac}">
data-mytreemac="${nodeData.data.devMac}">
<i class="fa fa-${collapseExpandIcon} pointer"></i>
</div>` : "";
selectedNodeMac = $(".nav-tabs-custom .active a").attr('data-mytabmac')
highlightedCss = nodeData.data.mac == selectedNodeMac ?
highlightedCss = nodeData.data.devMac == selectedNodeMac ?
" highlightedNode " : "";
cssNodeType = nodeData.data.devIsNetworkNodeDynamic ?
" node-network-device " : " node-standard-device ";
@@ -268,40 +270,35 @@ function initTree(myHierarchy)
<i class="fa-solid fa-hard-drive"></i>
</span>` : "";
const badgeConf = getStatusBadgeParts(
nodeData.data.presentLastScan,
nodeData.data.alertDown,
nodeData.data.flapping,
nodeData.data.mac,
'',
nodeData.data.sleeping || 0
);
const badgeConf = badgeFromDevice(nodeData.data);
return result = `<div
class="node-inner hover-node-info box pointer ${highlightedCss} ${cssNodeType}"
style="height:${nodeHeightPx}px;font-size:${nodeHeightPx-5}px;"
onclick="handleNodeClick(this)"
data-mac="${nodeData.data.mac}"
data-parentMac="${nodeData.data.parentMac}"
data-name="${nodeData.data.name}"
data-ip="${nodeData.data.ip}"
data-mac="${nodeData.data.mac}"
data-vendor="${nodeData.data.vendor}"
data-type="${nodeData.data.type}"
data-mac="${nodeData.data.devMac}"
data-parentMac="${nodeData.data.devParentMAC}"
data-name="${nodeData.data.devName}"
data-ip="${nodeData.data.devLastIP}"
data-mac="${nodeData.data.devMac}"
data-vendor="${nodeData.data.devVendor}"
data-type="${nodeData.data.devType}"
data-devIsNetworkNodeDynamic="${nodeData.data.devIsNetworkNodeDynamic}"
data-lastseen="${nodeData.data.lastseen}"
data-firstseen="${nodeData.data.firstseen}"
data-relationship="${nodeData.data.relType}"
data-flapping="${nodeData.data.flapping}"
data-sleeping="${nodeData.data.sleeping || 0}"
data-status="${nodeData.data.status}"
data-present="${nodeData.data.presentLastScan}"
data-alert="${nodeData.data.alertDown}"
data-icon="${nodeData.data.icon}"
data-lastseen="${nodeData.data.devLastConnection}"
data-firstseen="${nodeData.data.devFirstConnection}"
data-relationship="${nodeData.data.devParentRelType}"
data-flapping="${nodeData.data.devFlapping}"
data-sleeping="${nodeData.data.devIsSleeping || 0}"
data-archived="${nodeData.data.devIsArchived || 0}"
data-isnew="${nodeData.data.devIsNew || 0}"
data-status="${nodeData.data.devStatus}"
data-present="${nodeData.data.devPresentLastScan}"
data-alertdown="${nodeData.data.devAlertDown}"
data-icon="${nodeData.data.devIcon}"
>
<div class="netNodeText">
<strong><span>${devicePort} <span class="${badgeConf.cssText}">${deviceIcon}</span></span>
<span class="spanNetworkTree anonymizeDev" style="width:${nodeWidthPx-50}px">${nodeData.data.name}</span>
<span class="spanNetworkTree anonymizeDev" style="width:${nodeWidthPx-50}px">${nodeData.data.devName}</span>
${networkHardwareIcon}
</strong>
</div>
@@ -318,7 +315,7 @@ function initTree(myHierarchy)
hasPan: true,
marginLeft: '10',
marginRight: '10',
idKey: "mac",
idKey: "devMac",
hasFlatData: false,
relationnalField: "children",
linkLabel: {
@@ -339,7 +336,7 @@ function initTree(myHierarchy)
},
linkWidth: (nodeData) => 2,
linkColor: (nodeData) => {
relConf = getRelationshipConf(nodeData.data.relType)
relConf = getRelationshipConf(nodeData.data.devParentRelType)
return relConf.color;
}
// onNodeClick: (nodeData) => handleNodeClick(nodeData),

View File

@@ -738,37 +738,54 @@ function getColumnNameFromLangString(headStringKey) {
//--------------------------------------------------------------
// Generating the device status chip
function getStatusBadgeParts(devPresentLastScan, devAlertDown, devFlapping, devMac, statusText = '', devIsSleeping = 0) {
let css = 'bg-gray text-white statusUnknown';
let icon = '<i class="fa-solid fa-question"></i>';
let status = 'unknown';
function getStatusBadgeParts(devPresentLastScan, devAlertDown, devFlapping, devMac, statusText = '', devIsSleeping = 0, devIsArchived = 0, devIsNew = 0) {
let css = 'bg-gray text-white statusUnknown';
let icon = '<i class="fa-solid fa-question"></i>';
let status = 'unknown';
let cssText = '';
let label = getString('Gen_Offline');
if (devPresentLastScan == 1 && devFlapping == 0) {
css = 'bg-green text-white statusOnline';
css = 'bg-green text-white statusOnline';
cssText = 'text-green';
icon = '<i class="fa-solid fa-plug"></i>';
status = 'online';
icon = '<i class="fa-solid fa-plug"></i>';
status = 'online';
label = getString('Gen_Online');
} else if (devPresentLastScan == 1 && devFlapping == 1) {
css = 'bg-yellow text-white statusFlapping';
css = 'bg-yellow text-white statusFlapping';
cssText = 'text-yellow';
icon = '<i class="fa-solid fa-plug-circle-exclamation"></i>';
status = 'online';
icon = '<i class="fa-solid fa-plug-circle-exclamation"></i>';
status = 'flapping';
label = getString('Gen_Flapping');
} else if (devIsSleeping == 1) {
css = 'bg-aqua text-white statusSleeping';
css = 'bg-aqua text-white statusSleeping';
cssText = 'text-aqua';
icon = '<i class="fa-solid fa-moon"></i>';
status = 'sleeping';
} else if (devAlertDown == 1) {
css = 'bg-red text-white statusDown';
cssText = 'text-red';
icon = '<i class="fa-solid fa-triangle-exclamation"></i>';
status = 'down';
} else if (devPresentLastScan != 1) {
css = 'bg-gray text-white statusOffline';
icon = '<i class="fa-solid fa-moon"></i>';
status = 'sleeping';
label = getString('Gen_Sleeping');
} else if (devIsArchived == 1) {
css = 'bg-gray text-white statusArchived';
cssText = 'text-gray50';
icon = '<i class="fa-solid fa-xmark"></i>';
status = 'offline';
icon = '<i class="fa-solid fa-box-archive"></i>';
status = 'archived';
label = getString('Gen_Archived');
} else if (devAlertDown == 1) {
css = 'bg-red text-white statusDown';
cssText = 'text-red';
icon = '<i class="fa-solid fa-triangle-exclamation"></i>';
status = 'down';
label = getString('Gen_Down');
} else if (devPresentLastScan != 1) {
css = 'bg-gray text-white statusOffline';
cssText = 'text-gray50';
icon = '<i class="fa-solid fa-xmark"></i>';
status = 'offline';
label = getString('Gen_Offline');
}
// New devices keep the online/offline color & icon but show "New" as label
if (devIsNew == 1) {
label = getString('Gen_New');
}
const cleanedText = statusText.replace(/-/g, '');
@@ -776,15 +793,36 @@ function getStatusBadgeParts(devPresentLastScan, devAlertDown, devFlapping, devM
return {
cssClass: css,
cssText: cssText,
cssText: cssText,
iconHtml: icon,
mac: devMac,
text: cleanedText,
status: status,
url: url
mac: devMac,
text: cleanedText,
status: status,
label: label,
url: url
};
}
// Convenience wrappers — call getStatusBadgeParts with the right fields
// for each object shape used across the codebase.
// Any object with devXxx field names (API response, cache, SQL DevicesView row,
// network-api nodes, network-tree nodeData.data objects)
function badgeFromDevice(d) {
return getStatusBadgeParts(
d.devPresentLastScan, d.devAlertDown, d.devFlapping, d.devMac,
'', d.devIsSleeping || 0, d.devIsArchived || 0, d.devIsNew || 0
);
}
// hover-box: reads status fields from jQuery data-* attributes on an element
function badgeFromDataAttrs($el) {
return getStatusBadgeParts(
$el.data('present'), $el.data('alertdown'), $el.data('flapping') || 0, $el.data('mac'),
'', $el.data('sleeping') || 0, $el.data('archived') || 0, $el.data('isnew') || 0
);
}
//--------------------------------------------------------------
// Getting the color and css class for device relationships
function getRelationshipConf(relType) {
@@ -930,14 +968,7 @@ function renderDeviceLink(data, container, useName = false) {
}
// Build and return badge parts
const badge = getStatusBadgeParts(
device.devPresentLastScan,
device.devAlertDown,
device.devFlapping,
device.devMac,
'',
device.devIsSleeping || 0
);
const badge = badgeFromDevice(device);
// badge class and hover-info class to container
$(container)
@@ -954,8 +985,10 @@ function renderDeviceLink(data, container, useName = false) {
'data-status': device.devStatus,
'data-flapping': device.devFlapping,
'data-present': device.devPresentLastScan,
'data-alert': device.devAlertDown,
'data-alertdown': device.devAlertDown,
'data-sleeping': device.devIsSleeping || 0,
'data-archived': device.devIsArchived || 0,
'data-isnew': device.devIsNew || 0,
'data-icon': device.devIcon
});
@@ -1024,10 +1057,8 @@ function initHoverNodeInfo() {
const lastseen = $el.data('lastseen') || 'Unknown';
const firstseen = $el.data('firstseen') || 'Unknown';
const relationship = $el.data('relationship') || 'Unknown';
const flapping = $el.data('flapping') || 0;
const sleeping = $el.data('sleeping') || 0;
const badge = getStatusBadgeParts( $el.data('present'), $el.data('alert'), flapping, $el.data('mac'), '', sleeping)
const status =`<span class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.status}</span>`
const badge = badgeFromDataAttrs($el);
const status =`<span class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.label}</span>`
const html = `
<div>

View File

@@ -14,12 +14,13 @@ function renderSmallBox($params) {
$labelLang = isset($params['labelLang']) ? $params['labelLang'] : '';
$iconId = isset($params['iconId']) ? $params['iconId'] : '';
$iconClass = isset($params['iconClass']) ? $params['iconClass'] : '';
$iconHtml = isset($params['iconHtml']) ? $params['iconHtml'] : '';
$dataValue = isset($params['dataValue']) ? $params['dataValue'] : '';
return '
<div class="col-lg-3 col-sm-6 col-xs-6">
<a href="#" onclick="javascript: ' . htmlspecialchars($onclickEvent) . '">
<div class="small-box ' . htmlspecialchars($color) . '">
<div style="cursor:pointer" onclick="javascript: ' . htmlspecialchars($onclickEvent) . '">
<div class="small-box ' . htmlspecialchars($color) . '" style="pointer-events:none">
<div class="inner">
<div class="col-lg-6 col-sm-6 col-xs-6">
<div class="small-box-text col-lg-12 col-sm-12 col-xs-12" id="' . htmlspecialchars($headerId) . '" style="' . htmlspecialchars($headerStyle) . '"> <b>' . htmlspecialchars($dataValue) . '</b> </div>
@@ -27,10 +28,10 @@ function renderSmallBox($params) {
<div class="infobox_label col-lg-6 col-sm-6 col-xs-6">' . lang(htmlspecialchars($labelLang)) . '</div>
</div>
<div class="icon">
<i id="' . htmlspecialchars($iconId) . '" class="' . htmlspecialchars($iconClass) . '"></i>
' . ($iconHtml ? $iconHtml : '<i id="' . htmlspecialchars($iconId) . '" class="' . htmlspecialchars($iconClass) . '"></i>') . '
</div>
</div>
</a>
</div>
</div>';
}

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "إضافة جهاز",
"Gen_Add_All": "إضافة الكل",
"Gen_All_Devices": "جميع الأجهزة",
"Gen_Archived": "",
"Gen_AreYouSure": "هل أنت متأكد؟",
"Gen_Backup": "نسخة احتياطية",
"Gen_Cancel": "إلغاء",
@@ -326,8 +327,10 @@
"Gen_Delete": "حذف",
"Gen_DeleteAll": "حذف الكل",
"Gen_Description": "الوصف",
"Gen_Down": "",
"Gen_Error": "خطأ",
"Gen_Filter": "تصفية",
"Gen_Flapping": "",
"Gen_Generate": "إنشاء",
"Gen_InvalidMac": "عنوان MAC غير صالح.",
"Gen_Invalid_Value": "تم إدخال قيمة غير صالحة",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "اختيار أيقونة",
"Gen_SelectToPreview": "اختر للمعاينة",
"Gen_Selected_Devices": "الأجهزة المحددة",
"Gen_Sleeping": "",
"Gen_Subnet": "الشبكة الفرعية",
"Gen_Switch": "تبديل",
"Gen_Upd": "تحديث",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Afegir dispositiu",
"Gen_Add_All": "Afegeix tot",
"Gen_All_Devices": "Tots els dispositius",
"Gen_Archived": "",
"Gen_AreYouSure": "Estàs segur?",
"Gen_Backup": "Executar Backup",
"Gen_Cancel": "Cancel·lar",
@@ -326,8 +327,10 @@
"Gen_Delete": "Esborrar",
"Gen_DeleteAll": "Esborrar tot",
"Gen_Description": "Descripció",
"Gen_Down": "",
"Gen_Error": "Error",
"Gen_Filter": "Filtrar",
"Gen_Flapping": "",
"Gen_Generate": "Generar",
"Gen_InvalidMac": "Mac address invàlida.",
"Gen_Invalid_Value": "S'ha introduït un valor incorrecte",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Seleccioneu la vista prèvia",
"Gen_Selected_Devices": "Dispositius seleccionats:",
"Gen_Sleeping": "",
"Gen_Subnet": "Subxarxa",
"Gen_Switch": "Switch",
"Gen_Upd": "Actualitzat correctament",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "",
"Gen_Add_All": "Přidat vše",
"Gen_All_Devices": "Všechna zařízení",
"Gen_Archived": "",
"Gen_AreYouSure": "Jste si jistý?",
"Gen_Backup": "Spustit zálohování",
"Gen_Cancel": "Zrušit",
@@ -326,8 +327,10 @@
"Gen_Delete": "Smazat",
"Gen_DeleteAll": "Smazat vše",
"Gen_Description": "Popis",
"Gen_Down": "",
"Gen_Error": "Chyba",
"Gen_Filter": "Filtr",
"Gen_Flapping": "",
"Gen_Generate": "Vygenerovat",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Vybrat na náhled",
"Gen_Selected_Devices": "Vybraná zařízení:",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "Přepnout",
"Gen_Upd": "Úspěšně aktualizováno",

View File

@@ -320,6 +320,7 @@
"Gen_AddDevice": "Gerät hinzufügen",
"Gen_Add_All": "Alle hinzufügen",
"Gen_All_Devices": "Alle Geräte",
"Gen_Archived": "",
"Gen_AreYouSure": "Sind Sie sich sicher?",
"Gen_Backup": "Sichern",
"Gen_Cancel": "Abbrechen",
@@ -330,8 +331,10 @@
"Gen_Delete": "Löschen",
"Gen_DeleteAll": "Alles löschen",
"Gen_Description": "Beschreibung",
"Gen_Down": "",
"Gen_Error": "Fehler",
"Gen_Filter": "Filter",
"Gen_Flapping": "",
"Gen_Generate": "Generieren",
"Gen_InvalidMac": "Ungültige MAC-Adresse.",
"Gen_Invalid_Value": "",
@@ -354,6 +357,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Zur Vorschau auswählen",
"Gen_Selected_Devices": "Ausgewählte Geräte:",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "Umschalten",
"Gen_Upd": "Aktualisierung erfolgreich",

View File

@@ -139,7 +139,7 @@
"DevDetail_SessionTable_Duration": "Duration",
"DevDetail_SessionTable_IP": "IP",
"DevDetail_SessionTable_Order": "Order",
"DevDetail_Shortcut_CurrentStatus": "Current Status",
"DevDetail_Shortcut_CurrentStatus": "Status",
"DevDetail_Shortcut_DownAlerts": "Down Alerts",
"DevDetail_Shortcut_Presence": "Presence",
"DevDetail_Shortcut_Sessions": "Sessions",
@@ -316,6 +316,7 @@
"Gen_AddDevice": "Add device",
"Gen_Add_All": "Add all",
"Gen_All_Devices": "All devices",
"Gen_Archived": "Archived",
"Gen_AreYouSure": "Are you sure?",
"Gen_Backup": "Run Backup",
"Gen_Cancel": "Cancel",
@@ -326,13 +327,16 @@
"Gen_Delete": "Delete",
"Gen_DeleteAll": "Delete all",
"Gen_Description": "Description",
"Gen_Down": "Down",
"Gen_Error": "Error",
"Gen_Filter": "Filter",
"Gen_Flapping": "Flapping",
"Gen_Generate": "Generate",
"Gen_InvalidMac": "Invalid Mac address.",
"Gen_Invalid_Value": "An invalid value was entered",
"Gen_LockedDB": "ERROR - DB might be locked - Check F12 Dev tools -> Console or try later.",
"Gen_NetworkMask": "Network mask",
"Gen_New": "New",
"Gen_Offline": "Offline",
"Gen_Okay": "Ok",
"Gen_Online": "Online",
@@ -350,6 +354,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Select to preview",
"Gen_Selected_Devices": "Selected devices:",
"Gen_Sleeping": "Sleeping",
"Gen_Subnet": "Subnet",
"Gen_Switch": "Switch",
"Gen_Upd": "Updated successfully",

View File

@@ -318,6 +318,7 @@
"Gen_AddDevice": "Añadir dispositivo",
"Gen_Add_All": "Añadir todo",
"Gen_All_Devices": "Todos los dispositivos",
"Gen_Archived": "",
"Gen_AreYouSure": "¿Estás seguro?",
"Gen_Backup": "Ejecutar copia de seguridad",
"Gen_Cancel": "Cancelar",
@@ -328,8 +329,10 @@
"Gen_Delete": "Eliminar",
"Gen_DeleteAll": "Eliminar todo",
"Gen_Description": "Descripción",
"Gen_Down": "",
"Gen_Error": "Error",
"Gen_Filter": "Filtro",
"Gen_Flapping": "",
"Gen_Generate": "Generar",
"Gen_InvalidMac": "Dirección MAC inválida.",
"Gen_Invalid_Value": "Un valor inválido fue ingresado",
@@ -352,6 +355,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Seleccionar para previsualizar",
"Gen_Selected_Devices": "Dispositivos seleccionados:",
"Gen_Sleeping": "",
"Gen_Subnet": "Subred",
"Gen_Switch": "Cambiar",
"Gen_Upd": "Actualizado correctamente",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "",
"Gen_Add_All": "",
"Gen_All_Devices": "",
"Gen_Archived": "",
"Gen_AreYouSure": "",
"Gen_Backup": "",
"Gen_Cancel": "",
@@ -326,8 +327,10 @@
"Gen_Delete": "",
"Gen_DeleteAll": "",
"Gen_Description": "",
"Gen_Down": "",
"Gen_Error": "",
"Gen_Filter": "",
"Gen_Flapping": "",
"Gen_Generate": "",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "",
"Gen_SelectToPreview": "",
"Gen_Selected_Devices": "",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "",
"Gen_Upd": "",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Ajouter un appareil",
"Gen_Add_All": "Ajouter tous",
"Gen_All_Devices": "Tous les appareils",
"Gen_Archived": "",
"Gen_AreYouSure": "Êtes-vous sûr?",
"Gen_Backup": "Lancer la sauvegarde",
"Gen_Cancel": "Annuler",
@@ -326,8 +327,10 @@
"Gen_Delete": "Supprimer",
"Gen_DeleteAll": "Supprimer tous",
"Gen_Description": "Description",
"Gen_Down": "",
"Gen_Error": "Erreur",
"Gen_Filter": "Filtrer",
"Gen_Flapping": "",
"Gen_Generate": "Générer",
"Gen_InvalidMac": "Adresse MAC invalide.",
"Gen_Invalid_Value": "Une valeur invalide a été renseignée",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Sélectionnez pour prévisualiser",
"Gen_Selected_Devices": "Appareils sélectionnés :",
"Gen_Sleeping": "",
"Gen_Subnet": "Sous-réseau",
"Gen_Switch": "Basculer",
"Gen_Upd": "Mise à jour réussie",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Aggiungi dispositivo",
"Gen_Add_All": "Aggiungi tutti",
"Gen_All_Devices": "Tutti i dispositivi",
"Gen_Archived": "",
"Gen_AreYouSure": "Sei sicuro?",
"Gen_Backup": "Esegui backup",
"Gen_Cancel": "Annulla",
@@ -326,8 +327,10 @@
"Gen_Delete": "Elimina",
"Gen_DeleteAll": "Elimina tutti",
"Gen_Description": "Descrizione",
"Gen_Down": "",
"Gen_Error": "Errore",
"Gen_Filter": "Filtro",
"Gen_Flapping": "",
"Gen_Generate": "Genera",
"Gen_InvalidMac": "Indirizzo Mac non valido.",
"Gen_Invalid_Value": "È stato inserito un valore non valido",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Seleziona per anteprima",
"Gen_Selected_Devices": "Dispositivi selezionati:",
"Gen_Sleeping": "",
"Gen_Subnet": "Sottorete",
"Gen_Switch": "Cambia",
"Gen_Upd": "Aggiornato correttamente",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "デバイス追加",
"Gen_Add_All": "すべて追加",
"Gen_All_Devices": "全デバイス",
"Gen_Archived": "",
"Gen_AreYouSure": "本当によろしいですか?",
"Gen_Backup": "バックアップを実行",
"Gen_Cancel": "キャンセル",
@@ -326,8 +327,10 @@
"Gen_Delete": "削除",
"Gen_DeleteAll": "全削除",
"Gen_Description": "説明",
"Gen_Down": "",
"Gen_Error": "エラー",
"Gen_Filter": "フィルター",
"Gen_Flapping": "",
"Gen_Generate": "生成",
"Gen_InvalidMac": "無効なMacアドレス。",
"Gen_Invalid_Value": "無効な値が入力されました",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "プレビューを選択",
"Gen_Selected_Devices": "選択したデバイス:",
"Gen_Sleeping": "",
"Gen_Subnet": "サブネット",
"Gen_Switch": "スイッチ",
"Gen_Upd": "アップデートが正常に完了しました",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "",
"Gen_Add_All": "Legg til alle",
"Gen_All_Devices": "",
"Gen_Archived": "",
"Gen_AreYouSure": "Er du sikker?",
"Gen_Backup": "Kjør sikkerhetskopiering",
"Gen_Cancel": "Avbryt",
@@ -326,8 +327,10 @@
"Gen_Delete": "Slett",
"Gen_DeleteAll": "Slett alle",
"Gen_Description": "",
"Gen_Down": "",
"Gen_Error": "Feil",
"Gen_Filter": "Filter",
"Gen_Flapping": "",
"Gen_Generate": "",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "",
"Gen_SelectToPreview": "",
"Gen_Selected_Devices": "Valgte Enheter:",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "Bytt",
"Gen_Upd": "Oppdatering vellykket",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Dodaj urządzenie",
"Gen_Add_All": "Dodaj wszystko",
"Gen_All_Devices": "Wszystkie urządzenia",
"Gen_Archived": "",
"Gen_AreYouSure": "Jesteś pewien?",
"Gen_Backup": "Uruchom kopię zapasową",
"Gen_Cancel": "Anuluj",
@@ -326,8 +327,10 @@
"Gen_Delete": "Usuń",
"Gen_DeleteAll": "Usuń wszystko",
"Gen_Description": "Opis",
"Gen_Down": "",
"Gen_Error": "Błąd",
"Gen_Filter": "Filtr",
"Gen_Flapping": "",
"Gen_Generate": "Wygeneruj",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Wybierz, aby podglądnąć",
"Gen_Selected_Devices": "Wybrane urządzenia:",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "Switch",
"Gen_Upd": "Zaktualizowano pomyślnie",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Adicionar dispositivo",
"Gen_Add_All": "Adicionar todos",
"Gen_All_Devices": "Todos os Dispositivos",
"Gen_Archived": "",
"Gen_AreYouSure": "Tem certeza?",
"Gen_Backup": "Executar backup",
"Gen_Cancel": "Cancelar",
@@ -326,8 +327,10 @@
"Gen_Delete": "Excluir",
"Gen_DeleteAll": "Excluir todos",
"Gen_Description": "Descrição",
"Gen_Down": "",
"Gen_Error": "Erro",
"Gen_Filter": "Filtro",
"Gen_Flapping": "",
"Gen_Generate": "Gerar",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Selecionar para pré-visualizar",
"Gen_Selected_Devices": "Dispositivos selecionados:",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "Trocar",
"Gen_Upd": "Atualizado com sucesso",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Adicionar dispositivo",
"Gen_Add_All": "Adicionar todos",
"Gen_All_Devices": "Todos os dispostivos",
"Gen_Archived": "",
"Gen_AreYouSure": "Tem certeza?",
"Gen_Backup": "Executar backup",
"Gen_Cancel": "Cancelar",
@@ -326,8 +327,10 @@
"Gen_Delete": "Apagar",
"Gen_DeleteAll": "Apagar todos",
"Gen_Description": "Descrição",
"Gen_Down": "",
"Gen_Error": "Erro",
"Gen_Filter": "Filtro",
"Gen_Flapping": "",
"Gen_Generate": "Gerar",
"Gen_InvalidMac": "Endereço MAC Inválido.",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Selecionar para pré-visualizar",
"Gen_Selected_Devices": "Seleciona dispostivos:",
"Gen_Sleeping": "",
"Gen_Subnet": "Sub-rede",
"Gen_Switch": "Trocar",
"Gen_Upd": "Atualizado com sucesso",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Добавить устройство",
"Gen_Add_All": "Добавить все",
"Gen_All_Devices": "Все устройства",
"Gen_Archived": "",
"Gen_AreYouSure": "Вы уверены?",
"Gen_Backup": "Запустить резервное копирование",
"Gen_Cancel": "Отмена",
@@ -326,8 +327,10 @@
"Gen_Delete": "Удалить",
"Gen_DeleteAll": "Удалить все",
"Gen_Description": "Описание",
"Gen_Down": "",
"Gen_Error": "Ошибка",
"Gen_Filter": "Фильтр",
"Gen_Flapping": "",
"Gen_Generate": "Генерировать",
"Gen_InvalidMac": "Неверный Mac-адрес.",
"Gen_Invalid_Value": "Введено некорректное значение",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Выберите для предварительного просмотра",
"Gen_Selected_Devices": "Выбранные устройства:",
"Gen_Sleeping": "",
"Gen_Subnet": "Подсеть",
"Gen_Switch": "Переключить",
"Gen_Upd": "Успешное обновление",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "",
"Gen_Add_All": "",
"Gen_All_Devices": "",
"Gen_Archived": "",
"Gen_AreYouSure": "",
"Gen_Backup": "",
"Gen_Cancel": "",
@@ -326,8 +327,10 @@
"Gen_Delete": "",
"Gen_DeleteAll": "",
"Gen_Description": "",
"Gen_Down": "",
"Gen_Error": "",
"Gen_Filter": "",
"Gen_Flapping": "",
"Gen_Generate": "",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "",
"Gen_SelectToPreview": "",
"Gen_Selected_Devices": "",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "",
"Gen_Upd": "",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Cihaz Ekle",
"Gen_Add_All": "Tümünü ekle",
"Gen_All_Devices": "Tüm Cihazlar",
"Gen_Archived": "",
"Gen_AreYouSure": "Emin misiniz?",
"Gen_Backup": "Yedeklemeyi Çalıştır",
"Gen_Cancel": "İptal",
@@ -326,8 +327,10 @@
"Gen_Delete": "Sil",
"Gen_DeleteAll": "Tümünü sil",
"Gen_Description": "Açıklama",
"Gen_Down": "",
"Gen_Error": "Hata",
"Gen_Filter": "Filtre",
"Gen_Flapping": "",
"Gen_Generate": "Oluştur",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Önizleme yapmak için seçin",
"Gen_Selected_Devices": "Seçilmiş Cihazlar:",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "Switch",
"Gen_Upd": "Başarılı bir şekilde güncellendi",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "Додати пристрій",
"Gen_Add_All": "Додати все",
"Gen_All_Devices": "Усі пристрої",
"Gen_Archived": "",
"Gen_AreYouSure": "Ви впевнені?",
"Gen_Backup": "Запустіть резервне копіювання",
"Gen_Cancel": "Скасувати",
@@ -326,8 +327,10 @@
"Gen_Delete": "Видалити",
"Gen_DeleteAll": "Видалити все",
"Gen_Description": "Опис",
"Gen_Down": "",
"Gen_Error": "Помилка",
"Gen_Filter": "Фільтр",
"Gen_Flapping": "",
"Gen_Generate": "Генерувати",
"Gen_InvalidMac": "Недійсна Mac-адреса.",
"Gen_Invalid_Value": "Введено недійсне значення",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Виберіть для попереднього перегляду",
"Gen_Selected_Devices": "Вибрані пристрої:",
"Gen_Sleeping": "",
"Gen_Subnet": "Підмережа",
"Gen_Switch": "Перемикач",
"Gen_Upd": "Оновлено успішно",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "",
"Gen_Add_All": "",
"Gen_All_Devices": "",
"Gen_Archived": "",
"Gen_AreYouSure": "",
"Gen_Backup": "",
"Gen_Cancel": "",
@@ -326,8 +327,10 @@
"Gen_Delete": "",
"Gen_DeleteAll": "",
"Gen_Description": "",
"Gen_Down": "",
"Gen_Error": "",
"Gen_Filter": "",
"Gen_Flapping": "",
"Gen_Generate": "",
"Gen_InvalidMac": "",
"Gen_Invalid_Value": "",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "",
"Gen_SelectToPreview": "",
"Gen_Selected_Devices": "",
"Gen_Sleeping": "",
"Gen_Subnet": "",
"Gen_Switch": "",
"Gen_Upd": "",

View File

@@ -316,6 +316,7 @@
"Gen_AddDevice": "添加设备",
"Gen_Add_All": "全部添加",
"Gen_All_Devices": "所有设备",
"Gen_Archived": "",
"Gen_AreYouSure": "你确定吗?",
"Gen_Backup": "运行备份",
"Gen_Cancel": "取消",
@@ -326,8 +327,10 @@
"Gen_Delete": "删除",
"Gen_DeleteAll": "全部删除",
"Gen_Description": "描述",
"Gen_Down": "",
"Gen_Error": "错误",
"Gen_Filter": "筛选",
"Gen_Flapping": "",
"Gen_Generate": "生成",
"Gen_InvalidMac": "无效的 Mac 地址。",
"Gen_Invalid_Value": "输入了无效的值",
@@ -350,6 +353,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "选择预览",
"Gen_Selected_Devices": "选定的设备:",
"Gen_Sleeping": "",
"Gen_Subnet": "子网",
"Gen_Switch": "交换",
"Gen_Upd": "已成功更新",