network topology refactor

This commit is contained in:
jokob-sk
2025-07-19 20:45:46 +10:00
parent 5e3365935e
commit 26f0d0ac2f
19 changed files with 429 additions and 522 deletions

View File

@@ -3,13 +3,15 @@
The **Network** page lets you map how devices connect — visually and logically. The **Network** page lets you map how devices connect — visually and logically.
Its especially useful for planning infrastructure, assigning parent-child relationships, and spotting gaps. Its especially useful for planning infrastructure, assigning parent-child relationships, and spotting gaps.
![Network tree details](./img/NETWORK_TREE/Network_Sample.png)
To get started, youll need to define at least one root node and mark certain devices as network nodes (like Switches or Routers). To get started, youll need to define at least one root node and mark certain devices as network nodes (like Switches or Routers).
--- ---
Start by creating a root device with the MAC address `Internet`, if the application didnt create one already. Start by creating a root device with the MAC address `Internet`, if the application didnt create one already.
This is the only MAC currently supported as a root network node. This special MAC address (`Internet`) is required for the root network node — no other value is currently supported.
Set its **Type** to something valid in a networking context — for example: `Router` or `Gateway`. Set its **Type** to a valid network type — such as `Router` or `Gateway`.
> [!TIP] > [!TIP]
> If you dont have one, use the [Create new device](./DEVICE_MANAGEMENT.md#dummy-devices) button on the **Devices** page to add a root device. > If you dont have one, use the [Create new device](./DEVICE_MANAGEMENT.md#dummy-devices) button on the **Devices** page to add a root device.
@@ -19,7 +21,7 @@ Set its **Type** to something valid in a networking context — for example: `Ro
## ⚡ Quick Setup ## ⚡ Quick Setup
1. Open the device you want to use as a network node (e.g. a Switch). 1. Open the device you want to use as a network node (e.g. a Switch).
2. Set its **Type** to one of the following: 2. Set its **Type** to one of the following:
`AP`, `Firewall`, `Gateway`, `PLC`, `Powerline`, `Router`, `Switch`, `USB LAN Adapter`, `USB WIFI Adapter`, `WLAN` `AP`, `Firewall`, `Gateway`, `PLC`, `Powerline`, `Router`, `Switch`, `USB LAN Adapter`, `USB WIFI Adapter`, `WLAN`
*(Or add custom types under **Settings → General → `NETWORK_DEVICE_TYPES`**.)* *(Or add custom types under **Settings → General → `NETWORK_DEVICE_TYPES`**.)*
3. Save the device. 3. Save the device.
@@ -27,8 +29,6 @@ Set its **Type** to something valid in a networking context — for example: `Ro
5. Use the **Assign** button to connect unassigned devices to a network node. 5. Use the **Assign** button to connect unassigned devices to a network node.
6. If the **Port** is `0` or empty, a Wi-Fi icon is shown. Otherwise, an Ethernet icon appears. 6. If the **Port** is `0` or empty, a Wi-Fi icon is shown. Otherwise, an Ethernet icon appears.
![Network tree details](./img/NETWORK_TREE/Network_Sample.png)
> [!NOTE] > [!NOTE]
> Use [bulk editing](./DEVICES_BULK_EDITING.md) with _CSV Export_ to fix `Internet` root assignments or update many devices at once. > Use [bulk editing](./DEVICES_BULK_EDITING.md) with _CSV Export_ to fix `Internet` root assignments or update many devices at once.
@@ -44,14 +44,12 @@ Lets walk through setting up a device named `raspberrypi` to act as a network
- Go to the **Devices** page - Go to the **Devices** page
- Open the device detail view for `raspberrypi` - Open the device detail view for `raspberrypi`
- In the **Type** dropdown, select `Switch`
![Device details](./img/NETWORK_TREE/Network_Device_Details.png) ![Device details](./img/NETWORK_TREE/Network_Device_Details.png)
- In the **Type** dropdown, select `Switch` - Optionally assign a **Parent Node** (where this device connects to) and the **Relationship type** of the connection.
The `nic` relationship type can affect parent notifications — see the setting description and [Notifications documentation](./NOTIFICATIONS.md) for more.
![Parent Node dropdown](./img/NETWORK_TREE/Network_Device_ParentDropdown.png)
- Optionally assign a **Parent Node** (where this device connects to) and the **Relationship type** of the connection. The `nic` relationship type can affect parent notifications — see the setting description and [Notifications documentation](./NOTIFICATIONS.md) for more.
> [!NOTE] > [!NOTE]
> Only certain device types can act as network nodes: > Only certain device types can act as network nodes:
@@ -64,24 +62,41 @@ Lets walk through setting up a device named `raspberrypi` to act as a network
### 2. Confirm It Appears as a Network Node ### 2. Confirm It Appears as a Network Node
- Go to the **Network** page You can confirm that `raspberrypi` now acts as a network device in two places:
- Navigate to a different device and verify that `raspberrypi` now appears as an option for a **Parent Node**:
![Parent Node dropdown](./img/NETWORK_TREE/Network_Device_ParentDropdown.png)
- Go to the **Network** page — you'll now see a `raspberrypi` tab, meaning it's recognized as a network node (Switch):
![Network page](./img/NETWORK_TREE/Network_Assign.png) ![Network page](./img/NETWORK_TREE/Network_Assign.png)
- Youll now see a `raspberrypi` tab — its recognized as a network node (Switch) - You can now assign other devices to it.
- You can assign other devices to it
--- ---
### 3. Assign Connected Devices ### 3. Assign Connected Devices
- Use the **Assign** button to link other devices (e.g. PCs) to `raspberrypi` - Use the **Assign** button to link other devices (e.g. PCs) to `raspberrypi`.
- After assigning, connected devices will appear beneath the `raspberrypi` switch node.
![Assigned nodes](./img/NETWORK_TREE/Network_Assigned_Nodes.png) ![Assigned nodes](./img/NETWORK_TREE/Network_Assigned_Nodes.png)
- Once assigned, devices will show as connected to the `raspberrypi` switch node - Relationship lines may vary in color based on the selected Relationship type. These are editable on the device details page where you assign a parent node.
- Relationship lines may vary in color based on the selected Relationship type. These are editable on the device details.
![Hover detail](./img/NETWORK_TREE/Network_tree_setup_hover.png) ![Hover detail](./img/NETWORK_TREE/Network_tree_setup_hover.png)
Happy with your setup? [Back it up](./BACKUPS.md). > Hovering over devices in the tree reveals connection details and tooltips for quick inspection.
---
## ✅ Summary
To configure devices on the **Network** page:
- Ensure a device with MAC `Internet` is set up as the root
- Assign valid **Type** values to switches, routers, and other supported nodes that represent network devices
- Use the **Assign** button to connect devices logically to their parent node
Need to reset or undo changes? [Use backups](./BACKUPS.md) or [bulk editing](./DEVICES_BULK_EDITING.md) to manage devices at scale. You can also automate device assignment with [Workflows](./WORKFLOWS.md).

View File

@@ -340,6 +340,11 @@ body
width: 100%; width: 100%;
} }
.networkTable .nav-tabs-custom
{
margin-bottom: 0px;
}
.pa-small-box-2 .inner h3 { .pa-small-box-2 .inner h3 {
margin-left: 0em; margin-left: 0em;
margin-bottom: 1.3em; margin-bottom: 1.3em;
@@ -1785,6 +1790,16 @@ input[readonly] {
/* margin-left: 0.2em; */ /* margin-left: 0.2em; */
} }
.networkNodeTabHeaders .icon i
{
padding-top: 8px !important;
padding-left: 6px !important;
}
.networkTable .box-body {
padding-top: 5px;
}
.networkTable .networkNodeTabHeaders a { .networkTable .networkNodeTabHeaders a {
display: block; display: block;
height: 3em; height: 3em;
@@ -1813,6 +1828,8 @@ input[readonly] {
text-wrap: nowrap; text-wrap: nowrap;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
.networkNodeTabHeaders .node-name .networkNodeTabHeaders .node-name

View File

@@ -568,23 +568,23 @@ function getColumnNameFromLangString(headStringKey) {
//-------------------------------------------------------------- //--------------------------------------------------------------
// Generating the device status chip // Generating the device status chip
function getStatusBadgeParts(tmp_devPresentLastScan, tmp_devAlertDown, macAddress, statusText = '') { function getStatusBadgeParts(devPresentLastScan, devAlertDown, devMac, statusText = '') {
let css = 'bg-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'; let status = 'unknown';
let cssText = ''; let cssText = '';
if (tmp_devPresentLastScan == 1) { if (devPresentLastScan == 1) {
css = 'bg-green text-white statusOnline'; css = 'bg-green text-white statusOnline';
cssText = 'text-green'; cssText = 'text-green';
icon = '<i class="fa-solid fa-plug"></i>'; icon = '<i class="fa-solid fa-plug"></i>';
status = 'online'; status = 'online';
} else if (tmp_devAlertDown == 1) { } else if (devAlertDown == 1) {
css = 'bg-red text-white statusDown'; css = 'bg-red text-white statusDown';
cssText = 'text-red'; cssText = 'text-red';
icon = '<i class="fa-solid fa-triangle-exclamation"></i>'; icon = '<i class="fa-solid fa-triangle-exclamation"></i>';
status = 'down'; status = 'down';
} else if (tmp_devPresentLastScan != 1) { } else if (devPresentLastScan != 1) {
css = 'bg-gray text-white statusOffline'; css = 'bg-gray text-white statusOffline';
cssText = 'text-gray50'; cssText = 'text-gray50';
icon = '<i class="fa-solid fa-xmark"></i>'; icon = '<i class="fa-solid fa-xmark"></i>';
@@ -592,13 +592,13 @@ function getStatusBadgeParts(tmp_devPresentLastScan, tmp_devAlertDown, macAddres
} }
const cleanedText = statusText.replace(/-/g, ''); const cleanedText = statusText.replace(/-/g, '');
const url = `deviceDetails.php?mac=${encodeURIComponent(macAddress)}`; const url = `deviceDetails.php?mac=${encodeURIComponent(devMac)}`;
return { return {
cssClass: css, cssClass: css,
cssText: cssText, cssText: cssText,
iconHtml: icon, iconHtml: icon,
mac: macAddress, mac: devMac,
text: cleanedText, text: cleanedText,
status: status, status: status,
url: url url: url

View File

@@ -2,476 +2,337 @@
require 'php/templates/header.php'; require 'php/templates/header.php';
require 'php/templates/notification.php'; require 'php/templates/notification.php';
// online / offline badges HTML snippets
define('badge_online', '<div class="badge bg-green text-white" style="width: 60px;">Online</div>');
define('badge_offline', '<div class="badge bg-red text-white" style="width: 60px;">Offline</div>');
define('sortable_column', ' <span class="sort-btn" onclick="sortColumn(this)"><i class="fa-solid fa-arrow-up-short-wide"></i></span>');
?> ?>
<!-- // Create Top level tabs (List of network devices), explanation of the terminology below:
//
// Switch 1 (node)
// /(p1) \ (p2) <----- port numbers
// / \
// Smart TV (leaf) Switch 2 (node (for the PC) and leaf (for Switch 1))
// \
// PC (leaf) <------- leafs are not included in this SQL query -->
<script> <script>
// show spinning icon // show spinning icon
showSpinner() showSpinner()
</script> </script>
<!-- Page ------------------------------------------------------------------ --> <!-- Page ------------------------------------------------------------------ -->
<div class="content-wrapper"> <div class="content-wrapper">
<span class="helpIcon">
<a target="_blank" href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md">
<i class="fa fa-circle-question"></i>
</a>
</span>
<div id="networkTree" class="drag">
<span class="helpIcon"> <a target="_blank" href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md"><i class="fa fa-circle-question"></i></a></span> <!-- Tree topology Placeholder -->
</div>
<div id="networkTree" class="drag"></div>
<!-- Main content ---------------------------------------------------------- --> <!-- Main content ---------------------------------------------------------- -->
<section class="content networkTable"> <section class="content networkTable">
<?php
// Create top-level node (network devices) tabs
function createDeviceTabs($node_mac, $node_name, $node_status, $node_type, $node_ports_count, $icon, $node_alert, $activetab) {
// prepare string with port number in brackets if available
$str_port = "";
if ($node_ports_count != "") {
$str_port = ' ('.$node_ports_count.')';
}
// online/offline status circle (red/green)
$icon_class = "";
if($node_status == 0 && $node_alert == 1) // 1 means online, 0 offline
{
$icon_class = " text-red";
} elseif ($node_status == 1) {
$icon_class = " text-green";
} elseif ($node_status == 0) {
$icon_class = " text-gray50";
}
$decoded_icon = base64_decode($icon);
$idFromMac = str_replace(":", "_", $node_mac);
$str_tab_header = '<li class="networkNodeTabHeaders '.$activetab.' " >
<a href="#'.$idFromMac.'" data-mytabmac="'.$node_mac.'" id="'.$idFromMac.'_id" data-toggle="tab" title="'.$node_name.' ">' // _id is added so it doesn't conflict with AdminLTE tab behavior
.'<div class="icon '.$icon_class.'" >'.$decoded_icon.' </div> <span class="node-name">'.$node_name.'</span>' .$str_port.
'</a>
</li>';
echo $str_tab_header;
}
// Create pane content (displayed inside of the tabs)
function createPane($node_mac, $node_name, $node_status, $node_type, $node_ports_count, $node_parent_mac, $activetab){
// online/offline status circle (red/green)
$node_badge = "";
if($node_status == 1) // 1 means online, 0 offline
{
$node_badge = badge_online;
} else
{
$node_badge = badge_offline;
}
$idFromMac = str_replace(":", "_", $node_mac);
$idParentMac = str_replace(":", "_", $node_parent_mac);
$str_tab_pane = '<div class="tab-pane '.$activetab.'" id="'.$idFromMac.'">
<div>
<h2 class="page-header"><i class="fa fa-server"></i> '.lang('Network_Node'). '</h2>
</div>
<table class="table table-striped" >
<tbody>
<tr>
<td class="col-sm-3">
<b>'.lang('Network_Node').'</b>
</td>
<td class="anonymize">
<a href="./deviceDetails.php?mac='.$node_mac.'">
'.$node_name.'
</a>
</td>
</tr>
<tr>
<td >
<b>MAC</b>
</td>
<td data-mynodemac="'.$node_mac.'" class="anonymize">'
.$node_mac.
'</td>
</tr>
<tr>
<td>
<b>'.lang('Device_TableHead_Type').'</b>
</td>
<td>
' .$node_type. '
</td>
</tr>
<tr>
<td>
<b>'.lang('Network_Table_State').'</b>
</td>
<td> '
.$node_badge.
'</td>
</tr>
<tr>
<td>
<b>'.lang('Network_Parent').'</b>
</td>
<td>
<a href="./network.php?mac='.$idParentMac.'">
<b class="anonymize">
<span class="mac-to-name" my-data-mac="'.$node_parent_mac.'">'.$node_parent_mac.' </span>
<i class="fa fa-square-up-right"></i>
</b>
</a>
</td>
</tr>
</tbody>
</table>
<div id="assignedDevices" class="box-body no-padding">
<div class="page-header">
<h3>
<i class="fa fa-sitemap"></i> '.lang('Network_Connected').'
</h3>
</div>
';
$str_table = ' <table class="table table-striped">
<thead>
<tr>
<th class="col-sm-1" >Port</th>
<th class="col-sm-1" >'.lang('Network_Table_State').'</th>
<th class="col-sm-2" >'.lang('Network_Table_Hostname').sortable_column.'</th>
<th class="col-sm-1" >'.lang('Network_Table_IP').sortable_column.'</th>
<th class="col-sm-3" >'.lang('Network_ManageLeaf').'</th>
</tr>
</thead>
<tbody>
<tr>
</tr>';
// Prepare Array for Devices with Port value
// If no Port is set, the Port number is set to 0
if ($node_ports_count == "") {
$node_ports_count = 0;
}
// Get all leafs connected to a node based on the node_mac
$func_sql = 'SELECT devParentPort as port,
devMac as mac,
devPresentLastScan as online,
devName as name,
devType as type,
devLastIP as last_ip,
(select devType from Devices a where devMac = "'.$node_mac.'") as node_type
FROM Devices WHERE devParentMAC = "'.$node_mac.'" and devIsArchived = 0 order by port, name asc';
global $db;
$func_result = $db->query($func_sql);
// array
$tableData = array();
while ($row = $func_result -> fetchArray (SQLITE3_ASSOC)) {
// Push row data
$tableData[] = array( 'port' => $row['port'],
'mac' => $row['mac'],
'online' => $row['online'],
'name' => $row['name'],
'type' => $row['type'],
'last_ip' => $row['last_ip'],
'node_type' => $row['node_type']);
}
// Control no rows
if (empty($tableData)) {
$tableData = [];
}
$str_table_rows = "";
foreach ($tableData as $row) {
if ($row['online'] == 1) {
$port_state = badge_online;
} else {
$port_state = badge_offline;
}
// prepare HTML for the port table column cell
$port_content = "N/A";
if (($row['node_type'] == "WLAN" || $row['node_type'] == "AP" ) && ($row['port'] == NULL || $row['port'] == "") ){
$port_content = '<i class="fa fa-wifi"></i>';
} elseif ($row['node_type'] == "Powerline")
{
$port_content = '<i class="fa fa-flash"></i>';
} elseif ($row['port'] != NULL && $row['port'] != "")
{
$port_content = $row['port'];
}
$str_table_rows = $str_table_rows.
'<tr>
<td style="text-align: center;">
'.$port_content.'
</td>
<td>'
.$port_state.
'</td>
<td style="padding-left: 10px;">
<a href="./deviceDetails.php?mac='.$row['mac'].'">
<b class="anonymize">'.$row['name'].'</b>
</a>
</td>
<td class="anonymize">'
.$row['last_ip'].
'</td>
<td class="">
<button class="btn btn-primary btn-danger btn-sm" data-myleafmac="'.$row['mac'].'" >'.lang('Network_ManageUnassign').'</button>
</td>
</tr>';
}
$str_table_close = '</tbody>
</table>';
// no connected device - don't render table, just display some info
if($str_table_rows == "")
{
$str_table = "<div>
<div>
".lang("Network_NoAssignedDevices")."
</div>
</div>";
$str_table_close = "";
}
$str_close_pane = '</div>
</div>';
// write the HTML
echo ''.$str_tab_pane.
$str_table.
$str_table_rows.
$str_table_close.
$str_close_pane;
}
// Create Top level tabs (List of network devices), explanation of the terminology below:
//
// Switch 1 (node)
// /(p1) \ (p2) <----- port numbers
// / \
// Smart TV (leaf) Switch 2 (node (for the PC) and leaf (for Switch 1))
// \
// PC (leaf) <------- leafs are not included in this SQL query
$networkDeviceTypes = str_replace("]", "",(str_replace("[", "", getSettingValue("NETWORK_DEVICE_TYPES"))));
$sql = "SELECT node_name, node_mac, online, node_type, node_ports_count, parent_mac, node_icon, node_alert
FROM
(
SELECT a.devName as node_name,
a.devMac as node_mac,
a.devPresentLastScan as online,
a.devType as node_type,
a.devParentMAC as parent_mac,
a.devIcon as node_icon,
a.devAlertDown as node_alert
FROM Devices a
WHERE a.devType in (".$networkDeviceTypes.")
AND devIsArchived = 0
) t1
LEFT JOIN
(
SELECT b.devParentMAC as node_mac_2,
count() as node_ports_count
FROM Devices b
WHERE b.devParentMAC NOT NULL group by b.devParentMAC
) t2
ON (t1.node_mac = t2.node_mac_2);
";
$result = $db->query($sql);
// array
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
// Push row data
$tableData[] = array( 'node_mac' => $row['node_mac'],
'node_name' => $row['node_name'],
'online' => $row['online'],
'node_type' => $row['node_type'],
'parent_mac' => $row['parent_mac'],
'node_icon' => $row['node_icon'],
'node_ports_count' => $row['node_ports_count'],
'node_alert' => $row['node_alert']
);
}
// Control no rows
if (empty($tableData)) {
$tableData = [];
}
echo '<div class="nav-tabs-custom" style="margin-bottom: 0px;">
<ul class="nav nav-tabs">';
$activetab='active';
foreach ($tableData as $row) {
createDeviceTabs( $row['node_mac'],
$row['node_name'],
$row['online'],
$row['node_type'],
$row['node_ports_count'],
$row['node_icon'],
$row['node_alert'],
$activetab);
$activetab = ""; // reset active tab indicator, only the first tab is active
}
echo ' </ul> <div class="tab-content">';
$activetab='active';
foreach ($tableData as $row) {
createPane($row['node_mac'],
$row['node_name'],
$row['online'],
$row['node_type'],
$row['node_ports_count'],
$row['parent_mac'],
$activetab);
$activetab = ""; // reset active tab indicator, only the first tab is active
}
?>
<!-- /.tab-pane -->
</div>
</section>
<!-- Unassigned devices -->
<?php
// Get all Unassigned / unconnected nodes
$func_sql = 'SELECT
devMac AS mac,
devPresentLastScan AS online,
devName AS name,
devLastIP AS last_ip,
devParentMAC
FROM Devices
WHERE devParentMAC IS NULL
OR devParentMAC IN ("", " ", "undefined", "null")
AND devMac NOT LIKE "%internet%"
AND devIsArchived = 0
ORDER BY name ASC;';
global $db;
$func_result = $db->query($func_sql);
// array
$tableData = array();
while ($row = $func_result -> fetchArray (SQLITE3_ASSOC)) {
// Push row data
$tableData[] = array( 'mac' => $row['mac'],
'online' => $row['online'],
'name' => $row['name'],
'last_ip' => $row['last_ip']);
}
// Don't do anything if empty
if (!(empty($tableData))) {
$str_table_header = '
<div class="content">
<div id="unassignedDevices" class="box box-aqua box-body">
<section>
<h3>
<i class="fa fa-laptop"></i> '.lang('Network_UnassignedDevices').'
</h3>
<table class="table table-striped">
<thead>
<tr>
<th class="col-sm-1" ></th>
<th class="col-sm-1" >'.lang('Network_Table_State').'</th>
<th class="col-sm-2" >'.lang('Network_Table_Hostname').sortable_column.'</th>
<th class="col-sm-1" >'.lang('Network_Table_IP').sortable_column.'</th>
<th class="col-sm-3" >'.lang('Network_Assign').'</th>
</tr>
</thead>
<tbody>
<tr>
</tr>';
$str_table_rows = "";
foreach ($tableData as $row) {
if ($row['online'] == 1) {
$state = badge_online;
} else {
$state = badge_offline;
}
$str_table_rows = $str_table_rows.
'
<tr>
<td> </td>
<td>'
.$state.
'</td>
<td style="padding-left: 10px;">
<a href="./deviceDetails.php?mac='.$row['mac'].'">
<b class="anonymize">'.$row['name'].'</b>
</a>
</td>
<td>'
.$row['last_ip'].
'</td>
<td>
<button class="btn btn-primary btn-sm" data-myleafmac="'.$row['mac'].'" >'.lang('Network_ManageAssign').'</button>
</td>
</tr>';
}
$str_table_close = '</tbody>
</table>
</section>
</div>
</div>';
// write the html
echo $str_table_header.$str_table_rows.$str_table_close;
}
?>
<!-- /.content --> <!-- /.content -->
</div> <div class="nav-tabs-custom">
<!-- /.content-wrapper --> <ul class="nav nav-tabs">
<!-- Placeholder -->
</ul>
</div>
<div class="tab-content">
<!-- Placeholder -->
</div>
</section>
<section id="unassigned-devices-wrapper">
<!-- Placeholder -->
</section>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
<!-- ----------------------------------------------------------------------- --> <!-- ----------------------------------------------------------------------- -->
<?php <?php
require 'php/templates/footer.php'; require 'php/templates/footer.php';
?> ?>
<script src="lib/treeviz/bundle.js"></script> <script src="lib/treeviz/bundle.js"></script>
<script defer> <script defer>
// -----------------------------------------------------------------------
function loadNetworkNodes() {
// console.log(getSetting("NETWORK_DEVICE_TYPES").replace("[","").replace("]",""));
const rawSql = `
SELECT node_name, node_mac, online, node_type, node_ports_count, parent_mac, node_icon, node_alert
FROM (
SELECT a.devName as node_name, a.devMac as node_mac, a.devPresentLastScan as online,
a.devType as node_type, a.devParentMAC as parent_mac, a.devIcon as node_icon, a.devAlertDown as node_alert
FROM Devices a
WHERE a.devType in (${getSetting("NETWORK_DEVICE_TYPES").replace("[","").replace("]","")}) AND devIsArchived = 0
) t1
LEFT JOIN (
SELECT b.devParentMAC as node_mac_2, count() as node_ports_count
FROM Devices b
WHERE b.devParentMAC NOT NULL
GROUP BY b.devParentMAC
) t2
ON (t1.node_mac = t2.node_mac_2)
`;
const apiUrl = `php/server/dbHelper.php?action=read&rawSql=${btoa(encodeURIComponent(rawSql))}`;
$.get(apiUrl, function (data) {
const nodes = JSON.parse(data);
renderNetworkTabs(nodes);
loadUnassignedDevices();
});
}
// -----------------------------------------------------------------------
function renderNetworkTabs(nodes) {
let html = '';
nodes.forEach((node, i) => {
const iconClass = node.online == 1 ? "text-green" :
(node.node_alert == 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, '_');
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}">
<div class="icon ${iconClass}">${icon}</div>
<span class="node-name">${node.node_name}</span>${portLabel}
</a>
</li>`;
});
$('.nav-tabs').html(html);
// populate tabs
renderNetworkTabContent(nodes);
// init selected (first) tab
initTab();
// init selected node highlighting
initSelectedNodeHighlighting()
// Register events on tab change
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
initSelectedNodeHighlighting()
});
}
// -----------------------------------------------------------------------
function renderNetworkTabContent(nodes) {
$('.tab-content').empty();
nodes.forEach((node, i) => {
const id = node.node_mac.replace(/:/g, '_');
const badge = getStatusBadgeParts(
node.online,
node.node_alert,
node.node_mac
);
const badgeHtml = `<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.status}</a>`;
const parentId = node.parent_mac.replace(/:/g, '_');
const paneHtml = `
<div class="tab-pane box box-aqua box-body ${i === 0 ? 'active' : ''}" id="${id}">
<h2 class="page-header"><i class="fa fa-server"></i> ${getString('Network_Node')}</h2>
<table class="table table-striped">
<tbody>
<tr><td><b>${getString('Network_Node')}</b></td><td><a href="./deviceDetails.php?mac=${node.node_mac}" class="anonymize">${node.node_name}</a></td></tr>
<tr><td><b>MAC</b></td><td class="anonymize">${node.node_mac}</td></tr>
<tr><td><b>${getString('Device_TableHead_Type')}</b></td><td>${node.node_type}</td></tr>
<tr><td><b>${getString('Network_Table_State')}</b></td><td>${badgeHtml}</td></tr>
<tr><td><b>${getString('Network_Parent')}</b></td>
<td>
<a href="./network.php?mac=${parentId}">
<b class="anonymize"><span class="mac-to-name" my-data-mac="${node.parent_mac}">${node.parent_mac}</span>
<i class="fa fa-square-up-right"></i></b>
</a>
</td></tr>
</tbody>
</table>
<div class=" box box-aqua box-body" id="connected">
<h3 class="page-header">
<i class="fa fa-sitemap"></i>
${getString('Network_Connected')}
</h3>
<div id="leafs_${id}">
</div>
</div>
</div>`;
$('.tab-content').append(paneHtml);
loadConnectedDevices(node.node_mac);
});
}
// ----------------------------------------------------
function loadDeviceTable({ sql, containerSelector, tableId, wrapperHtml = null, assignMode = true }) {
const apiUrl = `php/server/dbHelper.php?action=read&rawSql=${btoa(encodeURIComponent(sql))}`;
$.get(apiUrl, function (data) {
const devices = JSON.parse(data);
const $container = $(containerSelector);
// end if nothing to show
if(devices.length == 0)
{
return;
}
$container.html(wrapperHtml);
const $table = $(`#${tableId}`);
const columns = [
{
title: getString('Network_Table_State'),
data: 'devStatus',
width: '15%',
render: function (_, type, device) {
const badge = getStatusBadgeParts(
device.devPresentLastScan,
device.devAlertDown,
device.devMac
);
return `<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.status}</a>`;
}
},
{
title: getString('Device_TableHead_Name'),
data: 'devName',
width: '15%',
render: function (name, type, device) {
return `<a href="./deviceDetails.php?mac=${device.devMac}">
<b class="anonymize">${name || '-'}</b>
</a>`;
}
},
{
title: 'MAC',
data: 'devMac',
width: '5%',
render: (data) => `<span class="anonymize">${data}</span>`
},
{
title: getString('Network_Table_IP'),
data: 'devLastIP',
width: '5%'
},
{
title: getString('Device_TableHead_Vendor'),
data: 'devVendor',
width: '20%'
},
{
title: assignMode ? getString('Network_ManageAssign') : getString('Network_ManageUnassign'),
data: 'devMac',
orderable: false,
width: '5%',
render: function (mac) {
const label = assignMode ? 'assign' : 'unassign';
const btnClass = assignMode ? 'btn-primary' : 'btn-primary bg-red';
const btnText = assignMode ? getString('Network_ManageAssign') : getString('Network_ManageUnassign');
return `<button class="btn ${btnClass} btn-sm" data-myleafmac="${mac}" onclick="updateLeaf('${mac}','${label}')">
${btnText}
</button>`;
}
}
].filter(Boolean);
tableConfig = {
data: devices,
columns: columns,
pageLength: 10,
order: assignMode ? [[2, 'asc']] : [],
responsive: true,
autoWidth: false,
searching: true
}
if ($.fn.DataTable.isDataTable($table)) {
$table.DataTable(tableConfig).clear().rows.add(devices).draw();
} else {
$table.DataTable(tableConfig);
}
});
}
// ----------------------------------------------------
function loadUnassignedDevices() {
const sql = `
SELECT devMac, devPresentLastScan, devName, devLastIP, devVendor, devAlertDown
FROM Devices
WHERE (devParentMAC IS NULL OR devParentMAC IN ("", " ", "undefined", "null"))
AND devMac NOT LIKE "%internet%"
AND devIsArchived = 0
ORDER BY devName ASC`;
const wrapperHtml = `
<div class="content">
<div id="unassignedDevices" class="box box-aqua box-body">
<section>
<h3><i class="fa fa-laptop"></i> ${getString('Network_UnassignedDevices')}</h3>
<table id="unassignedDevicesTable" class="table table-striped" width="100%"></table>
</section>
</div>
</div>`;
loadDeviceTable({
sql,
containerSelector: '#unassigned-devices-wrapper',
tableId: 'unassignedDevicesTable',
wrapperHtml,
assignMode: true
});
}
// ----------------------------------------------------
function loadConnectedDevices(node_mac) {
const sql = `
SELECT devName, devMac, devLastIP, devVendor, devPresentLastScan, devAlertDown,
CASE
WHEN devAlertDown != 0 AND devPresentLastScan = 0 THEN "Down"
WHEN devPresentLastScan = 1 THEN "On-line"
ELSE "Off-line"
END as devStatus
FROM Devices
WHERE devIsArchived = 0 AND devParentMac = '${node_mac}'`;
const id = node_mac.replace(/:/g, '_');
const wrapperHtml = `
<table class="table table-bordered table-striped node-leafs-table" id="table_leafs_${id}" data-node-mac="${node_mac}">
</table>`;
loadDeviceTable({
sql,
containerSelector: `#leafs_${id}`,
tableId: `table_leafs_${id}`,
wrapperHtml,
assignMode: false
});
}
// INIT
const apiUrl = `php/server/dbHelper.php?action=read&rawSql=${btoa(encodeURIComponent( const apiUrl = `php/server/dbHelper.php?action=read&rawSql=${btoa(encodeURIComponent(
`select *, CASE WHEN devAlertDown !=0 AND devPresentLastScan=0 THEN "Down" `select *, CASE WHEN devAlertDown !=0 AND devPresentLastScan=0 THEN "Down"
WHEN devPresentLastScan=1 THEN "On-line" WHEN devPresentLastScan=1 THEN "On-line"
@@ -528,6 +389,9 @@
// create tree // create tree
initTree(getHierarchy()); initTree(getHierarchy());
// bottom tables
loadNetworkNodes();
// attach on-click events // attach on-click events
attachTreeEvents(); attachTreeEvents();
}); });
@@ -825,14 +689,6 @@ function initTree(myHierarchy)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Tabs functionality // Tabs functionality
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Register events on tab change
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
initButtons()
});
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function initTab() function initTab()
@@ -885,15 +741,15 @@ function initDeviceNamesFromMACs()
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function initButtons() function initSelectedNodeHighlighting()
{ {
var currentNodeMac = $(".tab-content .active td[data-mynodemac]").attr('data-mynodemac'); var currentNodeMac = $(".networkNodeTabHeaders.active a").data("mytabmac");
// change highlighted node in the tree // change highlighted node in the tree
selNode = $("#networkTree .highlightedNode")[0] selNode = $("#networkTree .highlightedNode")[0]
// console.log(selNode) console.log(selNode)
if(selNode) if(selNode)
{ {
@@ -901,48 +757,41 @@ function initButtons()
} }
newSelNode = $("#networkTree div[data-mytreemacmain='"+currentNodeMac+"']")[0] newSelNode = $("#networkTree div[data-mytreemacmain='"+currentNodeMac+"']")[0]
console.log(newSelNode)
$(newSelNode).attr('class', $(newSelNode).attr('class') + ' highlightedNode') $(newSelNode).attr('class', $(newSelNode).attr('class') + ' highlightedNode')
// init the Assign buttons
$('#unassignedDevices button[data-myleafmac]').each(function(){
$(this).attr('onclick', `updateLeaf("${$(this).attr('data-myleafmac')}","${currentNodeMac}")`)
});
// init Unassign buttons
$('#assignedDevices button[data-myleafmac]').each(function(){
$(this).attr('onclick', `updateLeaf("${$(this).attr('data-myleafmac')}","")`)
});
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
function updateLeaf(leafMac,nodeMac) function updateLeaf(leafMac, action) {
{ console.log(leafMac); // child
console.log(leafMac) // child console.log(action); // action
console.log(nodeMac) // parent
console.log(nodeMac != "") // parent
// prevent the assignment of the Internet root node avoiding recursion when generating the network tree topology const nodeMac = $(".networkNodeTabHeaders.active a").data("mytabmac") || "";
if(leafMac.toLowerCase().includes('internet') && nodeMac != "")
{ if (action === "assign") {
showMessage(getString('Network_Cant_Assign')) if (!nodeMac) {
} showMessage(getString("Network_Cant_Assign_No_Node_Selected"));
else{ } else if (leafMac.toLowerCase().includes("internet")) {
saveData('updateNetworkLeaf', leafMac, nodeMac); showMessage(getString("Network_Cant_Assign"));
setTimeout("location.reload();", 500); // refresh page } else {
saveData("updateNetworkLeaf", leafMac, nodeMac);
setTimeout(() => location.reload(), 500);
}
} else if (action === "unassign") {
saveData("updateNetworkLeaf", leafMac, "");
setTimeout(() => location.reload(), 500);
} else {
console.warn("Unknown action:", action);
} }
} }
// init device names where macs are used // init device names where macs are used
initDeviceNamesFromMACs(); initDeviceNamesFromMACs();
// init selected (first) tab
initTab();
// init Assign/Unassign buttons
initButtons()
// init pop up hover boxes for device details // init pop up hover boxes for device details
initHoverNodeInfo(); initHoverNodeInfo();

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "تدفقات العمل", "Navigation_Workflows": "تدفقات العمل",
"Network_Assign": "تعيين", "Network_Assign": "تعيين",
"Network_Cant_Assign": "لا يمكن التعيين", "Network_Cant_Assign": "لا يمكن التعيين",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "خطأ في التكوين", "Network_Configuration_Error": "خطأ في التكوين",
"Network_Connected": "متصل", "Network_Connected": "متصل",
"Network_ManageAdd": "إضافة إدارة", "Network_ManageAdd": "إضافة إدارة",
@@ -715,6 +716,7 @@
"devices_old": "الأجهزة القديمة", "devices_old": "الأجهزة القديمة",
"general_event_description": "وصف الحدث العام", "general_event_description": "وصف الحدث العام",
"general_event_title": "عنوان الحدث العام", "general_event_title": "عنوان الحدث العام",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "تلميح الانتقال إلى العقدة", "go_to_node_event_tooltip": "تلميح الانتقال إلى العقدة",
"new_version_available": "يتوفر إصدار جديد", "new_version_available": "يتوفر إصدار جديد",
"report_guid": "معرف التقرير", "report_guid": "معرف التقرير",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Workflows", "Navigation_Workflows": "Workflows",
"Network_Assign": "Connecta el <i class=\"fa fa-server\"></i> node de Xarxa", "Network_Assign": "Connecta el <i class=\"fa fa-server\"></i> node de Xarxa",
"Network_Cant_Assign": "No es pot assignar el node arrel d'Internet com a node fill.", "Network_Cant_Assign": "No es pot assignar el node arrel d'Internet com a node fill.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Error de configuració", "Network_Configuration_Error": "Error de configuració",
"Network_Connected": "Dispositius connectats", "Network_Connected": "Dispositius connectats",
"Network_ManageAdd": "Afegir dispositiu", "Network_ManageAdd": "Afegir dispositiu",
@@ -715,6 +716,7 @@
"devices_old": "Refrescant...", "devices_old": "Refrescant...",
"general_event_description": "L'esdeveniment que has desencadenat pot trigar un temps fins que acabin els processos de fons. L'execució acabarà una cop buida la cua d'execució (Comprova el registre d'errors <a href='/maintenance.php#tab_Logging'></a> si hi ha problemes). <br/> <br/> Cua d'execució:", "general_event_description": "L'esdeveniment que has desencadenat pot trigar un temps fins que acabin els processos de fons. L'execució acabarà una cop buida la cua d'execució (Comprova el registre d'errors <a href='/maintenance.php#tab_Logging'></a> si hi ha problemes). <br/> <br/> Cua d'execució:",
"general_event_title": "Execució d'un esdeveniment ad-hoc", "general_event_title": "Execució d'un esdeveniment ad-hoc",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "Navegació a la pàgina de la Xarxa del node donat", "go_to_node_event_tooltip": "Navegació a la pàgina de la Xarxa del node donat",
"new_version_available": "Ja està disponible una nova versió.", "new_version_available": "Ja està disponible una nova versió.",
"report_guid": "Notificació guid:", "report_guid": "Notificació guid:",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "", "Navigation_Workflows": "",
"Network_Assign": "", "Network_Assign": "",
"Network_Cant_Assign": "", "Network_Cant_Assign": "",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "", "Network_Configuration_Error": "",
"Network_Connected": "", "Network_Connected": "",
"Network_ManageAdd": "", "Network_ManageAdd": "",
@@ -715,6 +716,7 @@
"devices_old": "Obnovuji…", "devices_old": "Obnovuji…",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "", "report_guid": "",

View File

@@ -528,6 +528,7 @@
"Navigation_Workflows": "Arbeitsabläufe", "Navigation_Workflows": "Arbeitsabläufe",
"Network_Assign": "Zum obigen <i class=\"fa fa-server\"></i> Netzwerkknoten zuweisen", "Network_Assign": "Zum obigen <i class=\"fa fa-server\"></i> Netzwerkknoten zuweisen",
"Network_Cant_Assign": "Internet-Wurzelknoten kann nicht als äußerer Kindknoten zugewiesen werden.", "Network_Cant_Assign": "Internet-Wurzelknoten kann nicht als äußerer Kindknoten zugewiesen werden.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Konfigurationsfehler", "Network_Configuration_Error": "Konfigurationsfehler",
"Network_Connected": "Verbundene Geräte", "Network_Connected": "Verbundene Geräte",
"Network_ManageAdd": "Gerät hinzufügen", "Network_ManageAdd": "Gerät hinzufügen",
@@ -796,6 +797,7 @@
"devices_old": "Aktualisiert...", "devices_old": "Aktualisiert...",
"general_event_description": "Das Ereignis, das Sie ausgelöst haben, könnte eine Weile dauern, bis Hintergrundprozesse abgeschlossen sind. Die Ausführung endet, wenn die unten ausgeführte Warteschlangen abgearbeitet ist. (Siehe <a href='/maintenance.php#tab_Logging'>error log</a>, wenn Probleme auftreten.)<br/> <br/> Ausführungsschlange:", "general_event_description": "Das Ereignis, das Sie ausgelöst haben, könnte eine Weile dauern, bis Hintergrundprozesse abgeschlossen sind. Die Ausführung endet, wenn die unten ausgeführte Warteschlangen abgearbeitet ist. (Siehe <a href='/maintenance.php#tab_Logging'>error log</a>, wenn Probleme auftreten.)<br/> <br/> Ausführungsschlange:",
"general_event_title": "", "general_event_title": "",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "Es ist eine neue Version verfügbar.", "new_version_available": "Es ist eine neue Version verfügbar.",
"report_guid": "", "report_guid": "",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Workflows", "Navigation_Workflows": "Workflows",
"Network_Assign": "Connect to the above <i class=\"fa fa-server\"></i> Network node", "Network_Assign": "Connect to the above <i class=\"fa fa-server\"></i> Network node",
"Network_Cant_Assign": "Can't assign the root Internet node as a child leaf node.", "Network_Cant_Assign": "Can't assign the root Internet node as a child leaf node.",
"Network_Cant_Assign_No_Node_Selected": "Can't assign, no parent node selected.",
"Network_Configuration_Error": "Configuration Error", "Network_Configuration_Error": "Configuration Error",
"Network_Connected": "Connected devices", "Network_Connected": "Connected devices",
"Network_ManageAdd": "Add Device", "Network_ManageAdd": "Add Device",
@@ -715,8 +716,8 @@
"devices_old": "Refreshing…", "devices_old": "Refreshing…",
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:", "general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
"general_event_title": "Executing an ad-hoc event", "general_event_title": "Executing an ad-hoc event",
"go_to_node_event_tooltip": "Navigate to the Network page of the given node",
"go_to_device_event_tooltip": "Navigate to the Device", "go_to_device_event_tooltip": "Navigate to the Device",
"go_to_node_event_tooltip": "Navigate to the Network page of the given node",
"new_version_available": "A new version is available.", "new_version_available": "A new version is available.",
"report_guid": "Notification guid:", "report_guid": "Notification guid:",
"report_guid_missing": "Linked notification not found. There is a small delay between recently sent notifications and them being available. Referesh your page and cache after a few seconds. It's also possible the selected notification have been deleted during maintenance as specified in the <code>DBCLNP_NOTIFI_HIST</code> setting. <br/> <br/>The latest notification is displayed instead. The missing notification has the following GUID:", "report_guid_missing": "Linked notification not found. There is a small delay between recently sent notifications and them being available. Referesh your page and cache after a few seconds. It's also possible the selected notification have been deleted during maintenance as specified in the <code>DBCLNP_NOTIFI_HIST</code> setting. <br/> <br/>The latest notification is displayed instead. The missing notification has the following GUID:",

View File

@@ -526,6 +526,7 @@
"Navigation_Workflows": "Flujo de trabajo", "Navigation_Workflows": "Flujo de trabajo",
"Network_Assign": "Conectar al nodo de <i class=\"fa fa-server\"></i> red", "Network_Assign": "Conectar al nodo de <i class=\"fa fa-server\"></i> red",
"Network_Cant_Assign": "No se puede asignar el nodo principal de Internet como nodo secundario.", "Network_Cant_Assign": "No se puede asignar el nodo principal de Internet como nodo secundario.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Error en la configuración", "Network_Configuration_Error": "Error en la configuración",
"Network_Connected": "Dispositivos conectados", "Network_Connected": "Dispositivos conectados",
"Network_ManageAdd": "Añadir dispositivo", "Network_ManageAdd": "Añadir dispositivo",
@@ -794,6 +795,7 @@
"devices_old": "Volviendo a actualizar....", "devices_old": "Volviendo a actualizar....",
"general_event_description": "El evento que ha activado puede tardar un poco hasta que finalicen los procesos en segundo plano. La ejecución finalizó una vez que se vacía la cola de ejecución a continuación (consulte el <a href='/maintenance.php#tab_Logging'>registro de errores</a> si encuentra problemas). <br/> <br/> Cola de ejecución:", "general_event_description": "El evento que ha activado puede tardar un poco hasta que finalicen los procesos en segundo plano. La ejecución finalizó una vez que se vacía la cola de ejecución a continuación (consulte el <a href='/maintenance.php#tab_Logging'>registro de errores</a> si encuentra problemas). <br/> <br/> Cola de ejecución:",
"general_event_title": "Ejecutar un evento ad-hoc", "general_event_title": "Ejecutar un evento ad-hoc",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "Vaya a la página de Red del nodo indicado", "go_to_node_event_tooltip": "Vaya a la página de Red del nodo indicado",
"new_version_available": "Una nueva versión está disponible.", "new_version_available": "Una nueva versión está disponible.",
"report_guid": "Guía de las notificaciones:", "report_guid": "Guía de las notificaciones:",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Flux de travail", "Navigation_Workflows": "Flux de travail",
"Network_Assign": "Se connecter à ce <i class=\"fa fa-server\"></i> nœud réseau", "Network_Assign": "Se connecter à ce <i class=\"fa fa-server\"></i> nœud réseau",
"Network_Cant_Assign": "Impossible d'assigner le noeud racine Internet comme enfant d'un noeud.", "Network_Cant_Assign": "Impossible d'assigner le noeud racine Internet comme enfant d'un noeud.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Erreur de configuration", "Network_Configuration_Error": "Erreur de configuration",
"Network_Connected": "Appareils connectés", "Network_Connected": "Appareils connectés",
"Network_ManageAdd": "Ajouter un appareil", "Network_ManageAdd": "Ajouter un appareil",
@@ -715,6 +716,7 @@
"devices_old": "Rafraichissement…", "devices_old": "Rafraichissement…",
"general_event_description": "L'événement que vous avez lancé peut prendre du temps avant que les tâches de fond ne soit terminées. La durée d'exécution finira une fois que la file d'exécution ci-dessous sera vide (consulter les <a href='/maintenance.php#tab_Logging'>journaux d'erreur</a> si vous rencontrez des erreurs). <br/> <br/> File d'exécution:", "general_event_description": "L'événement que vous avez lancé peut prendre du temps avant que les tâches de fond ne soit terminées. La durée d'exécution finira une fois que la file d'exécution ci-dessous sera vide (consulter les <a href='/maintenance.php#tab_Logging'>journaux d'erreur</a> si vous rencontrez des erreurs). <br/> <br/> File d'exécution:",
"general_event_title": "Lancement d'un événement sur mesure", "general_event_title": "Lancement d'un événement sur mesure",
"go_to_device_event_tooltip": "Naviguer vers cet appareil",
"go_to_node_event_tooltip": "Aller vers la page Réseau du nœud concerné", "go_to_node_event_tooltip": "Aller vers la page Réseau du nœud concerné",
"new_version_available": "Une nouvelle version est disponible.", "new_version_available": "Une nouvelle version est disponible.",
"report_guid": "GUID de la notification:", "report_guid": "GUID de la notification:",
@@ -748,6 +750,5 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Système", "settings_system_label": "Système",
"settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>", "settings_update_item_warning": "Mettre à jour la valeur ci-dessous. Veillez à bien suivre le même format qu'auparavant. <b>Il n'y a pas de pas de contrôle.</b>",
"test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage.", "test_event_tooltip": "Enregistrer d'abord vos modifications avant de tester vôtre paramétrage."
"go_to_device_event_tooltip": "Naviguer vers cet appareil" }
}

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Workflow", "Navigation_Workflows": "Workflow",
"Network_Assign": "Connetti al nodo di rete <i class=\"fa fa-server\"></i> sopra", "Network_Assign": "Connetti al nodo di rete <i class=\"fa fa-server\"></i> sopra",
"Network_Cant_Assign": "Impossibile assegnare il nodo Internet root come nodo foglia figlio.", "Network_Cant_Assign": "Impossibile assegnare il nodo Internet root come nodo foglia figlio.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Errore di configurazione", "Network_Configuration_Error": "Errore di configurazione",
"Network_Connected": "Dispositivi connessi", "Network_Connected": "Dispositivi connessi",
"Network_ManageAdd": "Aggiungi dispositivo", "Network_ManageAdd": "Aggiungi dispositivo",
@@ -715,6 +716,7 @@
"devices_old": "Aggiornamento…", "devices_old": "Aggiornamento…",
"general_event_description": "L'evento che hai attivato potrebbe richiedere del tempo prima che i processi in background vengano completati. L'esecuzione è terminata una volta che la coda di esecuzione sottostante si è svuotata (controlla il <a href='/maintenance.php#tab_Logging'>log degli errori</a> se riscontri problemi). <br/> <br/> Coda di esecuzione:", "general_event_description": "L'evento che hai attivato potrebbe richiedere del tempo prima che i processi in background vengano completati. L'esecuzione è terminata una volta che la coda di esecuzione sottostante si è svuotata (controlla il <a href='/maintenance.php#tab_Logging'>log degli errori</a> se riscontri problemi). <br/> <br/> Coda di esecuzione:",
"general_event_title": "Esecuzione di un evento ad-hoc", "general_event_title": "Esecuzione di un evento ad-hoc",
"go_to_device_event_tooltip": "Naviga al dispositivo",
"go_to_node_event_tooltip": "Passa alla pagina Rete del nodo specificato", "go_to_node_event_tooltip": "Passa alla pagina Rete del nodo specificato",
"new_version_available": "È disponibile una nuova versione.", "new_version_available": "È disponibile una nuova versione.",
"report_guid": "GUID notifica:", "report_guid": "GUID notifica:",
@@ -748,6 +750,5 @@
"settings_system_icon": "fa-solid fa-gear", "settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Sistema", "settings_system_label": "Sistema",
"settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>", "settings_update_item_warning": "Aggiorna il valore qui sotto. Fai attenzione a seguire il formato precedente. <b>La convalida non viene eseguita.</b>",
"test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni.", "test_event_tooltip": "Salva le modifiche prima di provare le nuove impostazioni."
"go_to_device_event_tooltip": "Naviga al dispositivo" }
}

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Arbeidsflyter", "Navigation_Workflows": "Arbeidsflyter",
"Network_Assign": "Koble til ovenfor <i class=\"fa fa-server\"></i> nettverksnode", "Network_Assign": "Koble til ovenfor <i class=\"fa fa-server\"></i> nettverksnode",
"Network_Cant_Assign": "Kan ikke tilordne rot-internettnoden som sekundær node.", "Network_Cant_Assign": "Kan ikke tilordne rot-internettnoden som sekundær node.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Konfigurasjonsfeil", "Network_Configuration_Error": "Konfigurasjonsfeil",
"Network_Connected": "Tilkoblede enheter", "Network_Connected": "Tilkoblede enheter",
"Network_ManageAdd": "Legg til enhet", "Network_ManageAdd": "Legg til enhet",
@@ -715,6 +716,7 @@
"devices_old": "Oppdaterer...", "devices_old": "Oppdaterer...",
"general_event_description": "Hendelsen du har utløst kan ta en stund til før bakgrunnsprosesser er ferdig. Utførelsen ble avsluttet når utførelseskøen nedenfor tømmes (sjekk <a href='/maintenance.php#tab_Logging'>Feillogg</a> Hvis du møter problemer). <br/> <br/> Utførelseskø:", "general_event_description": "Hendelsen du har utløst kan ta en stund til før bakgrunnsprosesser er ferdig. Utførelsen ble avsluttet når utførelseskøen nedenfor tømmes (sjekk <a href='/maintenance.php#tab_Logging'>Feillogg</a> Hvis du møter problemer). <br/> <br/> Utførelseskø:",
"general_event_title": "Utfører en ad-hoc hendelse", "general_event_title": "Utfører en ad-hoc hendelse",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "Notifikasjons GUID:", "report_guid": "Notifikasjons GUID:",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Przepływy pracy", "Navigation_Workflows": "Przepływy pracy",
"Network_Assign": "Połącz się z powyższym <i class=\"fa fa-server\"></i> węzłem sieciowym", "Network_Assign": "Połącz się z powyższym <i class=\"fa fa-server\"></i> węzłem sieciowym",
"Network_Cant_Assign": "Nie można przypisać głównego węzła internetowego jako podrzędnego węzła liścia.", "Network_Cant_Assign": "Nie można przypisać głównego węzła internetowego jako podrzędnego węzła liścia.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Błąd konfiguracji", "Network_Configuration_Error": "Błąd konfiguracji",
"Network_Connected": "Połączone urządzenia", "Network_Connected": "Połączone urządzenia",
"Network_ManageAdd": "Dodaj urządzenie", "Network_ManageAdd": "Dodaj urządzenie",
@@ -715,6 +716,7 @@
"devices_old": "Odświeżanie…", "devices_old": "Odświeżanie…",
"general_event_description": "Zdarzenie, które wywołałeś, może potrwać chwilę, zanim zakończą się procesy w tle. Wykonanie zostanie zakończone, gdy poniższa kolejka wykonania zostanie opróżniona (jeśli napotkasz problemy, sprawdź <a href='/maintenance.php#tab_Logging'>dziennik błędów</a>). <br/><br/>Kolejka wykonania:", "general_event_description": "Zdarzenie, które wywołałeś, może potrwać chwilę, zanim zakończą się procesy w tle. Wykonanie zostanie zakończone, gdy poniższa kolejka wykonania zostanie opróżniona (jeśli napotkasz problemy, sprawdź <a href='/maintenance.php#tab_Logging'>dziennik błędów</a>). <br/><br/>Kolejka wykonania:",
"general_event_title": "Wykonywanie zdarzenia ad-hoc", "general_event_title": "Wykonywanie zdarzenia ad-hoc",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "Przejdź do strony Sieć danego węzła", "go_to_node_event_tooltip": "Przejdź do strony Sieć danego węzła",
"new_version_available": "Dostępna jest nowa wersja.", "new_version_available": "Dostępna jest nowa wersja.",
"report_guid": "GUID powiadomienia:", "report_guid": "GUID powiadomienia:",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "", "Navigation_Workflows": "",
"Network_Assign": "", "Network_Assign": "",
"Network_Cant_Assign": "", "Network_Cant_Assign": "",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "", "Network_Configuration_Error": "",
"Network_Connected": "", "Network_Connected": "",
"Network_ManageAdd": "", "Network_ManageAdd": "",
@@ -715,6 +716,7 @@
"devices_old": "", "devices_old": "",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "", "report_guid": "",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Рабочие процессы", "Navigation_Workflows": "Рабочие процессы",
"Network_Assign": "Подключитесь к указанному выше сетевому узлу <i class=\"fa fa-server\"></i>", "Network_Assign": "Подключитесь к указанному выше сетевому узлу <i class=\"fa fa-server\"></i>",
"Network_Cant_Assign": "Невозможно назначить корневой узел Интернета в качестве дочернего конечного узла.", "Network_Cant_Assign": "Невозможно назначить корневой узел Интернета в качестве дочернего конечного узла.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Ошибка конфигурации", "Network_Configuration_Error": "Ошибка конфигурации",
"Network_Connected": "Подключенные устройства", "Network_Connected": "Подключенные устройства",
"Network_ManageAdd": "Добавить устройство", "Network_ManageAdd": "Добавить устройство",
@@ -715,6 +716,7 @@
"devices_old": "Актуализируется…", "devices_old": "Актуализируется…",
"general_event_description": "Событие, которое вы инициировали, может занять некоторое время, прежде чем фоновые процессы завершатся. Выполнение завершится, как только очередь выполнения, указанная ниже, опустеет (Проверьте <a href='/maintenance.php#tab_Logging'>журнал ошибок</a> при возникновении проблем). <br/> <br/>· · Очередь выполнения:", "general_event_description": "Событие, которое вы инициировали, может занять некоторое время, прежде чем фоновые процессы завершатся. Выполнение завершится, как только очередь выполнения, указанная ниже, опустеет (Проверьте <a href='/maintenance.php#tab_Logging'>журнал ошибок</a> при возникновении проблем). <br/> <br/>· · Очередь выполнения:",
"general_event_title": "Выполнение специального события", "general_event_title": "Выполнение специального события",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "Переход на страницу \"Сеть\" данного узла", "go_to_node_event_tooltip": "Переход на страницу \"Сеть\" данного узла",
"new_version_available": "Доступна новая версия.", "new_version_available": "Доступна новая версия.",
"report_guid": "Идентификатор уведомления:", "report_guid": "Идентификатор уведомления:",
@@ -749,4 +751,4 @@
"settings_system_label": "Система", "settings_system_label": "Система",
"settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>", "settings_update_item_warning": "Обновить значение ниже. Будьте осторожны, следуя предыдущему формату. <b>Проверка не выполняется.</b>",
"test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки." "test_event_tooltip": "Сначала сохраните изменения, прежде чем проверять настройки."
} }

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "İş Akışları", "Navigation_Workflows": "İş Akışları",
"Network_Assign": "Yukarıdakilere bağlanın <i class=\"fa fa-server\"></i> Ağ düğümü", "Network_Assign": "Yukarıdakilere bağlanın <i class=\"fa fa-server\"></i> Ağ düğümü",
"Network_Cant_Assign": "", "Network_Cant_Assign": "",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Kurulum Hatası", "Network_Configuration_Error": "Kurulum Hatası",
"Network_Connected": "Bağlanmış cihazlar", "Network_Connected": "Bağlanmış cihazlar",
"Network_ManageAdd": "Cihaz Ekle", "Network_ManageAdd": "Cihaz Ekle",
@@ -715,6 +716,7 @@
"devices_old": "Yenileniyor...", "devices_old": "Yenileniyor...",
"general_event_description": "", "general_event_description": "",
"general_event_title": "", "general_event_title": "",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "", "report_guid": "",

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "Робочі процеси", "Navigation_Workflows": "Робочі процеси",
"Network_Assign": "Підключіться до зазначеного вище <i class=\"fa fa-server\"></i> вузла мережі", "Network_Assign": "Підключіться до зазначеного вище <i class=\"fa fa-server\"></i> вузла мережі",
"Network_Cant_Assign": "Неможливо призначити кореневий вузол Інтернету як дочірній кінцевий вузол.", "Network_Cant_Assign": "Неможливо призначити кореневий вузол Інтернету як дочірній кінцевий вузол.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Помилка конфігурації", "Network_Configuration_Error": "Помилка конфігурації",
"Network_Connected": "Підключені пристрої", "Network_Connected": "Підключені пристрої",
"Network_ManageAdd": "Додати пристрій", "Network_ManageAdd": "Додати пристрій",
@@ -715,6 +716,7 @@
"devices_old": "Освіжає…", "devices_old": "Освіжає…",
"general_event_description": "Подія, яку ви ініціювали, може зайняти деякий час, поки завершаться фонові процеси. Виконання завершилося, коли наведена нижче черга виконання спорожнилася (перевірте <a href='/maintenance.php#tab_Logging'>журнал помилок</a>, якщо виникнуть проблеми). <br/> <br/> Черга виконання:", "general_event_description": "Подія, яку ви ініціювали, може зайняти деякий час, поки завершаться фонові процеси. Виконання завершилося, коли наведена нижче черга виконання спорожнилася (перевірте <a href='/maintenance.php#tab_Logging'>журнал помилок</a>, якщо виникнуть проблеми). <br/> <br/> Черга виконання:",
"general_event_title": "Виконання спеціальної події", "general_event_title": "Виконання спеціальної події",
"go_to_device_event_tooltip": "Перейдіть до пристрою",
"go_to_node_event_tooltip": "Перейдіть на сторінку Мережа даного вузла", "go_to_node_event_tooltip": "Перейдіть на сторінку Мережа даного вузла",
"new_version_available": "Доступна нова версія.", "new_version_available": "Доступна нова версія.",
"report_guid": "Довідник сповіщень:", "report_guid": "Довідник сповіщень:",
@@ -748,6 +750,5 @@
"settings_system_icon": "фа-твердий фа-передача", "settings_system_icon": "фа-твердий фа-передача",
"settings_system_label": "Система", "settings_system_label": "Система",
"settings_update_item_warning": "Оновіть значення нижче. Слідкуйте за попереднім форматом. <b>Перевірка не виконана.</b>", "settings_update_item_warning": "Оновіть значення нижче. Слідкуйте за попереднім форматом. <b>Перевірка не виконана.</b>",
"test_event_tooltip": "Перш ніж перевіряти налаштування, збережіть зміни.", "test_event_tooltip": "Перш ніж перевіряти налаштування, збережіть зміни."
"go_to_device_event_tooltip": "Перейдіть до пристрою" }
}

View File

@@ -491,6 +491,7 @@
"Navigation_Workflows": "工作流程", "Navigation_Workflows": "工作流程",
"Network_Assign": "连接上述 <i class=\"fa fa-server\"></i> 网络节点", "Network_Assign": "连接上述 <i class=\"fa fa-server\"></i> 网络节点",
"Network_Cant_Assign": "无法将根 Internet 节点指定为子节点。", "Network_Cant_Assign": "无法将根 Internet 节点指定为子节点。",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "配置错误", "Network_Configuration_Error": "配置错误",
"Network_Connected": "联网设备", "Network_Connected": "联网设备",
"Network_ManageAdd": "添加设备", "Network_ManageAdd": "添加设备",
@@ -715,6 +716,7 @@
"devices_old": "刷新中...", "devices_old": "刷新中...",
"general_event_description": "您触发的事件可能需要一段时间才能完成后台进程。一旦以下执行队列清空,执行就会结束(如果遇到问题,请检查<a href='/maintenance.php#tab_Logging'>错误日志</a>)。<br/> <br/> 执行队列:", "general_event_description": "您触发的事件可能需要一段时间才能完成后台进程。一旦以下执行队列清空,执行就会结束(如果遇到问题,请检查<a href='/maintenance.php#tab_Logging'>错误日志</a>)。<br/> <br/> 执行队列:",
"general_event_title": "执行自组织网络事件", "general_event_title": "执行自组织网络事件",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "", "go_to_node_event_tooltip": "",
"new_version_available": "", "new_version_available": "",
"report_guid": "通知guid", "report_guid": "通知guid",