Compare commits
34 Commits
4d401f60dc
...
v25.4.14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bb87fe8df | ||
|
|
71bcbbe7f9 | ||
|
|
f941133304 | ||
|
|
470997fcde | ||
|
|
d6b2ac587f | ||
|
|
e6962e0393 | ||
|
|
426dd48540 | ||
|
|
7da11d167d | ||
|
|
40e090c5c6 | ||
|
|
3ccb165658 | ||
|
|
a12da278c6 | ||
|
|
ffb0d0238d | ||
|
|
599603d9ff | ||
|
|
befb58619b | ||
|
|
f83cdc766b | ||
|
|
6fb1547fc4 | ||
|
|
ea9a07d29e | ||
|
|
2889be28e4 | ||
|
|
46a8bb66e7 | ||
|
|
578a6d0d48 | ||
|
|
e1f9ca05b7 | ||
|
|
4aaf86f0fc | ||
|
|
9bb21ad303 | ||
|
|
e1197eb3f8 | ||
|
|
2c445ccaeb | ||
|
|
8a07f7067b | ||
|
|
d86c2a5023 | ||
|
|
2b51674e52 | ||
|
|
eb6820dd93 | ||
|
|
b156246cb0 | ||
|
|
716c6a4046 | ||
|
|
114b5a2621 | ||
|
|
02b19c833e | ||
|
|
e0c06548ba |
3
.github/ISSUE_TEMPLATE/i-have-an-issue.yml
vendored
@@ -59,12 +59,15 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
|
id: installation_type
|
||||||
attributes:
|
attributes:
|
||||||
label: What installation are you running?
|
label: What installation are you running?
|
||||||
options:
|
options:
|
||||||
- Production (netalertx)
|
- Production (netalertx)
|
||||||
- Dev (netalertx-dev)
|
- Dev (netalertx-dev)
|
||||||
- Home Assistant (addon)
|
- Home Assistant (addon)
|
||||||
|
- Home Assistant fa (full-access addon)
|
||||||
|
- Bare-metal (community only support - Check Discord)
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
3
.github/ISSUE_TEMPLATE/setup-help.yml
vendored
@@ -44,12 +44,15 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: false
|
required: false
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
|
id: installation_type
|
||||||
attributes:
|
attributes:
|
||||||
label: What installation are you running?
|
label: What installation are you running?
|
||||||
options:
|
options:
|
||||||
- Production (netalertx)
|
- Production (netalertx)
|
||||||
- Dev (netalertx-dev)
|
- Dev (netalertx-dev)
|
||||||
- Home Assistant (addon)
|
- Home Assistant (addon)
|
||||||
|
- Home Assistant fa (full-access addon)
|
||||||
|
- Bare-metal (community only support - Check Discord)
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
2
.github/tweet.md
vendored
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
🎉 New release: **v25.4.1 - 🔀 Workflows - automate device management ** is live! 🚀
|
||||||
|
Check it out here: https://github.com/jokob-sk/NetAlertX/releases/tag/v25.4.1
|
||||||
7
.github/workflows/code_checks.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: URL Path Check
|
name: Code checks
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -25,4 +25,9 @@ jobs:
|
|||||||
else
|
else
|
||||||
echo "✅ No absolute path URLs found."
|
echo "✅ No absolute path URLs found."
|
||||||
fi
|
fi
|
||||||
|
- name: Check Python syntax
|
||||||
|
run: |
|
||||||
|
set -e
|
||||||
|
echo "🔍 Checking Python syntax..."
|
||||||
|
find . -name "*.py" -print0 | xargs -0 -n1 python3 -m py_compile
|
||||||
|
|
||||||
|
|||||||
43
.github/workflows/label-issues.yml
vendored
Executable file
@@ -0,0 +1,43 @@
|
|||||||
|
name: Label Issues by Installation Type
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [opened]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
add-label:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Get issue content
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const body = context.payload.issue.body;
|
||||||
|
|
||||||
|
const lowerBody = body.toLowerCase();
|
||||||
|
|
||||||
|
let labelsToAdd = [];
|
||||||
|
|
||||||
|
if (lowerBody.includes('bare-metal')) {
|
||||||
|
labelsToAdd.push('bare-metal ❗');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowerBody.includes('home assistant')) {
|
||||||
|
labelsToAdd.push('Home Assistant 🏠');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lowerBody.includes('production (netalertx)') || lowerBody.includes('dev (netalertx-dev)')) {
|
||||||
|
labelsToAdd.push('Docker 🐋');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labelsToAdd.length > 0) {
|
||||||
|
await github.rest.issues.addLabels({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
labels: labelsToAdd
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -41,6 +41,10 @@ Send notifications to more than 80+ services, including Telegram via [Apprise](h
|
|||||||
Feed your data and device changes into [Home Assistant](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HOME_ASSISTANT.md), read [API endpoints](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md), or use [Webhooks](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WEBHOOK_N8N.md) to setup custom automation flows. You can also
|
Feed your data and device changes into [Home Assistant](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HOME_ASSISTANT.md), read [API endpoints](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md), or use [Webhooks](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WEBHOOK_N8N.md) to setup custom automation flows. You can also
|
||||||
build your own scanners with the [Plugin system](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) in as little as [15 minutes](https://www.youtube.com/watch?v=cdbxlwiWhv8).
|
build your own scanners with the [Plugin system](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) in as little as [15 minutes](https://www.youtube.com/watch?v=cdbxlwiWhv8).
|
||||||
|
|
||||||
|
### Workflows
|
||||||
|
|
||||||
|
The [workflows module](https://github.com/jokob-sk/NetAlertX/blob/main/docs/WORKFLOWS.md) in NetAlertX allows to automate repetitive tasks, making network management more efficient. Whether you need to assign newly discovered devices to a specific Network Node, auto-group devices from a given vendor, unarchive a device if detected online, or automatically delete devices, this module provides the flexibility to tailor the automations to your needs.
|
||||||
|
|
||||||
|
|
||||||
## 📚 Documentation
|
## 📚 Documentation
|
||||||
<!--- --------------------------------------------------------------------- --->
|
<!--- --------------------------------------------------------------------- --->
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## High-level overview
|
## High-level overview
|
||||||
|
|
||||||
If a Plugin supplies data to the main app it's doine either vie a SQL query or via a script that updates the `last_result.log` file in the plugin folder (`front/plugins/<plugin>`).
|
If a Plugin supplies data to the main app it's done either vie a SQL query or via a script that updates the `last_result.log` file in the plugin log folder (`app/log/plugins/`).
|
||||||
|
|
||||||
For a more in-depth overview on how plugins work check the [Plugins development docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md).
|
For a more in-depth overview on how plugins work check the [Plugins development docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md).
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# `docker-compose.yaml` Examples
|
# `docker-compose.yaml` Examples
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> The container needs to run in `network_mode:"host"`.
|
> The container needs to run in `network_mode:"host"`. This also means that not all functionality is supported on a Windows host as Docker for Windows doesn't support this networking option.
|
||||||
|
|
||||||
### Example 1
|
### Example 1
|
||||||
|
|
||||||
@@ -103,3 +103,37 @@ DEV_LOCATION=/path/to/local/source/code
|
|||||||
```
|
```
|
||||||
|
|
||||||
To run the container execute: `sudo docker-compose --env-file /path/to/.env up`
|
To run the container execute: `sudo docker-compose --env-file /path/to/.env up`
|
||||||
|
|
||||||
|
|
||||||
|
### Example 4: Docker swarm
|
||||||
|
|
||||||
|
Notice how the host network is defined in a swarm setup:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
netalertx:
|
||||||
|
# Use the below line if you want to test the latest dev image
|
||||||
|
# image: "jokobsk/netalertx-dev:latest"
|
||||||
|
image: "ghcr.io/jokob-sk/netalertx:latest"
|
||||||
|
volumes:
|
||||||
|
- /mnt/MYSERVER/netalertx/config:/config:rw
|
||||||
|
- /mnt/MYSERVER/netalertx/db:/netalertx/db:rw
|
||||||
|
- /mnt/MYSERVER/netalertx/logs:/netalertx/front/log:rw
|
||||||
|
environment:
|
||||||
|
- TZ=Europe/London
|
||||||
|
- PORT=20211
|
||||||
|
networks:
|
||||||
|
- outside
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
|
||||||
|
networks:
|
||||||
|
outside:
|
||||||
|
external:
|
||||||
|
name: "host"
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
NetAlertX comes with MQTT support, allowing you to show all detected devices as devices in Home Assistant. It also supplies a collection of stats, such as number of online devices.
|
NetAlertX comes with MQTT support, allowing you to show all detected devices as devices in Home Assistant. It also supplies a collection of stats, such as number of online devices.
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> You can install NetAlertX also as a Home Assistant addon [](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) via the [alexbelgium/hassio-addons](https://github.com/alexbelgium/hassio-addons/). This is only possible if you run a supervised instance of Home Assistant. If not, you can still run NetAlertX in a separate Docker container and follow this guide to configure MQTT.
|
> You can install NetAlertX also as a Home Assistant addon [](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons) via the [alexbelgium/hassio-addons](https://github.com/alexbelgium/hassio-addons/) repository. This is only possible if you run a supervised instance of Home Assistant. If not, you can still run NetAlertX in a separate Docker container and follow this guide to configure MQTT.
|
||||||
|
|
||||||
## ⚠ Note
|
## ⚠ Note
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Installation options
|
## Installation options
|
||||||
|
|
||||||
NetAlertX can be installed several ways. The best supported option is Docker, followed by a supervised the Home Assistant instance, as an Unraid app and lastly on bare metal.
|
NetAlertX can be installed several ways. The best supported option is Docker, followed by a supervised Home Assistant instance, as an Unraid app, and lastly, on bare metal.
|
||||||
|
|
||||||
- [[Installation] Docker (recommended)](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
|
- [[Installation] Docker (recommended)](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md)
|
||||||
- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx)
|
- [[Installation] Home Assistant](https://github.com/alexbelgium/hassio-addons/tree/master/netalertx)
|
||||||
|
|||||||
26
docs/LOGGING.md
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
# Logging
|
||||||
|
|
||||||
|
NetAlertX comes with several logs that help to identify application issues.
|
||||||
|
|
||||||
|
For plugin-specific log debugging, please read the [Debug Plugins](./DEBUG_PLUGINS.md) guide.
|
||||||
|
|
||||||
|
When debugging any issue, increase the `LOG_LEVEL` Setting as per the [Debug tips](./DEBUG_TIPS.md) documentation.
|
||||||
|
|
||||||
|
|
||||||
|
## Main logs
|
||||||
|
|
||||||
|
You can find most of the logs exposed in the UI under _Maintenance -> Logs_.
|
||||||
|
|
||||||
|
If the UI is inaccessible, you can access them under `/app/log`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In the _Maintennace -> Logs_ you can **Purge logs**, download the full log file or Filter the lines with some substring to narrow down your search.
|
||||||
|
|
||||||
|
## Plugin logging
|
||||||
|
|
||||||
|
If a Plugin supplies data to the main app it's done either vie a SQL query or via a script that updates the `last_result.log` file in the plugin log folder (`app/log/plugins/`). These files are processed at the end of the scan and deleted on successful processing.
|
||||||
|
|
||||||
|
The data is in most of the cases then displayed in the application under _Integrations -> Plugins_ (or _Device -> Plugins_ if the plugin is supplying device-specific data).
|
||||||
|
|
||||||
|

|
||||||
47
docs/NAME_RESOLUTION.md
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
# Device Name Resolution
|
||||||
|
|
||||||
|
Name resolution in NetAlertX relies on multiple plugins to resolve device names from IP addresses. If you are seeing `(name not found)` as device names, follow these steps to diagnose and fix the issue.
|
||||||
|
|
||||||
|
## Required Plugins
|
||||||
|
|
||||||
|
For best results, ensure the following name resolution plugins are enabled:
|
||||||
|
|
||||||
|
- **AVAHISCAN** – Uses mDNS/Avahi to resolve local network names.
|
||||||
|
- **NBTSCAN** – Queries NetBIOS to find device names.
|
||||||
|
- **NSLOOKUP** – Performs standard DNS lookups.
|
||||||
|
|
||||||
|
You can check which plugins are active in your _Settings_ section and enable any that are missing.
|
||||||
|
|
||||||
|
There are other plugins that can supply device names as well, but they rely on bespoke hardware and services. See [Plugins overview](./PLUGINS.md) for details and look for plugins with name discovery (🆎) features.
|
||||||
|
|
||||||
|
## Checking Logs
|
||||||
|
|
||||||
|
If names are not resolving, check the logs for errors or timeouts.
|
||||||
|
|
||||||
|
See how to explore logs in the [Logging guide](./LOGGING.md).
|
||||||
|
|
||||||
|
Logs will show which plugins attempted resolution and any failures encountered.
|
||||||
|
|
||||||
|
## Adjusting Timeout Settings
|
||||||
|
|
||||||
|
If resolution is slow or failing due to timeouts, increase the timeout settings in your configuration, for example.
|
||||||
|
|
||||||
|
```ini
|
||||||
|
NSLOOKUP_RUN_TIMEOUT = 30
|
||||||
|
```
|
||||||
|
|
||||||
|
Raising the timeout may help if your network has high latency or slow DNS responses.
|
||||||
|
|
||||||
|
## Checking Plugin Objects
|
||||||
|
|
||||||
|
Each plugin stores results in its respective object. You can inspect these objects to see if they contain valid name resolution data.
|
||||||
|
|
||||||
|
See [Logging guide](./LOGGING.md) and [Debug plugins](./DEBUG_PLUGINS.md) guides for details.
|
||||||
|
|
||||||
|
If the object contains no results, the issue may be with DNS settings or network access.
|
||||||
|
|
||||||
|
## Improving name resolution
|
||||||
|
|
||||||
|
For more details how to improve name resolution refer to the
|
||||||
|
[Reverse DNS Documentation](./REVERSE_DNS.md).
|
||||||
|
|
||||||
@@ -21,6 +21,9 @@ There are 4 settings on the device for influencing notifications. You can:
|
|||||||
2. **Alert Down** - Alerts when a device goes down. This setting overrides a disabled **Alert Events** setting, so you will get a notification of a device going down even if you don't have **Alert Events** ticked. Disabling this will disable down and down reconnected notifications on the device.
|
2. **Alert Down** - Alerts when a device goes down. This setting overrides a disabled **Alert Events** setting, so you will get a notification of a device going down even if you don't have **Alert Events** ticked. Disabling this will disable down and down reconnected notifications on the device.
|
||||||
3. **Skip repeated notifications**, if for example you know there is a temporary issue and want to pause the same notification for this device for a given time.
|
3. **Skip repeated notifications**, if for example you know there is a temporary issue and want to pause the same notification for this device for a given time.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Please read through the [NTFPRCS plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/notification_processing/README.md) documentation to understand how device and global settings influence the notification processing.
|
||||||
|
|
||||||
## Plugin settings 🔌
|
## Plugin settings 🔌
|
||||||
|
|
||||||

|

|
||||||
@@ -38,7 +41,7 @@ Click the **Read more in the docs.** Link at the top of each plugin to get more
|
|||||||
|
|
||||||
In Notification Processing settings, you can specify blanket rules. These allow you to specify exceptions to the Plugin and Device settings and will override those.
|
In Notification Processing settings, you can specify blanket rules. These allow you to specify exceptions to the Plugin and Device settings and will override those.
|
||||||
|
|
||||||
1. Notify on (`NTFPRCS_INCLUDED_SECTIONS`) allows you to specify which events trigger notifications. Usual setups will have `new_devices`, `down_devices`, and possibly `down_reconnected` set. Including `plugin` (dependenton the Plugin `<plugin>_WATCH` and `<plugin>_REPORT_ON` settings) and `events` (dependent on the on-device **Alert Events** setting) might be too noisy for most setups. More info in the [NTFPRCS plugin](/front/plugins/notification_processing/README.md) on what events these selections include.
|
1. Notify on (`NTFPRCS_INCLUDED_SECTIONS`) allows you to specify which events trigger notifications. Usual setups will have `new_devices`, `down_devices`, and possibly `down_reconnected` set. Including `plugin` (dependenton the Plugin `<plugin>_WATCH` and `<plugin>_REPORT_ON` settings) and `events` (dependent on the on-device **Alert Events** setting) might be too noisy for most setups. More info in the [NTFPRCS plugin](https://github.com/jokob-sk/NetAlertX/blob/main/front/plugins/notification_processing/README.md) on what events these selections include.
|
||||||
2. Alert down after (`NTFPRCS_alert_down_time`) is useful if you want to wait for some time before the system sends out a down notification for a device. This is related to the on-device **Alert down** setting and only devices with this checked will trigger a down notification.
|
2. Alert down after (`NTFPRCS_alert_down_time`) is useful if you want to wait for some time before the system sends out a down notification for a device. This is related to the on-device **Alert down** setting and only devices with this checked will trigger a down notification.
|
||||||
3. A filter to allow you to set device-specific exceptions to New devices being added to the app.
|
3. A filter to allow you to set device-specific exceptions to New devices being added to the app.
|
||||||
4. A filter to allow you to set device-specific exceptions to generated Events.
|
4. A filter to allow you to set device-specific exceptions to generated Events.
|
||||||
|
|||||||
@@ -8,17 +8,38 @@ NetAlertX supports additional plugins to extend its functionality, each with its
|
|||||||
## ⚡ Quick start
|
## ⚡ Quick start
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> You can load additional Plugins via the General -> `LOADED_PLUGINS` setting.
|
> You can load additional Plugins via the General -> `LOADED_PLUGINS` setting. You need to save the settings for the new plugins to load (cache/page reload may be necessary).
|
||||||
|
> 
|
||||||
|
|
||||||
1. Pick your `🔍 dev scanner` plugin (e.g. `ARPSCAN` or `NMAPDEV`), or import devices into the application with an `📥 importer` plugin. (See **✅Enabling plugins** below)
|
1. Pick your `🔍 dev scanner` plugin (e.g. `ARPSCAN` or `NMAPDEV`), or import devices into the application with an `📥 importer` plugin. (See **Enabling plugins** below)
|
||||||
2. Pick a `▶️ publisher` plugin, if you want to send notifications. If you don't see a publisher you'd like to use, look at the [📚_publisher_apprise](/front/plugins/_publisher_apprise/) plugin which is a proxy for over 80 notification services.
|
2. Pick a `▶️ publisher` plugin, if you want to send notifications. If you don't see a publisher you'd like to use, look at the [📚_publisher_apprise](/front/plugins/_publisher_apprise/) plugin which is a proxy for over 80 notification services.
|
||||||
3. Setup your [Network topology diagram](./NETWORK_TREE.md)
|
3. Setup your [Network topology diagram](./NETWORK_TREE.md)
|
||||||
4. Fine-tune [Notifications](./NOTIFICATIONS.md)
|
4. Fine-tune [Notifications](./NOTIFICATIONS.md)
|
||||||
5. [Backup your setup](./BACKUPS.md)
|
5. Setup [Workflows](./WORKFLOWS.md)
|
||||||
6. Contribute and [Create custom plugins](./PLUGINS_DEV.md)
|
6. [Backup your setup](./BACKUPS.md)
|
||||||
|
7. Contribute and [Create custom plugins](./PLUGINS_DEV.md)
|
||||||
|
|
||||||
|
|
||||||
## 📑 Available Plugins
|
## Plugin types
|
||||||
|
|
||||||
|
| Plugin type | Icon | Description | When to run | Required | Data source [?](./PLUGINS_DEV.md) |
|
||||||
|
| -------------- | ---- | ---------------------------------------------------------------- | ----------------------------------- | -------- | ------------------------------------- |
|
||||||
|
| publisher | ▶️ | Sending notifications to services. | `on_notification` | ✖ | Script |
|
||||||
|
| dev scanner | 🔍 | Create devices in the app, manages online/offline device status. | `schedule` | ✖ | Script / SQLite DB |
|
||||||
|
| name discovery | 🆎 | Discovers names of devices via various protocols. | `before_name_updates`, `schedule` | ✖ | Script |
|
||||||
|
| importer | 📥 | Importing devices from another service. | `schedule` | ✖ | Script / SQLite DB |
|
||||||
|
| system | ⚙ | Providing core system functionality. | `schedule` / always on | ✖/✔ | Script / Template |
|
||||||
|
| other | ♻ | Other plugins | misc | ✖ | Script / Template |
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
| Icon | Description |
|
||||||
|
| ---- | ------------------------------------------------------------ |
|
||||||
|
| 🖧 | Auto-imports the network topology diagram |
|
||||||
|
| 🔄 | Has the option to sync some data back into the plugin source |
|
||||||
|
|
||||||
|
|
||||||
|
## Available Plugins
|
||||||
|
|
||||||
Device-detecting plugins insert values into the `CurrentScan` database table. The plugins that are not required are safe to ignore, however, it makes sense to have at least some device-detecting plugins enabled, such as `ARPSCAN` or `NMAPDEV`.
|
Device-detecting plugins insert values into the `CurrentScan` database table. The plugins that are not required are safe to ignore, however, it makes sense to have at least some device-detecting plugins enabled, such as `ARPSCAN` or `NMAPDEV`.
|
||||||
|
|
||||||
@@ -36,7 +57,7 @@ Device-detecting plugins insert values into the `CurrentScan` database table. T
|
|||||||
| `DHCPLSS` | 🔍/📥/🆎| Import devices from DHCP leases | | | Script | [dhcp_leases](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_leases/) |
|
| `DHCPLSS` | 🔍/📥/🆎| Import devices from DHCP leases | | | Script | [dhcp_leases](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_leases/) |
|
||||||
| `DHCPSRVS` | ♻ | DHCP servers | | | Script | [dhcp_servers](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_servers/) |
|
| `DHCPSRVS` | ♻ | DHCP servers | | | Script | [dhcp_servers](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_servers/) |
|
||||||
| `FREEBOX` | 🔍/♻/🆎| Pull data and names from Freebox/Iliadbox | | | Script | [freebox](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/freebox/) |
|
| `FREEBOX` | 🔍/♻/🆎| Pull data and names from Freebox/Iliadbox | | | Script | [freebox](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/freebox/) |
|
||||||
| `ICMP` | 🔍 | ICMP (ping) status checker | | | Script | [icmp_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/icmp_scan/) |
|
| `ICMP` | ♻ | ICMP (ping) status checker | | | Script | [icmp_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/icmp_scan/) |
|
||||||
| `INTRNT` | 🔍 | Internet IP scanner | | | Script | [internet_ip](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_ip/) |
|
| `INTRNT` | 🔍 | Internet IP scanner | | | Script | [internet_ip](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_ip/) |
|
||||||
| `INTRSPD` | ♻ | Internet speed test | | | Script | [internet_speedtest](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_speedtest/) |
|
| `INTRSPD` | ♻ | Internet speed test | | | Script | [internet_speedtest](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_speedtest/) |
|
||||||
| `IPNEIGH` | 🔍 | Scan ARP (IPv4) and NDP (IPv6) tables | | | Script | [ipneigh](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ipneigh/) |
|
| `IPNEIGH` | 🔍 | Scan ARP (IPv4) and NDP (IPv6) tables | | | Script | [ipneigh](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ipneigh/) |
|
||||||
@@ -72,27 +93,9 @@ Device-detecting plugins insert values into the `CurrentScan` database table. T
|
|||||||
> ❌ marked for removal
|
> ❌ marked for removal
|
||||||
> ⌚It's recommended to use the same schedule interval for all plugins responsible for discovering new devices.
|
> ⌚It's recommended to use the same schedule interval for all plugins responsible for discovering new devices.
|
||||||
|
|
||||||
## Plugin types
|
|
||||||
|
|
||||||
|
|
||||||
| Plugin type | Icon | Description | When to run | Required | Data source [?](./PLUGINS_DEV.md) |
|
## Enabling plugins
|
||||||
| -------------- | ---- | ---------------------------------------------------------------- | ----------------------------------- | -------- | ------------------------------------- |
|
|
||||||
| publisher | ▶️ | Sending notifications to services. | `on_notification` | ✖ | Script |
|
|
||||||
| dev scanner | 🔍 | Create devices in the app, manages online/offline device status. | `schedule` | ✖ | Script / SQLite DB |
|
|
||||||
| name discovery | 🆎 | Discovers names of devices via various protocols. | `before_name_updates`, `schedule` | ✖ | Script |
|
|
||||||
| importer | 📥 | Importing devices from another service. | `schedule` | ✖ | Script / SQLite DB |
|
|
||||||
| system | ⚙ | Providing core system functionality. | `schedule` / always on | ✖/✔ | Script / Template |
|
|
||||||
| other | ♻ | Other plugins | misc | ✖ | Script / Template |
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
| Icon | Description |
|
|
||||||
| ---- | ------------------------------------------------------------ |
|
|
||||||
| 🖧 | Auto-imports the network topology diagram |
|
|
||||||
| 🔄 | Has the option to sync some data back into the plugin source |
|
|
||||||
|
|
||||||
|
|
||||||
## ✅Enabling plugins
|
|
||||||
|
|
||||||
Plugins can be enabled via Settings, and can be disabled as needed.
|
Plugins can be enabled via Settings, and can be disabled as needed.
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ The following workarounds should work for most complex network setups.
|
|||||||
|
|
||||||
## Supplementing Plugins
|
## Supplementing Plugins
|
||||||
|
|
||||||
You can use supplementary plugins that employ alternate methods. Protocols used by the `SNMPDSC` or `DHCPLSS` plugins are widely supported on different routers and can be effective as workarounds. Check the [plugins list](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) to find a plugin that works with your router and network setup.
|
You can use supplementary plugins that employ alternate methods. Protocols used by the `SNMPDSC` or `DHCPLSS` plugins are widely supported on different routers and can be effective as workarounds. Check the [plugins list](./PLUGINS.md) to find a plugin that works with your router and network setup.
|
||||||
|
|
||||||
## Multiple NetAlertX Instances
|
## Multiple NetAlertX Instances
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ services:
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
7. Replace the paths to your volume and/or comment out unnecessary line(s):
|
7. Replace the paths to your volume and comment out unnecessary line(s):
|
||||||
|
|
||||||
- This is only an example, your paths will differ.
|
- This is only an example, your paths will differ.
|
||||||
|
|
||||||
|
|||||||
@@ -1,49 +1,70 @@
|
|||||||
# Debugging inaccessible UI
|
# Debugging inaccessible UI
|
||||||
|
|
||||||
## 1. Port conflicts
|
The application uses the following default ports:
|
||||||
|
|
||||||
When opening an issue please:
|
- **Web UI**: `20211`
|
||||||
|
- **GraphQL API**: `20212`
|
||||||
|
|
||||||
|
The **Web UI** is served by an **nginx** server, while the **API backend** runs on a **Flask (Python)** server.
|
||||||
|
|
||||||
|
## Changing Ports
|
||||||
|
|
||||||
|
- To change the **Web UI** port, update the `PORT` environment variable in the `docker-compose.yml` file.
|
||||||
|
- To change the **GraphQL API** port, use the `GRAPHQL_PORT` setting, either directly or via Docker:
|
||||||
|
```yaml
|
||||||
|
APP_CONF_OVERRIDE={"GRAPHQL_PORT":"20212"}
|
||||||
|
```
|
||||||
|
|
||||||
|
For more information, check the [Docker installation guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md).
|
||||||
|
|
||||||
|
## Possible issues and troubleshooting
|
||||||
|
|
||||||
|
Follow all of the below in order to disqualify potential causes of issues and to troubleshoot these problems faster.
|
||||||
|
|
||||||
|
### 1. Port conflicts
|
||||||
|
|
||||||
|
When opening an issue or debugging:
|
||||||
|
|
||||||
1. Include a screenshot of what you see when accessing `HTTP://<your rpi IP>/20211` (or your custom port)
|
1. Include a screenshot of what you see when accessing `HTTP://<your rpi IP>/20211` (or your custom port)
|
||||||
1. [Follow steps 1, 2, 3, 4 on this page](./DEBUG_TIPS.md)
|
1. [Follow steps 1, 2, 3, 4 on this page](./DEBUG_TIPS.md)
|
||||||
1. Execute the following in the container to see the processes and their ports and submit a screenshot of the result:
|
1. Execute the following in the container to see the processes and their ports and submit a screenshot of the result:
|
||||||
1. `sudo apk add lsof`
|
- `sudo apk add lsof`
|
||||||
1. `sudo lsof -i`
|
- `sudo lsof -i`
|
||||||
1. Try running the `nginx` command in the container
|
1. Try running the `nginx` command in the container:
|
||||||
1. if you get `nginx: [emerg] bind() to 0.0.0.0:20211 failed (98: Address in use)` try using a different port number
|
- if you get `nginx: [emerg] bind() to 0.0.0.0:20211 failed (98: Address in use)` try using a different port number
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 2. JavaScript issues
|
### 2. JavaScript issues
|
||||||
|
|
||||||
Check for browser console (F12 browser dev console) errors + check different browsers.
|
Check for browser console (F12 browser dev console) errors + check different browsers.
|
||||||
|
|
||||||
## 3. Clear the app cache and cached JavaScript files
|
### 3. Clear the app cache and cached JavaScript files
|
||||||
|
|
||||||
Refresh the browser cache (usually shoft + refresh), try a private window, or different browsers. Please also refresh the app cache by clicking the 🔃 (reload) button in the header of the application.
|
Refresh the browser cache (usually shoft + refresh), try a private window, or different browsers. Please also refresh the app cache by clicking the 🔃 (reload) button in the header of the application.
|
||||||
|
|
||||||
## 4. Disable proxy
|
### 4. Disable proxies
|
||||||
|
|
||||||
If you have any reverse proxy or similar, try disabling it.
|
If you have any reverse proxy or similar, try disabling it.
|
||||||
|
|
||||||
## 5. Disable your firewall
|
### 5. Disable your firewall
|
||||||
|
|
||||||
If you are using a firewall, try to temporarily disabling it.
|
If you are using a firewall, try to temporarily disabling it.
|
||||||
|
|
||||||
## 6. Post your docker start details
|
### 6. Post your docker start details
|
||||||
|
|
||||||
If you haven't, post your docker compose/run command.
|
If you haven't, post your docker compose/run command.
|
||||||
|
|
||||||
## 7. Check for errors in your PHP/NGINX error logs
|
### 7. Check for errors in your PHP/NGINX error logs
|
||||||
|
|
||||||
In the container execute:
|
In the container execute and investigate:
|
||||||
|
|
||||||
`cat /var/log/nginx/error.log`
|
`cat /var/log/nginx/error.log`
|
||||||
|
|
||||||
`cat /app/log/app.php_errors.log`
|
`cat /app/log/app.php_errors.log`
|
||||||
|
|
||||||
## 8. Make sure permissions are correct
|
### 8. Make sure permissions are correct
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> You can try to start the container without mapping the `/app/config` and `/app/db` dirs and if the UI shows up then the issue is most likely related to your file system permissions or file ownership.
|
> You can try to start the container without mapping the `/app/config` and `/app/db` dirs and if the UI shows up then the issue is most likely related to your file system permissions or file ownership.
|
||||||
|
|||||||
@@ -1,44 +1,59 @@
|
|||||||
# Workflows Overview
|
# Workflows Overview
|
||||||
|
|
||||||
The workflows module in NetAlertX allows you to automate repetitive tasks, making network management more efficient. Whether you need to assign newly discovered devices to a specific Network Node, auto-group devices from a given vendor, unarchive a device if detected online, or automatically delete or archive devices, this module provides the flexibility to tailor the automations to your needs.
|
The workflows module in NetAlertX allows to automate repetitive tasks, making network management more efficient. Whether you need to assign newly discovered devices to a specific Network Node, auto-group devices from a given vendor, unarchive a device if detected online, or automatically delete devices, this module provides the flexibility to tailor the automations to your needs.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Below are a few examples that demonstrate how this module can be used to simplify network management tasks.
|
Below are a few examples that demonstrate how this module can be used to simplify network management tasks.
|
||||||
|
|
||||||
|
## Updating Workflows
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> In order to apply a workflow change, you must first **Save** the changes and then reload the application by clicking **Restart server**.
|
> In order to apply a workflow change, you must first **Save** the changes and then reload the application by clicking **Restart server**.
|
||||||
|
|
||||||
## Triggers
|
## Workflow components
|
||||||
|
|
||||||
|
### Triggers
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
Triggers define the event that activates a workflow. They monitor changes to objects within the system, such as updates to devices or the insertion of new entries. When the specified event occurs, the workflow is executed.
|
Triggers define the event that activates a workflow. They monitor changes to objects within the system, such as updates to devices or the insertion of new entries. When the specified event occurs, the workflow is executed.
|
||||||
|
|
||||||
### Example Trigger:
|
> [!TIP]
|
||||||
|
> Workflows not running? Check the [Workflows debugging](./WORKFLOWS_DEBUGGING.md) guide how to troubleshoot triggers and conditions.
|
||||||
|
|
||||||
|
#### Example Trigger:
|
||||||
- **Object Type**: `Devices`
|
- **Object Type**: `Devices`
|
||||||
- **Event Type**: `update`
|
- **Event Type**: `update`
|
||||||
|
|
||||||
This trigger will activate when a `Device` object is updated.
|
This trigger will activate when a `Device` object is updated.
|
||||||
|
|
||||||
## Conditions
|
### Conditions
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
Conditions determine whether a workflow should proceed based on certain criteria. These criteria can be set for specific fields, such as whether a device is from a certain vendor, or whether it is new or archived. You can combine conditions using logical operators (`AND`, `OR`).
|
Conditions determine whether a workflow should proceed based on certain criteria. These criteria can be set for specific fields, such as whether a device is from a certain vendor, or whether it is new or archived. You can combine conditions using logical operators (`AND`, `OR`).
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide.
|
> To better understand how to use specific Device fields, please read through the [Database overview](./DATABASE.md) guide.
|
||||||
|
|
||||||
### Example Condition:
|
#### Example Condition:
|
||||||
- **Logic**: `AND`
|
- **Logic**: `AND`
|
||||||
- **Field**: `devVendor`
|
- **Field**: `devVendor`
|
||||||
- **Operator**: `contains`
|
- **Operator**: `contains` (case in-sensitive)
|
||||||
- **Value**: `Google`
|
- **Value**: `Google`
|
||||||
|
|
||||||
This condition checks if the device's vendor is `Google`. The workflow will only proceed if the condition is true.
|
This condition checks if the device's vendor is `Google`. The workflow will only proceed if the condition is true.
|
||||||
|
|
||||||
## Actions
|
### Actions
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
Actions define the tasks that the workflow will perform once the conditions are met. Actions can include updating fields or deleting devices.
|
Actions define the tasks that the workflow will perform once the conditions are met. Actions can include updating fields or deleting devices.
|
||||||
|
|
||||||
### Example Action:
|
You can include multiple actions that should execute once the conditions are met.
|
||||||
|
|
||||||
|
#### Example Action:
|
||||||
- **Action Type**: `update_field`
|
- **Action Type**: `update_field`
|
||||||
- **Field**: `devIsNew`
|
- **Field**: `devIsNew`
|
||||||
- **Value**: `0`
|
- **Value**: `0`
|
||||||
@@ -50,13 +65,17 @@ Actions define the tasks that the workflow will perform once the conditions are
|
|||||||
|
|
||||||
Below you can find a couple of configuration examples.
|
Below you can find a couple of configuration examples.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Example 1: Assign Device to Network Node Based on IP
|
## Example 1: Assign Device to Network Node Based on IP
|
||||||
|
|
||||||
|
This workflow assigns newly added devices with IP addresses in the `192.168.1.*` range to the device with the MAC address `6c:6d:6d:6c:6c:6c`.
|
||||||
|
|
||||||
### Trigger:
|
### Trigger:
|
||||||
- **Object Type**: `Devices`
|
- **Object Type**: `Devices`
|
||||||
- **Event Type**: `create`
|
- **Event Type**: `insert`
|
||||||
|
|
||||||
### Conditions:
|
### Conditions:
|
||||||
- **Logic**: `AND`
|
- **Logic**: `AND`
|
||||||
@@ -71,12 +90,12 @@ Below you can find a couple of configuration examples.
|
|||||||
- **Field**: `devNetworkNode`
|
- **Field**: `devNetworkNode`
|
||||||
- **Value**: `6c:6d:6d:6c:6c:6c`
|
- **Value**: `6c:6d:6d:6c:6c:6c`
|
||||||
|
|
||||||
This workflow assigns newly added devices with IP addresses in the `192.168.1.*` range to the device with the MAC address `6c:6d:6d:6c:6c:6c`.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Example 2: Mark Device as Not New and Delete If from Google Vendor
|
## Example 2: Mark Device as Not New and Delete If from Google Vendor
|
||||||
|
|
||||||
|
This workflow automates the process of marking Google devices as not new and deleting them if they meet the criteria.
|
||||||
|
|
||||||
### Trigger:
|
### Trigger:
|
||||||
- **Object Type**: `Devices`
|
- **Object Type**: `Devices`
|
||||||
- **Event Type**: `update`
|
- **Event Type**: `update`
|
||||||
@@ -107,10 +126,5 @@ This workflow assigns newly added devices with IP addresses in the `192.168.1.*`
|
|||||||
|
|
||||||
This action deletes the device after it is marked as not new.
|
This action deletes the device after it is marked as not new.
|
||||||
|
|
||||||
This workflow automates the process of marking Google devices as not new and deleting them if they meet the criteria.
|
> [!TIP]
|
||||||
|
> Share your workflows in [Discord](https://discord.com/invite/NczTUTWyRr) or [GitHub Discussions](https://github.com/jokob-sk/NetAlertX/discussions).
|
||||||
---
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
With workflows, NetAlertX can automatically adjust to network changes, saving time and reducing the manual overhead involved in maintaining your devices. You can create highly tailored automation rules to handle everything from basic updates to more complex device management.
|
|
||||||
|
|||||||
38
docs/WORKFLOWS_DEBUGGING.md
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
# Workflows debugging and troubleshooting
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Before troubleshooting, please ensure you have [Debugging enabled](./DEBUG_TIPS.md).
|
||||||
|
|
||||||
|
Workflows are triggered by various events. These events are captured and listed in the _Integrations -> App Events_ section of the application.
|
||||||
|
|
||||||
|
## Troubleshooting triggers
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Workflow events are processed once every 5 seconds. However, if a scan or other background tasks are running, this can cause a delay up to a few minutes.
|
||||||
|
|
||||||
|
If an event doesn't trigger a workflow as expected, check the _App Events_ section for the event. You can filter these by the ID of the device (`devMAC` or `devGUID`).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Once you find the _Event Guid_ and _Object GUID_, use them to find relevant debug entries.
|
||||||
|
|
||||||
|
Navigate to _Mainetenace -> Logs_ where you can filter the logs based on the _Event or Object GUID_.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Below you can find some example `app.log` entries that will help you understand why a Workflow was or was not triggered.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
16:27:03 [WF] Checking if '13f0ce26-1835-4c48-ae03-cdaf38f328fe' triggers the workflow 'Sample Device Update Workflow'
|
||||||
|
16:27:03 [WF] self.triggered 'False' for event '[[155], ['13f0ce26-1835-4c48-ae03-cdaf38f328fe'], [0], ['2025-04-02 05:26:56'], ['Devices'], ['050b6980-7af6-4409-950d-08e9786b7b33'], ['DEVICES'], ['00:11:32:ef:a5:6c'], ['192.168.1.82'], ['050b6980-7af6-4409-950d-08e9786b7b33'], [None], [0], [0], ['devPresentLastScan'], ['online'], ['update'], [None], [None], [None], [None]] and trigger {"object_type": "Devices", "event_type": "insert"}'
|
||||||
|
16:27:03 [WF] Checking if '13f0ce26-1835-4c48-ae03-cdaf38f328fe' triggers the workflow 'Location Change'
|
||||||
|
16:27:03 [WF] self.triggered 'True' for event '[[155], ['13f0ce26-1835-4c48-ae03-cdaf38f328fe'], [0], ['2025-04-02 05:26:56'], ['Devices'], ['050b6980-7af6-4409-950d-08e9786b7b33'], ['DEVICES'], ['00:11:32:ef:a5:6c'], ['192.168.1.82'], ['050b6980-7af6-4409-950d-08e9786b7b33'], [None], [0], [0], ['devPresentLastScan'], ['online'], ['update'], [None], [None], [None], [None]] and trigger {"object_type": "Devices", "event_type": "update"}'
|
||||||
|
16:27:03 [WF] Event with GUID '13f0ce26-1835-4c48-ae03-cdaf38f328fe' triggered the workflow 'Location Change'
|
||||||
|
```
|
||||||
|
|
||||||
|
Note how one trigger executed, but the other didn't based on different `"event_type"` values. One is `"event_type": "insert"`, the other `"event_type": "update"`.
|
||||||
|
|
||||||
|
Given the Event is a update event (note `...['online'], ['update'], [None]...` in the event structure), the `"event_type": "insert"` trigger didn't execute.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BIN
docs/img/LOGGING/logging_integrations_plugins.png
Executable file
|
After Width: | Height: | Size: 110 KiB |
BIN
docs/img/LOGGING/maintenance_logs.png
Executable file
|
After Width: | Height: | Size: 93 KiB |
BIN
docs/img/NAME_RESOLUTION/name_res_nslookup_timeout.png
Executable file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/img/PLUGINS/loaded_plugins_setting.png
Executable file
|
After Width: | Height: | Size: 77 KiB |
BIN
docs/img/WORKFLOWS/actions.jpg
Executable file
|
After Width: | Height: | Size: 17 KiB |
BIN
docs/img/WORKFLOWS/conditions.png
Executable file
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/img/WORKFLOWS/trigger.jpg
Executable file
|
After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 129 KiB |
BIN
docs/img/WORKFLOWS/workflows_app_events_search.png
Executable file
|
After Width: | Height: | Size: 166 KiB |
BIN
docs/img/WORKFLOWS/workflows_diagram.png
Executable file
|
After Width: | Height: | Size: 49 KiB |
BIN
docs/img/WORKFLOWS/workflows_logs_search.png
Executable file
|
After Width: | Height: | Size: 164 KiB |
@@ -1517,10 +1517,9 @@ input[readonly] {
|
|||||||
/* AdminLTE overrides */
|
/* AdminLTE overrides */
|
||||||
#networkTree .box
|
#networkTree .box
|
||||||
{
|
{
|
||||||
border-top:1px;
|
/* border-top:1px; */
|
||||||
border-top-color:grey;
|
border-top-color:grey;
|
||||||
padding:0px;
|
padding:0px;
|
||||||
padding-top:6px;
|
|
||||||
margin:0px;
|
margin:0px;
|
||||||
align-items:center;
|
align-items:center;
|
||||||
border-radius:20px;
|
border-radius:20px;
|
||||||
@@ -1528,7 +1527,7 @@ input[readonly] {
|
|||||||
/* display:flex; */
|
/* display:flex; */
|
||||||
flex-direction:column;
|
flex-direction:column;
|
||||||
justify-content:center;
|
justify-content:center;
|
||||||
display: inline-grid;
|
/* display: inline-grid; */
|
||||||
}
|
}
|
||||||
.helpIcon
|
.helpIcon
|
||||||
{
|
{
|
||||||
@@ -1577,17 +1576,16 @@ input[readonly] {
|
|||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#networkTree .netCollapse
|
#networkTree .netCollapse
|
||||||
{
|
{
|
||||||
display: block;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-left: 170px;
|
right: 0;
|
||||||
font-size: large;
|
margin-right: -3px;
|
||||||
left: -15px;
|
|
||||||
}
|
}
|
||||||
#networkTree .highlightedNode
|
#networkTree .highlightedNode
|
||||||
{
|
{
|
||||||
border: solid;
|
/* border: solid; */
|
||||||
border-color:cyan;
|
border-color:cyan;
|
||||||
}
|
}
|
||||||
#networkTree .netStatus-Off-line i,
|
#networkTree .netStatus-Off-line i,
|
||||||
@@ -1598,7 +1596,6 @@ input[readonly] {
|
|||||||
|
|
||||||
.spanNetworkTree {
|
.spanNetworkTree {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
/* width: 135px; */
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -1614,6 +1611,11 @@ input[readonly] {
|
|||||||
/* margin-left: 0.2em; */
|
/* margin-left: 0.2em; */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.networkTable .networkNodeTabHeaders a {
|
||||||
|
display: block;
|
||||||
|
height: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
.networkTable .icon {
|
.networkTable .icon {
|
||||||
/* padding-left:2em; */
|
/* padding-left:2em; */
|
||||||
width:2em;
|
width:2em;
|
||||||
@@ -1632,7 +1634,6 @@ input[readonly] {
|
|||||||
|
|
||||||
.networkNodeTabHeaders
|
.networkNodeTabHeaders
|
||||||
{
|
{
|
||||||
max-width: 200px;
|
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-wrap: nowrap;
|
text-wrap: nowrap;
|
||||||
@@ -1710,13 +1711,6 @@ input[readonly] {
|
|||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.login-page .login-custom
|
|
||||||
{
|
|
||||||
width:480px;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Hidden special button*/
|
/*Hidden special button*/
|
||||||
|
|
||||||
@media (max-width: 365px) {
|
@media (max-width: 365px) {
|
||||||
@@ -1863,6 +1857,11 @@ input[readonly] {
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workflows
|
||||||
|
{
|
||||||
|
max-width: 800px;
|
||||||
|
}
|
||||||
|
|
||||||
.workflows .col-sm-12, .workflows .col-sx-12
|
.workflows .col-sm-12, .workflows .col-sx-12
|
||||||
{
|
{
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
@@ -1975,6 +1974,7 @@ input[readonly] {
|
|||||||
right: 0.1em;
|
right: 0.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.workflows .remove-condition
|
.workflows .remove-condition
|
||||||
{
|
{
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|||||||
@@ -266,7 +266,7 @@
|
|||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}, 1);
|
}, 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -338,6 +338,7 @@
|
|||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
// Save device data to DB
|
||||||
function setDeviceData(direction = '', refreshCallback = '') {
|
function setDeviceData(direction = '', refreshCallback = '') {
|
||||||
// Check MAC
|
// Check MAC
|
||||||
if (mac === '') {
|
if (mac === '') {
|
||||||
|
|||||||
@@ -74,10 +74,10 @@
|
|||||||
|
|
||||||
<!-- box-header -->
|
<!-- box-header -->
|
||||||
<div class="box-header">
|
<div class="box-header">
|
||||||
<div class=" col-md-9 ">
|
<div class=" col-sm-8 ">
|
||||||
<h3 id="tableDevicesTitle" class="box-title text-gray "></h3>
|
<h3 id="tableDevicesTitle" class="box-title text-gray "></h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="dummyDevice col-md-3 ">
|
<div class="dummyDevice col-sm-4 ">
|
||||||
<span id="multiEditPlc">
|
<span id="multiEditPlc">
|
||||||
<!-- multi edit button placeholder -->
|
<!-- multi edit button placeholder -->
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
<link rel="stylesheet" href="css/app.css">
|
<link rel="stylesheet" href="css/app.css">
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
require dirname(__FILE__).'/php/server/init.php';
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
// check if authenticated
|
// check if authenticated
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
|
// Be CAREFUL WHEN INCLUDING NEW PHP FILES
|
||||||
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/server/db.php';
|
||||||
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/language/lang.php';
|
||||||
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
|
||||||
|
|
||||||
$CookieSaveLoginName = 'NetAlertX_SaveLogin';
|
$CookieSaveLoginName = 'NetAlertX_SaveLogin';
|
||||||
|
|
||||||
@@ -92,10 +95,8 @@ if (isset ($_SESSION["login"]) == FALSE || $_SESSION["login"] != 1)
|
|||||||
<!-- iCheck -->
|
<!-- iCheck -->
|
||||||
<link rel="stylesheet" href="lib/iCheck/square/blue.css">
|
<link rel="stylesheet" href="lib/iCheck/square/blue.css">
|
||||||
<!-- Font Awesome -->
|
<!-- Font Awesome -->
|
||||||
<link rel="stylesheet" href="lib/font-awesome/fontawesome.min.css">
|
<link rel="stylesheet" href="lib/font-awesome/all.min.css">
|
||||||
<link rel="stylesheet" href="lib/font-awesome/solid.css">
|
|
||||||
<link rel="stylesheet" href="lib/font-awesome/brands.css">
|
|
||||||
<link rel="stylesheet" href="lib/font-awesome/v5-font-face.css">
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link id="favicon" rel="icon" type="image/x-icon" href="img/NetAlertX_logo.png">
|
<link id="favicon" rel="icon" type="image/x-icon" href="img/NetAlertX_logo.png">
|
||||||
|
|
||||||
@@ -112,7 +113,7 @@ switch ($UI_THEME) {
|
|||||||
?>
|
?>
|
||||||
<link rel="stylesheet" href="/css/offline-font.css">
|
<link rel="stylesheet" href="/css/offline-font.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="hold-transition login-page">
|
<body class="hold-transition login-page col-sm-12 col-sx-12">
|
||||||
<div class="login-box login-custom">
|
<div class="login-box login-custom">
|
||||||
<div class="login-logo">
|
<div class="login-logo">
|
||||||
<a href="/index2.php">Net<b>Alert</b><sup>x</sup></a>
|
<a href="/index2.php">Net<b>Alert</b><sup>x</sup></a>
|
||||||
|
|||||||
@@ -68,11 +68,13 @@ function showModalWarning(
|
|||||||
callbackFunction = null,
|
callbackFunction = null,
|
||||||
triggeredBy = null
|
triggeredBy = null
|
||||||
) {
|
) {
|
||||||
|
prefix = "modal-warning";
|
||||||
|
|
||||||
// set captions
|
// set captions
|
||||||
$("#modal-warning-title").html(title);
|
$(`#${prefix}-title`).html(title);
|
||||||
$("#modal-warning-message").html(message);
|
$(`#${prefix}-message`).html(message);
|
||||||
$("#modal-warning-cancel").html(btnCancel);
|
$(`#${prefix}-cancel`).html(btnCancel);
|
||||||
$("#modal-warning-OK").html(btnOK);
|
$(`#${prefix}-OK`).html(btnOK);
|
||||||
|
|
||||||
if (callbackFunction != null) {
|
if (callbackFunction != null) {
|
||||||
modalCallbackFunction = callbackFunction;
|
modalCallbackFunction = callbackFunction;
|
||||||
@@ -83,7 +85,7 @@ function showModalWarning(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show modal
|
// Show modal
|
||||||
$("#modal-warning").modal("show");
|
$(`#${prefix}`).modal("show");
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -93,7 +95,8 @@ function showModalInput(
|
|||||||
btnCancel = getString("Gen_Cancel"),
|
btnCancel = getString("Gen_Cancel"),
|
||||||
btnOK = getString("Gen_Okay"),
|
btnOK = getString("Gen_Okay"),
|
||||||
callbackFunction = null,
|
callbackFunction = null,
|
||||||
triggeredBy = null
|
triggeredBy = null,
|
||||||
|
defaultValue = ""
|
||||||
) {
|
) {
|
||||||
prefix = "modal-input";
|
prefix = "modal-input";
|
||||||
|
|
||||||
@@ -102,6 +105,7 @@ function showModalInput(
|
|||||||
$(`#${prefix}-message`).html(message);
|
$(`#${prefix}-message`).html(message);
|
||||||
$(`#${prefix}-cancel`).html(btnCancel);
|
$(`#${prefix}-cancel`).html(btnCancel);
|
||||||
$(`#${prefix}-OK`).html(btnOK);
|
$(`#${prefix}-OK`).html(btnOK);
|
||||||
|
$(`#${prefix}-textarea`).val(defaultValue);
|
||||||
|
|
||||||
if (callbackFunction != null) {
|
if (callbackFunction != null) {
|
||||||
modalCallbackFunction = callbackFunction;
|
modalCallbackFunction = callbackFunction;
|
||||||
|
|||||||
9
front/lib/font-awesome/all.min.css
vendored
Executable file
1516
front/lib/font-awesome/brands.css
vendored
6
front/lib/font-awesome/brands.min.css
vendored
6
front/lib/font-awesome/fontawesome.min.css
vendored
19
front/lib/font-awesome/solid.css
vendored
@@ -1,19 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
|
||||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
|
||||||
* Copyright 2022 Fonticons, Inc.
|
|
||||||
*/
|
|
||||||
:root, :host {
|
|
||||||
--fa-style-family-classic: 'Font Awesome 6 Free';
|
|
||||||
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; }
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Font Awesome 6 Free';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 900;
|
|
||||||
font-display: block;
|
|
||||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
|
||||||
|
|
||||||
.fas,
|
|
||||||
.fa-solid {
|
|
||||||
font-weight: 900; }
|
|
||||||
6
front/lib/font-awesome/solid.min.css
vendored
@@ -1,6 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
|
||||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
|
||||||
* Copyright 2022 Fonticons, Inc.
|
|
||||||
*/
|
|
||||||
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}
|
|
||||||
22
front/lib/font-awesome/v5-font-face.css
vendored
@@ -1,22 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
|
||||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
|
||||||
* Copyright 2022 Fonticons, Inc.
|
|
||||||
*/
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Font Awesome 5 Brands';
|
|
||||||
font-display: block;
|
|
||||||
font-weight: 400;
|
|
||||||
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Font Awesome 5 Free';
|
|
||||||
font-display: block;
|
|
||||||
font-weight: 900;
|
|
||||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Font Awesome 5 Free';
|
|
||||||
font-display: block;
|
|
||||||
font-weight: 400;
|
|
||||||
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
|
|
||||||
6
front/lib/font-awesome/v5-font-face.min.css
vendored
@@ -1,6 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
|
||||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
|
||||||
* Copyright 2022 Fonticons, Inc.
|
|
||||||
*/
|
|
||||||
@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}
|
|
||||||
@@ -6,8 +6,6 @@
|
|||||||
// online / offline badges HTML snippets
|
// online / offline badges HTML snippets
|
||||||
define('badge_online', '<div class="badge bg-green text-white" style="width: 60px;">Online</div>');
|
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('badge_offline', '<div class="badge bg-red text-white" style="width: 60px;">Offline</div>');
|
||||||
define('circle_online', '<div class="badge bg-green text-white" style="width: 10px; height: 10px; padding:2px; margin-top: -25px;"> </div>');
|
|
||||||
define('circle_offline', '<div class="badge bg-red text-white" style="width: 10px; height: 10px; padding:2px; margin-top: -25px;"> </div>');
|
|
||||||
define('sortable_column', ' <span class="sort-btn" onclick="sortColumn(this)"><i class="fa-solid fa-arrow-up-short-wide"></i></span>');
|
define('sortable_column', ' <span class="sort-btn" onclick="sortColumn(this)"><i class="fa-solid fa-arrow-up-short-wide"></i></span>');
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -39,13 +37,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// online/offline status circle (red/green)
|
// online/offline status circle (red/green)
|
||||||
$node_badge = "";
|
$icon_style = "";
|
||||||
if($node_status == 1) // 1 means online, 0 offline
|
if($node_status == 0) // 1 means online, 0 offline
|
||||||
{
|
{
|
||||||
$node_badge = circle_online;
|
$icon_style = "style=\"color:var(--color-red);\"";
|
||||||
} else
|
|
||||||
{
|
|
||||||
$node_badge = circle_offline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$decoded_icon = base64_decode($icon);
|
$decoded_icon = base64_decode($icon);
|
||||||
@@ -53,7 +48,7 @@
|
|||||||
$str_tab_header = '<li class="networkNodeTabHeaders '.$activetab.' " >
|
$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
|
<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">'.$decoded_icon.' </div> <span class="node-name">'.$node_name.'</span>' .$str_port.$node_badge.
|
.'<div class="icon" '.$icon_style.'>'.$decoded_icon.' </div> <span class="node-name">'.$node_name.'</span>' .$str_port.
|
||||||
'</a>
|
'</a>
|
||||||
</li>';
|
</li>';
|
||||||
|
|
||||||
@@ -697,34 +692,56 @@ function attachTreeEvents()
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Handle network node click - select correct tab in the bottom table
|
// Handle network node click - select correct tab in the bottom table
|
||||||
function handleNodeClick(nodeData)
|
function handleNodeClick(el)
|
||||||
{
|
{
|
||||||
const targetTabMAC = nodeData.data.mac;
|
const targetTabMAC = $(el).attr("data-mytreemacmain");
|
||||||
|
|
||||||
var targetTab = $(`a[data-mytabmac="${targetTabMAC}"]`);
|
var targetTab = $(`a[data-mytabmac="${targetTabMAC}"]`);
|
||||||
|
|
||||||
// Simulate a click event on the target tab
|
if (targetTab.length) {
|
||||||
targetTab.click();
|
// Simulate a click event on the target tab
|
||||||
|
targetTab.click();
|
||||||
|
|
||||||
|
// Smooth scroll to the tab content
|
||||||
|
$('html, body').animate({
|
||||||
|
scrollTop: targetTab.offset().top - 50
|
||||||
|
}, 500); // Adjust the duration as needed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
var myTree;
|
var myTree;
|
||||||
var visibleTreeArea = $(window).height()-155;
|
|
||||||
var nodeWidth = 120;
|
|
||||||
var emSize;
|
var emSize;
|
||||||
var nodeHeight;
|
var nodeHeight;
|
||||||
var sizeCoefficient = 1.4
|
// var sizeCoefficient = 1.4
|
||||||
|
|
||||||
|
function pxToEm(px, element) {
|
||||||
|
var baseFontSize = parseFloat($(element || "body").css("font-size"));
|
||||||
|
return px / baseFontSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
function emToPx(em, element) {
|
||||||
|
var baseFontSize = parseFloat($(element || "body").css("font-size"));
|
||||||
|
return Math.round(em * baseFontSize);
|
||||||
|
}
|
||||||
|
|
||||||
function initTree(myHierarchy)
|
function initTree(myHierarchy)
|
||||||
{
|
{
|
||||||
// calculate the drawing area based on teh tree width and available screen size
|
// calculate the drawing area based on teh tree width and available screen size
|
||||||
var treeAreaHeight = visibleTreeArea > 800 ? 800 : visibleTreeArea;
|
|
||||||
let screenWidth = $('.content-header').width();
|
let baseFontSize = parseFloat($('html').css('font-size'));
|
||||||
let treeWidth = (nodeWidth + 20) * parentNodesCount;
|
let treeAreaHeight = ($(window).height() - 155); ;
|
||||||
let treeAreaWidth = screenWidth < treeWidth ? treeWidth : screenWidth;
|
// calculate the font size of the leaf nodes to fit everything into the tree area
|
||||||
|
leafNodesCount == 0 ? 1 : leafNodesCount;
|
||||||
|
|
||||||
|
emSize = pxToEm((treeAreaHeight/(leafNodesCount)).toFixed(2));
|
||||||
|
|
||||||
|
let screenWidthEm = pxToEm($('.networkTable').width());
|
||||||
|
|
||||||
// init the drawing area size
|
// init the drawing area size
|
||||||
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${treeAreaWidth}px`)
|
$("#networkTree").attr('style', `height:${treeAreaHeight}px; width:${emToPx(screenWidthEm)}px`)
|
||||||
|
|
||||||
if(myHierarchy.type == "")
|
if(myHierarchy.type == "")
|
||||||
{
|
{
|
||||||
@@ -733,13 +750,14 @@ function initTree(myHierarchy)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the font size of the leaf nodes to fit everything into the tree area
|
// handle if only a few nodes
|
||||||
leafNodesCount == 0 ? 1 : leafNodesCount;
|
emSize > 1 ? emSize = 1 : emSize = emSize;
|
||||||
emSize = ((treeAreaHeight/(25*leafNodesCount)).toFixed(2));
|
|
||||||
emSize = emSize > 1 ? 1 : emSize;
|
|
||||||
|
|
||||||
// nodeHeight = ((emSize*100*0.30).toFixed(0))
|
let nodeHeightPx = emToPx(emSize*1);
|
||||||
nodeHeight = ((emSize*100*0.30).toFixed(0))
|
let nodeWidthPx = emToPx(screenWidthEm / (parentNodesCount));
|
||||||
|
|
||||||
|
// handle if only a few nodes
|
||||||
|
nodeWidthPx > 160 ? nodeWidthPx = 160 : nodeWidthPx = nodeWidthPx;
|
||||||
|
|
||||||
console.log(Treeviz);
|
console.log(Treeviz);
|
||||||
|
|
||||||
@@ -747,7 +765,6 @@ function initTree(myHierarchy)
|
|||||||
htmlId: "networkTree",
|
htmlId: "networkTree",
|
||||||
renderNode: nodeData => {
|
renderNode: nodeData => {
|
||||||
|
|
||||||
var fontSize = "font-size:"+emSize+"em;";
|
|
||||||
|
|
||||||
(!emptyArr.includes(nodeData.data.port )) ? port = nodeData.data.port : port = "";
|
(!emptyArr.includes(nodeData.data.port )) ? port = nodeData.data.port : port = "";
|
||||||
|
|
||||||
@@ -761,10 +778,10 @@ function initTree(myHierarchy)
|
|||||||
${atob(nodeData.data.icon)}
|
${atob(nodeData.data.icon)}
|
||||||
</div>` : "";
|
</div>` : "";
|
||||||
devicePort = `<div class="netPort"
|
devicePort = `<div class="netPort"
|
||||||
style="width:${emSize*sizeCoefficient}em;height:${emSize*sizeCoefficient}em">
|
style="width:${emSize}em;height:${emSize}em">
|
||||||
${portHtml}</div>
|
${portHtml}</div>
|
||||||
<div class="portBckgIcon"
|
<div class="portBckgIcon"
|
||||||
style="margin-left:-${emSize*sizeCoefficient}em;">
|
style="margin-left:-${emSize}em;">
|
||||||
${portBckgIcon}
|
${portBckgIcon}
|
||||||
</div>`;
|
</div>`;
|
||||||
collapseExpandIcon = nodeData.data.hiddenChildren ?
|
collapseExpandIcon = nodeData.data.hiddenChildren ?
|
||||||
@@ -773,7 +790,7 @@ function initTree(myHierarchy)
|
|||||||
// generate +/- icon if node has children nodes
|
// generate +/- icon if node has children nodes
|
||||||
collapseExpandHtml = nodeData.data.hasChildren ?
|
collapseExpandHtml = nodeData.data.hasChildren ?
|
||||||
`<div class="netCollapse"
|
`<div class="netCollapse"
|
||||||
style="font-size:${emSize*sizeCoefficient}em;top:${emSize/6}em"
|
style="font-size:${nodeHeightPx/2}px;top:${nodeHeightPx/4}px"
|
||||||
data-mytreepath="${nodeData.data.path}"
|
data-mytreepath="${nodeData.data.path}"
|
||||||
data-mytreemac="${nodeData.data.mac}">
|
data-mytreemac="${nodeData.data.mac}">
|
||||||
<i class="fa fa-${collapseExpandIcon} pointer"></i>
|
<i class="fa fa-${collapseExpandIcon} pointer"></i>
|
||||||
@@ -787,21 +804,24 @@ function initTree(myHierarchy)
|
|||||||
// css indicating online/offline status
|
// css indicating online/offline status
|
||||||
statusCss = ` netStatus-${nodeData.data.status}`;
|
statusCss = ` netStatus-${nodeData.data.status}`;
|
||||||
|
|
||||||
return result = `<div class="box ${nodeData.data.hasChildren ? "pointer":""} ${statusCss} ${highlightedCss}"
|
return result = `<div
|
||||||
|
class="node-inner box ${nodeData.data.hasChildren ? "pointer":""} ${statusCss} ${highlightedCss}"
|
||||||
data-mytreemacmain="${nodeData.data.mac}"
|
data-mytreemacmain="${nodeData.data.mac}"
|
||||||
style="height:${nodeData.settings.nodeHeight}px;${fontSize}"
|
style="height:${nodeHeightPx}px;font-size:${nodeHeightPx-5}px;"
|
||||||
|
onclick="handleNodeClick(this)"
|
||||||
>
|
>
|
||||||
<div class="netNodeText">
|
<div class="netNodeText">
|
||||||
<strong>${devicePort} ${deviceIcon}
|
<strong>${devicePort} ${deviceIcon}
|
||||||
<span class="spanNetworkTree anonymizeDev" >${nodeData.data.name}</span>
|
<span class="spanNetworkTree anonymizeDev" style="width:${nodeWidthPx-50}px">${nodeData.data.name}</span>
|
||||||
</strong>
|
</strong>
|
||||||
${collapseExpandHtml}
|
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>
|
||||||
|
${collapseExpandHtml}`;
|
||||||
},
|
},
|
||||||
mainAxisNodeSpacing: 'auto',
|
mainAxisNodeSpacing: 'auto',
|
||||||
secondaryAxisNodeSpacing: 0.3,
|
// secondaryAxisNodeSpacing: 0.3,
|
||||||
nodeHeight: nodeHeight.toString(),
|
nodeHeight: nodeHeightPx,
|
||||||
|
nodeWidth: nodeWidthPx,
|
||||||
marginTop: '5',
|
marginTop: '5',
|
||||||
isHorizontal : true,
|
isHorizontal : true,
|
||||||
hasZoom: true,
|
hasZoom: true,
|
||||||
@@ -811,8 +831,8 @@ function initTree(myHierarchy)
|
|||||||
hasFlatData: false,
|
hasFlatData: false,
|
||||||
relationnalField: "children",
|
relationnalField: "children",
|
||||||
linkWidth: (nodeData) => 3,
|
linkWidth: (nodeData) => 3,
|
||||||
linkColor: (nodeData) => "#ffcc80",
|
linkColor: (nodeData) => "#ffcc80"
|
||||||
onNodeClick: (nodeData) => handleNodeClick(nodeData),
|
// onNodeClick: (nodeData) => handleNodeClick(nodeData),
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(deviceListGlobal);
|
console.log(deviceListGlobal);
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<div class="pull-right no-hidden-xs">
|
<div class="pull-right no-hidden-xs">
|
||||||
| <a href="https://gurubase.io/g/netalertx" class="pointer" target="_blank" title="Ask AI"><i class="fa-regular fa-comment-dots fa-flip-horizontal"></i></a>
|
| <a href="https://gurubase.io/g/netalertx" class="pointer" target="_blank" title="Ask AI"><i class="fa-regular fa-comment-dots fa-flip-horizontal"></i></a>
|
||||||
| <a href="https://jokob-sk.github.io/NetAlertX/" class="pointer" target="_blank" title="Documentation"><i class="fa fa-book"></i></a>
|
| <a href="https://jokob-sk.github.io/NetAlertX/" class="pointer" target="_blank" title="Documentation"><i class="fa fa-book"></i></a>
|
||||||
| <a href="https://github.com/jokob-sk/NetAlertX/issues" class="pointer" target="_blank"><i class="fa-solid fa-bug" title="Report a bug"></i></a>
|
| <a href="https://github.com/jokob-sk/NetAlertX/issues" class="pointer" target="_blank"><i class="fa fa-bug" title="Report a bug"></i></a>
|
||||||
| <a href="https://discord.com/invite/NczTUTWyRr" class="pointer" target="_blank"><i class="fa-brands fa-discord" title="Join Discord"></i></a>
|
| <a href="https://discord.com/invite/NczTUTWyRr" class="pointer" target="_blank"><i class="fa-brands fa-discord" title="Join Discord"></i></a>
|
||||||
| <?= lang('Maintenance_built_on');?>: <?php include 'php/templates/build.php'; ?>
|
| <?= lang('Maintenance_built_on');?>: <?php include 'php/templates/build.php'; ?>
|
||||||
| Version: <?php include 'php/templates/version.php'; ?>
|
| Version: <?php include 'php/templates/version.php'; ?>
|
||||||
|
|||||||
@@ -59,10 +59,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- Font Awesome -->
|
<!-- Font Awesome -->
|
||||||
<link rel="stylesheet" href="lib/font-awesome/fontawesome.min.css">
|
<link rel="stylesheet" href="lib/font-awesome/all.min.css">
|
||||||
<link rel="stylesheet" href="lib/font-awesome/solid.css">
|
|
||||||
<link rel="stylesheet" href="lib/font-awesome/brands.css">
|
|
||||||
<link rel="stylesheet" href="lib/font-awesome/v5-font-face.css">
|
|
||||||
|
|
||||||
<!-- Ionicons -->
|
<!-- Ionicons -->
|
||||||
<link rel="stylesheet" href="lib/Ionicons/ionicons.min.css">
|
<link rel="stylesheet" href="lib/Ionicons/ionicons.min.css">
|
||||||
@@ -421,20 +418,15 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- Integrations menu item -->
|
<!-- Integrations menu item -->
|
||||||
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php', 'appEvents.php' ) ) ){ echo 'active menu-open'; } ?>">
|
<li class=" treeview <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'appEvents.php' ) ) ){ echo 'active menu-open'; } ?>">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<i class="fa fa-fw fa-plug"></i> <span><?= lang('Navigation_Integrations');?></span>
|
<i class="fa fa-fw fa-plug"></i> <span><?= lang('Navigation_Integrations');?></span>
|
||||||
<span class="pull-right-container">
|
<span class="pull-right-container">
|
||||||
<i class="fa fa-angle-left pull-right"></i>
|
<i class="fa fa-angle-left pull-right"></i>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'workflows.php', 'appEvents.php' ) ) ){ echo 'block'; } else {echo 'none';} ?>;">
|
<ul class="treeview-menu " style="display: <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('plugins.php', 'appEvents.php' ) ) ){ echo 'block'; } else {echo 'none';} ?>;">
|
||||||
<li>
|
<li>
|
||||||
<div class="info-icon-nav"> </div>
|
|
||||||
<a href="workflows.php"><?= lang('Navigation_Workflows');?></a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<div class="info-icon-nav"> </div>
|
|
||||||
<a href="appEvents.php"><?= lang('Navigation_AppEvents');?></a>
|
<a href="appEvents.php"><?= lang('Navigation_AppEvents');?></a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -443,6 +435,11 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<!-- workflows menu item -->
|
||||||
|
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('workflows.php') ) ){ echo 'active'; } ?>">
|
||||||
|
<a href="workflows.php"><i class="fa fa-fw fa-shuffle"></i> <span><?= lang('Navigation_Workflows');?></span></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<!-- system info menu item -->
|
<!-- system info menu item -->
|
||||||
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('systeminfo.php') ) ){ echo 'active'; } ?>">
|
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('systeminfo.php') ) ){ echo 'active'; } ?>">
|
||||||
<a href="systeminfo.php"><i class="fa fa-fw fa-info-circle"></i> <span><?= lang('Navigation_SystemInfo');?></span></a>
|
<a href="systeminfo.php"><i class="fa fa-fw fa-info-circle"></i> <span><?= lang('Navigation_SystemInfo');?></span></a>
|
||||||
|
|||||||
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
6
front/php/templates/language/ca_ca.json
Normal file → Executable file
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
44
front/php/templates/language/de_de.json
Normal file → Executable file
@@ -16,8 +16,8 @@
|
|||||||
"About_Design": "Entworfen für:",
|
"About_Design": "Entworfen für:",
|
||||||
"About_Exit": "Abmelden",
|
"About_Exit": "Abmelden",
|
||||||
"About_Title": "Netzwerksicherheitsscanner und Benachrichtigungsframework",
|
"About_Title": "Netzwerksicherheitsscanner und Benachrichtigungsframework",
|
||||||
"AppEvents_AppEventProcessed": "",
|
"AppEvents_AppEventProcessed": "Verarbeitet",
|
||||||
"AppEvents_DateTimeCreated": "protokolliert",
|
"AppEvents_DateTimeCreated": "Protokolliert",
|
||||||
"AppEvents_Extra": "Extra",
|
"AppEvents_Extra": "Extra",
|
||||||
"AppEvents_GUID": "Anwendungsereignis-GUID",
|
"AppEvents_GUID": "Anwendungsereignis-GUID",
|
||||||
"AppEvents_Helper1": "Helfer 1",
|
"AppEvents_Helper1": "Helfer 1",
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"AppEvents_ObjectPlugin": "Verknüpfte Plugins",
|
"AppEvents_ObjectPlugin": "Verknüpfte Plugins",
|
||||||
"AppEvents_ObjectPrimaryID": "Primär ID",
|
"AppEvents_ObjectPrimaryID": "Primär ID",
|
||||||
"AppEvents_ObjectSecondaryID": "Sekundär ID",
|
"AppEvents_ObjectSecondaryID": "Sekundär ID",
|
||||||
"AppEvents_ObjectStatus": "Status (zum Log-Zeitpunkt)",
|
"AppEvents_ObjectStatus": "Protokollierter Status",
|
||||||
"AppEvents_ObjectStatusColumn": "Statusspalte",
|
"AppEvents_ObjectStatusColumn": "Statusspalte",
|
||||||
"AppEvents_ObjectType": "Objekttyp",
|
"AppEvents_ObjectType": "Objekttyp",
|
||||||
"AppEvents_Plugin": "Plugin",
|
"AppEvents_Plugin": "Plugin",
|
||||||
@@ -237,7 +237,7 @@
|
|||||||
"Device_TableHead_Name": "Name",
|
"Device_TableHead_Name": "Name",
|
||||||
"Device_TableHead_NetworkSite": "Netzwerkseite",
|
"Device_TableHead_NetworkSite": "Netzwerkseite",
|
||||||
"Device_TableHead_Owner": "Eigentümer",
|
"Device_TableHead_Owner": "Eigentümer",
|
||||||
"Device_TableHead_Parent_MAC": "Übergeordnete MAC",
|
"Device_TableHead_Parent_MAC": "Übergeordneter Netzwerkknoten",
|
||||||
"Device_TableHead_Port": "Port",
|
"Device_TableHead_Port": "Port",
|
||||||
"Device_TableHead_PresentLastScan": "Anwesenheit",
|
"Device_TableHead_PresentLastScan": "Anwesenheit",
|
||||||
"Device_TableHead_RowID": "Zeilen ID",
|
"Device_TableHead_RowID": "Zeilen ID",
|
||||||
@@ -499,7 +499,7 @@
|
|||||||
"NTFY_display_name": "NTFY",
|
"NTFY_display_name": "NTFY",
|
||||||
"NTFY_icon": "<i class=\"fa fa-terminal\"></i>",
|
"NTFY_icon": "<i class=\"fa fa-terminal\"></i>",
|
||||||
"Navigation_About": "Über",
|
"Navigation_About": "Über",
|
||||||
"Navigation_AppEvents": "",
|
"Navigation_AppEvents": "App-Ereignisse",
|
||||||
"Navigation_Devices": "Geräte",
|
"Navigation_Devices": "Geräte",
|
||||||
"Navigation_Donations": "Spenden",
|
"Navigation_Donations": "Spenden",
|
||||||
"Navigation_Events": "Ereignisse",
|
"Navigation_Events": "Ereignisse",
|
||||||
@@ -753,28 +753,34 @@
|
|||||||
"WF_Action_field": "",
|
"WF_Action_field": "",
|
||||||
"WF_Action_type": "",
|
"WF_Action_type": "",
|
||||||
"WF_Action_value": "",
|
"WF_Action_value": "",
|
||||||
"WF_Actions": "",
|
"WF_Actions": "Aktionen",
|
||||||
"WF_Add": "",
|
"WF_Add": "",
|
||||||
"WF_Add_Condition": "",
|
"WF_Add_Condition": "Bedingung hinzufügen",
|
||||||
"WF_Add_Group": "",
|
"WF_Add_Group": "Gruppe hinzufügen",
|
||||||
"WF_Condition_field": "",
|
"WF_Condition_field": "Feld",
|
||||||
"WF_Condition_operator": "",
|
"WF_Condition_operator": "Betreiber",
|
||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "Wert",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "Bedingungen",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "Logikregeln",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "Auslöser",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "Ereignistyp",
|
||||||
"WF_Trigger_type": "",
|
"WF_Trigger_type": "Auslösertyp",
|
||||||
"Webhooks_display_name": "Webhooks",
|
"Webhooks_display_name": "Webhooks",
|
||||||
"Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>",
|
"Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>",
|
||||||
"add_icon_event_icon": "",
|
"add_icon_event_icon": "",
|
||||||
"add_icon_event_tooltip": "",
|
"add_icon_event_tooltip": "Neues Symbol hinzufügen",
|
||||||
"add_option_event_icon": "",
|
"add_option_event_icon": "",
|
||||||
"add_option_event_tooltip": "",
|
"add_option_event_tooltip": "Neuen Wert hinzufügen",
|
||||||
"copy_icons_event_icon": "",
|
"copy_icons_event_icon": "",
|
||||||
"copy_icons_event_tooltip": "Icons aller Geräte mit demselben Gerätetyp überschreiben",
|
"copy_icons_event_tooltip": "Icons aller Geräte mit demselben Gerätetyp überschreiben",
|
||||||
"devices_old": "Aktualisiert...",
|
"devices_old": "Aktualisiert...",
|
||||||
@@ -782,7 +788,7 @@
|
|||||||
"general_event_title": "",
|
"general_event_title": "",
|
||||||
"go_to_node_event_icon": "",
|
"go_to_node_event_icon": "",
|
||||||
"go_to_node_event_tooltip": "",
|
"go_to_node_event_tooltip": "",
|
||||||
"new_version_available": "",
|
"new_version_available": "Es ist eine neue Version verfügbar.",
|
||||||
"report_guid": "",
|
"report_guid": "",
|
||||||
"report_guid_missing": "",
|
"report_guid_missing": "",
|
||||||
"report_select_format": "Format auswählen:",
|
"report_select_format": "Format auswählen:",
|
||||||
|
|||||||
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "Value",
|
"WF_Condition_value": "Value",
|
||||||
"WF_Conditions": "Conditions",
|
"WF_Conditions": "Conditions",
|
||||||
"WF_Conditions_logic_rules": "Logic rules",
|
"WF_Conditions_logic_rules": "Logic rules",
|
||||||
|
"WF_Duplicate": "Duplicate Workflow",
|
||||||
"WF_Enabled": "Workflow enabled",
|
"WF_Enabled": "Workflow enabled",
|
||||||
|
"WF_Export": "Export Workflow",
|
||||||
|
"WF_Export_Copy": "Copy the below workflow and import it where needed.",
|
||||||
|
"WF_Import": "Import Workflow",
|
||||||
|
"WF_Import_Copy": "Paste in the workflow you copied previously.",
|
||||||
"WF_Name": "Workflow name",
|
"WF_Name": "Workflow name",
|
||||||
"WF_Remove": "Remove Workflow",
|
"WF_Remove": "Remove Workflow",
|
||||||
|
"WF_Remove_Copy": "Do you want to remove this workflow?",
|
||||||
"WF_Save": "Save Workflows",
|
"WF_Save": "Save Workflows",
|
||||||
"WF_Trigger": "Trigger",
|
"WF_Trigger": "Trigger",
|
||||||
"WF_Trigger_event_type": "Event type",
|
"WF_Trigger_event_type": "Event type",
|
||||||
|
|||||||
6
front/php/templates/language/es_es.json
Normal file → Executable file
@@ -759,9 +759,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
52
front/php/templates/language/fr_fr.json
Normal file → Executable file
@@ -22,7 +22,7 @@
|
|||||||
"AppEvents_ObjectPlugin": "Plugin lié",
|
"AppEvents_ObjectPlugin": "Plugin lié",
|
||||||
"AppEvents_ObjectPrimaryID": "Identité primaire",
|
"AppEvents_ObjectPrimaryID": "Identité primaire",
|
||||||
"AppEvents_ObjectSecondaryID": "Identité secondaire",
|
"AppEvents_ObjectSecondaryID": "Identité secondaire",
|
||||||
"AppEvents_ObjectStatus": "État (au moment de l'enregistrement)",
|
"AppEvents_ObjectStatus": "État enregistré",
|
||||||
"AppEvents_ObjectStatusColumn": "Colonne d'état",
|
"AppEvents_ObjectStatusColumn": "Colonne d'état",
|
||||||
"AppEvents_ObjectType": "Type d'objet",
|
"AppEvents_ObjectType": "Type d'objet",
|
||||||
"AppEvents_Plugin": "Plugin",
|
"AppEvents_Plugin": "Plugin",
|
||||||
@@ -363,8 +363,8 @@
|
|||||||
"Maintenance_Title": "Outils de maintenance",
|
"Maintenance_Title": "Outils de maintenance",
|
||||||
"Maintenance_Tool_DownloadConfig": "Export des paramètres",
|
"Maintenance_Tool_DownloadConfig": "Export des paramètres",
|
||||||
"Maintenance_Tool_DownloadConfig_text": "Télécharger une sauvegarde complète de vos paramètres stockés dans le fichier <code>app.conf</code>.",
|
"Maintenance_Tool_DownloadConfig_text": "Télécharger une sauvegarde complète de vos paramètres stockés dans le fichier <code>app.conf</code>.",
|
||||||
"Maintenance_Tool_DownloadWorkflows": "",
|
"Maintenance_Tool_DownloadWorkflows": "Export des workflows",
|
||||||
"Maintenance_Tool_DownloadWorkflows_text": "",
|
"Maintenance_Tool_DownloadWorkflows_text": "Télécharger une sauvegarde complète de vos workflows enregistrés dans le fichier <code>workflows.json</code>.",
|
||||||
"Maintenance_Tool_ExportCSV": "Export des appareils (csv)",
|
"Maintenance_Tool_ExportCSV": "Export des appareils (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti": "Export des appareils (csv)",
|
"Maintenance_Tool_ExportCSV_noti": "Export des appareils (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti_text": "Êtes-vous sûr de vouloir générer un fichier CSV ?",
|
"Maintenance_Tool_ExportCSV_noti_text": "Êtes-vous sûr de vouloir générer un fichier CSV ?",
|
||||||
@@ -670,26 +670,32 @@
|
|||||||
"UI_REFRESH_name": "Rafraîchir automatiquement l'interface graphique",
|
"UI_REFRESH_name": "Rafraîchir automatiquement l'interface graphique",
|
||||||
"VERSION_description": "Valeur de la version ou du timestamp d'aide à vérifier si l'application a été mise à jour.",
|
"VERSION_description": "Valeur de la version ou du timestamp d'aide à vérifier si l'application a été mise à jour.",
|
||||||
"VERSION_name": "Version ou Timestamp",
|
"VERSION_name": "Version ou Timestamp",
|
||||||
"WF_Action_Add": "",
|
"WF_Action_Add": "Ajouter une action",
|
||||||
"WF_Action_field": "",
|
"WF_Action_field": "Champ",
|
||||||
"WF_Action_type": "",
|
"WF_Action_type": "Type",
|
||||||
"WF_Action_value": "",
|
"WF_Action_value": "Valeur",
|
||||||
"WF_Actions": "",
|
"WF_Actions": "Actions",
|
||||||
"WF_Add": "",
|
"WF_Add": "Ajouter un workflow",
|
||||||
"WF_Add_Condition": "",
|
"WF_Add_Condition": "Ajouter une condition",
|
||||||
"WF_Add_Group": "",
|
"WF_Add_Group": "Ajouter un groupe",
|
||||||
"WF_Condition_field": "",
|
"WF_Condition_field": "Champ",
|
||||||
"WF_Condition_operator": "",
|
"WF_Condition_operator": "Opérateur",
|
||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "Valeur",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "Conditions",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "Règles logiques",
|
||||||
"WF_Enabled": "",
|
"WF_Duplicate": "Dupliquer le workflow",
|
||||||
"WF_Name": "",
|
"WF_Enabled": "Workflow activé",
|
||||||
"WF_Remove": "",
|
"WF_Export": "Exporter le workflow",
|
||||||
"WF_Save": "",
|
"WF_Export_Copy": "Copier le workflow ci-dessous pour pouvoir l'importer au besoin.",
|
||||||
"WF_Trigger": "",
|
"WF_Import": "Importer un workflow",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Import_Copy": "Coller le workflow précédemment copié.",
|
||||||
"WF_Trigger_type": "",
|
"WF_Name": "Nom du workflow",
|
||||||
|
"WF_Remove": "Supprimer le workflow",
|
||||||
|
"WF_Remove_Copy": "Voulez-vous supprimer ce workflow ?",
|
||||||
|
"WF_Save": "Enregistrer les workflows",
|
||||||
|
"WF_Trigger": "Déclencheur",
|
||||||
|
"WF_Trigger_event_type": "Type d'événement",
|
||||||
|
"WF_Trigger_type": "Type de déclencheur",
|
||||||
"add_icon_event_icon": "fa-square-plus",
|
"add_icon_event_icon": "fa-square-plus",
|
||||||
"add_icon_event_tooltip": "Ajouter une nouvelle icône",
|
"add_icon_event_tooltip": "Ajouter une nouvelle icône",
|
||||||
"add_option_event_icon": "fa-square-plus",
|
"add_option_event_icon": "fa-square-plus",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"About_Design": "Progettato per:",
|
"About_Design": "Progettato per:",
|
||||||
"About_Exit": "Esci",
|
"About_Exit": "Esci",
|
||||||
"About_Title": "Scanner di sicurezza di rete e framework di notifica",
|
"About_Title": "Scanner di sicurezza di rete e framework di notifica",
|
||||||
"AppEvents_AppEventProcessed": "",
|
"AppEvents_AppEventProcessed": "Elaborato",
|
||||||
"AppEvents_DateTimeCreated": "Loggato",
|
"AppEvents_DateTimeCreated": "Loggato",
|
||||||
"AppEvents_Extra": "Extra",
|
"AppEvents_Extra": "Extra",
|
||||||
"AppEvents_GUID": "GUID evento applicazione",
|
"AppEvents_GUID": "GUID evento applicazione",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
"AppEvents_ObjectPlugin": "Plugin collegato",
|
"AppEvents_ObjectPlugin": "Plugin collegato",
|
||||||
"AppEvents_ObjectPrimaryID": "ID primario",
|
"AppEvents_ObjectPrimaryID": "ID primario",
|
||||||
"AppEvents_ObjectSecondaryID": "ID secondario",
|
"AppEvents_ObjectSecondaryID": "ID secondario",
|
||||||
"AppEvents_ObjectStatus": "Stato (al momento del log)",
|
"AppEvents_ObjectStatus": "Stato registrato",
|
||||||
"AppEvents_ObjectStatusColumn": "Colonna di stato",
|
"AppEvents_ObjectStatusColumn": "Colonna di stato",
|
||||||
"AppEvents_ObjectType": "Tipo oggetto",
|
"AppEvents_ObjectType": "Tipo oggetto",
|
||||||
"AppEvents_Plugin": "Plugin",
|
"AppEvents_Plugin": "Plugin",
|
||||||
@@ -225,7 +225,7 @@
|
|||||||
"Device_TableHead_Name": "Nome",
|
"Device_TableHead_Name": "Nome",
|
||||||
"Device_TableHead_NetworkSite": "Sito di rete",
|
"Device_TableHead_NetworkSite": "Sito di rete",
|
||||||
"Device_TableHead_Owner": "Proprietario",
|
"Device_TableHead_Owner": "Proprietario",
|
||||||
"Device_TableHead_Parent_MAC": "MAC del nodo principale",
|
"Device_TableHead_Parent_MAC": "Nodo di rete principale",
|
||||||
"Device_TableHead_Port": "Porta",
|
"Device_TableHead_Port": "Porta",
|
||||||
"Device_TableHead_PresentLastScan": "Presenza",
|
"Device_TableHead_PresentLastScan": "Presenza",
|
||||||
"Device_TableHead_RowID": "ID riga",
|
"Device_TableHead_RowID": "ID riga",
|
||||||
@@ -363,8 +363,8 @@
|
|||||||
"Maintenance_Title": "Strumenti di manutenzione",
|
"Maintenance_Title": "Strumenti di manutenzione",
|
||||||
"Maintenance_Tool_DownloadConfig": "Impostazioni Esporta",
|
"Maintenance_Tool_DownloadConfig": "Impostazioni Esporta",
|
||||||
"Maintenance_Tool_DownloadConfig_text": "Scarica un backup completo della configurazione delle tue Impostazioni memorizzata nel file <code>app.conf</code>.",
|
"Maintenance_Tool_DownloadConfig_text": "Scarica un backup completo della configurazione delle tue Impostazioni memorizzata nel file <code>app.conf</code>.",
|
||||||
"Maintenance_Tool_DownloadWorkflows": "",
|
"Maintenance_Tool_DownloadWorkflows": "Esportazione flussi di lavoro",
|
||||||
"Maintenance_Tool_DownloadWorkflows_text": "",
|
"Maintenance_Tool_DownloadWorkflows_text": "Scarica un backup completo dei tuoi flussi di lavoro archiviati nel file <code>workflows.json</code>.",
|
||||||
"Maintenance_Tool_ExportCSV": "Esporta dispositivi (csv)",
|
"Maintenance_Tool_ExportCSV": "Esporta dispositivi (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti": "Esporta dispositivi (csv)",
|
"Maintenance_Tool_ExportCSV_noti": "Esporta dispositivi (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti_text": "Sei sicuro di voler generare un file CSV?",
|
"Maintenance_Tool_ExportCSV_noti_text": "Sei sicuro di voler generare un file CSV?",
|
||||||
@@ -463,7 +463,7 @@
|
|||||||
"NETWORK_DEVICE_TYPES_description": "Quali tipi di dispositivo possono essere utilizzati come dispositivi di rete nella vista Rete. Il tipo di dispositivo deve corrispondere esattamente all'impostazione <code>Tipo</code> su un dispositivo specifico nei Dettagli dispositivo. Aggiungilo sul Dispositivo tramite il pulsante <code>+</code>. Non rimuovere i tipi esistenti, aggiungine solo di nuovi.",
|
"NETWORK_DEVICE_TYPES_description": "Quali tipi di dispositivo possono essere utilizzati come dispositivi di rete nella vista Rete. Il tipo di dispositivo deve corrispondere esattamente all'impostazione <code>Tipo</code> su un dispositivo specifico nei Dettagli dispositivo. Aggiungilo sul Dispositivo tramite il pulsante <code>+</code>. Non rimuovere i tipi esistenti, aggiungine solo di nuovi.",
|
||||||
"NETWORK_DEVICE_TYPES_name": "Tipi di dispositivi di rete",
|
"NETWORK_DEVICE_TYPES_name": "Tipi di dispositivi di rete",
|
||||||
"Navigation_About": "Informazioni su",
|
"Navigation_About": "Informazioni su",
|
||||||
"Navigation_AppEvents": "",
|
"Navigation_AppEvents": "Eventi app",
|
||||||
"Navigation_Devices": "Dispositivi",
|
"Navigation_Devices": "Dispositivi",
|
||||||
"Navigation_Donations": "Donazioni",
|
"Navigation_Donations": "Donazioni",
|
||||||
"Navigation_Events": "Eventi",
|
"Navigation_Events": "Eventi",
|
||||||
@@ -670,26 +670,32 @@
|
|||||||
"UI_REFRESH_name": "Aggiorna automaticamente la UI",
|
"UI_REFRESH_name": "Aggiorna automaticamente la UI",
|
||||||
"VERSION_description": "Valore di supporto della versione o della marca temporale per verificare se l'app è stata aggiornata.",
|
"VERSION_description": "Valore di supporto della versione o della marca temporale per verificare se l'app è stata aggiornata.",
|
||||||
"VERSION_name": "Versione o marca temporale",
|
"VERSION_name": "Versione o marca temporale",
|
||||||
"WF_Action_Add": "",
|
"WF_Action_Add": "Aggiungi azione",
|
||||||
"WF_Action_field": "",
|
"WF_Action_field": "Campo",
|
||||||
"WF_Action_type": "",
|
"WF_Action_type": "Tipo",
|
||||||
"WF_Action_value": "",
|
"WF_Action_value": "Valore",
|
||||||
"WF_Actions": "",
|
"WF_Actions": "Azioni",
|
||||||
"WF_Add": "",
|
"WF_Add": "Aggiungi flusso di lavoro",
|
||||||
"WF_Add_Condition": "",
|
"WF_Add_Condition": "Aggiungi condizione",
|
||||||
"WF_Add_Group": "",
|
"WF_Add_Group": "Aggiungi gruppo",
|
||||||
"WF_Condition_field": "",
|
"WF_Condition_field": "Campo",
|
||||||
"WF_Condition_operator": "",
|
"WF_Condition_operator": "Operatore",
|
||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "Valore",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "Condizioni",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "Regole logiche",
|
||||||
"WF_Enabled": "",
|
"WF_Duplicate": "Flusso di lavoro duplicato",
|
||||||
"WF_Name": "",
|
"WF_Enabled": "Flusso di lavoro abilitato",
|
||||||
"WF_Remove": "",
|
"WF_Export": "Esporta flusso di lavoro",
|
||||||
"WF_Save": "",
|
"WF_Export_Copy": "Copia il flusso di lavoro sottostante e importalo dove necessario.",
|
||||||
"WF_Trigger": "",
|
"WF_Import": "Importa flusso di lavoro",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Import_Copy": "Incolla il flusso di lavoro copiato in precedenza.",
|
||||||
"WF_Trigger_type": "",
|
"WF_Name": "Nome flusso di lavoro",
|
||||||
|
"WF_Remove": "Rimuovi flusso di lavoro",
|
||||||
|
"WF_Remove_Copy": "Vuoi rimuovere questo flusso di lavoro?",
|
||||||
|
"WF_Save": "Salva flussi di lavoro",
|
||||||
|
"WF_Trigger": "Trigger",
|
||||||
|
"WF_Trigger_event_type": "Tipo evento",
|
||||||
|
"WF_Trigger_type": "Tipo di trigger",
|
||||||
"add_icon_event_icon": "fa-square-plus",
|
"add_icon_event_icon": "fa-square-plus",
|
||||||
"add_icon_event_tooltip": "Aggiungi nuova icona",
|
"add_icon_event_tooltip": "Aggiungi nuova icona",
|
||||||
"add_option_event_icon": "fa-square-plus",
|
"add_option_event_icon": "fa-square-plus",
|
||||||
|
|||||||
6
front/php/templates/language/nb_no.json
Normal file → Executable file
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
6
front/php/templates/language/pl_pl.json
Normal file → Executable file
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
6
front/php/templates/language/pt_br.json
Normal file → Executable file
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
60
front/php/templates/language/ru_ru.json
Normal file → Executable file
@@ -8,7 +8,7 @@
|
|||||||
"About_Design": "Разработан:",
|
"About_Design": "Разработан:",
|
||||||
"About_Exit": "Зарегистрироваться",
|
"About_Exit": "Зарегистрироваться",
|
||||||
"About_Title": "Сетевой сканер и система уведомлений",
|
"About_Title": "Сетевой сканер и система уведомлений",
|
||||||
"AppEvents_AppEventProcessed": "",
|
"AppEvents_AppEventProcessed": "Обработанный",
|
||||||
"AppEvents_DateTimeCreated": "Журнал",
|
"AppEvents_DateTimeCreated": "Журнал",
|
||||||
"AppEvents_Extra": "Дополнительно",
|
"AppEvents_Extra": "Дополнительно",
|
||||||
"AppEvents_GUID": "GUID события приложения",
|
"AppEvents_GUID": "GUID события приложения",
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
"AppEvents_ObjectPlugin": "Связанный плагин",
|
"AppEvents_ObjectPlugin": "Связанный плагин",
|
||||||
"AppEvents_ObjectPrimaryID": "Первичный ID",
|
"AppEvents_ObjectPrimaryID": "Первичный ID",
|
||||||
"AppEvents_ObjectSecondaryID": "Вторичный ID",
|
"AppEvents_ObjectSecondaryID": "Вторичный ID",
|
||||||
"AppEvents_ObjectStatus": "Состояние (во время входа в систему)",
|
"AppEvents_ObjectStatus": "Зарегистрированный статус",
|
||||||
"AppEvents_ObjectStatusColumn": "Колонка состояния",
|
"AppEvents_ObjectStatusColumn": "Колонка состояния",
|
||||||
"AppEvents_ObjectType": "Тип объекта",
|
"AppEvents_ObjectType": "Тип объекта",
|
||||||
"AppEvents_Plugin": "Плагин",
|
"AppEvents_Plugin": "Плагин",
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"DevDetail_Copy_Device_Tooltip": "Скопируйте данные с устройства из раскрывающегося списка. Все на этой странице будет перезаписано",
|
"DevDetail_Copy_Device_Tooltip": "Скопируйте данные с устройства из раскрывающегося списка. Все на этой странице будет перезаписано",
|
||||||
"DevDetail_CustomProperties_Title": "Пользовательские свойства",
|
"DevDetail_CustomProperties_Title": "Пользовательские свойства",
|
||||||
"DevDetail_CustomProps_reset_info": "Это удалит ваши пользовательские свойства на этом устройстве и вернет их к значению по умолчанию.",
|
"DevDetail_CustomProps_reset_info": "Это удалит ваши пользовательские свойства на этом устройстве и вернет их к значению по умолчанию.",
|
||||||
"DevDetail_DisplayFields_Title": "Дисплей",
|
"DevDetail_DisplayFields_Title": "Отображение",
|
||||||
"DevDetail_EveandAl_AlertAllEvents": "Оповещения о событиях",
|
"DevDetail_EveandAl_AlertAllEvents": "Оповещения о событиях",
|
||||||
"DevDetail_EveandAl_AlertDown": "Оповещение о доступности",
|
"DevDetail_EveandAl_AlertDown": "Оповещение о доступности",
|
||||||
"DevDetail_EveandAl_Archived": "Архив",
|
"DevDetail_EveandAl_Archived": "Архив",
|
||||||
@@ -225,7 +225,7 @@
|
|||||||
"Device_TableHead_Name": "Имя",
|
"Device_TableHead_Name": "Имя",
|
||||||
"Device_TableHead_NetworkSite": "Сайт устройства",
|
"Device_TableHead_NetworkSite": "Сайт устройства",
|
||||||
"Device_TableHead_Owner": "Владелец",
|
"Device_TableHead_Owner": "Владелец",
|
||||||
"Device_TableHead_Parent_MAC": "MAC род. узла",
|
"Device_TableHead_Parent_MAC": "Родительский узел сети",
|
||||||
"Device_TableHead_Port": "Порт",
|
"Device_TableHead_Port": "Порт",
|
||||||
"Device_TableHead_PresentLastScan": "Присутствие",
|
"Device_TableHead_PresentLastScan": "Присутствие",
|
||||||
"Device_TableHead_RowID": "ID строки",
|
"Device_TableHead_RowID": "ID строки",
|
||||||
@@ -363,8 +363,8 @@
|
|||||||
"Maintenance_Title": "Инструменты обслуживания",
|
"Maintenance_Title": "Инструменты обслуживания",
|
||||||
"Maintenance_Tool_DownloadConfig": "Экспорт настроек",
|
"Maintenance_Tool_DownloadConfig": "Экспорт настроек",
|
||||||
"Maintenance_Tool_DownloadConfig_text": "Загрузите полную резервную копию конфигурации настроек, хранящуюся в файле <code>app.conf</code>.",
|
"Maintenance_Tool_DownloadConfig_text": "Загрузите полную резервную копию конфигурации настроек, хранящуюся в файле <code>app.conf</code>.",
|
||||||
"Maintenance_Tool_DownloadWorkflows": "",
|
"Maintenance_Tool_DownloadWorkflows": "Экспорт Workflow",
|
||||||
"Maintenance_Tool_DownloadWorkflows_text": "",
|
"Maintenance_Tool_DownloadWorkflows_text": "Загрузите полную резервную копию ваших Workflow, хранящихся в файле <code> hairpflows.json </code>.",
|
||||||
"Maintenance_Tool_ExportCSV": "Экспорт устройств (csv)",
|
"Maintenance_Tool_ExportCSV": "Экспорт устройств (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti": "Экспорт устройств (csv)",
|
"Maintenance_Tool_ExportCSV_noti": "Экспорт устройств (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti_text": "Вы уверены, что хотите создать файл CSV?",
|
"Maintenance_Tool_ExportCSV_noti_text": "Вы уверены, что хотите создать файл CSV?",
|
||||||
@@ -463,7 +463,7 @@
|
|||||||
"NETWORK_DEVICE_TYPES_description": "Какие типы устройств разрешено использовать в качестве сетевых устройств в представлении Сеть. Тип устройства должен точно соответствовать настройке <code>Type</code> для конкретного устройства в сведениях об устройстве. Добавьте его на устройство с помощью кнопки <code>+</code>. Не удаляйте существующие типы, а только добавляйте новые.",
|
"NETWORK_DEVICE_TYPES_description": "Какие типы устройств разрешено использовать в качестве сетевых устройств в представлении Сеть. Тип устройства должен точно соответствовать настройке <code>Type</code> для конкретного устройства в сведениях об устройстве. Добавьте его на устройство с помощью кнопки <code>+</code>. Не удаляйте существующие типы, а только добавляйте новые.",
|
||||||
"NETWORK_DEVICE_TYPES_name": "Типы сетевых устройств",
|
"NETWORK_DEVICE_TYPES_name": "Типы сетевых устройств",
|
||||||
"Navigation_About": "О NetAlertX",
|
"Navigation_About": "О NetAlertX",
|
||||||
"Navigation_AppEvents": "",
|
"Navigation_AppEvents": "События приложения",
|
||||||
"Navigation_Devices": "Устройства",
|
"Navigation_Devices": "Устройства",
|
||||||
"Navigation_Donations": "Пожертвования",
|
"Navigation_Donations": "Пожертвования",
|
||||||
"Navigation_Events": "События",
|
"Navigation_Events": "События",
|
||||||
@@ -670,26 +670,32 @@
|
|||||||
"UI_REFRESH_name": "Автоматическое обновление интерфейса",
|
"UI_REFRESH_name": "Автоматическое обновление интерфейса",
|
||||||
"VERSION_description": "Вспомогательное значение версии или метки времени, позволяющее проверить, было ли приложение обновлено.",
|
"VERSION_description": "Вспомогательное значение версии или метки времени, позволяющее проверить, было ли приложение обновлено.",
|
||||||
"VERSION_name": "Версия или временная метка",
|
"VERSION_name": "Версия или временная метка",
|
||||||
"WF_Action_Add": "",
|
"WF_Action_Add": "Добавить действие",
|
||||||
"WF_Action_field": "",
|
"WF_Action_field": "Поле",
|
||||||
"WF_Action_type": "",
|
"WF_Action_type": "Тип",
|
||||||
"WF_Action_value": "",
|
"WF_Action_value": "Значение",
|
||||||
"WF_Actions": "",
|
"WF_Actions": "Действия",
|
||||||
"WF_Add": "",
|
"WF_Add": "Добавить Workflow",
|
||||||
"WF_Add_Condition": "",
|
"WF_Add_Condition": "Добавить условие",
|
||||||
"WF_Add_Group": "",
|
"WF_Add_Group": "Добавить группу",
|
||||||
"WF_Condition_field": "",
|
"WF_Condition_field": "Поле",
|
||||||
"WF_Condition_operator": "",
|
"WF_Condition_operator": "Оператор",
|
||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "Значение",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "Условия",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "Правила логики",
|
||||||
"WF_Enabled": "",
|
"WF_Duplicate": "Дублировать Workflow",
|
||||||
"WF_Name": "",
|
"WF_Enabled": "Включить Workflow",
|
||||||
"WF_Remove": "",
|
"WF_Export": "Экспорт Workflow",
|
||||||
"WF_Save": "",
|
"WF_Export_Copy": "Скопируйте приведенный ниже Workflow и импортируйте его, где это необходимо.",
|
||||||
"WF_Trigger": "",
|
"WF_Import": "Импорт Workflow",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Import_Copy": "Вставьте в Workflow, который вы скопировали ранее.",
|
||||||
"WF_Trigger_type": "",
|
"WF_Name": "Имя Workflow",
|
||||||
|
"WF_Remove": "Удалить Workflow",
|
||||||
|
"WF_Remove_Copy": "Вы хотите удалить этот Workflow?",
|
||||||
|
"WF_Save": "Сохранить Workflow",
|
||||||
|
"WF_Trigger": "Триггер",
|
||||||
|
"WF_Trigger_event_type": "Тип события",
|
||||||
|
"WF_Trigger_type": "Тип триггера",
|
||||||
"add_icon_event_icon": "fa-square-plus",
|
"add_icon_event_icon": "fa-square-plus",
|
||||||
"add_icon_event_tooltip": "Добавить новую иконку",
|
"add_icon_event_tooltip": "Добавить новую иконку",
|
||||||
"add_option_event_icon": "fa-square-plus",
|
"add_option_event_icon": "fa-square-plus",
|
||||||
|
|||||||
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
52
front/php/templates/language/uk_ua.json
Normal file → Executable file
@@ -22,7 +22,7 @@
|
|||||||
"AppEvents_ObjectPlugin": "Пов’язаний плагін",
|
"AppEvents_ObjectPlugin": "Пов’язаний плагін",
|
||||||
"AppEvents_ObjectPrimaryID": "Основний ідентифікатор",
|
"AppEvents_ObjectPrimaryID": "Основний ідентифікатор",
|
||||||
"AppEvents_ObjectSecondaryID": "Вторинний ідентифікатор",
|
"AppEvents_ObjectSecondaryID": "Вторинний ідентифікатор",
|
||||||
"AppEvents_ObjectStatus": "Статус (під час журналу)",
|
"AppEvents_ObjectStatus": "Зареєстрований статус",
|
||||||
"AppEvents_ObjectStatusColumn": "Колонка статусу",
|
"AppEvents_ObjectStatusColumn": "Колонка статусу",
|
||||||
"AppEvents_ObjectType": "Тип об'єкта",
|
"AppEvents_ObjectType": "Тип об'єкта",
|
||||||
"AppEvents_Plugin": "Плагін",
|
"AppEvents_Plugin": "Плагін",
|
||||||
@@ -363,8 +363,8 @@
|
|||||||
"Maintenance_Title": "Інструменти обслуговування",
|
"Maintenance_Title": "Інструменти обслуговування",
|
||||||
"Maintenance_Tool_DownloadConfig": "Експорт налаштувань",
|
"Maintenance_Tool_DownloadConfig": "Експорт налаштувань",
|
||||||
"Maintenance_Tool_DownloadConfig_text": "Завантажте повну резервну копію конфігурації налаштувань, яка зберігається у файлі <code>app.conf</code>.",
|
"Maintenance_Tool_DownloadConfig_text": "Завантажте повну резервну копію конфігурації налаштувань, яка зберігається у файлі <code>app.conf</code>.",
|
||||||
"Maintenance_Tool_DownloadWorkflows": "",
|
"Maintenance_Tool_DownloadWorkflows": "Експорт робочих процесів",
|
||||||
"Maintenance_Tool_DownloadWorkflows_text": "",
|
"Maintenance_Tool_DownloadWorkflows_text": "Завантажте повну резервну копію робочих процесів, які зберігаються у файлі <code>workflows.json</code>.",
|
||||||
"Maintenance_Tool_ExportCSV": "Експорт пристроїв (csv)",
|
"Maintenance_Tool_ExportCSV": "Експорт пристроїв (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti": "Експорт пристроїв (csv)",
|
"Maintenance_Tool_ExportCSV_noti": "Експорт пристроїв (csv)",
|
||||||
"Maintenance_Tool_ExportCSV_noti_text": "Ви впевнені, що хочете створити файл CSV?",
|
"Maintenance_Tool_ExportCSV_noti_text": "Ви впевнені, що хочете створити файл CSV?",
|
||||||
@@ -670,26 +670,32 @@
|
|||||||
"UI_REFRESH_name": "Автоматичне оновлення інтерфейсу користувача",
|
"UI_REFRESH_name": "Автоматичне оновлення інтерфейсу користувача",
|
||||||
"VERSION_description": "Допоміжне значення версії або позначки часу, щоб перевірити, чи було оновлено додаток.",
|
"VERSION_description": "Допоміжне значення версії або позначки часу, щоб перевірити, чи було оновлено додаток.",
|
||||||
"VERSION_name": "Версія або позначка часу",
|
"VERSION_name": "Версія або позначка часу",
|
||||||
"WF_Action_Add": "",
|
"WF_Action_Add": "Додати дію",
|
||||||
"WF_Action_field": "",
|
"WF_Action_field": "Поле",
|
||||||
"WF_Action_type": "",
|
"WF_Action_type": "Тип",
|
||||||
"WF_Action_value": "",
|
"WF_Action_value": "Значення",
|
||||||
"WF_Actions": "",
|
"WF_Actions": "Дії",
|
||||||
"WF_Add": "",
|
"WF_Add": "Додати робочий процес",
|
||||||
"WF_Add_Condition": "",
|
"WF_Add_Condition": "Додати умову",
|
||||||
"WF_Add_Group": "",
|
"WF_Add_Group": "Додати групу",
|
||||||
"WF_Condition_field": "",
|
"WF_Condition_field": "Поле",
|
||||||
"WF_Condition_operator": "",
|
"WF_Condition_operator": "Оператор",
|
||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "Значення",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "Умови",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "Логічні правила",
|
||||||
"WF_Enabled": "",
|
"WF_Duplicate": "Дубльований робочий процес",
|
||||||
"WF_Name": "",
|
"WF_Enabled": "Робочий процес увімкнено",
|
||||||
"WF_Remove": "",
|
"WF_Export": "Робочий процес експорту",
|
||||||
"WF_Save": "",
|
"WF_Export_Copy": "Скопіюйте наведений нижче робочий процес і імпортуйте його, де потрібно.",
|
||||||
"WF_Trigger": "",
|
"WF_Import": "Робочий процес імпорту",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Import_Copy": "Вставте робочий процес, який ви скопіювали раніше.",
|
||||||
"WF_Trigger_type": "",
|
"WF_Name": "Назва робочого процесу",
|
||||||
|
"WF_Remove": "Видалити робочий процес",
|
||||||
|
"WF_Remove_Copy": "Ви хочете видалити цей робочий процес?",
|
||||||
|
"WF_Save": "Зберегти робочі процеси",
|
||||||
|
"WF_Trigger": "Тригер",
|
||||||
|
"WF_Trigger_event_type": "Тип події",
|
||||||
|
"WF_Trigger_type": "Тип тригера",
|
||||||
"add_icon_event_icon": "фа-квадрат-плюс",
|
"add_icon_event_icon": "фа-квадрат-плюс",
|
||||||
"add_icon_event_tooltip": "додати новий значок",
|
"add_icon_event_tooltip": "додати новий значок",
|
||||||
"add_option_event_icon": "фа-квадрат-плюс",
|
"add_option_event_icon": "фа-квадрат-плюс",
|
||||||
|
|||||||
6
front/php/templates/language/zh_cn.json
Normal file → Executable file
@@ -683,9 +683,15 @@
|
|||||||
"WF_Condition_value": "",
|
"WF_Condition_value": "",
|
||||||
"WF_Conditions": "",
|
"WF_Conditions": "",
|
||||||
"WF_Conditions_logic_rules": "",
|
"WF_Conditions_logic_rules": "",
|
||||||
|
"WF_Duplicate": "",
|
||||||
"WF_Enabled": "",
|
"WF_Enabled": "",
|
||||||
|
"WF_Export": "",
|
||||||
|
"WF_Export_Copy": "",
|
||||||
|
"WF_Import": "",
|
||||||
|
"WF_Import_Copy": "",
|
||||||
"WF_Name": "",
|
"WF_Name": "",
|
||||||
"WF_Remove": "",
|
"WF_Remove": "",
|
||||||
|
"WF_Remove_Copy": "",
|
||||||
"WF_Save": "",
|
"WF_Save": "",
|
||||||
"WF_Trigger": "",
|
"WF_Trigger": "",
|
||||||
"WF_Trigger_event_type": "",
|
"WF_Trigger_event_type": "",
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ The OMADA SDN plugin aims at synchronizing data between NetAlertX and a TPLINK O
|
|||||||
OMADA SDN limitation fixed by the plugin:
|
OMADA SDN limitation fixed by the plugin:
|
||||||
0. OMADA SDN can't use DNS for names and keep using MAC ref: https://community.tp-link.com/en/business/forum/topic/503782
|
0. OMADA SDN can't use DNS for names and keep using MAC ref: https://community.tp-link.com/en/business/forum/topic/503782
|
||||||
- when you use an OMADA user Role = Administrator, the plugin will attempt to fix OMADA's shortcoming and populat the NAME field from NetAlertX (from DNS/DHCP/...)
|
- when you use an OMADA user Role = Administrator, the plugin will attempt to fix OMADA's shortcoming and populat the NAME field from NetAlertX (from DNS/DHCP/...)
|
||||||

|

|
||||||
-
|
|
||||||
|
|
||||||
can not fix some of tplinks OMADA SDN own limitations/bugs:
|
can not fix some of tplinks OMADA SDN own limitations/bugs:
|
||||||
1. OMADA SDN switches uplinks/downlinks is broken if the default router is not an OMADA native device
|
1. OMADA SDN switches uplinks/downlinks is broken if the default router is not an OMADA native device
|
||||||
|
|||||||
@@ -285,16 +285,18 @@ def main():
|
|||||||
mylog("verbose", [f"[{pluginName}] login to omada result is: {omada_login}"])
|
mylog("verbose", [f"[{pluginName}] login to omada result is: {omada_login}"])
|
||||||
|
|
||||||
clients_list = callomada(["-t", "myomada", "clients"])
|
clients_list = callomada(["-t", "myomada", "clients"])
|
||||||
|
client_list_count = clients_list.count("\n")
|
||||||
mylog(
|
mylog(
|
||||||
"verbose",
|
"verbose",
|
||||||
[f'[{pluginName}] clients found:"{clients_list.count("\n")}"\n{clients_list}'],
|
[f'[{pluginName}] clients found:"{client_list_count}"\n{clients_list}'],
|
||||||
)
|
)
|
||||||
|
|
||||||
switches_and_aps = callomada(["-t", "myomada", "devices"])
|
switches_and_aps = callomada(["-t", "myomada", "devices"])
|
||||||
|
switches_and_aps_count = switches_and_aps.count("\n")
|
||||||
mylog(
|
mylog(
|
||||||
"verbose",
|
"verbose",
|
||||||
[
|
[
|
||||||
f'[{pluginName}] omada devices (switches, access points) found:"{switches_and_aps.count("\n")}" \n {switches_and_aps}'
|
f'[{pluginName}] omada devices (switches, access points) found:"{switches_and_aps_count}" \n {switches_and_aps}'
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -11,19 +11,24 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id="buttons" class="bottom-buttons col-sm-12 col-xs-12">
|
<div id="buttons" class="bottom-buttons col-sm-12 col-xs-12">
|
||||||
<div class="add-workflow col-sm-12 col-xs-12">
|
<div class="add-workflow col-sm-4 col-xs-12">
|
||||||
<button type="button" class="btn btn-primary add-workflow-btn col-sm-12 col-xs-12" id="add">
|
<button type="button" class="btn btn-primary add-workflow-btn col-sm-12 col-xs-12" id="add">
|
||||||
<?= lang('WF_Add');?>
|
<i class="fa fa-fw fa-plus"></i> <?= lang('WF_Add');?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="save-workflows col-sm-12 col-xs-12">
|
<div class="import-wf col-sm-4 col-xs-12">
|
||||||
<button type="button" class="btn btn-primary col-sm-12 col-xs-12" id="save" onclick="saveWorkflows()">
|
<button type="button" class="btn btn-primary col-sm-12 col-xs-12" id="import">
|
||||||
<?= lang('WF_Save');?>
|
<i class="fa fa-fw fa-file-import"></i> <?= lang('WF_Import');?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="restart-app col-sm-12 col-xs-12">
|
<div class="restart-app col-sm-4 col-xs-12">
|
||||||
<button type="button" class="btn btn-primary col-sm-12 col-xs-12" id="save" onclick="askRestartBackend()">
|
<button type="button" class="btn btn-primary col-sm-12 col-xs-12" id="save" onclick="askRestartBackend()">
|
||||||
<?= lang('Maint_RestartServer');?>
|
<i class="fa fa-fw fa-arrow-rotate-right"></i> <?= lang('Maint_RestartServer');?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="save-workflows col-xs-12">
|
||||||
|
<button type="button" class="btn btn-primary bg-green col-sm-12 col-xs-12" id="save" onclick="saveWorkflows()">
|
||||||
|
<i class="fa fa-fw fa-floppy-disk"></i> <?= lang('WF_Save');?>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,6 +50,9 @@ let fieldOptions = [
|
|||||||
let triggerTypes = [
|
let triggerTypes = [
|
||||||
"Devices"
|
"Devices"
|
||||||
];
|
];
|
||||||
|
let triggerEvents = [
|
||||||
|
"update", "insert", "delete"
|
||||||
|
];
|
||||||
|
|
||||||
let wfEnabledOptions = [
|
let wfEnabledOptions = [
|
||||||
"Yes", "No"
|
"Yes", "No"
|
||||||
@@ -58,6 +66,18 @@ let actionTypes = [
|
|||||||
"update_field", "delete_device"
|
"update_field", "delete_device"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let emptyWorkflow = {
|
||||||
|
"name": "New Workflow",
|
||||||
|
"trigger": {
|
||||||
|
"object_type": "Devices",
|
||||||
|
"event_type": "insert"
|
||||||
|
},
|
||||||
|
"conditions": [
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
// --------------------------------------
|
// --------------------------------------
|
||||||
// Retrieve and process the data
|
// Retrieve and process the data
|
||||||
function getData() {
|
function getData() {
|
||||||
@@ -108,6 +128,8 @@ function renderWorkflows() {
|
|||||||
// Generate UI for a single workflow
|
// Generate UI for a single workflow
|
||||||
function generateWorkflowUI(wf, wfIndex) {
|
function generateWorkflowUI(wf, wfIndex) {
|
||||||
|
|
||||||
|
let wfEnabled = (wf?.enabled ?? "No") == "Yes";
|
||||||
|
|
||||||
let $wfContainer = $("<div>", {
|
let $wfContainer = $("<div>", {
|
||||||
class: "workflow-card panel col-sm-12 col-sx-12",
|
class: "workflow-card panel col-sm-12 col-sx-12",
|
||||||
id: `wf-${wfIndex}-container`
|
id: `wf-${wfIndex}-container`
|
||||||
@@ -121,6 +143,11 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let $wfEnabledIcon = $("<i>", {
|
||||||
|
class: `alignRight fa-regular ${wfEnabled ? "fa-dot-circle" : "fa-circle" }`
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
let $wfHeaderLink = $("<a>",
|
let $wfHeaderLink = $("<a>",
|
||||||
{
|
{
|
||||||
"class": "pointer ",
|
"class": "pointer ",
|
||||||
@@ -137,7 +164,7 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
}
|
}
|
||||||
).text(wf.name)
|
).text(wf.name)
|
||||||
|
|
||||||
$wfContainer.append($wfHeaderLink.append($wfLinkWrap.append($wfHeaderHeading)));
|
$wfContainer.append($wfHeaderLink.append($wfLinkWrap.append($wfHeaderHeading.append($wfEnabledIcon))));
|
||||||
|
|
||||||
// Collapsible panel start
|
// Collapsible panel start
|
||||||
|
|
||||||
@@ -157,7 +184,7 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
`[${wfIndex}].enabled`,
|
`[${wfIndex}].enabled`,
|
||||||
getString("WF_Enabled"),
|
getString("WF_Enabled"),
|
||||||
wfEnabledOptions,
|
wfEnabledOptions,
|
||||||
wf?.enabled ?? "No",
|
wfEnabled ? "Yes" :"No",
|
||||||
`wf-${wfIndex}-enabled`
|
`wf-${wfIndex}-enabled`
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -201,7 +228,7 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
let $eventTypeDropdown = createEditableDropdown(
|
let $eventTypeDropdown = createEditableDropdown(
|
||||||
`[${wfIndex}].trigger.event_type`,
|
`[${wfIndex}].trigger.event_type`,
|
||||||
getString("WF_Trigger_event_type"),
|
getString("WF_Trigger_event_type"),
|
||||||
["update", "create", "delete"],
|
triggerEvents,
|
||||||
wf.trigger.event_type,
|
wf.trigger.event_type,
|
||||||
`wf-${wfIndex}-trigger-event-type`
|
`wf-${wfIndex}-trigger-event-type`
|
||||||
);
|
);
|
||||||
@@ -210,9 +237,10 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
class: "fa-solid fa-bolt bckg-icon-2-line"
|
class: "fa-solid fa-bolt bckg-icon-2-line"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$triggerSection.append($triggerIcon);
|
||||||
$triggerSection.append($triggerTypeDropdown);
|
$triggerSection.append($triggerTypeDropdown);
|
||||||
$triggerSection.append($eventTypeDropdown);
|
$triggerSection.append($eventTypeDropdown);
|
||||||
$triggerSection.append($triggerIcon);
|
|
||||||
$wfCollapsiblePanel.append($triggerSection);
|
$wfCollapsiblePanel.append($triggerSection);
|
||||||
|
|
||||||
// Conditions
|
// Conditions
|
||||||
@@ -323,11 +351,13 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
$actionRemoveButtonWrap.append($actionRemoveButton);
|
$actionRemoveButtonWrap.append($actionRemoveButton);
|
||||||
|
|
||||||
let $actionIcon = $("<i>", {
|
let $actionIcon = $("<i>", {
|
||||||
class: `fa-solid fa-person-running fa-flip-horizontal bckg-icon-${numberOfLines}-line `
|
class: `fa-solid fa-person-running fa-flip-horizontal bckg-icon-${numberOfLines}-line `
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$actionEl.prepend($actionIcon)
|
||||||
|
|
||||||
$actionElWrap.append($actionEl)
|
$actionElWrap.append($actionEl)
|
||||||
$actionElWrap.append($actionIcon)
|
|
||||||
$actionElWrap.append($actionRemoveButtonWrap)
|
$actionElWrap.append($actionRemoveButtonWrap)
|
||||||
|
|
||||||
$actionsContainer.append($actionElWrap);
|
$actionsContainer.append($actionElWrap);
|
||||||
@@ -350,7 +380,7 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
$actionsContainer.append($actionAddButtonWrap)
|
$actionsContainer.append($actionAddButtonWrap)
|
||||||
|
|
||||||
|
|
||||||
let $wfRemoveButtonWrap = $("<div>", { class: "button-container col-sm-12 col-sx-12" });
|
let $wfRemoveButtonWrap = $("<div>", { class: "button-container col-sm-4 col-sx-12" });
|
||||||
|
|
||||||
let $wfRemoveIcon = $("<i>", {
|
let $wfRemoveIcon = $("<i>", {
|
||||||
class: "fa-solid fa-trash"
|
class: "fa-solid fa-trash"
|
||||||
@@ -363,10 +393,40 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
.append($wfRemoveIcon) // Add icon
|
.append($wfRemoveIcon) // Add icon
|
||||||
.append(` ${getString("WF_Remove")}`); // Add text
|
.append(` ${getString("WF_Remove")}`); // Add text
|
||||||
|
|
||||||
|
|
||||||
|
let $wfDuplicateButtonWrap = $("<div>", { class: "button-container col-sm-4 col-sx-12" });
|
||||||
|
|
||||||
|
let $wfDuplicateIcon = $("<i>", {
|
||||||
|
class: "fa-solid fa-copy"
|
||||||
|
});
|
||||||
|
|
||||||
|
let $wfDuplicateButton = $("<div>", {
|
||||||
|
class: "pointer duplicate-wf green-hover-text",
|
||||||
|
wfIndex: wfIndex
|
||||||
|
})
|
||||||
|
.append($wfDuplicateIcon) // Add icon
|
||||||
|
.append(` ${getString("WF_Duplicate")}`); // Add text
|
||||||
|
|
||||||
|
let $wfExportButtonWrap = $("<div>", { class: "button-container col-sm-4 col-sx-12" });
|
||||||
|
|
||||||
|
let $wfExportIcon = $("<i>", {
|
||||||
|
class: "fa-solid fa-file-export"
|
||||||
|
});
|
||||||
|
|
||||||
|
let $wfExportButton = $("<div>", {
|
||||||
|
class: "pointer export-wf green-hover-text",
|
||||||
|
wfIndex: wfIndex
|
||||||
|
})
|
||||||
|
.append($wfExportIcon) // Add icon
|
||||||
|
.append(` ${getString("WF_Export")}`); // Add text
|
||||||
|
|
||||||
$wfCollapsiblePanel.append($actionsContainer);
|
$wfCollapsiblePanel.append($actionsContainer);
|
||||||
|
|
||||||
|
$wfCollapsiblePanel.append($wfDuplicateButtonWrap.append($wfDuplicateButton))
|
||||||
|
$wfCollapsiblePanel.append($wfExportButtonWrap.append($wfExportButton))
|
||||||
$wfCollapsiblePanel.append($wfRemoveButtonWrap.append($wfRemoveButton))
|
$wfCollapsiblePanel.append($wfRemoveButtonWrap.append($wfRemoveButton))
|
||||||
|
|
||||||
|
|
||||||
$wfContainer.append($wfCollapsiblePanel)
|
$wfContainer.append($wfCollapsiblePanel)
|
||||||
|
|
||||||
return $wfContainer;
|
return $wfContainer;
|
||||||
@@ -377,7 +437,7 @@ function generateWorkflowUI(wf, wfIndex) {
|
|||||||
// Render conditions recursively
|
// Render conditions recursively
|
||||||
function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, conditions) {
|
function renderConditions(wfIndex, parentIndexPath, conditionGroupsIndex, conditions) {
|
||||||
let $conditionList = $("<div>", {
|
let $conditionList = $("<div>", {
|
||||||
class: "condition-list panel panel-secondary col-sm-12 col-sx-12",
|
class: "condition-list panel col-sm-12 col-sx-12",
|
||||||
parentIndexPath: parentIndexPath
|
parentIndexPath: parentIndexPath
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -755,7 +815,62 @@ function addWorkflow(workflows) {
|
|||||||
// Function to remove a Workflow
|
// Function to remove a Workflow
|
||||||
function removeWorkflow(workflows, wfIndex) {
|
function removeWorkflow(workflows, wfIndex) {
|
||||||
|
|
||||||
workflows.splice(wfIndex, 1);
|
showModalWarning ('<?= lang('WF_Remove');?>', '<?= lang('WF_Remove_Copy');?>',
|
||||||
|
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Delete');?>', `executeRemoveWorkflow`, wfIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
// Function to execute the remove of a Workflow
|
||||||
|
function executeRemoveWorkflow() {
|
||||||
|
|
||||||
|
workflows = getWorkflowsJson()
|
||||||
|
|
||||||
|
workflows.splice($('#modal-warning').attr("data-myparam-triggered-by"), 1);
|
||||||
|
|
||||||
|
updateWorkflowsJson(workflows)
|
||||||
|
|
||||||
|
// Re-render the UI
|
||||||
|
renderWorkflows();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
// Function to duplicate a Workflow
|
||||||
|
function duplicateWorkflow(workflows, wfIndex) {
|
||||||
|
|
||||||
|
workflows.push(workflows[wfIndex])
|
||||||
|
|
||||||
|
updateWorkflowsJson(workflows)
|
||||||
|
|
||||||
|
// Re-render the UI
|
||||||
|
renderWorkflows();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
// Function to export a Workflow
|
||||||
|
function exportWorkflow(workflows, wfIndex) {
|
||||||
|
|
||||||
|
// Add new icon as base64 string
|
||||||
|
showModalInput ('<i class="fa fa-file-export pointer"></i> <?= lang('WF_Export');?>', '<?= lang('WF_Export_Copy');?>',
|
||||||
|
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Okay');?>', null, null, JSON.stringify(workflows[wfIndex], null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
// Function to import a Workflow
|
||||||
|
function importWorkflow(workflows, wfIndex) {
|
||||||
|
|
||||||
|
// Add new icon as base64 string
|
||||||
|
showModalInput ('<i class="fa fa-file-import pointer"></i> <?= lang('WF_Import');?>', '<?= lang('WF_Import_Copy');?>',
|
||||||
|
'<?= lang('Gen_Cancel');?>', '<?= lang('Gen_Okay');?>', 'importWorkflowExecute', null, "" );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function importWorkflowExecute()
|
||||||
|
{
|
||||||
|
var json = JSON.parse($('#modal-input-textarea').val());
|
||||||
|
|
||||||
|
workflows = getWorkflowsJson()
|
||||||
|
|
||||||
|
workflows.push(json);
|
||||||
|
|
||||||
updateWorkflowsJson(workflows)
|
updateWorkflowsJson(workflows)
|
||||||
|
|
||||||
@@ -970,17 +1085,7 @@ function updateWorkflowsJson(workflows)
|
|||||||
// Get empty workflow JSON
|
// Get empty workflow JSON
|
||||||
function getEmptyWorkflowJson()
|
function getEmptyWorkflowJson()
|
||||||
{
|
{
|
||||||
return {
|
return emptyWorkflow;
|
||||||
"name": "New Workflow",
|
|
||||||
"trigger": {
|
|
||||||
"object_type": "Devices",
|
|
||||||
"event_type": "create"
|
|
||||||
},
|
|
||||||
"conditions": [
|
|
||||||
],
|
|
||||||
"actions": [
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------
|
// ---------------------------------------------------
|
||||||
@@ -1009,6 +1114,21 @@ $(document).on("click", ".remove-wf", function () {
|
|||||||
removeWorkflow(getWorkflowsJson(), wfIndex);
|
removeWorkflow(getWorkflowsJson(), wfIndex);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on("click", ".duplicate-wf", function () {
|
||||||
|
let wfIndex = $(this).attr("wfindex");
|
||||||
|
duplicateWorkflow(getWorkflowsJson(), wfIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("click", ".export-wf", function () {
|
||||||
|
let wfIndex = $(this).attr("wfindex");
|
||||||
|
exportWorkflow(getWorkflowsJson(), wfIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).on("click", ".import-wf", function () {
|
||||||
|
let wfIndex = $(this).attr("wfindex");
|
||||||
|
importWorkflow(getWorkflowsJson(), wfIndex);
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on("click", ".add-condition", function () {
|
$(document).on("click", ".add-condition", function () {
|
||||||
let wfIndex = $(this).attr("wfindex");
|
let wfIndex = $(this).attr("wfindex");
|
||||||
let parentIndexPath = $(this).attr("parentIndexPath");
|
let parentIndexPath = $(this).attr("parentIndexPath");
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ nav:
|
|||||||
- Advanced guides:
|
- Advanced guides:
|
||||||
- Remote Networks: REMOTE_NETWORKS.md
|
- Remote Networks: REMOTE_NETWORKS.md
|
||||||
- Notifications Guide: NOTIFICATIONS.md
|
- Notifications Guide: NOTIFICATIONS.md
|
||||||
|
- Name Resolution: NAME_RESOLUTION.md
|
||||||
- Authelia: AUTHELIA.md
|
- Authelia: AUTHELIA.md
|
||||||
- Performance: PERFORMANCE.md
|
- Performance: PERFORMANCE.md
|
||||||
- Reverse DNS: REVERSE_DNS.md
|
- Reverse DNS: REVERSE_DNS.md
|
||||||
@@ -57,10 +58,12 @@ nav:
|
|||||||
- Icons: ICONS.md
|
- Icons: ICONS.md
|
||||||
- Network Topology: NETWORK_TREE.md
|
- Network Topology: NETWORK_TREE.md
|
||||||
- Troubleshooting:
|
- Troubleshooting:
|
||||||
|
- Inspecting Logs: LOGGING.md
|
||||||
- Debugging Tips: DEBUG_TIPS.md
|
- Debugging Tips: DEBUG_TIPS.md
|
||||||
- Debugging Invalid JSON: DEBUG_INVALID_JSON.md
|
- Debugging Invalid JSON: DEBUG_INVALID_JSON.md
|
||||||
- Debugging Plugins: DEBUG_PLUGINS.md
|
- Debugging Plugins: DEBUG_PLUGINS.md
|
||||||
- Debugging Web UI Port: WEB_UI_PORT_DEBUG.md
|
- Debugging Web UI Port: WEB_UI_PORT_DEBUG.md
|
||||||
|
- Debugging Workflows: WORKFLOWS_DEBUGGING.md
|
||||||
- Development:
|
- Development:
|
||||||
- Plugin and app development:
|
- Plugin and app development:
|
||||||
- Environment Setup: DEV_ENV_SETUP.md
|
- Environment Setup: DEV_ENV_SETUP.md
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ class DB():
|
|||||||
|
|
||||||
return arr
|
return arr
|
||||||
|
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
def upgradeDB(self):
|
def upgradeDB(self):
|
||||||
"""
|
"""
|
||||||
@@ -543,7 +542,6 @@ class DB():
|
|||||||
sql_Plugins_Objects = """ CREATE TABLE IF NOT EXISTS Plugins_Objects(
|
sql_Plugins_Objects = """ CREATE TABLE IF NOT EXISTS Plugins_Objects(
|
||||||
"Index" INTEGER,
|
"Index" INTEGER,
|
||||||
Plugin TEXT NOT NULL,
|
Plugin TEXT NOT NULL,
|
||||||
ObjectGUID TEXT,
|
|
||||||
Object_PrimaryID TEXT NOT NULL,
|
Object_PrimaryID TEXT NOT NULL,
|
||||||
Object_SecondaryID TEXT NOT NULL,
|
Object_SecondaryID TEXT NOT NULL,
|
||||||
DateTimeCreated TEXT NOT NULL,
|
DateTimeCreated TEXT NOT NULL,
|
||||||
@@ -561,6 +559,7 @@ class DB():
|
|||||||
"HelpVal2" TEXT,
|
"HelpVal2" TEXT,
|
||||||
"HelpVal3" TEXT,
|
"HelpVal3" TEXT,
|
||||||
"HelpVal4" TEXT,
|
"HelpVal4" TEXT,
|
||||||
|
ObjectGUID TEXT,
|
||||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||||
); """
|
); """
|
||||||
self.sql.execute(sql_Plugins_Objects)
|
self.sql.execute(sql_Plugins_Objects)
|
||||||
@@ -930,3 +929,18 @@ def get_all_devices(db):
|
|||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def get_array_from_sql_rows(rows):
|
||||||
|
# Convert result into list of lists
|
||||||
|
arr = []
|
||||||
|
for row in rows:
|
||||||
|
if isinstance(row, sqlite3.Row):
|
||||||
|
arr.append(list(row)) # Convert row to list
|
||||||
|
elif isinstance(row, (tuple, list)):
|
||||||
|
arr.append(list(row)) # Already iterable, just convert to list
|
||||||
|
else:
|
||||||
|
arr.append([row]) # Handle single values safely
|
||||||
|
|
||||||
|
return arr
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -819,7 +819,7 @@ class plugin_object_class:
|
|||||||
|
|
||||||
# Check if self.status is valid
|
# Check if self.status is valid
|
||||||
if self.status not in ["exists", "watched-changed", "watched-not-changed", "new", "not-processed", "missing-in-last-scan"]:
|
if self.status not in ["exists", "watched-changed", "watched-not-changed", "new", "not-processed", "missing-in-last-scan"]:
|
||||||
raise ValueError("Invalid status value for plugin object:", self.status)
|
raise ValueError(f"Invalid status value for plugin object ({self.pluginPref}|{self.primaryId}|{self.watched1}) invalid status: {self.status} on objDbRow:", objDbRow)
|
||||||
|
|
||||||
self.idsHash = str(hash(str(self.primaryId) + str(self.secondaryId)))
|
self.idsHash = str(hash(str(self.primaryId) + str(self.secondaryId)))
|
||||||
# self.idsHash = str(self.primaryId) + str(self.secondaryId)
|
# self.idsHash = str(self.primaryId) + str(self.secondaryId)
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class Condition:
|
|||||||
if self.operator == "equals":
|
if self.operator == "equals":
|
||||||
result = str(obj_value) == str(self.value)
|
result = str(obj_value) == str(self.value)
|
||||||
elif self.operator == "contains":
|
elif self.operator == "contains":
|
||||||
result = str(self.value) in str(obj_value)
|
result = str(self.value).lower() in str(obj_value).lower()
|
||||||
elif self.operator == "regex":
|
elif self.operator == "regex":
|
||||||
result = bool(re.match(self.value, str(obj_value)))
|
result = bool(re.match(self.value, str(obj_value)))
|
||||||
else:
|
else:
|
||||||
@@ -57,9 +57,7 @@ class ConditionGroup:
|
|||||||
|
|
||||||
def __init__(self, group_json):
|
def __init__(self, group_json):
|
||||||
|
|
||||||
mylog('none', ["[WF] json.dumps(group_json)"])
|
mylog('verbose', [f"[WF] ConditionGroup json.dumps(group_json): {json.dumps(group_json)}"])
|
||||||
mylog('none', [json.dumps(group_json)])
|
|
||||||
mylog('none', [group_json])
|
|
||||||
|
|
||||||
self.logic = group_json.get("logic", "AND").upper()
|
self.logic = group_json.get("logic", "AND").upper()
|
||||||
self.conditions = []
|
self.conditions = []
|
||||||
@@ -78,6 +76,6 @@ class ConditionGroup:
|
|||||||
elif self.logic == "OR":
|
elif self.logic == "OR":
|
||||||
return any(results)
|
return any(results)
|
||||||
else:
|
else:
|
||||||
m = f"[WF] Unsupported logic: {self.logic}"
|
m = f"[WF] ConditionGroup unsupported logic: {self.logic}"
|
||||||
mylog('none', [m])
|
mylog('verbose', [m])
|
||||||
raise ValueError(m)
|
raise ValueError(m)
|
||||||
|
|||||||
@@ -50,20 +50,24 @@ class WorkflowManager:
|
|||||||
def process_event(self, event):
|
def process_event(self, event):
|
||||||
"""Process the events. Check if events match a workflow trigger"""
|
"""Process the events. Check if events match a workflow trigger"""
|
||||||
|
|
||||||
mylog('verbose', [f"[WF] Processing event with GUID {event["GUID"]}"])
|
evGuid = event["GUID"]
|
||||||
|
|
||||||
|
mylog('verbose', [f"[WF] Processing event with GUID {evGuid}"])
|
||||||
|
|
||||||
# Check if the trigger conditions match
|
# Check if the trigger conditions match
|
||||||
for workflow in self.workflows:
|
for workflow in self.workflows:
|
||||||
|
|
||||||
# Ensure workflow is enabled before proceeding
|
# Ensure workflow is enabled before proceeding
|
||||||
if workflow.get("enabled", "No").lower() == "yes":
|
if workflow.get("enabled", "No").lower() == "yes":
|
||||||
|
wfName = workflow["name"]
|
||||||
|
mylog('debug', [f"[WF] Checking if '{evGuid}' triggers the workflow '{wfName}'"])
|
||||||
|
|
||||||
# construct trigger object which also evaluates if the current event triggers it
|
# construct trigger object which also evaluates if the current event triggers it
|
||||||
trigger = Trigger(workflow["trigger"], event, self.db)
|
trigger = Trigger(workflow["trigger"], event, self.db)
|
||||||
|
|
||||||
if trigger.triggered:
|
if trigger.triggered:
|
||||||
|
|
||||||
mylog('verbose', [f"[WF] Event with GUID '{event["GUID"]}' triggered the workflow '{workflow["name"]}'"])
|
mylog('verbose', [f"[WF] Event with GUID '{evGuid}' triggered the workflow '{wfName}'"])
|
||||||
|
|
||||||
self.execute_workflow(workflow, trigger)
|
self.execute_workflow(workflow, trigger)
|
||||||
|
|
||||||
@@ -80,6 +84,8 @@ class WorkflowManager:
|
|||||||
def execute_workflow(self, workflow, trigger):
|
def execute_workflow(self, workflow, trigger):
|
||||||
"""Execute the actions in the given workflow if conditions are met."""
|
"""Execute the actions in the given workflow if conditions are met."""
|
||||||
|
|
||||||
|
wfName = workflow["name"]
|
||||||
|
|
||||||
# Ensure conditions exist
|
# Ensure conditions exist
|
||||||
if not isinstance(workflow.get("conditions"), list):
|
if not isinstance(workflow.get("conditions"), list):
|
||||||
m = f"[WF] workflow['conditions'] must be a list"
|
m = f"[WF] workflow['conditions'] must be a list"
|
||||||
@@ -93,7 +99,7 @@ class WorkflowManager:
|
|||||||
|
|
||||||
if evaluator.evaluate(trigger): # If any group evaluates to True
|
if evaluator.evaluate(trigger): # If any group evaluates to True
|
||||||
|
|
||||||
mylog('none', [f"[WF] Workflow {workflow["name"]} will be executed - conditions were evaluated as TRUE"])
|
mylog('none', [f"[WF] Workflow {wfName} will be executed - conditions were evaluated as TRUE"])
|
||||||
mylog('debug', [f"[WF] Workflow condition_group: {condition_group}"])
|
mylog('debug', [f"[WF] Workflow condition_group: {condition_group}"])
|
||||||
|
|
||||||
self.execute_actions(workflow["actions"], trigger)
|
self.execute_actions(workflow["actions"], trigger)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import sys
|
import sys
|
||||||
|
import json
|
||||||
|
|
||||||
# Register NetAlertX directories
|
# Register NetAlertX directories
|
||||||
INSTALL_PATH="/app"
|
INSTALL_PATH="/app"
|
||||||
@@ -7,6 +8,7 @@ sys.path.extend([f"{INSTALL_PATH}/server"])
|
|||||||
import conf
|
import conf
|
||||||
from logger import mylog, Logger
|
from logger import mylog, Logger
|
||||||
from helper import get_setting_value, timeNowTZ
|
from helper import get_setting_value, timeNowTZ
|
||||||
|
from database import get_array_from_sql_rows
|
||||||
|
|
||||||
# Make sure log level is initialized correctly
|
# Make sure log level is initialized correctly
|
||||||
Logger(get_setting_value('LOG_LEVEL'))
|
Logger(get_setting_value('LOG_LEVEL'))
|
||||||
@@ -27,7 +29,8 @@ class Trigger:
|
|||||||
self.event = event # Store the triggered event context, if provided
|
self.event = event # Store the triggered event context, if provided
|
||||||
self.triggered = self.object_type == event["ObjectType"] and self.event_type == event["AppEventType"]
|
self.triggered = self.object_type == event["ObjectType"] and self.event_type == event["AppEventType"]
|
||||||
|
|
||||||
mylog('verbose', [f"[WF] self.triggered '{self.triggered}'"])
|
mylog('debug', [f"""[WF] self.triggered '{self.triggered}' for event '{get_array_from_sql_rows(event)} and trigger {json.dumps(triggerJson)}' """])
|
||||||
|
|
||||||
|
|
||||||
if self.triggered:
|
if self.triggered:
|
||||||
# object type corresponds with the DB table name
|
# object type corresponds with the DB table name
|
||||||
|
|||||||