Compare commits

..

310 Commits

Author SHA1 Message Date
jokob-sk
4ee652cfda Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-30 22:31:55 +10:00
jokob-sk
abaffa4042 better Apprise settings description 2025-07-30 22:31:38 +10:00
Hosted Weblate
ad4b5d7c64 Merge branch 'origin/main' into Weblate. 2025-07-30 13:59:20 +02:00
Максим Горпиніч
3b38476c5a Translated using Weblate (Ukrainian)
Currently translated at 100.0% (758 of 758 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-30 13:59:17 +02:00
jokob-sk
a42f6a20e4 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-30 21:58:37 +10:00
jokob-sk
da2afb2fb7 code refactor 2025-07-30 21:58:31 +10:00
Hosted Weblate
dda0d6a898 Merge branch 'origin/main' into Weblate.
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-29 23:45:45 +00:00
jokob-sk
36068aaf77 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.8% (755 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-29 23:45:43 +00:00
Safeguard
3cb65fa4ec Translated using Weblate (Russian)
Currently translated at 91.9% (695 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-07-29 23:45:42 +00:00
jokob-sk
26cc757f75 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-30 09:31:39 +10:00
jokob-sk
2337f96685 Available Ips in System Info #1127 2025-07-30 09:31:34 +10:00
Hosted Weblate
82ec3b239e Merge branch 'origin/main' into Weblate.
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-29 12:09:14 +02:00
jokob-sk
aa72b0216d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 92.0% (696 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-29 12:09:13 +02:00
jokob-sk
b002bc34ac Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-29 20:01:58 +10:00
jokob-sk
a84f0d4faf cache fix on details page, small css fixes 2025-07-29 20:01:50 +10:00
Hosted Weblate
a9715cb087 Merge branch 'origin/main' into Weblate.
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-28 23:27:47 +02:00
Marco Rios
827b0d15d1 Translated using Weblate (Spanish)
Currently translated at 100.0% (756 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-07-28 23:27:46 +02:00
jokob-sk
4b4b2f914f Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-29 07:25:26 +10:00
jokob-sk
bf679cdc5d strings cleanup, small fixes 2025-07-29 07:25:22 +10:00
Jokob @NetAlertX
4c430c6d5d Merge pull request #1123 from dougmaitelli/feat/apprise-tag
Add support for Apprise Tags
2025-07-29 07:22:24 +10:00
Максим Горпиніч
905279aabe Translated using Weblate (Ukrainian)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 100.0% (756 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-28 08:02:18 +02:00
Massimo Pissarello
d92a5da029 Translated using Weblate (Italian)
Currently translated at 100.0% (756 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-28 08:02:16 +02:00
Sylvain Pichon
a3a27fc27a Translated using Weblate (French)
Currently translated at 100.0% (756 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-28 08:02:14 +02:00
Douglas Maitelli
0d6bc71d2b Review comments 2025-07-28 00:29:14 +00:00
Douglas Maitelli
41397be1bd Review comments 2025-07-27 23:09:48 +00:00
Douglas Maitelli
8fbcb07267 Review comments 2025-07-27 23:09:20 +00:00
Douglas Maitelli
3c18540c8c Add support for Apprise Tags 2025-07-27 22:35:04 +00:00
Douglas Maitelli
ab9c940d01 Add support for Apprise Tags 2025-07-27 22:29:19 +00:00
Hosted Weblate
7e573282d0 Merge branch 'origin/main' into Weblate.
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-27 01:42:30 +00:00
jokob-sk
d08368e4f5 net devices fix 2025-07-27 11:26:12 +10:00
Hosted Weblate
2c1718bb0e Merge branch 'origin/main' into Weblate. 2025-07-27 01:22:48 +00:00
Deleted User
5a0bf03b81 Translated using Weblate (Ukrainian)
Currently translated at 92.7% (701 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-27 01:22:46 +00:00
anton garcias
6978c9446c Translated using Weblate (Catalan)
Currently translated at 90.0% (681 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-07-27 01:22:45 +00:00
HAMAD ABDULLA
d3fd160cf3 Translated using Weblate (Arabic)
Currently translated at 89.9% (680 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-07-27 01:22:44 +00:00
Ondřej Karaffa
c3421c8699 Translated using Weblate (Czech)
Currently translated at 7.1% (54 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/cs/
2025-07-27 01:22:43 +00:00
blomusti
0a3ebc931b Translated using Weblate (Turkish)
Currently translated at 60.4% (457 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-07-27 01:22:42 +00:00
Ptsa Daniel
83c593a1e2 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 92.7% (701 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-27 01:22:41 +00:00
Adam Stańczyk
60c812327a Translated using Weblate (Polish)
Currently translated at 91.2% (690 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-27 01:22:40 +00:00
Cesar Osvaldo Müller
d27ba5c046 Translated using Weblate (Portuguese (Brazil))
Currently translated at 53.5% (405 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-07-27 01:22:39 +00:00
Massimo Pissarello
120a88d12d Translated using Weblate (Italian)
Currently translated at 92.5% (700 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-27 01:22:38 +00:00
Safeguard
054df2ed79 Translated using Weblate (Russian)
Currently translated at 91.2% (690 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-07-27 01:22:37 +00:00
Marcus Isdahl
94240f61ca Translated using Weblate (Norwegian Bokmål)
Currently translated at 74.4% (563 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-07-27 01:22:36 +00:00
BlueTurtle
9c77a25d9a Translated using Weblate (French)
Currently translated at 92.7% (701 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-27 01:22:35 +00:00
Anonymous
7819f2774c Translated using Weblate (Spanish)
Currently translated at 89.0% (673 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-07-27 01:22:34 +00:00
Ettore Atalan
a07bdd7469 Translated using Weblate (German)
Currently translated at 82.4% (623 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-07-27 01:22:32 +00:00
jokob-sk
68c3712539 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-27 11:16:58 +10:00
jokob-sk
be5fc6dccb css fixes, removal of ionicons 2025-07-27 11:16:35 +10:00
Hosted Weblate
414110e575 Merge branch 'origin/main' into Weblate. 2025-07-26 23:02:37 +00:00
Sylvain Pichon
bd641273ff Translated using Weblate (French)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-26 23:02:35 +00:00
jokob-sk
404a97fb89 network devices list, strings cleanup 2025-07-27 08:58:54 +10:00
Hosted Weblate
e3cab610ec Merge branch 'origin/main' into Weblate.
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-26 09:34:03 +02:00
Максим Горпиніч
cd87f6db0d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-26 09:34:02 +02:00
kkumakuma
dc015077e4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-26 09:34:02 +02:00
jokob-sk
f778932fd6 weblate 2025-07-26 17:19:54 +10:00
jokob-sk
c284d27d31 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-26 17:19:23 +10:00
jokob-sk
acac02a672 fixes 2025-07-26 17:19:05 +10:00
Максим Горпиніч
e8d3d5c2a9 Translated using Weblate (Ukrainian)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 99.8% (754 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-26 05:02:50 +02:00
Ashtin
d4b898358f Translated using Weblate (Catalan)
Currently translated at 97.0% (733 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-07-26 05:02:50 +02:00
Ashtin
bd5a9b4f72 Translated using Weblate (Arabic)
Currently translated at 97.0% (733 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-07-26 05:02:50 +02:00
Ondřej Karaffa
5f1d2ee26c Translated using Weblate (Czech)
Currently translated at 7.4% (56 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/cs/
2025-07-26 05:02:50 +02:00
Ashtin
9175a5a45f Translated using Weblate (Turkish)
Currently translated at 65.8% (497 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-07-26 05:02:50 +02:00
kkumakuma
2af60c034f Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 88.3% (667 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-26 05:02:49 +02:00
Adam Stańczyk
c503aeaf00 Translated using Weblate (Polish)
Currently translated at 98.4% (743 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-26 05:02:49 +02:00
Ashtin
3f9922b7df Translated using Weblate (Portuguese (Brazil))
Currently translated at 57.2% (432 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-07-26 05:02:49 +02:00
Massimo Pissarello
91fc1da896 Translated using Weblate (Italian)
Currently translated at 99.8% (754 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-26 05:02:49 +02:00
Safeguard
3d2e4f6343 Translated using Weblate (Russian)
Currently translated at 98.4% (743 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-07-26 05:02:49 +02:00
Ashtin
39d44689de Translated using Weblate (Norwegian Bokmål)
Currently translated at 80.0% (604 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-07-26 05:02:49 +02:00
Sylvain Pichon
2547e6e805 Translated using Weblate (French)
Currently translated at 99.8% (754 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-26 05:02:49 +02:00
Ashtin
3c5a76b512 Translated using Weblate (Spanish)
Currently translated at 96.0% (725 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-07-26 05:02:48 +02:00
Ettore Atalan
dc76ba2fda Translated using Weblate (German)
Currently translated at 88.7% (670 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-07-26 05:02:48 +02:00
Hosted Weblate
386ee473bd Merge branch 'origin/main' into Weblate. 2025-07-26 02:59:43 +00:00
kkumakuma
feebe96fec Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 88.0% (665 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-26 02:59:41 +00:00
jokob-sk
86f83eff5b Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-26 12:59:00 +10:00
jokob-sk
54fa2743f9 refactor, tab async loading on focus 2025-07-26 12:58:45 +10:00
Hosted Weblate
2475133405 Merge branch 'origin/main' into Weblate. 2025-07-25 22:46:56 +00:00
kkumakuma
cdb3dee8ed Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 86.8% (656 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-25 22:46:54 +00:00
Massimo Pissarello
e667abf6fb Translated using Weblate (Italian)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-25 22:46:53 +00:00
Sylvain Pichon
d5b2e2f0ee Translated using Weblate (French)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-25 22:46:52 +00:00
jokob-sk
cd7cbcc4c8 weblate 2025-07-26 08:45:52 +10:00
jokob-sk
a055c2450a Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-26 08:45:13 +10:00
jokob-sk
170a3c0ae1 presence rework #1119, plugin history filter 2025-07-26 08:45:07 +10:00
Максим Горпиніч
6fe865e115 Translated using Weblate (Ukrainian)
Some checks failed
Deploy MkDocs / deploy (push) Has been cancelled
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-24 16:46:53 +02:00
Anonymous
1c1c5bd32b Translated using Weblate (Catalan)
Currently translated at 96.9% (732 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-07-24 16:46:53 +02:00
Anonymous
d40ad8bd09 Translated using Weblate (Arabic)
Currently translated at 96.9% (732 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-07-24 16:46:53 +02:00
Anonymous
2b70e1c2e5 Translated using Weblate (Turkish)
Currently translated at 65.6% (496 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-07-24 16:46:53 +02:00
Anonymous
da8ea98c28 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 81.1% (613 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-24 16:46:52 +02:00
Anonymous
caac65f4f9 Translated using Weblate (Polish)
Currently translated at 98.5% (744 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-24 16:46:52 +02:00
Anonymous
a92d66c981 Translated using Weblate (Portuguese (Brazil))
Currently translated at 57.0% (431 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-07-24 16:46:52 +02:00
Massimo Pissarello
5fd709ed35 Translated using Weblate (Italian)
Currently translated at 99.8% (754 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-24 16:46:52 +02:00
Anonymous
29f120e66b Translated using Weblate (Russian)
Currently translated at 98.5% (744 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-07-24 16:46:52 +02:00
Anonymous
74f5933627 Translated using Weblate (Norwegian Bokmål)
Currently translated at 79.8% (603 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-07-24 16:46:52 +02:00
Sylvain Pichon
56a93ee75b Translated using Weblate (French)
Currently translated at 99.8% (754 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-24 16:46:51 +02:00
Anonymous
3a8634844f Translated using Weblate (Spanish)
Currently translated at 95.8% (724 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-07-24 16:46:51 +02:00
Anonymous
26d546f6ec Translated using Weblate (German)
Currently translated at 88.8% (671 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-07-24 16:46:51 +02:00
jokob-sk
0265c41612 partial rollback #1119 2025-07-24 22:13:19 +10:00
jokob-sk
a53b410713 double-bars work #1119
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-24 21:44:23 +10:00
jokob-sk
3035b5b6b2 double-bars work #1119 2025-07-24 21:15:36 +10:00
jokob-sk
266d7c25da weblate 2025-07-24 21:06:17 +10:00
jokob-sk
77b25a9740 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-24 21:05:39 +10:00
jokob-sk
618bafa514 miss match work #1119 2025-07-24 21:05:33 +10:00
Максим Горпиніч
415f589716 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-24 12:33:00 +02:00
Massimo Pissarello
54c7c820b8 Translated using Weblate (Italian)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-24 12:32:59 +02:00
Sylvain Pichon
89864f7070 Translated using Weblate (French)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-24 12:32:59 +02:00
anton garcias
b4916cd3b6 Translated using Weblate (Catalan)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 96.9% (732 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-07-24 05:44:30 +02:00
HAMAD ABDULLA
97567ad472 Translated using Weblate (Arabic)
Currently translated at 96.9% (732 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-07-24 05:44:30 +02:00
Bekir Kayra Çiğdem
b00dbd560f Translated using Weblate (Turkish)
Currently translated at 65.6% (496 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-07-24 05:44:30 +02:00
Ptsa Daniel
c41fbab8ee Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 81.1% (613 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-07-24 05:44:30 +02:00
Adam Stańczyk
771db9fa0e Translated using Weblate (Polish)
Currently translated at 98.5% (744 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-24 05:44:30 +02:00
GoldBull3t
dd6ccf830c Translated using Weblate (Portuguese (Brazil))
Currently translated at 57.0% (431 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-07-24 05:44:30 +02:00
Massimo Pissarello
b0e079aeb2 Translated using Weblate (Italian)
Currently translated at 99.7% (753 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-24 05:44:29 +02:00
Safeguard
d1d49572e2 Translated using Weblate (Russian)
Currently translated at 98.5% (744 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-07-24 05:44:29 +02:00
Marcus Isdahl
774078df9c Translated using Weblate (Norwegian Bokmål)
Currently translated at 79.8% (603 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-07-24 05:44:29 +02:00
Sylvain Pichon
8c708f2c96 Translated using Weblate (French)
Currently translated at 99.7% (753 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-24 05:44:29 +02:00
Deleted User
3c68b0151d Translated using Weblate (Spanish)
Currently translated at 95.8% (724 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-07-24 05:44:29 +02:00
Norbert (Noschvie)
6cb252c0ed Translated using Weblate (German)
Currently translated at 88.8% (671 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-07-24 05:44:29 +02:00
Hosted Weblate
11f2a74b5d Merge branch 'origin/main' into Weblate. 2025-07-24 04:54:34 +02:00
Максим Горпиніч
9bba3c9e50 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (755 of 755 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-24 04:54:34 +02:00
jokob-sk
b3d71a5fec Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-24 12:54:10 +10:00
jokob-sk
a111ed929b nnetwork and link tweaks 2025-07-24 12:53:24 +10:00
Jokob @NetAlertX
21dd85f62f Merge pull request #1121 from fuad00/patch-1
hotfix: invalid volume variable
2025-07-24 07:40:13 +10:00
Fuad
b08bca5ce4 hotfix: invalid volume variable 2025-07-23 17:59:57 +03:00
jokob-sk
dff6cba2d8 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-23 22:25:47 +10:00
jokob-sk
10a0921e35 plugins columns cleanup, devDetail cleanup, better icon selector CUSTPROP 2025-07-23 22:25:35 +10:00
Massimo Pissarello
70443942ff Translated using Weblate (Italian)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-22 06:03:06 +02:00
jokob-sk
7d26966250 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-21 17:57:08 +10:00
jokob-sk
9ada27cf7e sync plugin, plugins UI css fixes 2025-07-21 17:56:49 +10:00
jokob-sk
752322bbad network tree filter counts 2025-07-21 09:38:28 +10:00
jokob-sk
0444e338ec indexes 4 the win 2025-07-21 09:15:40 +10:00
Максим Горпиніч
a669abd47e Translated using Weblate (Ukrainian)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-20 16:03:11 +02:00
Sylvain Pichon
4e46fcb9e6 Translated using Weblate (French)
Currently translated at 100.0% (754 of 754 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-20 16:03:10 +02:00
jokob-sk
31d7d0c143 docs and refactor 2025-07-20 22:45:17 +10:00
jokob-sk
b470b985e9 network page refactor
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-20 08:31:50 +10:00
jokob-sk
c90c6b5c90 network topology refactor
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-19 22:00:57 +10:00
jokob-sk
26f0d0ac2f network topology refactor 2025-07-19 20:45:46 +10:00
jokob-sk
5e3365935e docs
Some checks failed
Deploy MkDocs / deploy (push) Has been cancelled
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
2025-07-17 19:09:56 +10:00
jokob-sk
5b6424d405 hover-box in devices lists
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-16 22:28:40 +10:00
jokob-sk
698ad8e45d refactor ui init 2025-07-16 22:00:55 +10:00
jokob-sk
09fd345528 color alignemnt network tab, pop-up box devDetails
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-07-16 08:32:51 +10:00
jokob-sk
edfba9f1bc hover box css fixes, docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-15 23:21:28 +10:00
Максим Горпиніч
bb844ceac4 Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-15 06:03:36 +00:00
Massimo Pissarello
c6f3b60671 Translated using Weblate (Italian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-15 06:03:35 +00:00
Massimo Pissarello
3178a65e72 Translated using Weblate (Italian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-15 06:03:35 +00:00
Sylvain Pichon
aedfb4e5dd Translated using Weblate (French)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-07-15 06:03:34 +00:00
jokob-sk
e0dcc191c7 hover box, network page improvements, Last Seen changed logic ⚠
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-15 08:34:47 +10:00
jokob-sk
c80e6d3474 css hover box #724
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-14 20:42:12 +10:00
jokob-sk
46cd4887a3 css fixes #724 2025-07-14 19:52:16 +10:00
jokob-sk
bfbf70cf1a colored relationships #724
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-14 15:24:38 +10:00
jokob-sk
61de54bc34 net refactor 2025-07-14 11:01:16 +10:00
Максим Горпиніч
e27af88690 Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (756 of 756 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-07-13 18:01:48 +02:00
jokob-sk
393c3fd3b6 nics work 724
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-13 09:02:21 +10:00
Hosted Weblate
0e53aef9ea Merge branch 'origin/main' into Weblate.
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-12 05:45:29 +00:00
Safeguard
8a742b0ec0 Translated using Weblate (Russian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-07-12 05:45:27 +00:00
jokob-sk
b17b70a91f pl conflict resolution 2025-07-12 15:44:58 +10:00
jokob-sk
6f536f9952 ntfy disable cert #1117, initial nics work #724 2025-07-12 15:40:08 +10:00
Adam Stańczyk
034caf965a Translated using Weblate (Polish)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:22 +00:00
Adam Stańczyk
6322e3f4cf Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:20 +00:00
Adam Stańczyk
6b78adb702 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:19 +00:00
Adam Stańczyk
6e8c931bf3 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:18 +00:00
Adam Stańczyk
b80fe44c08 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:17 +00:00
Adam Stańczyk
0921773666 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:16 +00:00
Adam Stańczyk
13e960f5cb Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:15 +00:00
Adam Stańczyk
094583b8f6 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:14 +00:00
Adam Stańczyk
fd7ec5d2cf Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:13 +00:00
Adam Stańczyk
370659f461 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:12 +00:00
Adam Stańczyk
1f853a8bb1 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:11 +00:00
Adam Stańczyk
b93c3b6093 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:10 +00:00
Adam Stańczyk
6145fff2fd Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:09 +00:00
Adam Stańczyk
48687dc6dd Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:08 +00:00
Adam Stańczyk
4591cc87e2 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:07 +00:00
Adam Stańczyk
67491615c0 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:06 +00:00
Adam Stańczyk
fadf64450b Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:05 +00:00
Adam Stańczyk
34bb7bb93f Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:04 +00:00
Adam Stańczyk
67f8401dce Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:03 +00:00
Adam Stańczyk
f9fb711881 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:01 +00:00
Adam Stańczyk
26c35a01f3 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:02:00 +00:00
Adam Stańczyk
9538842fcb Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:59 +00:00
Adam Stańczyk
8ca31ab049 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:58 +00:00
Adam Stańczyk
b19c9b5eb6 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:58 +00:00
Adam Stańczyk
896ead0bb8 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:56 +00:00
Adam Stańczyk
9835381186 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:55 +00:00
Adam Stańczyk
d49ced8942 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:54 +00:00
Adam Stańczyk
9a01263d70 Translated using Weblate (Polish)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-07-07 12:01:53 +00:00
jokob-sk
7980554924 small refactor, docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-07 09:05:35 +10:00
jokob-sk
8949bcb567 icon and device type guessing from @slammingprogramming
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-06 17:08:11 +10:00
jokob-sk
ac90bb702e string issue #1104
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-06 12:22:42 +10:00
jokob-sk
088c913ede session events fix 2025-07-06 09:03:26 +10:00
jokob-sk
7554a7f246 apprise_telegram settings screenshot update 2025-07-06 08:23:04 +10:00
jokob-sk
31e5c9fe96 twitter automation removal 2025-07-05 09:04:46 +10:00
jokob-sk
e21c1771c7 docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-05 08:14:24 +10:00
jokob-sk
502a331754 docs 2025-07-05 07:33:42 +10:00
Jokob @NetAlertX
6203c3c257 Merge pull request #1108 from scalerow/bugfix/unifimp_not_running
nax_pyunifi.controller not found
2025-07-05 07:23:00 +10:00
Jan Fredrik Sundblom
c7d9ef97ee nax_pyunifi.controller not found
Could not import nax_pyunifi.controller, pyunifi.controller works as expected.
2025-07-04 15:46:40 +02:00
GitHub Actions
608fc5bbd0 Add release tweet for v25.7.3 - 🌍 Arabic translation and various fixes
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-03 22:07:40 +00:00
jokob-sk
dbf7104dd0 docs, smtp logging 2025-07-04 07:41:01 +10:00
jokob-sk
1f26de4b76 docs, smtp logging 2025-07-04 07:21:18 +10:00
jokob-sk
ad43e4a2b2 docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-07-03 07:42:10 +10:00
jokob-sk
171feda4fe docs 2025-07-03 07:41:10 +10:00
jokob-sk
e5a4e07b8b Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-03 07:40:09 +10:00
anton garcias
44a5600108 Translated using Weblate (Catalan)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 98.4% (739 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-07-02 03:01:52 +02:00
Ondřej Karaffa
d059c5c584 Translated using Weblate (Czech)
Currently translated at 7.9% (60 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/cs/
2025-07-02 03:01:51 +02:00
Ondřej Karaffa
523ff8e877 Translated using Weblate (Czech)
Currently translated at 7.9% (60 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/cs/
2025-07-02 03:01:50 +02:00
Ondřej Karaffa
ba9115bac1 Translated using Weblate (Czech)
Currently translated at 7.9% (60 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/cs/
2025-07-02 03:01:49 +02:00
Massimo Pissarello
11f6f50748 Translated using Weblate (Italian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-07-02 03:01:47 +02:00
jokob-sk
d85c52bceb Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-07-01 07:51:01 +10:00
jokob-sk
9cf1d7b461 lang 2025-07-01 07:50:57 +10:00
Hosted Weblate
e7a2a53d18 Merge branch 'origin/main' into Weblate.
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-06-30 07:38:01 +02:00
Ettore Atalan
1ffdfc17fb Translated using Weblate (German)
Currently translated at 89.4% (672 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-06-30 07:38:01 +02:00
jokob-sk
190c6fb007 refactor db upgrade 2025-06-30 15:37:40 +10:00
Максим Горпиніч
0cd806fb74 Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-06-29 09:02:07 +02:00
Sylvain Pichon
9f55471f0f Translated using Weblate (Catalan)
Currently translated at 97.3% (731 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-06-29 09:02:07 +02:00
HAMAD ABDULLA
4add27e83c Translated using Weblate (Arabic)
Currently translated at 98.4% (739 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-06-29 09:02:06 +02:00
Sylvain Pichon
7a3ab14fca Translated using Weblate (Turkish)
Currently translated at 66.1% (497 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-06-29 09:02:04 +02:00
Sylvain Pichon
589af685ac Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 81.7% (614 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-06-29 09:02:03 +02:00
Sylvain Pichon
8cb861df6c Translated using Weblate (Polish)
Currently translated at 81.3% (611 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-06-29 09:02:01 +02:00
Sylvain Pichon
5ebda7eb1a Translated using Weblate (Portuguese (Brazil))
Currently translated at 57.5% (432 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-06-29 09:01:59 +02:00
Massimo Pissarello
e3bbd509c3 Translated using Weblate (Italian)
Currently translated at 98.4% (739 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-06-29 09:01:57 +02:00
Sylvain Pichon
65acca5380 Translated using Weblate (Norwegian Bokmål)
Currently translated at 80.6% (606 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-06-29 09:01:54 +02:00
Sylvain Pichon
e1d4a80e57 Translated using Weblate (French)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-06-29 09:01:52 +02:00
Sylvain Pichon
08f1db2641 Translated using Weblate (Spanish)
Currently translated at 97.3% (731 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-06-29 09:01:50 +02:00
Sylvain Pichon
d78b0b3929 Translated using Weblate (German)
Currently translated at 88.5% (665 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-06-29 09:01:48 +02:00
jokob-sk
14f376cacb Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-28 16:58:50 +10:00
jokob-sk
8ccbc12024 docs + hiding archived devices in Network view 2025-06-28 16:58:37 +10:00
jokob-sk
c646c36f4f docs + hiding archived devices in Network view 2025-06-28 16:46:05 +10:00
Safeguard
d5a5e7bcf9 Translated using Weblate (Russian)
Some checks failed
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Code checks / check-url-paths (push) Has been cancelled
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-06-27 11:01:49 +02:00
jokob-sk
73f6e6d785 docs #1095
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-27 07:24:40 +10:00
Hosted Weblate
87b36562cc Merge branch 'origin/main' into Weblate.
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-26 04:25:52 +00:00
Максим Горпиніч
7406b6688d Translated using Weblate (Ukrainian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-06-26 04:25:50 +00:00
Sylvain Pichon
f58dd121d5 Translated using Weblate (French)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-06-26 04:25:49 +00:00
jokob-sk
443b10a990 docs 2025-06-26 14:25:20 +10:00
jokob-sk
e8e48a2cc4 integer causing normalization issue in MQTT #1102
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-26 07:25:10 +10:00
Ashtin
94edcee382 Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 98.5% (740 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-06-25 21:46:40 +02:00
Ashtin
737a53a589 Translated using Weblate (Catalan)
Currently translated at 97.3% (731 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-06-25 21:46:39 +02:00
Ashtin
85bff56bd5 Translated using Weblate (Arabic)
Currently translated at 98.5% (740 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-06-25 21:46:39 +02:00
Ashtin
0f149098a3 Translated using Weblate (Czech)
Currently translated at 1.1% (9 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/cs/
2025-06-25 21:46:38 +02:00
Ashtin
13b5b145e4 Translated using Weblate (Turkish)
Currently translated at 66.1% (497 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-06-25 21:46:38 +02:00
Ashtin
a050beea72 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 81.7% (614 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-06-25 21:46:38 +02:00
Ashtin
3952e8dd91 Translated using Weblate (Polish)
Currently translated at 81.3% (611 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-06-25 21:46:37 +02:00
Ashtin
68f3c02eb9 Translated using Weblate (Portuguese (Brazil))
Currently translated at 57.5% (432 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-06-25 21:46:37 +02:00
Ashtin
b4c2703cbb Translated using Weblate (Italian)
Currently translated at 98.5% (740 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-06-25 21:46:37 +02:00
Ashtin
cb4fda1786 Translated using Weblate (Russian)
Currently translated at 98.4% (739 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-06-25 21:46:37 +02:00
Ashtin
058b17fcbc Translated using Weblate (Norwegian Bokmål)
Currently translated at 80.6% (606 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-06-25 21:46:37 +02:00
Ashtin
9bfdc7209b Translated using Weblate (French)
Currently translated at 98.5% (740 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-06-25 21:46:37 +02:00
Ashtin
1a44e84112 Translated using Weblate (Spanish)
Currently translated at 97.3% (731 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-06-25 21:46:36 +02:00
Ashtin
b722fcbe6e Translated using Weblate (German)
Currently translated at 88.5% (665 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-06-25 21:46:36 +02:00
Ashtin
d1d26409fc Translated using Weblate (English (United States))
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/en_US/
2025-06-25 21:46:36 +02:00
Jokob @NetAlertX
fef1e17935 Merge pull request #1101 from slammingprogramming/docs-overhaul
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Improvements
2025-06-25 20:43:22 +10:00
Ashtin
5a3782c9f1 Improvements
Fixes a few things here and there
2025-06-25 06:40:10 -04:00
Jokob @NetAlertX
27e9472ce1 Merge pull request #1099 from slammingprogramming/docs-overhaul
Docs overhaul
2025-06-25 20:11:32 +10:00
Ashtin
23a0a98b4f Remove screenshots link from table of contents
They'll find it if they want to see them.
2025-06-25 05:26:29 -04:00
Ashtin
e724c22941 REALLY fix screenshots this time 2025-06-25 05:25:28 -04:00
Ashtin
27d69ff5ed Fix screenshots link 2025-06-25 05:24:41 -04:00
Ashtin
cb2cce5326 Add more issue templates
Adds templates for enhancements to differentiate enhancing existing features and adding whole new ones.

Refactor/Code quality is mostly for dev/contributor use for doc purposes.

Security report is essential and also directs them to reach out with sensitive details directly

Translation requests added to allow additional accessibility to be requested as-needed and to allow prioritization based on need.
2025-06-25 05:17:34 -04:00
Ashtin
e790ca2257 Add Pull Request templates
Add code pr template and docs pr template for conformity.
2025-06-25 05:05:09 -04:00
Ashtin
70a0f9260a Reword and update Security docs
Add Responsibility disclaimer

Add TLDR

Add more formatting

Deep dives into configurations more specifically

Adds responsible disclosure section
2025-06-25 05:00:51 -04:00
Ashtin
23003aa82f Update contributing page
Updated the page for better readability, additional information, and to add recent additions in this branch to it
2025-06-25 04:51:27 -04:00
Jokob @NetAlertX
cc51391d14 Merge pull request #1098 from slammingprogramming/fix-numeric-hostnames
Sanitize hostnames, macs, and vendor names before running .lower/.upper on them to prevent AttributeError
2025-06-25 18:49:48 +10:00
Ashtin
9242a8f55d Add Code of Conduct
Adding Contributor Covenant v2.1 with a special ethical clause specific to NetAlertX
2025-06-25 04:48:46 -04:00
Jokob @NetAlertX
6b32190acd Merge pull request #1097 from slammingprogramming/docs-update
add documentation feedback issue template
2025-06-25 18:48:28 +10:00
Ashtin
69834c7771 Freshen up the README
Add Table of Contents

Add Quick Start guide for Docker and Home Assistant

Fix typo in line 67 (was 33) lits -> list

Add Security & Privacy section

Add FAQ

Add Known Issues
2025-06-25 04:41:08 -04:00
Ashtin
3513fc9617 Update device_handling.py
Fixes #1088 by sanitizing the inputs to mac, vendor, and name before running .upper/.lower to ensure they are type STR to avoid AttributeError
2025-06-25 03:59:29 -04:00
Ashtin
1348987f08 add documentation feedback issue template
Adds a new GitHub issue template for reporting documentation-related suggestions, inconsistencies, or improvements.

This template helps contributors provide clear, categorized feedback on docs, making it easier to track and prioritize structural or content-related issues separately from codebase bugs or feature requests.

Includes fields for:
- Affected document/section
- Description of the issue
- Proposed solution
- Type of documentation issue
- Optional implementation offer

Helps improve overall clarity, uniformity, and contributor experience with documentation.
2025-06-25 03:20:54 -04:00
jokob-sk
b31dff2815 docs
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-24 19:57:24 +10:00
jokob-sk
3483d833a0 docs
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-06-23 08:38:27 +10:00
jokob-sk
ddad1468d9 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-06-23 08:12:17 +10:00
jokob-sk
f20fc8e123 docs 2025-06-23 08:12:06 +10:00
Jokob @NetAlertX
3bffb2d8f5 Merge pull request #1091 from slammingprogramming/revert-1089-main
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Revert "Sanitize device fields and prevent crash with numeric hostnames"
2025-06-21 11:32:20 +10:00
Ashtin
0bd4a7b8dd Revert "Sanitize device fields and prevent crash with numeric hostnames" 2025-06-20 21:22:35 -04:00
Jokob @NetAlertX
69d79dbd7c Merge pull request #1089 from slammingprogramming/main
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Sanitize device fields and prevent crash with numeric hostnames
2025-06-20 15:52:45 +10:00
Ashtin
31806c707f Fixed, Again
Fixes #1088 again. turns out that same thing is used twice. same fix applied
2025-06-20 01:25:04 -04:00
Ashtin
2a4198c2c8 Sanitize device fields and prevent crash with numeric hostnames
This patch improves the resilience of the guess_icon function by sanitizing mac, vendor, and name fields to avoid crashes caused by unexpected data types (e.g., numeric hostnames).

Specifically:

mac is now cast to a string before being uppercased, with a newly added fallback to "00:00:00:00:00:00" if empty or invalid.

vendor is sanitized to a string before lowercasing, still defaulting to "unknown".

name is cast to a string before lowercasing, still falling back to "(unknown)" when empty.

This change not only resolves the error caused by numeric-only hostnames (which triggered an AttributeError due to calling .lower() on an int), but also proactively prevents similar crashes from malformed or unexpected input in the future.

References: Fixes issue #1088 and also let's me sleep a little easier tonight.
2025-06-20 00:46:24 -04:00
Hosted Weblate
cecfe60bac Merge branch 'origin/main' into Weblate.
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-20 01:33:42 +02:00
HAMAD ABDULLA
ef42eb1fef Translated using Weblate (Arabic)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-06-20 01:33:38 +02:00
jokob-sk
1e2be52371 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX 2025-06-20 09:32:25 +10:00
jokob-sk
0034e49c1a case insentive sorting #1087 2025-06-20 09:32:06 +10:00
Максим Горпиніч
350412be33 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-06-19 23:24:20 +02:00
HAMAD ABDULLA
c9312719ea Translated using Weblate (Arabic)
Currently translated at 3.0% (23 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ar/
2025-06-19 23:24:20 +02:00
Massimo Pissarello
3010bbf1df Translated using Weblate (Italian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-06-19 16:43:17 +02:00
Максим Горпиніч
59d5f1053f Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-06-18 17:31:31 +02:00
Sylvain Pichon
ae81b86e78 Translated using Weblate (French)
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-06-18 17:31:31 +02:00
Sylvain Pichon
1f80a7d8ca Translated using Weblate (English (United States))
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/en_US/
2025-06-18 17:31:30 +02:00
Anonymous
047797daf2 Translated using Weblate (Ukrainian)
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Currently translated at 99.8% (750 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/uk/
2025-06-17 22:41:36 +02:00
Anonymous
f62e0513f9 Translated using Weblate (Catalan)
Currently translated at 98.6% (741 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ca/
2025-06-17 22:41:35 +02:00
Anonymous
b7471fd91c Translated using Weblate (Turkish)
Currently translated at 67.1% (504 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/tr/
2025-06-17 22:41:35 +02:00
Anonymous
0e8f8a09cb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 83.0% (624 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/zh_Hans/
2025-06-17 22:41:35 +02:00
Anonymous
8cc85a3203 Translated using Weblate (Polish)
Currently translated at 82.6% (621 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pl/
2025-06-17 22:41:35 +02:00
Anonymous
8f41d71ac4 Translated using Weblate (Portuguese (Brazil))
Currently translated at 58.1% (437 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/pt_BR/
2025-06-17 22:41:35 +02:00
Anonymous
470d362ab4 Translated using Weblate (Italian)
Currently translated at 99.8% (750 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/it/
2025-06-17 22:41:35 +02:00
Anonymous
a342f73f68 Translated using Weblate (Norwegian Bokmål)
Currently translated at 82.0% (616 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/nb_NO/
2025-06-17 22:41:34 +02:00
Anonymous
05842ab4a0 Translated using Weblate (French)
Currently translated at 99.8% (750 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/fr/
2025-06-17 22:41:34 +02:00
Anonymous
b54d95e5af Translated using Weblate (Spanish)
Currently translated at 98.6% (741 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/es/
2025-06-17 22:41:33 +02:00
Anonymous
202dcf16b9 Translated using Weblate (German)
Currently translated at 89.7% (674 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-06-17 22:41:33 +02:00
jokob-sk
153383343b Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-17 20:18:23 +10:00
jokob-sk
6f138d95ca docs 2025-06-17 20:18:18 +10:00
Safeguard
e3bbb0afff Translated using Weblate (Russian)
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Currently translated at 100.0% (751 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/ru/
2025-06-15 00:01:49 +02:00
jokob-sk
8e05e5739b Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-14 11:57:42 +10:00
jokob-sk
7a2c4942bf achnged AVAHISCAN defaults #847 2025-06-14 11:57:37 +10:00
Jokob @NetAlertX
95189a9d4b Merge pull request #1085 from mathoudebine/patch-1
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
Update freebox.py: add missing entries in device_type_map
2025-06-12 06:59:50 +10:00
Matthieu Houdebine
ded15aa628 Update freebox.py: do not fail if unknown device type
If a new device type has not been mapped yet, do not fail the scan but return "Unknown" instead
2025-06-11 22:56:04 +02:00
Patrick Seidel
b1d74dcfea Translated using Weblate (German)
Currently translated at 89.8% (675 of 751 strings)

Translation: NetAlertX/core
Translate-URL: https://hosted.weblate.org/projects/pialert/core/de/
2025-06-11 20:26:57 +02:00
Matthieu Houdebine
f4db748eae Update freebox.py: add missing entries in device_type_map
New entries extracted from latest Freebox Server web interface
2025-06-11 19:01:18 +02:00
jokob-sk
b797713b2d Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-11 07:26:58 +10:00
jokob-sk
69cf4057ac FQDN incorrect check #1081, vendor work #1080 2025-06-11 07:26:52 +10:00
Jokob @NetAlertX
a1d5341840 Merge pull request #1076 from vladaurosh/main
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
Updating base image to Alpine 3.22
2025-06-10 12:52:41 +10:00
vladaurosh
8b1e705a96 Updating base image to Alpine 3.22 2025-06-08 21:38:43 +01:00
jokob-sk
dff63b74f5 Merge branch 'main' of https://github.com/jokob-sk/NetAlertX
Some checks failed
Code checks / check-url-paths (push) Has been cancelled
docker / docker_dev (push) Has been cancelled
Deploy MkDocs / deploy (push) Has been cancelled
2025-06-08 08:55:13 +10:00
jokob-sk
f709c97602 GraphQL docs #1074 2025-06-08 08:55:06 +10:00
Jokob @NetAlertX
0b2a722218 Merge pull request #1075 from YouFoundAlpha/main
Added buymeacoffee to FUNDING.yml and move it to the correct directory
2025-06-08 07:53:10 +10:00
YouFoundAlpha
168275343c Move the FUNDING.yml to the .github directory 2025-06-07 22:10:52 +03:00
YouFoundAlpha
05335df9bf Add buymeacoffee to FUNDING.yml 2025-06-07 21:53:25 +03:00
GitHub Actions
de2e924aa2 Add release tweet for v25.6.7 - Legacy upgrade removal and Fully Qualified Domain Names 🆎
Some checks are pending
Code checks / check-url-paths (push) Waiting to run
docker / docker_dev (push) Waiting to run
Deploy MkDocs / deploy (push) Waiting to run
2025-06-07 00:00:05 +00:00
175 changed files with 9242 additions and 6588 deletions

View File

@@ -1,2 +1,3 @@
github: jokob-sk
patreon: 84385063
buy_me_a_coffee: jokobsk

View File

@@ -0,0 +1,56 @@
name: Documentation Feedback 📝
description: Suggest improvements, clarify inconsistencies, or report issues related to the documentation.
labels: ['documentation 📚']
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an open or closed issue already exists for the documentation change you're suggesting.
options:
- label: I have searched the existing open and closed issues
required: true
- type: textarea
attributes:
label: What document or section does this relate to?
description: |
Please include a link to the file and section, if applicable. Be specific about what part of the documentation you are referencing.
placeholder: e.g. https://github.com/jokob-sk/NetAlertX/blob/main/docs/FRONTEND_DEVELOPMENT.md
validations:
required: true
- type: textarea
attributes:
label: Describe the issue
description: A clear and concise explanation of the issue or inconsistency you found in the documentation.
placeholder: e.g. The linked file is referred to as "Contributor Guidelines" but only covers frontend topics.
validations:
required: true
- type: textarea
attributes:
label: Your suggestion or proposed solution
description: Suggest how the documentation could be improved, clarified, or reorganized.
placeholder: e.g. Combine frontend and backend development into a single CONTRIBUTING.md file with common sections to reduce fragmentation.
validations:
required: true
- type: checkboxes
attributes:
label: What type of issue is this?
options:
- label: Missing information
- label: Inaccurate or outdated information
- label: Unclear or confusing content
- label: Structure or organization improvements
- label: Other (explain in issue)
- type: textarea
attributes:
label: Anything else?
description: |
Additional context, references, screenshots, or related issues. You can also mention if youre willing to help implement the suggestion.
validations:
required: false
- type: checkboxes
attributes:
label: Can I help implement this? 👩‍💻👨‍💻
description: The maintainer can provide guidance and review your changes.
options:
- label: "Yes, Id like to help implement the improvement"
- label: "No, Im just suggesting the idea"

View File

@@ -0,0 +1,33 @@
name: Enhancement Request
description: Propose an improvement to an existing feature or UX behavior.
labels: ['enhancement ♻️']
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
options:
- label: I have searched existing open and closed issues
required: true
- type: textarea
attributes:
label: What is the enhancement?
description: Describe the change or optimization youd like to see to an existing feature.
placeholder: e.g. Make scan intervals configurable from UI instead of just `app.conf`
required: true
- type: textarea
attributes:
label: What problem does this solve or improve?
description: Describe why this change would improve user experience or project maintainability.
required: true
- type: textarea
attributes:
label: Additional context or examples
description: |
Screenshots? Comparisons? Reference repos?
required: false
- type: checkboxes
attributes:
label: Are you willing to help implement this?
options:
- label: "Yes"
- label: "No"

View File

@@ -0,0 +1,37 @@
name: Refactor / Code Quality Request ♻️
description: Suggest improvements to code structure, style, or maintainability.
labels: ['enhancement ♻️']
body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please check if a similar request already exists.
options:
- label: I have searched the existing open and closed issues
required: true
- type: textarea
attributes:
label: What part of the code needs refactoring or improvement?
description: Specify files, modules, or components.
required: true
- type: textarea
attributes:
label: Describe the proposed changes
description: Explain the refactoring or quality improvements you suggest.
required: true
- type: textarea
attributes:
label: Why is this improvement needed?
description: Benefits such as maintainability, readability, performance, or scalability.
required: true
- type: textarea
attributes:
label: Additional context or examples
description: Any relevant links, references, or related issues.
required: false
- type: checkboxes
attributes:
label: Can you help implement this change?
options:
- label: Yes
- label: No

28
.github/ISSUE_TEMPLATE/security-report.yml vendored Executable file
View File

@@ -0,0 +1,28 @@
name: Security Report 🔐
description: Report a security vulnerability or concern privately.
labels: ['security 🔐']
body:
- type: markdown
attributes:
value: |
**Important:** For security reasons, please do **not** post sensitive security issues publicly in the issue tracker.
Instead, send details to our security contact email: [jokob@duck.com](mailto:jokob@duck.com).
We appreciate your responsible disclosure.
- type: textarea
attributes:
label: Brief summary (non-sensitive)
description: Provide a non-sensitive overview of the security issue.
required: true
- type: textarea
attributes:
label: Additional context or references
description: Any other information or related reports.
required: false
- type: checkboxes
attributes:
label: Have you sent this report via email to the security contact?
options:
- label: Yes, I have sent the details to jokob@duck.com
required: true
- label: Not yet, I will send it after opening this issue

View File

@@ -0,0 +1,36 @@
name: Translation / Localization Request 🌐
description: Suggest adding or improving translations or localization support.
labels: ['enhancement 🌐']
body:
- type: checkboxes
attributes:
label: Have you checked for existing translation efforts or related issues?
options:
- label: I have searched existing open and closed issues
required: true
- type: textarea
attributes:
label: Language(s) involved
description: Specify the language(s) this request pertains to.
required: true
- type: textarea
attributes:
label: Describe the translation or localization improvement
description: Examples include adding new language support, fixing translation errors, or improving formatting.
required: true
- type: textarea
attributes:
label: Why is this important for the project or users?
description: Describe the benefits or target audience.
required: false
- type: textarea
attributes:
label: Additional context or references
description: Link to files, previous translation PRs, or external resources.
required: false
- type: checkboxes
attributes:
label: Can you help with translation or review?
options:
- label: Yes
- label: No

View File

@@ -0,0 +1,53 @@
## 📌 Description
<!-- Provide a brief description of the changes you're introducing. Be clear and concise. -->
---
## 🔍 Related Issues
<!-- Reference any related issues (e.g., closes #123, fixes #456) -->
---
## 📋 Type of Change
Please check the relevant option(s):
- [ ] 🐛 Bug fix
- [ ] ✨ New feature
- [ ] ♻️ Code refactor
- [ ] 📚 Documentation update
- [ ] 🧪 Test addition or change
- [ ] 🔧 Build/config update
- [ ] 🚀 Performance improvement
- [ ] 🔨 CI/CD or automation
- [ ] 🧹 Cleanup / chore
---
## 📷 Screenshots or Logs (if applicable)
<!-- Add screenshots, terminal output, logs, or anything that helps understand your change -->
---
## 🧪 Testing Steps
<!-- Describe how the change was tested. Manual steps, test cases, or automated test runs -->
---
## ✅ Checklist
- [ ] I have read the [Contribution Guidelines](../../CONTRIBUTING)
- [ ] I have tested my changes locally
- [ ] I have updated relevant documentation (if applicable)
- [ ] I have verified my changes do not break existing behavior
- [ ] I am willing to respond to requested changes and feedback
---
## 🙋 Additional Notes
<!-- Anything else you want reviewers to know? Future follow-ups? Questions? -->

View File

@@ -0,0 +1,37 @@
## 📚 Documentation Update
<!-- Describe the purpose of this PR in one or two sentences. Example: "This PR updates the contributor guidelines by merging frontend and backend sections." -->
---
## 📝 Whats Changed?
<!-- Briefly outline what parts of the documentation were added, changed, removed, or reorganized -->
- Combined frontend and backend development guidelines into a single file
- Updated `mkdocs.yml` to reflect new structure
- Added clarification on contribution process
- Fixed outdated links in sidebar
---
## 🔍 Related Issue(s)
<!-- Link to related issues, discussions, or context (e.g., closes #123) -->
---
## ✅ Checklist
- [ ] I followed the formatting/style of existing documentation
- [ ] I have read the [Contribution Guidelines](../../CONTRIBUTING)
- [ ] I updated `mkdocs.yml` if necessary
- [ ] I verified links and references still work
- [ ] I checked that my changes improve clarity, structure, or accuracy
- [ ] I'm open to feedback and suggestions
---
## 🙋 Additional Notes
<!-- Optional: Include anything you want reviewers to be aware of -->

2
.github/tweet.md vendored
View File

@@ -1,2 +0,0 @@
🎉 New release: **v25.5.24 - MQTT, UI improvements, multiple notification emails** is live! 🚀
Check it out here: https://github.com/jokob-sk/NetAlertX/releases/tag/v25.5.24

View File

@@ -1,4 +1,4 @@
name: 📧 Twitter and Discord Posts
name: 📧 Social Posts
on:
release:
types: [published]
@@ -16,38 +16,3 @@ jobs:
-d '{"content": "🎉 New release: **${{ github.event.release.name }}** is live! 🚀\nCheck it out here: ${{ github.event.release.html_url }}"}' \
${{ secrets.DISCORD_WEBHOOK_URL }}
post-twitter:
runs-on: ubuntu-latest
steps:
- name: Wait for 15 minutes
run: sleep 900 # 15 minutes delay
- name: Checkout repository
uses: actions/checkout@v3
- name: Set Git config
run: |
git config --global user.email "github-actions@github.com"
git config --global user.name "GitHub Actions"
- name: Create tweet file
run: |
echo "🎉 New release: **${{ github.event.release.name }}** is live! 🚀" > .github/tweet.md
echo "Check it out here: ${{ github.event.release.html_url }}" >> .github/tweet.md
git add .github/tweet.md
git commit -m "Add release tweet for ${{ github.event.release.name }}"
- name: Push changes
run: |
git push https://github.com/${{ github.repository }}.git HEAD:main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Tweet
uses: twitter-together/action@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TWITTER_ACCESS_TOKEN: ${{ secrets.TWITTER_ACCESS_TOKEN }}
TWITTER_ACCESS_TOKEN_SECRET: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }}
TWITTER_API_KEY: ${{ secrets.TWITTER_API_KEY }}
TWITTER_API_SECRET_KEY: ${{ secrets.TWITTER_API_SECRET_KEY }}

137
CODE_OF_CONDUCT.md Executable file
View File

@@ -0,0 +1,137 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of
any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address,
without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official email address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at <jokob@duck.com>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Ethical Use Clause (Project-Specific)
While NetAlertX is a tool designed to empower users with greater insight into their own networks, we expect and encourage all users to use this software **ethically and legally**.
- Do not use this software to scan or monitor networks without **explicit authorization**.
- Respect privacy, consent, and data protection laws applicable in your jurisdiction.
- Any use of NetAlertX for malicious surveillance, stalking, or unauthorized access is explicitly discouraged and may be grounds for removal from the community and revocation of support.
We reserve the right to take appropriate action to uphold the ethical integrity of this project.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the
[Contributor Covenant](https://www.contributor-covenant.org/), version 2.1,
available at
<https://www.contributor-covenant.org/version/2/1/code_of_conduct/>.
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/inclusion).
For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq/>. Translations are available at
<https://www.contributor-covenant.org/translations/>.

View File

@@ -1,14 +1,53 @@
# Contributing to this project
# 🤝 Contributing to NetAlertX
## Issues, bugs, feature requests
First off, **thank you** for taking the time to contribute! NetAlertX is built and improved with the help of passionate people like you.
The issue tracker is the preferred channel for bug reports, features requests and submitting pull requests.
---
Before submitting a new issue please spend a couple of minutes on research:
## 📂 Issues, Bugs, and Feature Requests
* Check [🛑 Common issues](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md#common-issues)
* Check [💡 Closed issues](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue+is%3Aclosed) if a similar issue was solved in the past.
Please use the [GitHub Issue Tracker](https://github.com/jokob-sk/NetAlertX/issues) for:
- Bug reports 🐞
- Feature requests 💡
- Documentation feedback 📖
## Pull-requests (PRs)
Before opening a new issue:
- 🛑 [Check Common Issues & Debug Tips](https://github.com/jokob-sk/NetAlertX/blob/main/docs/DEBUG_TIPS.md#common-issues)
- 🔍 [Search Closed Issues](https://github.com/jokob-sk/NetAlertX/issues?q=is%3Aissue+is%3Aclosed)
If you submit a PR please do check that your changes are backward compatible with existing installations. Existing features should be always preserved.
---
## 🚀 Submitting Pull Requests (PRs)
We welcome PRs to improve the code, docs, or UI!
Please:
- Ensure **backward compatibility** with existing installations
- Preserve existing features unless a breaking change is intentional and discussed
- Follow existing **code style and structure**
- Provide a clear title and description for your PR
- If relevant, add or update tests and documentation
- For plugins, refer to the [Plugin Dev Guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS_DEV.md)
---
## 🌟 First-Time Contributors
New to open source? Check out these resources:
- [How to Fork and Submit a PR](https://opensource.guide/how-to-contribute/)
- Ask questions or get support in our [Discord](https://discord.gg/NczTUTWyRr)
---
## 🔐 Code of Conduct
By participating, you agree to follow our [Code of Conduct](./CODE_OF_CONDUCT.md), which ensures a respectful and welcoming community.
---
## 📬 Contact
If you have more in-depth questions or want to discuss contributing in other ways, feel free to reach out at:
📧 [jokob@duck.com](mailto:jokob@duck.com?subject=NetAlertX%20Contribution)
We appreciate every contribution, big or small! 💙

View File

@@ -1,4 +1,4 @@
FROM alpine:3.21 AS builder
FROM alpine:3.22 AS builder
ARG INSTALL_DIR=/app
@@ -22,7 +22,7 @@ RUN pip install openwrt-luci-rpc asusrouter asyncio aiohttp graphene flask tplin
RUN cat ${INSTALL_DIR}/install/freebox_certificate.pem >> /opt/venv/lib/python3.12/site-packages/aiofreepybox/freebox_certificates.pem
# second stage
FROM alpine:3.21 AS runner
FROM alpine:3.22 AS runner
ARG INSTALL_DIR=/app

View File

@@ -8,6 +8,42 @@
Get visibility of what's going on on your WIFI/LAN network and enable presence detection of important devices. Schedule scans for devices, port changes and get alerts if unknown devices or changes are found. Write your own [Plugin](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) with auto-generated UI and in-build notification system. Build out and easily maintain your network source of truth (NSoT).
## 📋 Table of Contents
- [Features](#-features)
- [Documentation](#-documentation)
- [Quick Start](#-quick-start)
- [Alternative Apps](#-other-alternative-apps)
- [Security & Privacy](#-security--privacy)
- [FAQ](#-faq)
- [Known Issues](#-known-issues)
- [Donations](#-donations)
- [Contributors](#-contributors)
- [Translations](#-translations)
- [License](#license)
## 🚀 Quick Start
Start NetAlertX in seconds with Docker:
```bash
docker run -d --rm --network=host \
-v local_path/config:/app/config \
-v local_path/db:/app/db \
--mount type=tmpfs,target=/app/api \
-e PUID=200 -e PGID=300 \
-e TZ=Europe/Berlin \
-e PORT=20211 \
ghcr.io/jokob-sk/netalertx:latest
```
Need help configuring it? Check the [usage guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/README.md) or [full documentation](https://jokob-sk.github.io/NetAlertX/).
For Home Assistant users: [Click here to add NetAlertX](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Falexbelgium%2Fhassio-addons)
For other install methods, check the [installation docs](#-documentation)
| [📑 Docker guide](https://github.com/jokob-sk/NetAlertX/blob/main/dockerfiles/README.md) | [🚀 Releases](https://github.com/jokob-sk/NetAlertX/releases) | [📚 Docs](https://jokob-sk.github.io/NetAlertX/) | [🔌 Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS.md) | [🤖 Ask AI](https://gurubase.io/g/netalertx)
|----------------------| ----------------------| ----------------------| ----------------------| ----------------------|
@@ -30,7 +66,7 @@ Get visibility of what's going on on your WIFI/LAN network and enable presence d
### Scanners
The app scans your network for **New devices**, **New connections** (re-connections), **Disconnections**, **"Always Connected" devices down**, Devices **IP changes** and **Internet IP address changes**. Discovery & scan methods include: **arp-scan**, **Pi-hole - DB import**, **Pi-hole - DHCP leases import**, **Generic DHCP leases import**, **UNIFI controller import**, **SNMP-enabled router import**. Check the [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) docs for a full lits of avaliable plugins.
The app scans your network for **New devices**, **New connections** (re-connections), **Disconnections**, **"Always Connected" devices down**, Devices **IP changes** and **Internet IP address changes**. Discovery & scan methods include: **arp-scan**, **Pi-hole - DB import**, **Pi-hole - DHCP leases import**, **Generic DHCP leases import**, **UNIFI controller import**, **SNMP-enabled router import**. Check the [Plugins](https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md#readme) docs for a full list of avaliable plugins.
### Notification gateways
@@ -59,6 +95,46 @@ Supported browsers: Chrome, Firefox
- [[Development] API docs](https://github.com/jokob-sk/NetAlertX/blob/main/docs/API.md)
- [[Development] Custom Plugins](https://github.com/jokob-sk/NetAlertX/blob/main/docs/PLUGINS_DEV.md)
...or explore all the [documentation here](https://jokob-sk.github.io/NetAlertX/).
## 🔐 Security & Privacy
NetAlertX scans your local network and can store metadata about connected devices. By default, all data is stored **locally**. No information is sent to external services unless you explicitly configure notifications or integrations.
To further secure your installation:
- Run it behind a reverse proxy with authentication
- Use firewalls to restrict access to the web UI
- Regularly update to the latest version for security patches
See [Security Best Practices](https://github.com/jokob-sk/NetAlertX/security) for more details.
## ❓ FAQ
**Q: Why dont I see any devices?**
A: Ensure the container has proper network access (e.g., use `--network host` on Linux). Also check that your scan method is properly configured in the UI.
**Q: Does this work on Wi-Fi-only devices like Raspberry Pi?**
A: Yes, but some scanners (e.g. ARP) work best on Ethernet. For Wi-Fi, try SNMP, DHCP, or Pi-hole import.
**Q: Will this send any data to the internet?**
A: No. All scans and data remain local, unless you set up cloud-based notifications.
**Q: Can I use this without Docker?**
A: Yes! You can install it bare-metal. See the [bare metal installation guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/HW_INSTALL.md).
**Q: Where is the data stored?**
A: In the `/config` and `/db` folders, mapped in Docker. Back up these folders regularly.
## 🐞 Known Issues
- Some scanners (e.g. ARP) may not detect devices on different subnets. See the [Remote networks guide](https://github.com/jokob-sk/NetAlertX/blob/main/docs/REMOTE_NETWORKS.md) for workarounds.
- Wi-Fi-only networks may require alternate scanners for accurate detection.
- Notification throttling may be needed for large networks to prevent spam.
- On some systems, elevated permissions (like `CAP_NET_RAW`) may be needed for low-level scanning.
Check the [GitHub Issues](https://github.com/jokob-sk/NetAlertX/issues) for the latest bug reports and solutions and consult [the official documentation](https://jokob-sk.github.io/NetAlertX/).
## 📃 Everything else
<!--- --------------------------------------------------------------------- --->
@@ -111,7 +187,6 @@ Proudly using [Weblate](https://hosted.weblate.org/projects/pialert/). Help out
### License
> GPL 3.0 | [Read more here](LICENSE.txt) | Source of the [animated GIF (Loading Animation)](https://commons.wikimedia.org/wiki/File:Loading_Animation.gif) | Source of the [selfhosted Fonts](https://github.com/adobe-fonts/source-sans)
<!--- --------------------------------------------------------------------- --->
@@ -131,4 +206,3 @@ Proudly using [Weblate](https://hosted.weblate.org/projects/pialert/). Help out
[main_dark]: /docs/img/1_devices_dark.jpg "Main screen dark"
[maintain_dark]: /docs/img/5_maintain.jpg "Maintain screen dark"
[follow_star]: /docs/img/Follow_Releases_and_Star.gif "Follow and Star"

View File

@@ -20,7 +20,7 @@
DISCOVER_PLUGINS=True
SCAN_SUBNETS=['--localnet']
TIMEZONE='Europe/Berlin'
LOADED_PLUGINS=['ARPSCAN','CSVBCKP','DBCLNP', 'DIGSCAN', 'INTRNT','MAINT','NEWDEV', 'NBTSCAN', 'NSLOOKUP','NTFPRCS', 'AVAHISCAN', 'SETPWD','SMTP', 'SYNC', 'VNDRPDT', 'WORKFLOWS', 'UI']
LOADED_PLUGINS=['ARPSCAN', 'AVAHISCAN', 'CSVBCKP','DBCLNP', 'DIGSCAN', 'INTRNT', 'MAINT', 'NEWDEV', 'NBTSCAN', 'NSLOOKUP','NTFPRCS', 'SETPWD', 'SMTP', 'SYNC', 'VNDRPDT', 'WORKFLOWS', 'UI']
DAYS_TO_KEEP_EVENTS=90
# Used for generating links in emails. Make sure not to add a trailing slash!
@@ -30,6 +30,8 @@ REPORT_DASHBOARD_URL='http://127.0.0.1'
INTRNT_RUN='schedule'
ARPSCAN_RUN='schedule'
NSLOOKUP_RUN='before_name_updates'
AVAHISCAN_RUN='before_name_updates'
NBTSCAN_RUN='before_name_updates'
# Email
#-------------------------------------

View File

@@ -23,11 +23,11 @@ services:
# - ${DEV_LOCATION}/api:/app/api
# ---------------------------------------------------------------------------
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_full.leases:/etc/pihole/dhcp.leases
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_2.leases:/etc/pihole/dhcp2.leases
- ${APP_DATA_LOCATION}/pihole/etc-pihole/pihole-FTL.db:/etc/pihole/pihole-FTL.db
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_full.leases:/etc/pihole/dhcp.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/netalertx/dhcp_samples/pihole_dhcp_2.leases:/etc/pihole/dhcp2.leases # test data for DCPLSS plugin
- ${APP_DATA_LOCATION}/pihole/etc-pihole/pihole-FTL.db:/etc/pihole/pihole-FTL.db # test data for PIHOLE plugin
- ${DEV_LOCATION}/mkdocs.yml:/app/mkdocs.yml
- ${DEV_LOCATION}/docs:/app/docs
- ${DEV_LOCATION}/server:/app/server
@@ -66,7 +66,7 @@ services:
- ${DEV_LOCATION}/front/appEvents.php:/app/front/appEvents.php
- ${DEV_LOCATION}/front/appEventsCore.php:/app/front/appEventsCore.php
- ${DEV_LOCATION}/front/multiEditCore.php:/app/front/multiEditCore.php
- ${DEV_LOCATION}/front/plugins:/app/front/plugins
- ${DEV_LOCATION}/front/plugins:/app/front/plugins
# DELETE END anyone trying to use this file: comment out / delete ABOVE lines, they are only for development purposes
# ---------------------------------------------------------------------------
environment:

View File

@@ -49,6 +49,8 @@ query GetDevices($options: PageQueryOptionsInput) {
}
```
See also: [Debugging GraphQL issues](./DEBUG_GRAPHQL.md)
### `curl` Command
You can use the following `curl` command to execute the query.

View File

@@ -2,6 +2,7 @@
Use the official installation guides at first and use community content as supplementary material. Open an issue or PR if you'd like to add your link to the list 🙏 (Ordered by last update time)
- ▶ [Discover & Monitor Your Network with This Self-Hosted Open Source Tool - Lawrence Systems](https://www.youtube.com/watch?v=R3b5cxLZMpo) (June 2025)
- ▶ [Home Lab Network Monitoring - Scotti-BYTE Enterprise Consulting Services](https://www.youtube.com/watch?v=0DryhzrQSJA) (July 2024)
- 📄 [How to Install NetAlertX on Your Synology NAS - Marius hosting](https://mariushosting.com/how-to-install-pi-alert-on-your-synology-nas/) (Updated frequently)
- 📄 [Using the PiAlert Network Security Scanner on a Raspberry Pi - PiMyLifeUp](https://pimylifeup.com/raspberry-pi-pialert/)

View File

@@ -39,6 +39,8 @@
| `devSourcePlugin` | Source plugin that discovered the device. | `ARPSCAN` |
| `devCustomProps` | [Custom properties](./CUSTOM_PROPERTIES.md) related to the device. The value is a base64-encoded JSON object. | `PHN2ZyB...` |
| `devFQDN` | Fully qualified domain name. | `raspberrypi.local` |
| `devParentRelType` | The type of relationship between the current device and it's parent node. By default, selecting `nic` will hide it from lists. | `nic` |
| `devReqNicsOnline` | If all NICs are required to be online to mark teh current device online. | `0` |
To understand how values of these fields influuence application behavior, such as Notifications or Network topology, see also:

64
docs/DEBUG_GRAPHQL.md Executable file
View File

@@ -0,0 +1,64 @@
# Debugging GraphQL server issues
The GraphQL server is an API middle layer, running on it's own port specified by `GRAPHQL_PORT`, to retrieve and show the data in the UI. It can also be used to retrieve data for custom third party integarions. Check the [API documentation](./API.md) for details.
The most common issue is that the GraphQL server doesn't start properly, usually due to a **port conflict**. If you are running multiple NetAlertX instances, make sure to use **unique ports** by changing the `GRAPHQL_PORT` setting. The default is `20212`.
## How to update the `GRAPHQL_PORT` in case of issues
As a first troubleshooting step try changing the default `GRAPHQL_PORT` setting. Please remember NetAlertX is running on the host so any application uising the same port will cause issues.
### Updating the setting via the Settings UI
Ideally use the Settings UI to update the setting under General -> Core -> GraphQL port:
![GrapQL settings](./img/DEBUG_GRAPHQL/graphql_settings_port_token.png)
You might need to temporarily stop other applications or NetAlertX instances causing conflicts to update the setting. The `API_TOKEN` is used to authenticate any API calls, including GraphQL requests.
### Updating the `app.conf` file
If the UI is not accessible, you can directly edit the `app.conf` file in your `/config` folder:
![Editing app.conf](./img/DEBUG_GRAPHQL/app_conf_graphql_port.png)
### Using a docker variable
All application settings can also be initialized via the `APP_CONF_OVERRIDE` docker env variable.
```yaml
...
environment:
- TZ=Europe/Berlin
- PORT=20213
- APP_CONF_OVERRIDE={"GRAPHQL_PORT":"20214"}
...
```
## How to check the GraphQL server is running?
There are several ways to check if the GraphQL server is running.
### Init Check
You can navigate to Maintenance -> Init Check to see if `isGraphQLServerRunning` is ticked:
![Init Check](./img/DEBUG_GRAPHQL/Init_check.png)
### Checking the Logs
You can navigate to Maintenance -> Logs and search for `graphql` to see if it started correctly and serving requests:
![GraphQL Logs](./img/DEBUG_GRAPHQL/graphql_running_logs.png)
### Inspecting the Browser console
In your browser open the dev console (usually F12) and navigate to the Network tab where you can filter GraphQL requests (e.g., reload the Devices page).
![Browser Network Tab](./img/DEBUG_GRAPHQL/network_graphql.png)
You can then inspect any of the POST requests by opening them in a new tab.
![Browser GraphQL Json](./img/DEBUG_GRAPHQL/dev_console_graphql_json.png)

View File

@@ -10,7 +10,7 @@ Check the the HTTP response of the failing backend call by following these steps
- Copy the URL causing the error and enter it in the address bar of your browser directly and hit enter. The copied URLs could look something like this (notice the query strings at the end):
- `http://<NetAlertX URL>:20211/api/table_devices.json?nocache=1704141103121`
- `http://<NetAlertX URL>:20211/php/server/devices.php?action=getDevicesTotals`
- `http://<NetAlertX URL>:20211/php/server/devices.php?action=getDevicesList&status=all`
- Post the error response in the existing issue thread on GitHub or create a new issue and include the redacted response of the failing query.

View File

@@ -8,8 +8,13 @@ This set of settings allows you to group Devices under different views. The Arch
## Status Colors
![Sattus colors](./img/DEVICE_MANAGEMENT/device_management_display_settings.png)
![Sattus colors](./img/DEVICE_MANAGEMENT/device_management_status_colors.png)
1. Online (Green) = A device that is no longer marked as a "New Device"
2. New (Green) = A newly discovered device that is online and is still "ticked" as a "New Device"
3. New (Grey) = Same as No.2 but device is now offline.
1. 🔌 Online (Green) = A device that is no longer marked as a "New Device".
2. 🔌 New (Green) = A newly discovered device that is online and is still marked as a "New Device".
3. New (Grey) = Same as No.2 but device is now offline.
4. ✖ Offline (Grey) = A device that was not detected online in the last scan.
5. ⚠ Down (Red) = A device that has "Alert Down" marked and has been offline for the time set in the Setting `NTFPRCS_alert_down_time`.
See also [Notification guide](./NOTIFICATIONS.md).

View File

@@ -69,7 +69,7 @@ services:
network_mode: "host"
restart: unless-stopped
volumes:
- ${APP_DATA_LOCATION}/netalertx/config:/app/config
- ${APP_CONFIG_LOCATION}/netalertx/config:/app/config
- ${APP_DATA_LOCATION}/netalertx/db/:/app/db/
# (optional) useful for debugging if you have issues setting up the container
- ${LOGS_LOCATION}:/app/log

78
docs/FIX_OFFLINE_DETECTION.md Executable file
View File

@@ -0,0 +1,78 @@
# Troubleshooting: Devices Show Offline When They Are Online
In some network setups, certain devices may intermittently appear as **offline** in NetAlertX, even though they are connected and responsive. This issue is often more noticeable with devices that have **higher IP addresses** within the subnet.
> [!NOTE]
>
> Network presence graph showing increased drop outs before enabling additional `ICMP` scans and continuous online presence after following this guide. This graph shows a sudden spike in drop outs probably caused by a device software update.
> ![before after presence](./img/FIX_OFFLINE_DETECTION/presence_graph_before_after.png)
## Symptoms
* Devices sporadically show as offline in the presence timeline.
* This behavior often affects devices with higher IPs (e.g., `192.168.1.240+`).
* Presence data appears inconsistent or unreliable despite the device being online.
## Cause
This issue is typically related to scanning limitations:
* **ARP scan timeouts** may prevent full subnet coverage.
* **Sole reliance on ARP** can result in missed detections:
* Some devices (like iPhones) suppress or reject frequent ARP requests.
* ARP responses may be blocked or delayed due to power-saving features or OS behavior.
* **Scanning frequency conflicts**, where devices ignore repeated scans within a short period.
## Recommended Fixes
To improve presence accuracy and reduce false offline states:
### ✅ Increase ARP Scan Timeout
Extend the ARP scanner timeout to ensure full subnet coverage:
```env
ARPSCAN_RUN_TIMEOUT=360
```
> Adjust based on your network size and device count.
### ✅ Add ICMP (Ping) Scanning
Enable the `ICMP` scan plugin to complement ARP detection. ICMP is often more reliable for detecting active hosts, especially when ARP fails.
### ✅ Use Multiple Detection Methods
A combined approach greatly improves detection robustness:
* `ARPSCAN` (default)
* `ICMP` (ping)
* `NMAPDEV` (nmap)
This hybrid strategy increases reliability, especially for down detection and alerting. See [other plugins](./PLUGINS.md) that might be compatible with your setup. See benefits and drawbacks of individual scan methods in their respective docs.
## Results
After increasing the ARP timeout and adding ICMP scanning (on select IP ranges), users typically report:
* More consistent presence graphs
* Fewer false offline events
* Better coverage across all IP ranges
## Summary
| Setting | Recommendation |
| --------------------- | --------------------------------------------- |
| `ARPSCAN_RUN_TIMEOUT` | Increase to ensure scans reach all IPs |
| `ICMP` Scan | Enable to detect devices ARP might miss |
| Multi-method Scanning | Use a mix of ARP, ICMP, and NMAP-based methods |
---
**Tip:** Each environment is unique. Consider fine-tuning scan settings based on your network size, device behavior, and desired detection accuracy.
Let us know in the [NetAlertX Discussions](https://github.com/jokob-sk/NetAlertX/discussions) if you have further feedback or edge cases.
See also [Remote Networks](./REMOTE_NETWORKS.md) for more advanced setups.

View File

@@ -5,7 +5,8 @@ To download and install NetAlertX on the hardware/server directly use the `curl`
> [!NOTE]
> This is an Experimental feature 🧪 and it relies on community support.
>
> 🙏 Looking for maintainers for this installation method 🙂
> 🙏 Looking for maintainers for this installation method 🙂 Current community volunteers:
> - [slammingprogramming](https://github.com/slammingprogramming)
>
> There is no guarantee that the install script or any other script will gracefully handle other installed software.
> Data loss is a possibility, **it is recommended to install NetAlertX using the supplied Docker image**.

View File

@@ -9,7 +9,7 @@ Get **NetAlertX** up and running in a few simple steps.
> [!TIP]
> Enable additional plugins under **Settings → `LOADED_PLUGINS`**.
> Make sure to **save** your changes and **reload the page** to activate them.
> ![Loaded plugins settings](./img/PLUGINS/loaded_plugins_setting.png)
> ![Loaded plugins settings](./img/PLUGINS/enable_plugin.gif)
**Initial configuration**: `ARPSCAN`, `INTRNT`

View File

@@ -1,63 +1,104 @@
## How to setup your Network page
## How to Set Up Your Network Page
Make sure you have a root device with the MAC `Internet` (No other MAC addresses are currently supported as the root node) set to a network device type (e.g.: **Type**:`Router`).
The **Network** page lets you map how devices connect — visually and logically.
Its especially useful for planning infrastructure, assigning parent-child relationships, and spotting gaps.
> 💡 Tip: You can add dummy devices via the [Create dummy device](./DEVICE_MANAGEMENT.md#dummy-devices) button in the Devices listing page.
![Network tree details](./img/NETWORK_TREE/Network_Sample.png)
> 💡 Tip: Export your configuration of the Network and Devices once in a while via the Export CSV feature under **Maintenance** -> **Backup/Restore** -> **CSV Export**.
To get started, youll need to define at least one root node and mark certain devices as network nodes (like Switches or Routers).
## ⚡Quick setup:
---
* Go to a Device you want to use as network device (network nodes, such as a Switch).
* Set the **Type** of such a device to one of the following: AP, Firewall, Gateway, PLC, Powerline, Router, Switch, USB LAN Adapter, USB WIFI Adapter and WLAN (you can create a custom network type device with in Settings -> General -> `NETWORK_DEVICE_TYPES`).
* Save and go to Network where the devices you've marked as network devices (by selecting the Type as mentioned above) will show up as tabs.
* You can now assign the Unassigend devices to the network node.
* If port is empty or 0 a wifi icon is rendered, otherwise a ethernet port icon.
Start by creating a root device with the MAC address `Internet`, if the application didnt create one already.
This special MAC address (`Internet`) is required for the root network node — no other value is currently supported.
Set its **Type** to a valid network type — such as `Router` or `Gateway`.
> [!TIP]
> If you dont have one, use the [Create new device](./DEVICE_MANAGEMENT.md#dummy-devices) button on the **Devices** page to add a root device.
> [!NOTE]
>
> [Bulk-edit devices](./DEVICES_BULK_EDITING.md) by using the _CSV Export_ functionality in the _Maintenance_ section. You can use this to fix `Internet` node assignment issues.
---
## 🔍Detailed example:
## ⚡ Quick Setup
In this example you will setup a device named `rapberrypi` as a `Switch` in our network.
1. Open the device you want to use as a network node (e.g. a Switch).
2. Set its **Type** to one of the following:
`AP`, `Firewall`, `Gateway`, `PLC`, `Powerline`, `Router`, `Switch`, `USB LAN Adapter`, `USB WIFI Adapter`, `WLAN`
*(Or add custom types under **Settings → General → `NETWORK_DEVICE_TYPES`**.)*
3. Save the device.
4. Go to the **Network** page — supported device types will appear as tabs.
5. Use the **Assign** button to connect unassigned devices to a network node.
6. If the **Port** is `0` or empty, a Wi-Fi icon is shown. Otherwise, an Ethernet icon appears.
### 1. Device details page
> [!NOTE]
> Use [bulk editing](./DEVICES_BULK_EDITING.md) with _CSV Export_ to fix `Internet` root assignments or update many devices at once.
- Go to the `Devices` (1) page:
---
![Device details](./img/NETWORK_TREE/Device_Details_Network_Type.png)
## Example: Setting up a `raspberrypi` as a Switch
- In the (2) `Details` tab navigate to the the `Type` (3) dropdown and select the type `Switch` (4).
Lets walk through setting up a device named `raspberrypi` to act as a network Switch that other devices connect through.
> Note: Only the following device types will show up as selectable Network nodes ( = devices you can connect other devices to):
> AP, Firewall, Gateway, Hypervisor, PLC, Powerline, Router, Switch, USB LAN Adapter, USB WIFI Adapter and WLAN. Custom types can be added via the `NETWORK_DEVICE_TYPES` setting.
---
- Assign a device to your root device from the `Node` (5) dropdown which has the MAC `Internet` (6) (Your name may differ, but the MAC needs to be set to `Internet` - this is done by default).
### 1. Set Device Type and Parent
- Save your changes (7)
- Go to the **Devices** page
- Open the device detail view for `raspberrypi`
- In the **Type** dropdown, select `Switch`
### 2. Network page
![Device details](./img/NETWORK_TREE/Network_Device_Details.png)
- Navigate to your `Network` (1) page:
- Optionally assign a **Parent Node** (where this device connects to) and the **Relationship type** of the connection.
The `nic` relationship type can affect parent notifications — see the setting description and [Notifications documentation](./NOTIFICATIONS.md) for more.
![Network page](./img/NETWORK_TREE/Network_Page.png)
![Device details](./img/NETWORK_TREE/Network_Device_Details_Parent.png)
- Notice the newly added `raspberrypi` (2) tab which now represents a network node, also showing up in the tree (3).
- As we asssigned the `raspberrypi` in the previous (1) Device details page section to the `Internet` parent network node in step (6), the link is also showing up in the tree diagram (4)
- We can now assign the device `(AppleTV)` (5) to this `raspberrypi` node, representing a network Switch in this example
> [!NOTE]
> Only certain device types can act as network nodes:
> `AP`, `Firewall`, `Gateway`, `Hypervisor`, `PLC`, `Powerline`, `Router`, `Switch`, `USB LAN Adapter`, `USB WIFI Adapter`, `WLAN`
> You can add custom types via the `NETWORK_DEVICE_TYPES` setting.
### 3. Network page with 2 levels
- Click **Save**
- After clicking the `Assign` button in the previous section, the `(AppleTV)` (1) device is now connected to our `raspberrypi` (2).
---
![Network page with 2 levels](./img/NETWORK_TREE/Network_Page_2_Levels.png)
### 2. Confirm The Device Appears as a Network Node
- You can see the `raspberrypi` represents the Network node type `Switch` (3)
- The `(AppleTV)` to `raspberrypi` connection is also displayed in the table of `Connected devices` (4).
- You can also see that our `raspberrypi` node is connected to it's Parent network device node with the MAC `Internet` (5). This connection again shows up in the tree (6) as well.
You can confirm that `raspberrypi` now acts as a network device in two places:
- Navigate to a different device and verify that `raspberrypi` now appears as an option for a **Parent Node**:
![Parent Node dropdown](./img/NETWORK_TREE/Network_Device_ParentDropdown.png)
- Go to the **Network** page — you'll now see a `raspberrypi` tab, meaning it's recognized as a network node (Switch):
![Network page](./img/NETWORK_TREE/Network_Assign.png)
- You can now assign other devices to it.
---
### 3. Assign Connected Devices
- Use the **Assign** button to link other devices (e.g. PCs) to `raspberrypi`.
- After assigning, connected devices will appear beneath the `raspberrypi` switch node.
![Assigned nodes](./img/NETWORK_TREE/Network_Assigned_Nodes.png)
- Relationship lines may vary in color based on the selected Relationship type. These are editable on the device details page where you can also assign a parent node.
![Hover detail](./img/NETWORK_TREE/Network_tree_setup_hover.png)
> Hovering over devices in the tree reveals connection details and tooltips for quick inspection.
---
## ✅ Summary
To configure devices on the **Network** page:
- Ensure a device with MAC `Internet` is set up as the root
- Assign valid **Type** values to switches, routers, and other supported nodes that represent network devices
- Use the **Assign** button to connect devices logically to their parent node
Need to reset or undo changes? [Use backups](./BACKUPS.md) or [bulk editing](./DEVICES_BULK_EDITING.md) to manage devices at scale. You can also automate device assignment with [Workflows](./WORKFLOWS.md).

View File

@@ -15,11 +15,12 @@ There are 4 ways how to influence notifications:
![Device notification settings](./img/NOTIFICATIONS/Device-notification-settings.png)
There are 4 settings on the device for influencing notifications. You can:
The following device properties influence notifications. You can:
1. **Alert Events** - Enables alerts of connections, disconnections, IP changes (down and down reconnected notifications are still sent even if this is disabled).
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.
4. **Require NICs Online** - Indicates whether this device should be considered online only if all associated NICs (devices with the `nic` relationship type) are online. If disabled, the device is considered online if any NIC is online. If a NIC is online it sets the parent (this) device's status to online irrespectivelly of the detected device's status. The Relationship type is set on the childern device.
> [!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.

View File

@@ -85,8 +85,8 @@ services:
# (Optional) Useful for debugging setup issues
- local/path/logs:/app/log
# (API: OPTION 1) Store temporary files in memory (recommended for performance)
- type: tmpfs # ◀
target: /app/api # ◀
- type: tmpfs # ◀ 🔺
target: /app/api # ◀ 🔺
# (API: OPTION 2) Store API data on disk (useful for debugging)
# - local/path/api:/app/api
environment:

View File

@@ -9,7 +9,7 @@ NetAlertX supports additional plugins to extend its functionality, each with its
> [!TIP]
> 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).
> ![Loaded plugins settings](./img/PLUGINS/loaded_plugins_setting.png)
> ![Loaded plugins settings](./img/PLUGINS/enable_plugin.gif)
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.
@@ -43,51 +43,50 @@ NetAlertX supports additional plugins to extend its functionality, each with its
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`.
| ID | Type | Description | Features | Required | Data source | Detailed docs |
|---------------|---------|--------------------------------------------|----------|----------|--------------|---------------------------------------------------------------------|
| `APPRISE` | ▶️ | Apprise notification proxy | | | Script | [_publisher_apprise](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_apprise/) |
| `ARPSCAN` | 🔍 | ARP-scan on current network | | | Script | [arp_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/arp_scan/) |
| `AVAHISCAN` | 🆎 | Avahi (mDNS-based) name resolution | | | Script | [avahi_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/avahi_scan/) |
| `ASUSWRT` | 🔍 | Import connected devices from AsusWRT | | | Script | [asuswrt_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/asuswrt_import/) |
| `CSVBCKP` | ⚙ | CSV devices backup | | | Script | [csv_backup](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup/) |
| `CUSTPROP` | ⚙ | Managing custom device properties values | | Yes | Template | [custom_props](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/custom_props/) |
| `DBCLNP` | ⚙ | Database cleanup | | Yes* | Script | [db_cleanup](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/db_cleanup/) |
| `DDNS` | ⚙ | DDNS update | | | Script | [ddns_update](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ddns_update/) |
| `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/) |
| `DIGSCAN` | 🆎 | Dig (DNS) Name resolution | | | Script | [dig_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dig_scan/) |
| `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/) |
| `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/) |
| `IPNEIGH` | 🔍 | Scan ARP (IPv4) and NDP (IPv6) tables | | | Script | [ipneigh](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ipneigh/) |
| `LUCIRPC` | 🔍 | Import connected devices from OpenWRT | | | Script | [luci_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/luci_import/) |
| `MAINT` | ⚙ | Maintenance of logs, etc. | | | Script | [maintenance](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/maintenance/) |
| `MQTT` | ▶️ | MQTT for synching to Home Assistant | | | Script | [_publisher_mqtt](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_mqtt/) |
| `NBTSCAN` | 🆎 | Nbtscan (NetBIOS-based) name resolution | | | Script | [nbtscan_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nbtscan_scan/) |
| `NEWDEV` | ⚙ | New device template | | Yes | Template | [newdev_template](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/newdev_template/) |
| `NMAP` | ♻ | Nmap port scanning & discovery | | | Script | [nmap_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_scan/) |
| `NMAPDEV` | 🔍 | Nmap dev scan on current network | | | Script | [nmap_dev_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_dev_scan/) |
| `NSLOOKUP` | 🆎 | NSLookup (DNS-based) name resolution | | | Script | [nslookup_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nslookup_scan/) |
| `NTFPRCS` | ⚙ | Notification processing | | Yes | Template | [notification_processing](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/notification_processing/)|
| `NTFY` | ▶️ | NTFY notifications | | | Script | [_publisher_ntfy](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_ntfy/) |
| `OMDSDN` | 📥/🆎 ❌ | UNMAINTAINED use `OMDSDNOPENAPI` | 🖧 🔄 | | Script | [omada_sdn_imp](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/omada_sdn_imp/) |
| `OMDSDNOPENAPI`| 📥/🆎 | OMADA TP-Link import via OpenAPI | 🖧 | | Script | [omada_sdn_openapi](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/omada_sdn_openapi/) |
| `PIHOLE` | 🔍/🆎/📥| Pi-hole device import & sync | | | SQLite DB | [pihole_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/pihole_scan/) |
| `PUSHSAFER` | ▶️ | Pushsafer notifications | | | Script | [_publisher_pushsafer](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_pushsafer/) |
| `PUSHOVER` | ▶️ | Pushover notifications | | | Script | [_publisher_pushover](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_pushover/) |
| `SETPWD` | ⚙ | Set password | | Yes | Template | [set_password](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/set_password/) |
| `SMTP` | ▶️ | Email notifications | | | Script | [_publisher_email](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_email/) |
| `SNMPDSC` | 🔍/📥 | SNMP device import & sync | | | Script | [snmp_discovery](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/snmp_discovery/) |
| `SYNC` | 🔍/⚙/📥| Sync & import from NetAlertX instances | 🖧 🔄 | Yes | Script | [sync](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/sync/) |
| `TELEGRAM` | ▶️ | Telegram notifications | | | Script | [_publisher_telegram](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_telegram/) |
| `UI` | ♻ | UI specific settings | | Yes | Template | [ui_settings](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ui_settings/) |
| `UNFIMP` | 🔍/📥/🆎| UniFi device import & sync | 🖧 | | Script | [unifi_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/unifi_import/) |
| `VNDRPDT` | ⚙ | Vendor database update | | | Script | [vendor_update](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/vendor_update/) |
| `WEBHOOK` | ▶️ | Webhook notifications | | | Script | [_publisher_webhook](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_webhook/) |
| `WEBMON` | ♻ | Website down monitoring | | | Script | [website_monitor](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/website_monitor/) |
| `WOL` | ♻ | Automatic wake-on-lan | | | Script | [wake_on_lan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/wake_on_lan/) |
| ID | Plugin docs | Type | Description | Features | Required |
| --------------- | ------------------------------------------------------------------------------------------------------------------ | -------- | ----------------------------------------- | -------- | -------- |
| `APPRISE` | [_publisher_apprise](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_apprise/) | ▶️ | Apprise notification proxy | | |
| `ARPSCAN` | [arp_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/arp_scan/) | 🔍 | ARP-scan on current network | | |
| `AVAHISCAN` | [avahi_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/avahi_scan/) | 🆎 | Avahi (mDNS-based) name resolution | | |
| `ASUSWRT` | [asuswrt_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/asuswrt_import/) | 🔍 | Import connected devices from AsusWRT | | |
| `CSVBCKP` | [csv_backup](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/csv_backup/) | ⚙ | CSV devices backup | | |
| `CUSTPROP` | [custom_props](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/custom_props/) | ⚙ | Managing custom device properties values | | Yes |
| `DBCLNP` | [db_cleanup](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/db_cleanup/) | ⚙ | Database cleanup | | Yes\* |
| `DDNS` | [ddns_update](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ddns_update/) | ⚙ | DDNS update | | |
| `DHCPLSS` | [dhcp_leases](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_leases/) | 🔍/📥/🆎 | Import devices from DHCP leases | | |
| `DHCPSRVS` | [dhcp_servers](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dhcp_servers/) | ♻ | DHCP servers | | |
| `DIGSCAN` | [dig_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/dig_scan/) | 🆎 | Dig (DNS) Name resolution | | |
| `FREEBOX` | [freebox](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/freebox/) | 🔍/♻/🆎 | Pull data and names from Freebox/Iliadbox | | |
| `ICMP` | [icmp_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/icmp_scan/) | ♻ | ICMP (ping) status checker | | |
| `INTRNT` | [internet_ip](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_ip/) | 🔍 | Internet IP scanner | | |
| `INTRSPD` | [internet_speedtest](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/internet_speedtest/) | ♻ | Internet speed test | | |
| `IPNEIGH` | [ipneigh](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ipneigh/) | 🔍 | Scan ARP (IPv4) and NDP (IPv6) tables | | |
| `LUCIRPC` | [luci_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/luci_import/) | 🔍 | Import connected devices from OpenWRT | | |
| `MAINT` | [maintenance](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/maintenance/) | ⚙ | Maintenance of logs, etc. | | |
| `MQTT` | [_publisher_mqtt](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_mqtt/) | ▶️ | MQTT for synching to Home Assistant | | |
| `NBTSCAN` | [nbtscan_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nbtscan_scan/) | 🆎 | Nbtscan (NetBIOS-based) name resolution | | |
| `NEWDEV` | [newdev_template](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/newdev_template/) | ⚙ | New device template | | Yes |
| `NMAP` | [nmap_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_scan/) | ♻ | Nmap port scanning & discovery | | |
| `NMAPDEV` | [nmap_dev_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_dev_scan/) | 🔍 | Nmap dev scan on current network | | |
| `NSLOOKUP` | [nslookup_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nslookup_scan/) | 🆎 | NSLookup (DNS-based) name resolution | | |
| `NTFPRCS` | [notification_processing](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/notification_processing/) | ⚙ | Notification processing | | Yes |
| `NTFY` | [_publisher_ntfy](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_ntfy/) | ▶️ | NTFY notifications | | |
| `OMDSDN` | [omada_sdn_imp](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/omada_sdn_imp/) | 📥/🆎 ❌ | UNMAINTAINED use `OMDSDNOPENAPI` | 🖧 🔄 | |
| `OMDSDNOPENAPI` | [omada_sdn_openapi](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/omada_sdn_openapi/) | 📥/🆎 | OMADA TP-Link import via OpenAPI | 🖧 | |
| `PIHOLE` | [pihole_scan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/pihole_scan/) | 🔍/🆎/📥 | Pi-hole device import & sync | | |
| `PUSHSAFER` | [_publisher_pushsafer](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_pushsafer/) | ▶️ | Pushsafer notifications | | |
| `PUSHOVER` | [_publisher_pushover](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_pushover/) | ▶️ | Pushover notifications | | |
| `SETPWD` | [set_password](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/set_password/) | ⚙ | Set password | | Yes |
| `SMTP` | [_publisher_email](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_email/) | ▶️ | Email notifications | | |
| `SNMPDSC` | [snmp_discovery](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/snmp_discovery/) | 🔍/📥 | SNMP device import & sync | | |
| `SYNC` | [sync](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/sync/) | 🔍/⚙/📥 | Sync & import from NetAlertX instances | 🖧 🔄 | Yes |
| `TELEGRAM` | [_publisher_telegram](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_telegram/) | ▶️ | Telegram notifications | | |
| `UI` | [ui_settings](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/ui_settings/) | ♻ | UI specific settings | | Yes |
| `UNFIMP` | [unifi_import](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/unifi_import/) | 🔍/📥/🆎 | UniFi device import & sync | 🖧 | |
| `VNDRPDT` | [vendor_update](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/vendor_update/) | ⚙ | Vendor database update | | |
| `WEBHOOK` | [_publisher_webhook](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/_publisher_webhook/) | ▶️ | Webhook notifications | | |
| `WEBMON` | [website_monitor](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/website_monitor/) | ♻ | Website down monitoring | | |
| `WOL` | [wake_on_lan](https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/wake_on_lan/) | ♻ | Automatic wake-on-lan | | |
> \* The database cleanup plugin (`DBCLNP`) is not _required_ but the app will become unusable after a while if not executed.

View File

@@ -1,29 +1,102 @@
# Securing your NetAlertX instance
## 🧭 Responsibility Disclaimer
NetAlertX is an execution framework. In order to run scanners and plugins, the application has to have access to privileged system resources. It is not recommended to expose NetAlertX to the internet without taking basic security precautions. It is highly recommended to use a VPN to access the application and to set up a password for the web interface before exposing the UI online.
NetAlertX provides powerful tools for network scanning, presence detection, and automation. However, **it is up to you—the deployer—to ensure that your instance is properly secured**.
## VPN
This includes (but is not limited to):
- Controlling who has access to the UI and API
- Following network and container security best practices
- Running NetAlertX only on networks where you have legal authorization
- Keeping your deployment up to date with the latest patches
VPNs allow you to securely access your NetAlertX instance from remote locations without exposing it to the internet. A VPN encrypts your connection and prevents unauthorized access.
> NetAlertX is not responsible for misuse, misconfiguration, or unsecure deployments. Always test and secure your setup before exposing it to the outside world.
### Tailscale as an Alternative
# 🔐 Securing Your NetAlertX Instance
If setting up a traditional VPN is not ideal, you can use [Tailscale](https://tailscale.com/) as an easy alternative. Tailscale creates a secure, encrypted connection between your devices without complex configuration. Since NetAlertX is designed to be run on private networks, Tailscale can provide a simple way to securely connect to your instance from anywhere.
NetAlertX is a powerful network scanning and automation framework. With that power comes responsibility. **It is your responsibility to secure your deployment**, especially if you're running it outside a trusted local environment.
## Setting a Password
---
By default, NetAlertX does not enforce authentication, but it is highly recommended to set a password before exposing the web interface.
## ⚠️ TL;DR Key Security Recommendations
Configure `SETPWD_enable_password` to `true` and enter your password in `SETPWD_password`. When enabled, a login dialog is displayed. If facing issues, you can always disable the login by setting `SETPWD_enable_password=false` in your `app.conf` file.
-**NEVER expose NetAlertX directly to the internet without protection**
- ✅ Use a **VPN or Tailscale** to access remotely
- ✅ Enable **password protection** for the web UI
- ✅ Harden your container environment (e.g., no unnecessary privileges)
- ✅ Use **firewalls and IP whitelisting**
- ✅ Keep the software **updated**
- ✅ Limit the scope of **plugins and API keys**
- The default password is `123456`.
- Passwords are stored as SHA256 hashes for security.
---
## Additional Security Measures
## 🔗 Access Control with VPN (or Tailscale)
- **Firewall Rules**: Ensure that only trusted IPs can access the NetAlertX instance.
- **Limit Plugin Permissions**: Only enable the plugins necessary for your setup.
- **Keep Software Updated**: Regularly update NetAlertX to receive the latest security patches.
- **Use Read-Only API Keys**: If exposing APIs, limit privileges with read-only keys where applicable.
NetAlertX is designed to be run on **private LANs**, not the open internet.
By following these security recommendations, you can help protect your NetAlertX instance from unauthorized access and potential misuse.
**Recommended**: Use a VPN to access NetAlertX from remote locations.
### ✅ Tailscale (Easy VPN Alternative)
Tailscale sets up a private mesh network between your devices. It's fast to configure and ideal for NetAlertX.
👉 [Get started with Tailscale](https://tailscale.com/)
---
## 🔑 Web UI Password Protection
By default, NetAlertX does **not** require login. Before exposing the UI in any way:
1. Enable password protection:
```ini
SETPWD_enable_password=true
SETPWD_password=your_secure_password
```
2. Passwords are stored as SHA256 hashes
3. Default password (if not changed): 123456 — change it ASAP!
> To disable authenticated login, set `SETPWD_enable_password=false` in `app.conf`
---
## 🔥 Additional Security Measures
- **Firewall / Network Rules**
Restrict UI/API access to trusted IPs only.
- **Limit Docker Capabilities**
Avoid `--privileged`. Use `--cap-add=NET_RAW` and others **only if required** by your scan method.
- **Keep NetAlertX Updated**
Regular updates contain bug fixes and security patches.
- **Plugin Permissions**
Disable unused plugins. Only install from trusted sources.
- **Use Read-Only API Keys**
When integrating NetAlertX with other tools, scope keys tightly.
---
## 🧱 Docker Hardening Tips
- Use `read-only` mount options where possible (`:ro`)
- Avoid running as `root` unless absolutely necessary
- Consider using `docker scan` or other container image vulnerability scanners
- Run with `--network host` **only on trusted networks** and only if needed for ARP-based scans
---
## 📣 Responsible Disclosure
If you discover a vulnerability or security concern, please report it **privately** to:
📧 [jokob@duck.com](mailto:jokob@duck.com?subject=NetAlertX%20Security%20Disclosure)
We take security seriously and will work to patch confirmed issues promptly. Your help in responsible disclosure is appreciated!
---
By following these recommendations, you can ensure your NetAlertX deployment is both powerful **and** secure.

View File

@@ -1,6 +1,49 @@
# 📧 SMTP guides
# 📧 SMTP server guides
## Using the GMX SMTP server
The SMTP plugin supports any SMTP server. Here are some commonly used services to help speed up your configuration.
> [!NOTE]
> If you are using a self hosted SMTP server ssh into the container and verify (e.g. via ping) that your server is reachable from within the NetAlertX container. See also how to ssh into the container if you are running it as a [Home Assistant](./HOME_ASSISTANT.md) addon.
## Gmail
1. Create an app password by following the instructions from Google, you need to Enable 2FA for this to work.
[https://support.google.com/accounts/answer/185833](https://support.google.com/accounts/answer/185833)
2. Specify the following settings:
```python
SMTP_RUN='on_notification'
SMTP_SKIP_TLS=True
SMTP_FORCE_SSL=True
SMTP_PORT=465
SMTP_SERVER='smtp.gmail.com'
SMTP_PASS='16-digit passcode from google'
SMTP_REPORT_TO='some_target_email@gmail.com'
```
## Brevo
Brevo allows for 300 free emails per day as of time of writing.
1. Create an account on Brevo: https://www.brevo.com/free-smtp-server/
2. Click your name -> SMTP & API
3. Click Generate a new SMTP key
4. Save the details and fill in the NetAlertX settings as below.
```python
SMTP_SERVER='smtp-relay.brevo.com'
SMTP_PORT=587
SMTP_SKIP_LOGIN=False
SMTP_USER='user@email.com'
SMTP_PASS='xsmtpsib-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxx'
SMTP_SKIP_TLS=False
SMTP_FORCE_SSL=False
SMTP_REPORT_TO='some_target_email@gmail.com'
SMTP_REPORT_FROM='NetAlertX <user@email.com>'
```
## GMX
1. Go to your GMX account https://account.gmx.com
2. Under Security Options enable 2FA (Two-factor authentication)
@@ -21,21 +64,3 @@
SMTP_REPORT_TO='some_target_email@gmail.com'
```
## Using the Gmail SMTP server
1. Create an app password by following the instructions from Google, you need to Enable 2FA for this to work.
[https://support.google.com/accounts/answer/185833](https://support.google.com/accounts/answer/185833)
2. Specify the following settings:
```python
SMTP_RUN='on_notification'
SMTP_SKIP_TLS=True
SMTP_FORCE_SSL=True
SMTP_PORT=465
SMTP_SERVER='smtp.gmail.com'
SMTP_PASS='16-digit passcode from google'
SMTP_REPORT_TO='some_target_email@gmail.com'
```

View File

@@ -1,13 +1,14 @@
# Docker Update Strategies to upgrade NetAlertX
> [!WARNING]
> For versions prior to `v25.6.7` upgrade to version `v25.5.24` first (`docker pull ghcr.io/jokob-sk/netalertx:25.5.24`) as later versions don't support a full upgrade. Alternatovelly, devices and settings can be migrated manually, e.g. via [CSV import](./DEVICES_BULK_EDITING.md).
> For versions prior to `v25.6.7` upgrade to version `v25.5.24` first (`docker pull ghcr.io/jokob-sk/netalertx:25.5.24`) as later versions don't support a full upgrade. Alternatively, devices and settings can be migrated manually, e.g. via [CSV import](./DEVICES_BULK_EDITING.md).
This guide outlines approaches for updating Docker containers, usually when upgrading to a newer version of NetAlertX. Each method offers different benefits depending on the situation. Here are the methods:
- Manual: Direct commands to stop, remove, and rebuild containers.
- Dockcheck: Semi-automated with more control, suited for bulk updates.
- Watchtower: Fully automated, runs continuously to check and update containers.
- Portainer: Manual with UI.
You can choose any approach that fits your workflow.
@@ -107,10 +108,42 @@ docker run -d \
```
## 4. Portainer controlled image
This assumes you're using Portainer to manage Docker (or Docker Swarm) and want to pull the latest version of an image and redeploy the container.
> [!NOTE]
> * Portainer does **not auto-update** containers. For automation, use **Watchtower** or similar tools.
> * Make sure you have the [persistent volumes mounted or backups ready](BACKUPS.md) before recreating.
### 4.1 Steps to Update an Image in Portainer (Standalone Docker)
1. **Login to Portainer.**
2. Go to **"Containers"** in the left sidebar.
3. Find the container you want to update, click its name.
4. Click **"Recreate"** (top right).
5. **Tick**: _Pull latest image_ (this ensures Portainer fetches the newest version from Docker Hub or your registry).
6. Click **"Recreate"** again.
7. Wait for the container to be stopped, removed, and recreated with the updated image.
### 4.2 For Docker Swarm Services
If you're using Docker Swarm (under **"Stacks"** or **"Services"**):
1. Go to **"Stacks"**.
2. Select the stack managing the container.
3. Click **"Editor"** (or "Update the Stack").
4. Add a version tag or use `:latest` if your image tag is `latest` (not recommended for production).
5. Click **"Update the Stack"**. ⚠ Portainer will not pull the new image unless the tag changes OR the stack is forced to recreate.
6. If image tag hasn't changed, go to **"Services"**, find the service, and click **"Force Update"**.
## Summary
- Manual: Ideal for individual or critical updates.
- Dockcheck: Suitable for controlled, mass updates.
- Watchtower: Fully automated, best for continuous deployment setups.
| Method | Type | Pros | Cons |
|------------|--------------|----------------------------------|------------------------------|
| Manual | CLI | Full control, no dependencies | Tedious for many containers |
| Dockcheck | CLI Script | Great for batch updates | Needs setup, semi-automated |
| Watchtower | Daemonized | Fully automated updates | Less control, version drift |
| Portainer | UI | Easy via web interface | No auto-updates |
These approaches allow you to maintain flexibility in how you update Docker containers, depending on the urgency and scale of the update.

View File

@@ -22,4 +22,4 @@ For a comparison, this is how the UI looks like if you are on the latest stable
## Implementation details
During build a [/app/front/buildtimestamp.txt](https://github.com/jokob-sk/NetAlertX/blob/092797e75ccfa8359444ad149e727358ac4da05f/Dockerfile#L44) file is created. The app then periodically checks if a new release is available with a newer timestamp in GitHub's rest-based JSON endpoint (check the `def isNewVersion():` method for details).
During build a [/app/front/buildtimestamp.txt](https://github.com/jokob-sk/NetAlertX/blob/092797e75ccfa8359444ad149e727358ac4da05f/Dockerfile#L44) file is created. The app then periodically checks if a new release is available with a newer timestamp in GitHub's rest-based JSON endpoint (check the `def isNewVersion:` method for details).

View File

@@ -1,5 +1,8 @@
### Create a simple n8n workflow
> [!NOTE]
> You need to enable the `WEBHOOK` plugin first in order to follow this guide. See the [Plugins guide](./PLUGINS.md) for details.
N8N can be used for more advanced conditional notification use cases. For example, you want only to get notified if two out of a specified list of devices is down. Or you can use other plugins to process the notifiations further. The below is a simple example of sending an email on a webhook.
![n8n workflow](./img/WEBHOOK_N8N/n8n_workflow.png)

View File

@@ -1,5 +1,8 @@
# Webhook Secrets
> [!NOTE]
> You need to enable the `WEBHOOK` plugin first in order to follow this guide. See the [Plugins guide](./PLUGINS.md) for details.
## How does the signing work?
NetAlertX will use the configured secret to create a hash signature of the request body. This SHA256-HMAC signature will appear in the `X-Webhook-Signature` header of each request to the webhook target URL. You can use the value of this header to validate the request was sent by NetAlertX.

View File

@@ -63,68 +63,8 @@ You can include multiple actions that should execute once the conditions are met
# Examples
Below you can find a couple of configuration examples.
You can find a couple of configuration examples in [Workflow Examples](WORKFLOW_EXAMPLES.md).
![Workflow example](./img/WORKFLOWS/workflows.png)
---
## 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:
- **Object Type**: `Devices`
- **Event Type**: `insert`
### Conditions:
- **Logic**: `AND`
- `Field`: `devLastIP`
- `Operator`: `contains`
- `Value`: `192.168.1.`
This condition ensures that the workflow only applies to devices with an IP address in the `192.168.1.*` range.
### Actions:
- **Action Type**: `update_field`
- **Field**: `devNetworkNode`
- **Value**: `6c:6d:6d:6c:6c:6c`
---
## 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:
- **Object Type**: `Devices`
- **Event Type**: `update`
### Conditions:
- **Logic**: `AND`
- `Field`: `devVendor`
- `Operator`: `contains`
- `Value`: `Google`
This condition checks if the device's vendor is `Google`.
- **Logic**: `AND`
- `Field`: `devIsNew`
- `Operator`: `equals`
- `Value`: `1`
This ensures the workflow applies only to new devices.
### Actions:
1. **Action Type**: `update_field`
- **Field**: `devIsNew`
- **Value**: `0`
This action marks the device as no longer new.
2. **Action Type**: `delete_device`
This action deletes the device after it is marked as not new.
> [!TIP]
> Share your workflows in [Discord](https://discord.com/invite/NczTUTWyRr) or [GitHub Discussions](https://github.com/jokob-sk/NetAlertX/discussions).

185
docs/WORKFLOW_EXAMPLES.md Executable file
View File

@@ -0,0 +1,185 @@
# Workflow examples
Workflows in NetAlertX automate actions based on real-time events and conditions. Below are practical examples that demonstrate how to build automation using triggers, conditions, and actions.
## Example 1: Un-archive devices if detected online
This workflow automatically unarchives a device if it was previously archived but has now been detected as online.
### 📋 Use Case
Sometimes devices are manually archived (e.g., no longer expected on the network), but they reappear unexpectedly. This workflow reverses the archive status when such devices are detected during a scan.
### ⚙️ Workflow Configuration
```json
{
"name": "Un-archive devices if detected online",
"trigger": {
"object_type": "Devices",
"event_type": "update"
},
"conditions": [
{
"logic": "AND",
"conditions": [
{
"field": "devIsArchived",
"operator": "equals",
"value": "1"
},
{
"field": "devPresentLastScan",
"operator": "equals",
"value": "1"
}
]
}
],
"actions": [
{
"type": "update_field",
"field": "devIsArchived",
"value": "0"
}
],
"enabled": "Yes"
}
```
### 🔍 Explanation
- Trigger: Listens for updates to device records.
- Conditions:
- `devIsArchived` is `1` (archived).
- `devPresentLastScan` is `1` (device was detected in the latest scan).
- Action: Updates the device to set `devIsArchived` to `0` (unarchived).
### ✅ Result
Whenever a previously archived device shows up during a network scan, it will be automatically unarchived — allowing it to reappear in your device lists and dashboards.
Here is your updated version of **Example 2** and **Example 3**, fully aligned with the format and structure of **Example 1** for consistency and professionalism:
---
## Example 2: Assign Device to Network Node Based on IP
This workflow assigns newly added devices with IP addresses in the `192.168.1.*` range to a specific network node with MAC address `6c:6d:6d:6c:6c:6c`.
### 📋 Use Case
When new devices join your network, assigning them to the correct network node is important for accurate topology and grouping. This workflow ensures devices in a specific subnet are automatically linked to the intended node.
### ⚙️ Workflow Configuration
```json
{
"name": "Assign Device to Network Node Based on IP",
"trigger": {
"object_type": "Devices",
"event_type": "insert"
},
"conditions": [
{
"logic": "AND",
"conditions": [
{
"field": "devLastIP",
"operator": "contains",
"value": "192.168.1."
}
]
}
],
"actions": [
{
"type": "update_field",
"field": "devNetworkNode",
"value": "6c:6d:6d:6c:6c:6c"
}
],
"enabled": "Yes"
}
```
### 🔍 Explanation
* **Trigger**: Activates when a new device is added.
* **Condition**:
* `devLastIP` contains `192.168.1.` (matches subnet).
* **Action**:
* Sets `devNetworkNode` to the specified MAC address.
### ✅ Result
New devices with IPs in the `192.168.1.*` subnet are automatically assigned to the correct network node, streamlining device organization and reducing manual work.
---
## Example 3: Mark Device as Not New and Delete If from Google Vendor
This workflow automatically marks newly detected Google devices as not new and deletes them immediately.
### 📋 Use Case
You may want to automatically clear out newly detected Google devices (such as Chromecast or Google Home) if theyre not needed in your device database. This workflow handles that clean-up automatically.
### ⚙️ Workflow Configuration
```json
{
"name": "Mark Device as Not New and Delete If from Google Vendor",
"trigger": {
"object_type": "Devices",
"event_type": "update"
},
"conditions": [
{
"logic": "AND",
"conditions": [
{
"field": "devVendor",
"operator": "contains",
"value": "Google"
},
{
"field": "devIsNew",
"operator": "equals",
"value": "1"
}
]
}
],
"actions": [
{
"type": "update_field",
"field": "devIsNew",
"value": "0"
},
{
"type": "delete_device"
}
],
"enabled": "Yes"
}
```
### 🔍 Explanation
* **Trigger**: Runs on device updates.
* **Conditions**:
* Vendor contains `Google`.
* Device is marked as new (`devIsNew` is `1`).
* **Actions**:
1. Set `devIsNew` to `0` (mark as not new).
2. Delete the device.
### ✅ Result
Any newly detected Google devices are cleaned up instantly — first marked as not new, then deleted — helping you avoid clutter in your device records.

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -1,3 +1,8 @@
<span class="helpIcon">
<a target="_blank" href="https://github.com/jokob-sk/NetAlertX/blob/main/docs/WORKFLOWS_DEBUGGING.md">
<i class="fa fa-circle-question"></i>
</a>
</span>
<section class="content">
<div class="nav-tabs-custom app-event-content" style="margin-bottom: 0px;">
<ul id="tabs-location" class="nav nav-tabs col-sm-2 hidden">

View File

@@ -12,10 +12,12 @@
----------------------------------------------------------------------------- */
:root {
--color-aqua: #00c0ef;
--color-lightblue: #3c8dbc;
--color-blue: #0060df;
--color-green: #00a65a;
--color-yellow: #f39c12;
--color-red: #dd4b39;
--color-gray: #8c8c8c;
}
.input-group .checkbox
@@ -28,6 +30,45 @@ h5
font-size: medium;
}
a[target="_blank"] {
position: relative;
display: inline-block; /* Needed for positioning */
padding-right: 0.6em; /* Space for the icon */
}
a[target="_blank"]::after {
content: '↗';
position: absolute;
top: 0;
right: 0;
font-size: 0.75em;
line-height: 1;
}
.select2 .hover-node-info::after {
padding-left: 1px ;
}
/* .node-standard-device .netNodeText::after
{
right: -7px;
top: 1px;
} */
/* .select2-container--default .select2-selection--multiple .select2-selection__choice
{
padding-right: 15px !important;
} */
.hoverHighlight
{
opacity: 0.7;
}
.hoverHighlight:hover
{
opacity: 1;
}
/* -----------------------------------------------------------------------------
Helper Classes
----------------------------------------------------------------------------- */
@@ -48,6 +89,7 @@ h5
float: inline-end;
}
/* -----------------------------------------------------------------------------
Text Classes
----------------------------------------------------------------------------- */
@@ -340,6 +382,11 @@ body
width: 100%;
}
.networkTable .nav-tabs-custom
{
margin-bottom: 0px;
}
.pa-small-box-2 .inner h3 {
margin-left: 0em;
margin-bottom: 1.3em;
@@ -474,7 +521,7 @@ body
}
.bottom-border-primary {
border-bottom-color: #3c8dbc;
border-bottom-color: var(--color-lightblue);
border-bottom-style: solid;
border-bottom-width: 3px
}
@@ -879,6 +926,10 @@ height: 50px;
margin: 10px;
padding: 10px;
}
#notifications .notification-box{
min-height: 90vh;
}
#notificationData textarea{
width: 100%;
@@ -1032,7 +1083,7 @@ height: 50px;
.myhidden
{
display:none;
display:none !important;
}
.center
@@ -1354,6 +1405,7 @@ input[readonly] {
.iconPreview {
min-width: 40px;
/* display: inherit; */
}
.iconPreview svg{
@@ -1399,7 +1451,8 @@ input[readonly] {
cursor: -webkit-grab;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice
#settingsPage .select2-container--default .select2-selection--multiple .select2-selection__choice,
#maintenancePage .select2-container--default .select2-selection--multiple .select2-selection__choice
{
background-color:#258744 !important;
}
@@ -1413,6 +1466,15 @@ input[readonly] {
background-color:#606060 !important;
}
.select2-container--default .select2-selection--multiple,
.select2-container--default .select2-selection--single
{
border-radius: 0px !important;
border-color: #d2d6de !important;
min-height: 42px;
}
.helpIconSmallTopRight{
position: absolute;
font-size: x-small;
@@ -1449,6 +1511,11 @@ input[readonly] {
text-align: left;
}
#panDetails .input-group {
min-height: 40px;
}
#devicePageInfoPlc
{
display: none;
@@ -1527,18 +1594,98 @@ input[readonly] {
}
/* #panDetails .dataTables_wrapper .bottom .paging_simple_numbers */
#panDetails #NEWDEV_devIcon
{
display: none;
}
#panDetails #NEWDEV_devCustomProps_label
{
display: none;
}
#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice a
{
color: #fff;
}
#deviceDetailsEdit .iconPreview svg
{
height: 14px;
}
#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice
{
height: 20px;
}
#deviceDetailsEdit .select2-container--disabled
{
background-color: #606060;
}
#deviceDetailsEdit .select2-container--default .select2-selection--multiple .select2-selection__choice span
{
font-size: 14px;
}
#deviceDetailsEdit .select2-selection
{
width: initial;
display: inline-block;
min-height: 42px;
}
/* Remove the default Select2 chevron (the down arrow) */
.select2-container .select2-selection__arrow b {
display: none !important;
}
/* Add custom icon */
.select2-container .select2-selection__arrow::after {
font-family: 'Font Awesome 6 Free';
content: "\f078"; /* fa-chevron-down */
font-weight: 700;
position: absolute;
top: 75%;
left: 30%;
transform: translate(-50%, -50%);
pointer-events: none;
}
#deviceDetailsEdit .form-control
{
min-height: 42px;
}
.select2-selection--single .custom-chip
{
margin-top: 11px;
display: flex;
}
.select2-container--default .select2-selection--single .select2-selection__rendered,
.select2-container--default .select2-selection--single, .select2-selection .select2-selection--single
{
padding: 0px 0px;
min-height: 42px;
}
/* .select2-container--default .select2-selection--single .select2-selection__rendered, */
.select2-container--default .select2-selection--single
{
/* color:initial !important; */
background-color:initial !important;
}
#deviceDetailsEdit .select2-container
{
width: 100% !important;
}
#deviceDetailsEdit .select2-container .selection
{
width: 100% !important;
display: inline-grid;
}
/* ----------------------------------------------------------------- */
/* MODAL popups */
/* ----------------------------------------------------------------- */
@@ -1557,10 +1704,30 @@ input[readonly] {
/* NETWORK page */
/* ----------------------------------------------------------------- */
.hide-node-names .node-name {
display: none;
}
#toggleFilters
{
display: block;
position: fixed;
padding-left: 32px;
padding-top: 10px;
background-color: inherit;
z-index: 3;
width: 190px;
box-shadow: 4px 4px 4px rgba(0, 0, 0, 0.1);
}
/* AdminLTE overrides */
.content-wrapper {
min-height: calc(100vh - 31px) !important;
}
#networkTree .box
{
/* border-top:1px; */
border-width:1px;
border-top-color:grey;
padding:0px;
margin:0px;
@@ -1596,6 +1763,7 @@ input[readonly] {
opacity: 0.3;
display: initial;
float: left;
width: 1em;
}
#networkTree
@@ -1619,6 +1787,42 @@ input[readonly] {
width: auto;
}
#hover-box
{
background-color: #ffffff;;
}
#hover-box .iconPreview
{
padding: 0px;
display: flex;
}
#hover-box .devName
{
font-size: larger;
display: contents;
}
#hover-box b
{
float: left;
}
#hover-box .line
{
float: left;
width: 100%;
}
#hover-box span
{
float: right;
text-overflow: ellipsis;
overflow: hidden;
display: block;
max-width: 200px;
}
#networkTree .netCollapse
{
@@ -1626,11 +1830,39 @@ input[readonly] {
right: 0;
margin-right: -3px;
}
/* var(--color-aqua);
--color-aqua: #00c0ef;
--color-blue: #0060df;
--color-green: #00a65a;
--color-yellow: #f39c12;
--color-red: #dd4b39; */
#networkTree .node-inner.node-network-device:hover
{
box-shadow: var(--color-aqua) 0px 0px 20px;
}
#networkTree .node-inner.node-standard-device:hover
{
box-shadow: var(--color-gray) 0px 0px 10px;
}
#networkTree .network-hw-icon
{
position: absolute;
margin-left: -0.4em;
opacity: 0.3;
margin-top: 0.1em;
}
#networkTree .highlightedNode
{
/* border: solid; */
border-color:cyan;
border-color:var(--color-lightblue);
box-shadow: var(--color-lightblue) 0px 0px 20px;
}
#networkTree .netStatus-Off-line i,
#networkTree .netStatus-Off-line svg
{
@@ -1654,6 +1886,23 @@ input[readonly] {
/* margin-left: 0.2em; */
}
.networkTable
{
padding-bottom: 1px;
z-index: 3;
position: relative;
}
.networkNodeTabHeaders .icon i
{
padding-top: 8px !important;
padding-left: 6px !important;
}
.networkTable .box-body {
padding-top: 5px;
}
.networkTable .networkNodeTabHeaders a {
display: block;
height: 3em;
@@ -1682,6 +1931,8 @@ input[readonly] {
text-wrap: nowrap;
}
@media (max-width: 767px) {
.networkNodeTabHeaders .node-name
@@ -1712,7 +1963,10 @@ input[readonly] {
/* PLUGINS page */
/* ----------------------------------------------------------------- */
#tabs-location
{
padding-right: 0px;
}
.plugin-filters
{
@@ -1727,15 +1981,31 @@ input[readonly] {
padding-bottom: 0px;
}
.plugin-content .left-nav{
.plugin-content .nav-tabs li a
{
border-right-width: 0px;
}
#tabs-content-location-wrap
{
min-height: 90vh;
}
#tabs-content-location textarea {
width: 100%;
}
.plugin-content .left-nav{
width: calc(100%);
padding-right: 0px;
z-index: 2;
background-color: inherit !important;
}
.plugin-content #tabs-content-location
{
margin: 0px;
/* padding-top: 0; */
padding-top: 0;
}
.integrations-plugins .content
@@ -1803,6 +2073,9 @@ input[readonly] {
.pluginBadge
{
float: right;
margin-right: 10px;
opacity: 0.6;
margin-top: 4px;
}
.pluginBadgeWrap
@@ -1811,42 +2084,56 @@ input[readonly] {
display: ruby;
z-index: 1;
position: sticky;
margin-top: 1px;
margin-top: 4px;
}
/* -----------------------------------------------------------------------------
Spin
----------------------------------------------------------------------------- */
.pa_semitransparent-panel {
position: absolute;
width: 100%; /*calc (100% -40px);*/
height: 100%;
left: 0;
#loadingSpinner {
position: fixed;
z-index: 1000;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.3s ease-in-out;
pointer-events: none;
display: block;
opacity: 0.8;
background-color: #fff;
z-index: 800;
}
.fa-spinner
{
font-size: initial;
}
#loadingSpinner.visible {
opacity: 1;
pointer-events: auto;
}
.pa_semitransparent-panel {
position: absolute;
width: 100%;
height: 100%;
background-color: #fff;
opacity: 0.8;
z-index: 99;
}
.pa_spinner {
position: fixed;
left: 0;
right: 0;
position: absolute;
top: 100px;
margin-left: auto;
margin-right: auto;
left: 50%;
transform: translateX(-50%);
padding: 15px;
width: 200px;
background-color: #fff;
z-index: 801;
z-index: 1000;
}
#loadingSpinner
{
z-index: 100;
}
/* Multi-edit adjustements */
.box-header

View File

@@ -10,6 +10,16 @@
*
* Additional fixes For Pi.Alert UI by leiweibau */
:root {
--color-aqua: #00c0ef;
--color-lightblue: #3c8dbc;
--color-blue: #0060df;
--color-green: #00a65a;
--color-yellow: #f39c12;
--color-red: #dd4b39;
--color-gray: #8c8c8c;
}
:root {
--datatable-bgcolor: rgba(64, 76, 88, 0.8);
}
@@ -649,8 +659,14 @@ input[type="password"]::-webkit-caps-lock-indicator {
border-color: #888888;
}
.table-hover tbody tr:hover td, .table-hover tbody tr:hover th {
background-color: rgb(189,192,198);
color: #444;
background-color: var(--datatable-bgcolor);
color: var(--fbc-white);
}
table.dataTable tbody tr.selected, table.dataTable tbody tr .selected
{
background-color: var(--datatable-bgcolor);
color: var(--fbc-white);
}
.db_info_table_cell:nth-child(1) {background: #272c30}
@@ -722,7 +738,7 @@ input[type="password"]::-webkit-caps-lock-indicator {
margin-left: 0px;
}
.small-box:hover .icon {
font-size: 3.74em;
font-size: 3em;
}
.small-box .icon {
top: 0.01em;
@@ -732,6 +748,36 @@ input[type="password"]::-webkit-caps-lock-indicator {
background-color: #000 !important;
}
.select2-container--default .select2-selection--single {
color: initial !important;
background-color: #353c42 !important;
}
/* Chevron color */
.select2-container .select2-selection__arrow::after {
color: #bec5cb;
}
/* Chevron color */
.select2-selection .select2-selection--single {
color: #bec5cb;
}
.select2-container--default .select2-selection--multiple, .select2-container--default .select2-selection--single {
border-color: #3d444b !important;
}
.select2-container--default .select2-selection--single .select2-selection__rendered .custom-chip
{
color: #bec5cb;
}
#hover-box
{
background-color: #353c42 !important;
}
.callout code {
background-color: #fff !important;
color:#000 !important;
@@ -740,4 +786,9 @@ input[type="password"]::-webkit-caps-lock-indicator {
.thresholdFormControl
{
color:#000;
}
.btn:hover
{
color: var(--color-gray);
}

View File

@@ -11,6 +11,16 @@
* Additional fixes For Pi.Alert UI by leiweibau */
@media (prefers-color-scheme: dark) {
:root {
--color-aqua: #00c0ef;
--color-lightblue: #3c8dbc;
--color-blue: #0060df;
--color-green: #00a65a;
--color-yellow: #f39c12;
--color-red: #dd4b39;
--color-gray: #8c8c8c;
}
:root {
--datatable-bgcolor: rgba(64, 76, 88, 0.8);
@@ -651,8 +661,14 @@
border-color: #888888;
}
.table-hover tbody tr:hover td, .table-hover tbody tr:hover th {
background-color: rgb(189,192,198);
color: #444;
background-color: var(--datatable-bgcolor);
color: var(--fbc-white);
}
table.dataTable tbody tr.selected, table.dataTable tbody tr .selected
{
background-color: var(--datatable-bgcolor);
color: var(--fbc-white);
}
.db_info_table_cell:nth-child(1) {background: #272c30}
@@ -724,7 +740,7 @@
margin-left: 0px;
}
.small-box:hover .icon {
font-size: 3.74em;
font-size: 3em;
}
.small-box .icon {
top: 0.01em;
@@ -734,6 +750,35 @@
background-color: #000 !important;
}
.select2-container--default .select2-selection--single {
color: initial !important;
background-color: #353c42 !important;
}
/* Chevron color */
.select2-container .select2-selection__arrow::after {
color: #bec5cb;
}
/* Chevron color */
.select2-selection .select2-selection--single {
color: #bec5cb;
}
.select2-container--default .select2-selection--multiple, .select2-container--default .select2-selection--single {
border-color: #3d444b !important;
}
.select2-container--default .select2-selection--single .select2-selection__rendered .custom-chip
{
color: #bec5cb;
}
#hover-box
{
background-color: #353c42 !important;
}
}
.callout code {
@@ -746,3 +791,7 @@
color:#000;
}
.btn:hover
{
color: var(--color-gray);
}

View File

@@ -16,8 +16,9 @@
require 'php/templates/header.php';
?>
<script>
showSpinner();
</script>
<!-- Page ------------------------------------------------------------------ -->
<div class="content-wrapper">
@@ -125,15 +126,11 @@
<div class="tab-content" style="min-height: 430px;">
<!-- tab page 1 ------------------------------------------------------------ -->
<!--
<div class="tab-pane fade in active" id="panDetails">
-->
<div class="tab-pane fade" id="panDetails">
<div class="tab-pane fade" id="panDetails">
<?php
require 'deviceDetailsEdit.php';
?>
</div>
<!-- tab page 2 ------------------------------------------------------------ -->
@@ -141,51 +138,38 @@
<?php
require 'deviceDetailsSessions.php';
?>
</div>
<!-- tab page "Tools" ------------------------------------------------------------ -->
<div class="tab-pane fade" id="panTools">
<?php
require 'deviceDetailsTools.php';
?>
?>
</div>
<!-- tab page 3 ------------------------------------------------------------ -->
<div class="tab-pane fade table-responsive" id="panPresence">
<div class="tab-pane fade table-responsive" id="panPresence">
<?php
// Include the other page
include 'deviceDetailsPresence.php';
?>
</div>
<!-- tab page 4 ------------------------------------------------------------ -->
<div class="tab-pane fade table-responsive" id="panEvents">
<?php
// Include the other page
include 'deviceDetailsEvents.php';
?>
?>
</div>
<!-- tab page 7 ------------------------------------------------------------ -->
<div class="tab-pane fade table-responsive" id="panPlugins">
<?php
// Include the other page
include 'pluginsCore.php';
?>
</div>
</div>
@@ -241,13 +225,6 @@ switch ($UI_THEME) {
var selectedTab = 'tabDetails';
var emptyArr = ['undefined', "", undefined, null];
// Call renderSmallBoxes, then main
(async () => {
await renderSmallBoxes();
main();
})();
// -----------------------------------------------------------------------------
function main () {
@@ -273,7 +250,7 @@ function main () {
period = '1 day';
sessionsRows = 50;
eventsRows = 50;
$('#chkHideConnectionEvents')[0].checked = eval(eventsHide == 'true');
// $('#chkHideConnectionEvents')[0].checked = eval(eventsHide == 'true');
// Initialize components with parameters
@@ -282,26 +259,7 @@ function main () {
$( document ).ready(function() {
initializeTabs();
});
// Events tab toggle conenction events
$('input').on('ifToggled', function(event){
// Hide / Show Events
if (event.currentTarget.id == 'chkHideConnectionEvents') {
getDeviceEvents();
} else {
// Activate save & restore
// activateSaveRestoreData();
// Ask skip notifications
// if (event.currentTarget.id == 'chkArchived' ) {
// askSkipNotifications();
// }
}
});
}
@@ -328,6 +286,63 @@ function recordSwitch(direction) {
}
}
// ----------------------------------------
// Handle previous/next arrows/chevrons
function updateChevrons(currentMac) {
const devicesList = getDevicesList();
pos = devicesList.findIndex(item => item.devMac === currentMac);
if (pos === -1) {
console.warn('Device not found in cache. Re-caching devices...', currentMac);
showSpinner();
cacheDevices().then(() => {
hideSpinner();
// Retry after re-caching
const refreshedList = getDevicesList();
pos = refreshedList.findIndex(item => item.devMac === currentMac);
if (pos === -1) {
console.error('Still not found after re-cache:', currentMac);
return;
}
console.log('Device found after re-cache:', refreshedList[pos]);
// Proceed with using `refreshedList[pos]`
}).catch((err) => {
hideSpinner();
console.error('Failed to cache devices:', err);
});
return;
}
// Update the record number display
$('#txtRecord').html((pos + 1) + ' / ' + devicesList.length);
// Enable/disable previous button
if (pos <= 0) {
$('#btnPrevious').attr('disabled', '');
$('#btnPrevious').addClass('text-gray50');
} else {
$('#btnPrevious').removeAttr('disabled');
$('#btnPrevious').removeClass('text-gray50');
}
// Enable/disable next button
if (pos >= devicesList.length - 1) {
$('#btnNext').attr('disabled', '');
$('#btnNext').addClass('text-gray50');
} else {
$('#btnNext').removeAttr('disabled');
$('#btnNext').removeClass('text-gray50');
}
}
// -----------------------------------------------------------------------------
function performSwitch(direction)
@@ -338,7 +353,9 @@ function performSwitch(direction)
// Update the global position in the devices list variable 'pos'
if (direction === "next") {
if (pos < devicesList.length - 1) {
console.log("direction:" + direction);
if (pos < devicesList.length) {
pos++;
}
} else if (direction === "prev") {
@@ -358,15 +375,12 @@ function performSwitch(direction)
}
// -----------------------------------------------------------------------------
// Activate save & restore on any value change
$(document).on('input', 'input:text', function() {
settingsChanged();
});
// -----------------------------------------------------------------------------
function initializeTabs () {
@@ -380,8 +394,6 @@ function initializeTabs () {
}
$('.nav-tabs a[id='+ selectedTab +']').tab('show');
// $('.nav-tabs a[id='+ selectedTab +']').parent().click();
// $('.nav-tabs a[id="tabPlugins"]').tab('show');
// When changed save new current tab
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
@@ -391,11 +403,6 @@ function initializeTabs () {
// events on tab change
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
var target = $(e.target).attr("href") // activated tab
// if(target == "#panTools")
// {
// // loadTools();
// }
});
}
@@ -415,7 +422,6 @@ async function renderSmallBoxes() {
}
const deviceData = await response.json();
console.log(deviceData);
// Prepare custom data
const customData = [
@@ -447,7 +453,7 @@ async function renderSmallBoxes() {
"labelLang": "DevDetail_Shortcut_Presence",
"iconId": "deviceEventsIcon",
"iconClass": "fa fa-calendar",
"dataValue": `${deviceData.devPresenceHours}h`
"dataValue": `${deviceData.devPresenceHours ?? 0}h`
},
{
"onclickEvent": "$('#tabEvents').trigger('click');",
@@ -482,22 +488,65 @@ async function renderSmallBoxes() {
console.error('Error in renderSmallBoxes:', error);
} finally {
// Hide loading dialog
hideSpinner();
// hideSpinner();
}
}
function updateDevicePageName(mac) {
let name = getDevDataByMac(mac, "devName");
let owner = getDevDataByMac(mac, "devOwner");
// If data is missing, re-cache and retry once
if (name === "Unknown" || owner === "Unknown") {
console.warn("Device not found in cache, retrying after re-cache:", mac);
showSpinner();
cacheDevices().then(() => {
hideSpinner();
// Retry after successful cache
updateDevicePageName(mac);
}).catch((err) => {
hideSpinner();
console.error("Failed to refresh devices:", err);
});
return; // Exit early to avoid showing bad data
}
// Page title - Name
if (mac == "new") {
$('#pageTitle').html(
`<i title="${getString("Gen_create_new_device")}" class="fa fa-square-plus"></i> ` + getString("Gen_create_new_device")
);
$('#devicePageInfoPlc .inner').html(
`<i class="fa fa-circle-info"></i> ` + getString("Gen_create_new_device_info")
);
$('#devicePageInfoPlc').show();
} else if (!owner || (name.toString()).indexOf(owner) !== -1) {
$('#pageTitle').html(name);
$('#devicePageInfoPlc').hide();
} else {
$('#pageTitle').html(name + ' (' + owner + ')');
$('#devicePageInfoPlc').hide();
}
}
//-----------------------------------------------------------------------------------
// Call renderSmallBoxes, then main
(async () => {
await renderSmallBoxes();
main();
})();
window.onload = function async()
{
initializeTabs();
updateChevrons(mac);
updateDevicePageName(mac);
}
</script>

View File

@@ -5,7 +5,7 @@
?>
<div class="row">
<div class="row" id="deviceDetailsEdit">
<div class="box-body form-horizontal">
<form id="edit-form">
<!-- Form fields will be appended here -->
@@ -39,7 +39,7 @@
// -------------------------------------------------------------------
// Get plugin and settings data from API endpoints
function getDeviceData(readAllData){
function getDeviceData(){
mac = getMac()
@@ -53,17 +53,21 @@
var deviceData = JSON.parse(data);
// Deactivate next previous buttons
if (readAllData) {
$('#btnPrevious').attr ('disabled','');
$('#btnPrevious').addClass ('text-gray50');
$('#btnNext').attr ('disabled','');
$('#btnNext').addClass ('text-gray50');
}
// // Deactivate next previous buttons
// if (readAllData) {
// $('#btnPrevious').attr ('disabled','');
// $('#btnPrevious').addClass ('text-gray50');
// $('#btnNext').attr ('disabled','');
// $('#btnNext').addClass ('text-gray50');
// }
// some race condition, need to implement delay
setTimeout(() => {
$.get('php/server/query_json.php', { file: 'table_settings.json', nocache: Date.now() }, function(res) {
$.get('php/server/query_json.php', {
file: 'table_settings.json',
// nocache: Date.now()
},
function(res) {
settingsData = res["data"];
@@ -85,7 +89,7 @@
},
// Group for event and alert settings
DevDetail_EveandAl_Title: {
data: ["devAlertEvents", "devAlertDown", "devSkipRepeated"],
data: ["devAlertEvents", "devAlertDown", "devSkipRepeated", "devReqNicsOnline", "devChildrenNicsDynamic"],
docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NOTIFICATIONS.md",
iconClass: "fa fa-bell",
inputGroupClasses: "field-group alert-group col-lg-4 col-sm-6 col-xs-12",
@@ -94,9 +98,9 @@
},
// Group for network details
DevDetail_MainInfo_Network_Title: {
data: ["devParentMAC", "devParentPort", "devSSID", "devSite", "devSyncHubNode"],
data: ["devParentMAC", "devParentRelType", "devParentPort", "devSSID", "devSite", "devSyncHubNode"],
docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md",
iconClass: "fa fa-network-wired",
iconClass: "fa fa-sitemap fa-rotate-270",
inputGroupClasses: "field-group network-group col-lg-4 col-sm-6 col-xs-12",
labelClasses: "col-sm-4 col-xs-12 control-label",
inputClasses: "col-sm-8 col-xs-12 input-group"
@@ -119,12 +123,21 @@
labelClasses: "col-sm-4 col-xs-12 control-label",
inputClasses: "col-sm-8 col-xs-12 input-group"
},
// Group for Children.
DevDetail_Children_Title: {
data: ["devChildrenDynamic"],
docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md",
iconClass: "fa fa-list",
inputGroupClasses: "field-group cutprop-group col-lg-6 col-sm-12 col-xs-12",
labelClasses: "col-sm-12 col-xs-12 control-label",
inputClasses: "col-sm-12 col-xs-12 input-group"
},
// Group for Custom properties.
DevDetail_CustomProperties_Title: {
data: ["devCustomProps"],
docs: "https://github.com/jokob-sk/NetAlertX/blob/main/docs/CUSTOM_PROPERTIES.md",
iconClass: "fa fa-list",
inputGroupClasses: "field-group cutprop-group col-lg-12 col-sm-12 col-xs-12",
inputGroupClasses: "field-group cutprop-group col-lg-6 col-sm-12 col-xs-12",
labelClasses: "col-sm-12 col-xs-12 control-label",
inputClasses: "col-sm-12 col-xs-12 input-group"
}
@@ -167,6 +180,7 @@
// Get the field data (replace 'NEWDEV_' prefix from the key)
fieldData = deviceData[setting.setKey.replace('NEWDEV_', '')]
fieldData = fieldData == null ? "" : fieldData;
fieldOptionsOverride = null;
// console.log(setting.setKey);
// console.log(fieldData);
@@ -198,16 +212,21 @@
<i class="fa-solid fa-dice" ></i>
</span>`;
}
// handle generate IP for new device
if (setting.setKey == "NEWDEV_devIcon") {
inlineControl += `<span class="input-group-addon pointer"
onclick="showIconSelection()"
title="${getString("Gen_Select")}">
<i class="fa-solid fa-chevron-down" ></i>
</span>`;
}
// handle devChildrenDynamic or NEWDEV_devChildrenNicsDynamic - selected values and options are the same
if (
Array.isArray(fieldData) &&
(setting.setKey == "NEWDEV_devChildrenDynamic" ||
setting.setKey == "NEWDEV_devChildrenNicsDynamic" )
)
{
fieldDataNew = []
fieldData.forEach(child => {
fieldDataNew.push(child.devMac)
})
fieldData = fieldDataNew;
fieldOptionsOverride = fieldDataNew;
}
// Generate the input field HTML
const inputFormHtml = `<div class="form-group col-xs-12">
@@ -219,7 +238,7 @@
</i>
</label>
<div class="${obj.inputClasses}">
${generateFormHtml(settingsData, setting, fieldData.toString(), null, null)}
${generateFormHtml(settingsData, setting, fieldData.toString(), fieldOptionsOverride, null)}
${inlineControl}
</div>
</div>`;
@@ -236,32 +255,18 @@
updateAllIconPreviews();
// update readonly fields
handleReadOnly(settingsData, disabledFields);
// Page title - Name
if (mac == "new") {
$('#pageTitle').html(`<i title="${getString("Gen_create_new_device")}" class="fa fa-square-plus"></i> ` + getString("Gen_create_new_device"));
$('#devicePageInfoPlc .inner').html(`<i class="fa fa-circle-info"></i> ` + getString("Gen_create_new_device_info"));
$('#devicePageInfoPlc').show();
} else if (deviceData['devOwner'] == null || deviceData['devOwner'] == '' ||
(deviceData['devName'].toString()).indexOf(deviceData['devOwner']) != -1) {
$('#pageTitle').html(deviceData['devName']);
$('#devicePageInfoPlc').hide();
} else {
$('#pageTitle').html(deviceData['devName'] + ' (' + deviceData['devOwner'] + ')');
$('#devicePageInfoPlc').hide();
}
handleReadOnly(settingsData, disabledFields);
};
// console.log(relevantSettings)
generateSimpleForm(relevantSettings);
// <> chevrons
updateChevrons(deviceData)
toggleNetworkConfiguration(mac == 'Internet')
initSelect2();
initHoverNodeInfo();
hideSpinner();
})
@@ -272,46 +277,6 @@
}
// ----------------------------------------
// Handle previous/next arrows/chevrons
function updateChevrons(deviceData) {
devicesList = getDevicesList();
// console.log(devicesList);
// Check if device is part of the devicesList
pos = devicesList.findIndex(item => item.rowid == deviceData['rowid']);
// console.log(pos);
if (pos == -1) {
devicesList.push({"rowid" : deviceData['rowid'], "mac" : deviceData['devMac'], "name": deviceData['devName'], "type": deviceData['devType']});
pos=0;
}
// Record number
$('#txtRecord').html (pos+1 +' / '+ devicesList.length);
// Deactivate previous button
if (pos <= 0) {
$('#btnPrevious').attr ('disabled','');
$('#btnPrevious').addClass ('text-gray50');
} else {
$('#btnPrevious').removeAttr ('disabled');
$('#btnPrevious').removeClass ('text-gray50');
}
// Deactivate next button
if (pos >= (devicesList.length-1)) {
$('#btnNext').attr ('disabled','');
$('#btnNext').addClass ('text-gray50');
} else {
$('#btnNext').removeAttr ('disabled');
$('#btnNext').removeClass ('text-gray50');
}
}
// ----------------------------------------
// Handle the read-only fields
function handleReadOnly(settingsData, disabledFields) {
@@ -364,7 +329,7 @@
mac: $('#NEWDEV_devMac').val(),
name: encodeURIComponent($('#NEWDEV_devName').val().replace(/'/g, "")),
owner: encodeURIComponent($('#NEWDEV_devOwner').val().replace(/'/g, "")),
type: $('#NEWDEV_devType').val().replace(/'/g, ""),
type: $('#NEWDEV_devType').val().replace(/'/g, ""),
vendor: encodeURIComponent($('#NEWDEV_devVendor').val().replace(/'/g, "")),
icon: encodeURIComponent($('#NEWDEV_devIcon').val()),
favorite: ($('#NEWDEV_devFavorite')[0].checked * 1),
@@ -380,6 +345,8 @@
alertevents: ($('#NEWDEV_devAlertEvents')[0].checked * 1),
alertdown: ($('#NEWDEV_devAlertDown')[0].checked * 1),
skiprepeated: $('#NEWDEV_devSkipRepeated').val().split(' ')[0],
relType: $('#NEWDEV_devParentRelType').val().replace(/'/g, ""),
reqNics: ($('#NEWDEV_devReqNicsOnline')[0].checked * 1),
newdevice: ($('#NEWDEV_devIsNew')[0].checked * 1),
archived: ($('#NEWDEV_devIsArchived')[0].checked * 1),
devFirstConnection: ($('#NEWDEV_devFirstConnection').val()),
@@ -427,9 +394,47 @@
}
}
// -----------------------------------------------
// INIT with polling for panel element visibility
// -----------------------------------------------
var deviceDetailsPageInitialized = false;
function initdeviceDetailsPage()
{
// Only proceed if .plugin-content is visible
if (!$('#panDetails:visible').length) {
return; // exit early if nothing is visible
}
// init page once
if (deviceDetailsPageInitialized) return; // ENSURE ONCE
deviceDetailsPageInitialized = true;
showSpinner();
getDeviceData();
}
// -----------------------------------------------------------------------------
// Recurring function to monitor the URL and reinitialize if needed
function deviceDetailsPageUpdater() {
initdeviceDetailsPage();
// Run updater again after delay
setTimeout(deviceDetailsPageUpdater, 200);
}
// if visible, load immediately, if not start updater
if (!$('#panDetails:visible').length) {
deviceDetailsPageUpdater();
}
else
{
getDeviceData();
}
// -------------------- INIT ------------------------
getDeviceData(true);
</script>

View File

@@ -7,11 +7,11 @@
<!-- Hide Connections -->
<div class="text-center">
<label>
<input class="checkbox blue hidden" id="chkHideConnectionEvents" type="checkbox" checked>
<?= lang('DevDetail_Events_CheckBox');?>
<div class="col-sm-12 col-xs-12">
<label class="col-sm-3 col-xs-10">
<?= lang('DevDetail_Events_CheckBox');?>
</label>
<input class="checkbox blue col-sm-1 col-xs-2" id="chkHideConnectionEvents" type="checkbox" onChange="loadEventsData()">
</div>
<!-- Datatable Events -->
@@ -19,6 +19,7 @@
<thead>
<tr>
<th><?= lang("DevDetail_Tab_EventsTableDate");?></th>
<th><?= lang("DevDetail_Tab_EventsTableDate");?></th>
<th><?= lang("DevDetail_Tab_EventsTableEvent");?></th>
<th><?= lang("DevDetail_Tab_EventsTableIP");?></th>
<th><?= lang("DevDetail_Tab_EventsTableInfo");?></th>
@@ -29,66 +30,135 @@
<script>
var eventsRows = 10;
var eventsHide = true;
var parEventsRows = 'Front_Details_Events_Rows';
var parEventsHide = 'Front_Details_Events_Hide';
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
function loadEventsData() {
const hideConnections = $('#chkHideConnectionEvents')[0].checked;
const hideConnectionsStr = hideConnections ? 'true' : 'false';
function loadEventsData() {
// Define Events datasource and query dada
hideConnections = $('#chkHideConnectionEvents')[0].checked;
$('#tableEvents').DataTable().ajax.url('php/server/events.php?action=getDeviceEvents&mac=' + mac +'&period='+ period +'&hideConnections='+ hideConnections).load();
}
mac = getMac()
function initializeSessionsDatatable () {
const rawSql = `
SELECT eve_DateTime, eve_DateTime, eve_EventType, eve_IP, eve_AdditionalInfo
FROM Events
WHERE eve_MAC = "${mac}"
AND (
(eve_EventType NOT IN ("Connected", "Disconnected", "VOIDED - Connected", "VOIDED - Disconnected"))
OR "${hideConnectionsStr}" = "false"
)
`;
// Events datatable
$('#tableEvents').DataTable({
'paging' : true,
'lengthChange': true,
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
'searching' : true,
'ordering' : true,
'info' : true,
'autoWidth' : false,
'order' : [[0,'desc']],
const apiUrl = `php/server/dbHelper.php?action=read&rawSql=${btoa(encodeURIComponent(rawSql))}`;
// Parameters
'pageLength' : eventsRows,
// Manually load the data first
$.get(apiUrl, function (data) {
const parsed = JSON.parse(data);
const rows = parsed.map(row => {
const rawDate = row.eve_DateTime;
const formattedDate = rawDate ? localizeTimestamp(rawDate) : '-';
return [
formattedDate,
row.eve_DateTime,
row.eve_EventType,
row.eve_IP,
row.eve_AdditionalInfo
];
});
'columnDefs' : [
// Replace HTML codes
{targets: [0],
'createdCell': function (td, cellData, rowData, row, col) {
$(td).html (translateHTMLcodes (localizeTimestamp(cellData)));
} }
],
// Processing
'processing' : true,
'language' : {
processing: '<table><td width="130px" align="middle"><?= lang("DevDetail_Loading");?></td>'+
'<td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw">'+
'</td></table>',
emptyTable: 'No data',
"lengthMenu": "<?= lang('Events_Tablelenght');?>",
"search": "<?= lang('Events_Searchbox');?>: ",
"paginate": {
"next": "<?= lang('Events_Table_nav_next');?>",
"previous": "<?= lang('Events_Table_nav_prev');?>"
},
"info": "<?= lang('Events_Table_info');?>",
}
});
// Fill the table manually
const table = $('#tableEvents').DataTable();
table.clear();
table.rows.add(rows); // assuming each row is an array
table.draw();
hideSpinner();
});
}
initializeSessionsDatatable();
loadEventsData();
function initializeEventsDatatable (eventsRows) {
if ($.fn.dataTable.isDataTable('#tableEvents')) {
$('#tableEvents').DataTable().clear().destroy();
}
$('#tableEvents').DataTable({
'paging' : true,
'lengthChange': true,
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
'searching' : true,
'ordering' : true,
'info' : true,
'autoWidth' : false,
'order' : [[0,'desc']],
'pageLength' : eventsRows,
'columnDefs' : [
{ orderData: [1], targets: [0] },
{ visible: false, targets: [1] },
{
targets: [0],
'createdCell': function (td, cellData, rowData, row, col) {
$(td).html(translateHTMLcodes(localizeTimestamp(cellData)));
}
}
],
'processing' : true,
'language' : {
processing: '<table><td width="130px" align="middle"><?= lang("DevDetail_Loading");?></td>'+
'<td><i class="fa-solid fa-spinner fa-spin-pulse"></i></td></table>',
emptyTable: 'No data',
"lengthMenu": "<?= lang('Events_Tablelenght');?>",
"search": "<?= lang('Events_Searchbox');?>: ",
"paginate": {
"next": "<?= lang('Events_Table_nav_next');?>",
"previous": "<?= lang('Events_Table_nav_prev');?>"
},
"info": "<?= lang('Events_Table_info');?>",
}
});
}
// -----------------------------------------------
// INIT with polling for panel element visibility
// -----------------------------------------------
var eventsPageInitialized = false;
function initDeviceEventsPage()
{
// Only proceed if .plugin-content is visible
if (!$('#panEvents:visible').length) {
return; // exit early if nothing is visible
}
// init page once
if (eventsPageInitialized) return; // ENSURE ONCE
eventsPageInitialized = true;
showSpinner();
var eventsRows = 10;
var eventsHide = true;
initializeEventsDatatable(eventsRows);
loadEventsData();
}
// -----------------------------------------------------------------------------
// Recurring function to monitor the URL and reinitialize if needed
function deviceEventsPageUpdater() {
initDeviceEventsPage();
// Run updater again after delay
setTimeout(deviceEventsPageUpdater, 200);
}
deviceEventsPageUpdater();
</script>

View File

@@ -23,8 +23,6 @@
<script>
initializeCalendar();
loadPresenceData();
// Force re-render calendar on tab change
// (bugfix for render error at left panel)
@@ -234,6 +232,37 @@ function initializeCalendar() {
})
}
// -----------------------------------------------
// INIT with polling for panel element visibility
// -----------------------------------------------
var presencePageInitialized = false;
function initDevicePresencePage() {
// Only proceed if the Presence tab is visible
if (!$('#panPresence:visible').length) {
return; // Exit early if nothing is visible
}
// Ensure initialization only happens once
if (presencePageInitialized) return;
presencePageInitialized = true;
showSpinner();
initializeCalendar();
loadPresenceData();
}
// Recurring check to initialize when visible
function devicePresencePageUpdater() {
initDevicePresencePage();
setTimeout(devicePresencePageUpdater, 200);
}
devicePresencePageUpdater();
</script>

View File

@@ -24,77 +24,126 @@
<script>
var parSessionsRows = 'Front_Details_Sessions_Rows';
function initializeSessionsDatatable (sessionsRows) {
// Sessions datatable
$('#tableSessions').DataTable({
'paging' : true,
'lengthChange': true,
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
'searching' : true,
'ordering' : true,
'info' : true,
'autoWidth' : false,
'order' : [[0,'desc'], [1,'desc']],
// Parameters
'pageLength' : sessionsRows,
'columnDefs' : [
{visible: false, targets: [0]},
// Replace HTML codes
{targets: [3,5],
'createdCell': function (td, cellData, rowData, row, col) {
$(td).html (translateHTMLcodes (cellData));
} },
// Date
{targets: [1,2],
"createdCell": function (td, cellData, rowData, row, col) {
// console.log(cellData);
if (!cellData.includes("missing event") && !cellData.includes("..."))
{
if (cellData.includes("+")) { // Check if timezone offset is present
cellData = cellData.split('+')[0]; // Remove timezone offset
}
// console.log(cellData);
result = localizeTimestamp(cellData);
} else
{
result = translateHTMLcodes(cellData)
}
$(td).html (result);
} }
],
// Processing
'processing' : true,
'language' : {
processing: '<table><td width="130px" align="middle"><?= lang("DevDetail_Loading");?></td>'+
'<td><i class="fa-solid fa-spinner fa-spin-pulse"></i>'+
'</td></table>',
emptyTable: 'No data',
"lengthMenu": "<?= lang('Events_Tablelenght');?>",
"search": "<?= lang('Events_Searchbox');?>: ",
"paginate": {
"next": "<?= lang('Events_Table_nav_next');?>",
"previous": "<?= lang('Events_Table_nav_prev');?>"
},
"info": "<?= lang('Events_Table_info');?>",
}
});
}
// -----------------------------------------------
// INIT with polling for panel element visibility
// -----------------------------------------------
// -----------------------------------------------------------
// Init datatable
function loadSessionsData(period){
const table = $('#tableSessions').DataTable();
showSpinner();
// table.clear().draw(); // Clear existing data before reloading
table.ajax
.url('php/server/events.php?action=getDeviceSessions&mac=' + getMac() + '&period=' + period)
.load(function () {
hideSpinner();
});
}
var sessionsPageInitialized = false;
// -----------------------------------------------------------
// Main init function
function initDeviceSessionsPage()
{
// Only proceed if .plugin-content is visible
if (!$('#panSessions:visible').length) {
return; // exit early if nothing is visible
}
// init page once
if (sessionsPageInitialized) return;
sessionsPageInitialized = true;
showSpinner();
var sessionsRows = 10;
var period = '1 month';
function initializeSessionsDatatable () {
// Sessions datatable
$('#tableSessions').DataTable({
'paging' : true,
'lengthChange': true,
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, 'All']],
'searching' : true,
'ordering' : true,
'info' : true,
'autoWidth' : false,
'order' : [[0,'desc'], [1,'desc']],
initializeSessionsDatatable(sessionsRows);
loadSessionsData(period);
}
// Parameters
'pageLength' : sessionsRows,
// -----------------------------------------------------------------------------
// Recurring function to monitor the URL and reinitialize if needed
function deviceSessionsPageUpdater() {
initDeviceSessionsPage();
'columnDefs' : [
{visible: false, targets: [0]},
// Run updater again after delay
setTimeout(deviceSessionsPageUpdater, 200);
}
// Replace HTML codes
{targets: [3,5],
'createdCell': function (td, cellData, rowData, row, col) {
$(td).html (translateHTMLcodes (cellData));
} },
// Date
{targets: [1,2],
"createdCell": function (td, cellData, rowData, row, col) {
// console.log(cellData);
if (!cellData.includes("missing event") && !cellData.includes("..."))
{
if (cellData.includes("+")) { // Check if timezone offset is present
cellData = cellData.split('+')[0]; // Remove timezone offset
}
// console.log(cellData);
result = localizeTimestamp(cellData);
} else
{
result = translateHTMLcodes(cellData)
}
$(td).html (result);
} }
],
// Processing
'processing' : true,
'language' : {
processing: '<table><td width="130px" align="middle"><?= lang("DevDetail_Loading");?></td>'+
'<td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw">'+
'</td></table>',
emptyTable: 'No data',
"lengthMenu": "<?= lang('Events_Tablelenght');?>",
"search": "<?= lang('Events_Searchbox');?>: ",
"paginate": {
"next": "<?= lang('Events_Table_nav_next');?>",
"previous": "<?= lang('Events_Table_nav_prev');?>"
},
"info": "<?= lang('Events_Table_info');?>",
}
});
}
function loadSessionsData(){
$('#tableSessions').DataTable().ajax.url('php/server/events.php?action=getDeviceSessions&mac=' + getMac() +'&period='+ period).load();
}
initializeSessionsDatatable();
loadSessionsData();
// start updater
deviceSessionsPageUpdater();
</script>

View File

@@ -14,7 +14,7 @@
<?= lang("DevDetail_Tab_Tools_Internet_Info_Description") ?>
</h5>
<br>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="internetinfo()">
<?= lang("DevDetail_Tab_Tools_Internet_Info_Start") ?></button>
<br>
@@ -33,13 +33,13 @@
<?= lang("DevDetail_Copy_Device_Tooltip") ?>
</h5>
<br>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<select class="form-control"
title="<?= lang('DevDetail_Copy_Device_Tooltip');?>"
id="txtCopyFromDevice" >
<option value="lemp_loading" id="lemp_loading">Loading</option>
</select>
<button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="()">
<button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto; margin-top:10px;" onclick="copyFromDevice()">
<?= lang("BackDevDetail_Copy_Title") ?></button>
<br>
</div>
@@ -56,7 +56,7 @@
<?= lang("DevDetail_Tools_WOL_noti_text") ?>
</h5>
<br>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<button type="button" id="internetinfo" class="btn btn-primary pa-btn" style="margin: auto;" onclick="wakeonlan()">
<?= lang("DevDetail_Tools_WOL_noti") ?></button>
<br>
@@ -74,7 +74,7 @@
<?= lang("DevDetail_button_DeleteEvents_Warning") ?>
</h5>
<br>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<button type="button"
class="btn btn-default pa-btn pa-btn-delete"
style="margin-left:0px;"
@@ -94,7 +94,7 @@
<?= lang("DevDetail_CustomProps_reset_info") ?>
</h5>
<br>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<button type="button"
class="btn btn-default pa-btn pa-btn-delete"
style="margin-left:0px;"
@@ -116,7 +116,7 @@
<?= lang("DevDetail_Tab_Tools_Speedtest_Description") ?>
</h5>
<br>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<button type="button" id="speedtestcli" class="btn btn-primary pa-btn" style="margin: auto;" onclick="speedtestcli()">
<?= lang("DevDetail_Tab_Tools_Speedtest_Start") ?></button>
<br>
@@ -133,7 +133,7 @@
<h5 class="">
<?= lang("DevDetail_Tab_Tools_Traceroute_Description") ?>
</h5>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<button type="button" id="traceroute" class="btn btn-primary pa-btn" style="margin: auto;" onclick="traceroute()">
<?= lang("DevDetail_Tab_Tools_Traceroute_Start") ?>
</button>
@@ -151,7 +151,7 @@
<h5 class="">
<?= lang("DevDetail_Tab_Tools_Nslookup_Description") ?>
</h5>
<div style="width:100%; text-align: center; margin-bottom: 50px;">
<div style="width:100%; text-align: center;">
<button type="button" id="nslookup" class="btn btn-primary pa-btn" style="margin: auto;" onclick="nslookup()">
<?= lang("DevDetail_Tab_Tools_Nslookup_Start") ?>
</button>
@@ -295,7 +295,7 @@
function initCopyFromDevice() {
const devices = getVisibleDevicesList()
console.log(devices);
// console.log(devices);
const $select = $('#txtCopyFromDevice');
$select.empty(); // Clear existing options

View File

@@ -148,10 +148,7 @@ function main () {
//initialize the table headers in the correct order
var availableColumns = getSettingOptions("UI_device_columns").split(",");
headersDefaultOrder = availableColumns.map(val => getString(val));
console.log(headersDefaultOrder);
headersDefaultOrder = availableColumns.map(val => getString(val));
var selectedColumns = JSON.parse(getSetting("UI_device_columns").replace(/'/g, '"'));
@@ -266,14 +263,16 @@ function getDevicesTotals() {
function processDeviceTotals(devicesData) {
// Define filter conditions and corresponding objects
const filters = [
{ status: 'my_devices', color: 'bg-aqua', label: getString('Device_Shortcut_AllDevices'), icon: 'fa-laptop' },
{ status: 'all', color: 'bg-aqua', label: getString('Gen_All_Devices'), icon: 'fa-laptop' },
{ status: 'connected', color: 'bg-green', label: getString('Device_Shortcut_Connected'), icon: 'fa-plug' },
{ status: 'favorites', color: 'bg-yellow', label: getString('Device_Shortcut_Favorites'), icon: 'fa-star' },
{ status: 'new', color: 'bg-yellow', label: getString('Device_Shortcut_NewDevices'), icon: 'fa-plus' },
{ status: 'down', color: 'bg-red', label: getString('Device_Shortcut_DownOnly'), icon: 'fa-warning' },
{ status: 'archived', color: 'bg-gray', label: getString('Device_Shortcut_Archived'), icon: 'fa-eye-slash' },
{ status: 'offline', color: 'bg-gray', label: getString('Gen_Offline'), icon: 'fa-xmark' }
{ status: 'my_devices', color: 'bg-aqua', label: getString('Device_Shortcut_AllDevices'), icon: 'fa-laptop' },
{ status: 'all', color: 'bg-aqua', label: getString('Gen_All_Devices'), icon: 'fa-laptop' },
{ status: 'connected', color: 'bg-green', label: getString('Device_Shortcut_Connected'), icon: 'fa-plug' },
{ status: 'favorites', color: 'bg-yellow', label: getString('Device_Shortcut_Favorites'), icon: 'fa-star' },
{ status: 'new', color: 'bg-yellow', label: getString('Device_Shortcut_NewDevices'), icon: 'fa-plus' },
{ status: 'down', color: 'bg-red', label: getString('Device_Shortcut_DownOnly'), icon: 'fa-warning' },
{ status: 'archived', color: 'bg-gray', label: getString('Device_Shortcut_Archived'), icon: 'fa-eye-slash' },
{ status: 'offline', color: 'bg-gray', label: getString('Gen_Offline'), icon: 'fa-xmark' },
{ status: 'all_devices', color: 'bg-gray', label: getString('Gen_All_Devices'), icon: 'fa-laptop' },
{ status: 'network_devices', color: 'bg-aqua', label: getString('Network_Devices'), icon: 'fa-sitemap fa-rotate-270' }
];
// Initialize an empty array to store the final objects
@@ -299,13 +298,7 @@ function processDeviceTotals(devicesData) {
}
});
// Render info boxes/tile cards
console.log(getSetting('UI_hide_empty'));
console.log(dataArray);
console.log(devicesData);
// Render info boxes/tile cards
renderInfoboxes(dataArray);
}
@@ -357,8 +350,6 @@ function initFilters() {
// Clear any existing filters in the DOM
$('#columnFilters').empty();
console.log(displayedFilters);
// Ensure displayedFilters is an array and not empty
if (Array.isArray(displayedFilters) && displayedFilters.length > 0) {
$('#columnFiltersWrap').removeClass("hidden");
@@ -539,7 +530,9 @@ function mapColumnIndexToFieldName(index, tableColumnVisible) {
"devPresentLastScan",
"devAlertDown",
"devCustomProps",
"devFQDN"
"devFQDN",
"devParentRelType",
"devReqNicsOnline"
];
// console.log("OrderBy: " + columnNames[tableColumnOrder[index]]);
@@ -562,15 +555,17 @@ function initializeDatatable (status) {
// Define color & title for the status selected
switch (deviceStatus) {
case 'my_devices': tableTitle = getString('Device_Shortcut_AllDevices'); color = 'aqua'; break;
case 'connected': tableTitle = getString('Device_Shortcut_Connected'); color = 'green'; break;
case 'all': tableTitle = getString('Gen_All_Devices'); color = 'aqua'; break;
case 'favorites': tableTitle = getString('Device_Shortcut_Favorites'); color = 'yellow'; break;
case 'new': tableTitle = getString('Device_Shortcut_NewDevices'); color = 'yellow'; break;
case 'down': tableTitle = getString('Device_Shortcut_DownOnly'); color = 'red'; break;
case 'archived': tableTitle = getString('Device_Shortcut_Archived'); color = 'gray'; break;
case 'offline': tableTitle = getString('Gen_Offline'); color = 'gray'; break;
default: tableTitle = getString('Device_Shortcut_Devices'); color = 'gray'; break;
case 'my_devices': tableTitle = getString('Device_Shortcut_AllDevices'); color = 'aqua'; break;
case 'connected': tableTitle = getString('Device_Shortcut_Connected'); color = 'green'; break;
case 'all': tableTitle = getString('Gen_All_Devices'); color = 'aqua'; break;
case 'favorites': tableTitle = getString('Device_Shortcut_Favorites'); color = 'yellow'; break;
case 'new': tableTitle = getString('Device_Shortcut_NewDevices'); color = 'yellow'; break;
case 'down': tableTitle = getString('Device_Shortcut_DownOnly'); color = 'red'; break;
case 'archived': tableTitle = getString('Device_Shortcut_Archived'); color = 'gray'; break;
case 'offline': tableTitle = getString('Gen_Offline'); color = 'gray'; break;
case 'all_devices': tableTitle = getString('Gen_All_Devices'); color = 'gray'; break;
case 'network_devices': tableTitle = getString('Network_Devices'); color = 'aqua'; break;
default: tableTitle = getString('Device_Shortcut_Devices'); color = 'gray'; break;
}
// Set title and color
@@ -599,7 +594,6 @@ function initializeDatatable (status) {
}
}
// todo: dynamically filter based on status
var table = $('#tableDevices').DataTable({
"serverSide": true,
"processing": true,
@@ -650,6 +644,8 @@ function initializeDatatable (status) {
devIpLong
devCustomProps
devFQDN
devParentRelType
devReqNicsOnline
}
count
}
@@ -688,8 +684,6 @@ function initializeDatatable (status) {
return JSON.stringify(query); // Send the JSON request
},
"dataSrc": function (json) {
console.log(json);
// Set the total number of records for pagination
json.recordsTotal = json.devices.count || 0;
json.recordsFiltered = json.devices.count || 0;
@@ -725,7 +719,9 @@ function initializeDatatable (status) {
device.devPresentLastScan || "",
device.devAlertDown || "",
device.devCustomProps || "",
device.devFQDN || ""
device.devFQDN || "",
device.devParentRelType || "",
device.devReqNicsOnline || 0
];
const newRow = [];
@@ -770,17 +766,34 @@ function initializeDatatable (status) {
// Device Name and FQDN
{targets: [mapIndx(0), mapIndx(27)],
'createdCell': function (td, cellData, rowData, row, col) {
'createdCell': function (td, cellData, rowData, row, col) {
// console.log(cellData)
$(td).html ('<b class="anonymizeDev"><a href="deviceDetails.php?mac='+ rowData[mapIndx(11)] +'" class="">'+ cellData +'</a></b>');
$(td).html (
`<b class="anonymizeDev "
>
<a href="deviceDetails.php?mac=${rowData[mapIndx(11)]}" class="hover-node-info"
data-name="${cellData}"
data-ip="${rowData[mapIndx(8)]}"
data-mac="${rowData[mapIndx(11)]}"
data-vendor="${rowData[mapIndx(17)]}"
data-type="${rowData[mapIndx(2)]}"
data-firstseen="${rowData[mapIndx(6)]}"
data-lastseen="${rowData[mapIndx(7)]}"
data-relationship="${rowData[mapIndx(28)]}"
data-status="${rowData[mapIndx(10)]}"
data-present="${rowData[mapIndx(24)]}"
data-alert="${rowData[mapIndx(25)]}"
data-icon="${rowData[mapIndx(3)]}">
${cellData}
</a>
</b>`
);
} },
// Connected Devices
{targets: [mapIndx(15)],
'createdCell': function (td, cellData, rowData, row, col) {
'createdCell': function (td, cellData, rowData, row, col) {
// check if this is a network device
if(getSetting("NETWORK_DEVICE_TYPES").includes(`'${rowData[mapIndx(2)]}'`) )
{
@@ -822,7 +835,7 @@ function initializeDatatable (status) {
<a href="http://${cellData}" class="pointer" target="_blank">
${cellData}
</a>
<span class="alignRight">
<span class="alignRight lockIcon">
<a href="https://${cellData}" class="pointer" target="_blank">
<i class="fa fa-lock "></i>
</a>
@@ -893,25 +906,14 @@ function initializeDatatable (status) {
tmp_devPresentLastScan = rowData[mapIndx(24)]
tmp_devAlertDown = rowData[mapIndx(25)]
if (tmp_devPresentLastScan == 1)
{
css = "green text-white statusOnline"
icon = '<i class="fa-solid fa-plug"></i>'
} else if (tmp_devPresentLastScan != 1 && tmp_devAlertDown == 1)
{
css = "red text-white statusDown"
icon = '<i class="fa-solid fa-triangle-exclamation"></i>'
} else if(tmp_devPresentLastScan != 1)
{
css = "gray text-white statusOffline"
icon = '<i class="fa-solid fa-xmark"></i>'
} else
{
css = "gray text-white statusUnknown"
icon = '<i class="fa-solid fa-question"></i>'
}
const badge = getStatusBadgeParts(
rowData[mapIndx(24)], // tmp_devPresentLastScan
rowData[mapIndx(25)], // tmp_devAlertDown
rowData[mapIndx(11)], // MAC
cellData // optional text
);
$(td).html (`<a href="deviceDetails.php?mac=${rowData[mapIndx(11)]}" class="badge bg-${css}">${icon} ${cellData.replace('-', '')}</a>`);
$(td).html (`<a href="${badge.url}" class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.text}</a>`);
} },
],
@@ -970,7 +972,7 @@ function initializeDatatable (status) {
}, debounceTime);
});
initHoverNodeInfo();
hideSpinner();
},
@@ -1035,40 +1037,24 @@ function multiEditDevices()
// -----------------------------------------------------------------------------
// Function collects shown devices from the DataTable
function getMacsOfShownDevices() {
rows = $('#tableDevices')[0].rows;
macs = [];
var table = $('#tableDevices').DataTable();
// var devicesDataTableData = $('#tableDevices').dataTable().fnGetData();
var devicesDataTableData = $('#tableDevices').DataTable().rows({ selected: false, page: 'current' }).data().toArray();
var macs = [];
console.log(devicesDataTableData);
// Get all row indexes on current page, in display order
var allIndexes = table.rows({ page: 'current' }).indexes();
var selectedDevices = [];
// first row is the heading, skip
for (var i = 1; i < rows.length; i++) {
var rowIndex = rows[i]._DT_RowIndex;
// Ensure the rowIndex is valid and within bounds of devicesDataTableData
if (rowIndex >= 0 && rowIndex < devicesDataTableData.length) {
selectedDevices.push(devicesDataTableData[rowIndex]);
} else {
console.log(`Invalid rowIndex: ${rowIndex} at row ${i}`);
allIndexes.each(function(idx) {
var rowData = table.row(idx).data();
if (rowData) {
macs.push(rowData[mapIndx(11)]); // mapIndx(11) == MAC column
}
}
for (var j = 0; j < selectedDevices.length; j++) {
// Ensure that selectedDevices[j] is not undefined
if (selectedDevices[j]) {
macs.push(selectedDevices[j][mapIndx(11)]); // mapIndx(11) == MAC
} else {
console.log(`selectedDevices[${j}] is undefined`);
}
}
});
return macs;
}
// -----------------------------------------------------------------------------
// Handle custom actions/properties on a device
function renderCustomProps(custProps, mac) {

View File

@@ -2,6 +2,10 @@
require 'php/templates/header.php';
?>
<script>
showSpinner();
</script>
<!-- ----------------------------------------------------------------------- -->
<!-- Page ------------------------------------------------------------------ -->
@@ -67,7 +71,7 @@
<div class="inner"> <h3 id="eventsNewDevices"> -- </h3>
<p class="infobox_label"><?= lang('Events_Shortcut_NewDevices');?></p>
</div>
<div class="icon"> <i class="ion ion-plus-round text-yellow-40"></i> </div>
<div class="icon"> <i class="fa-solid fa-circle-plus text-yellow-40"></i> </div>
</div>
</a>
</div>
@@ -238,7 +242,7 @@ function initializeDatatable () {
// Processing
'processing' : true,
'language' : {
processing: '<table><td width="130px" align="middle"><?= lang("Events_Loading");?></td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td></table>',
processing: '<table><td width="130px" align="middle"><?= lang("Events_Loading");?></td><td><i class="fa-solid fa-spinner fa-spin-pulse"></i></td></table>',
emptyTable: 'No data',
"lengthMenu": "<?= lang('Events_Tablelenght');?>",
"search": "<?= lang('Events_Searchbox');?>: ",
@@ -247,6 +251,9 @@ function initializeDatatable () {
"previous": "<?= lang('Events_Table_nav_prev');?>"
},
"info": "<?= lang('Events_Table_info');?>",
},
initComplete: function(settings, json) {
hideSpinner(); // Called after the DataTable is fully initialized
}
});

View File

@@ -99,18 +99,6 @@ if (isset ($_SESSION["login"]) == FALSE || $_SESSION["login"] != 1)
<!-- Favicon -->
<link id="favicon" rel="icon" type="image/x-icon" href="img/NetAlertX_logo.png">
<!-- Dark-Mode Patch -->
<?php
switch ($UI_THEME) {
case "Dark":
echo '<link rel="stylesheet" href="css/dark-patch.css">';
break;
case "System":
echo '<link rel="stylesheet" href="css/system-dark-patch.css">';
break;
}
?>
<link rel="stylesheet" href="/css/offline-font.css">
</head>
<body class="hold-transition login-page col-sm-12 col-sx-12">

View File

@@ -362,18 +362,64 @@ function getLangCode() {
// -----------------------------------------------------------------------------
// String utilities
// -----------------------------------------------------------------------------
function localizeTimestamp(input) {
let tz = getSetting("TIMEZONE") || 'Europe/Berlin';
// Convert to string and trim
input = String(input || '').trim();
function localizeTimestamp(result)
{
// contains TZ in format Europe/Berlin
tz = getSetting("TIMEZONE")
// Normalize multiple spaces and remove commas
const cleaned = input.replace(',', ' ').replace(/\s+/g, ' ');
// set default if not available or app still loading
tz == "" ? tz = 'Europe/Berlin' : tz = tz;
const date = new Date(result); // Assumes result is a timestamp or ISO string
const formatter = new Intl.DateTimeFormat('default', {
// DD/MM/YYYY format check
const dateTimeParts = cleaned.split(' ');
if (dateTimeParts.length >= 2 && dateTimeParts[0].includes('/')) {
const [day, month, year] = dateTimeParts[0].split('/');
const timePart = dateTimeParts[1];
if (day && month && year && timePart) {
const isoString = `${year}-${month}-${day}T${timePart.length === 5 ? timePart + ':00' : timePart}`;
const date = new Date(isoString);
if (!isFinite(date)) return 'b-';
return new Intl.DateTimeFormat('default', {
timeZone: tz,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
}).format(date);
}
}
// ISO style YYYY-MM-DD HH:mm(:ss)?
const match = cleaned.match(/^(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2})(:\d{2})?$/);
if (match) {
let iso = `${match[1]}T${match[2]}${match[3] || ':00'}`;
const date = new Date(iso);
if (!isFinite(date)) return 'c-';
return new Intl.DateTimeFormat('default', {
timeZone: tz,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
}).format(date);
}
// Fallback: try to parse any other string input
const date = new Date(input);
if (!isFinite(date)) return 'Failed conversion: ' + input;
return new Intl.DateTimeFormat('default', {
timeZone: tz,
year: 'numeric',
month: '2-digit',
@@ -381,12 +427,12 @@ function localizeTimestamp(result)
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false // change to true if you want AM/PM format
});
return formatter.format(date);
hour12: false
}).format(date);
}
// ----------------------------------------------------
/**
* Replaces double quotes within single-quoted strings, then converts all single quotes to double quotes,
@@ -993,11 +1039,8 @@ function getDevDataByMac(macAddress, dbColumn) {
// Cache the devices as one JSON
function cacheDevices()
{
return new Promise((resolve, reject) => {
// if(!getCache('completedCalls').includes('cacheDevices'))
// {
$.get('php/server/query_json.php', { file: 'table_devices.json', nocache: Date.now() }, function(data) {
// console.log(data)
@@ -1021,8 +1064,7 @@ function cacheDevices()
// console.log(getCache('devicesListAll_JSON'))
}).then(() => handleSuccess('cacheDevices', resolve())).catch(() => handleFailure('cacheDevices', reject("cacheDevices already completed"))); // handle AJAX synchronization
}
// }
);
);
}
var devicesListAll_JSON = []; // this will contain a list off all devices
@@ -1063,47 +1105,48 @@ function getGuid() {
// -----------------------------------------------------------------------------
// Loading Spinner overlay
// -----------------------------------------------------------------------------
spinnerHtml = `
<!-- spinner -->
<div id="loadingSpinner" style="display: block">
<div class="pa_semitransparent-panel"></div>
<div class="panel panel-default pa_spinner">
<table>
<td width="130px" align="middle">_text_</td>
<td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td>
</table>
</div>
</div>
`
function showSpinner(stringKey='Loading')
{
let spinnerTimeout = null;
let animationTime = 300
if(stringKey == "")
{
text = ''
} else
{
text = getString(stringKey)
}
function showSpinner(stringKey = 'Loading') {
const text = isEmpty(stringKey) ? "Loading" : getString(stringKey || "Loading");
const spinner = $("#loadingSpinner");
if (spinner.length && spinner.is(':visible')) {
clearTimeout(spinnerTimeout);
$("#loadingSpinnerText").text(text);
spinner.addClass("visible");
text = isEmpty(text) ? "Loading" : text;
spinner.fadeIn(animationTime);
} else {
$("#loadingSpinnerText").text(text);
if($("#loadingSpinner").length)
{
$("#loadingSpinner").show();
}
else{
$(".wrapper").append(spinnerHtml.replace('_text_',text))
requestAnimationFrame(() => {
spinner.addClass("visible");
spinner.fadeIn(animationTime);
});
}
}
// -----------------------------------------------------------------------------
function hideSpinner()
{
$("#loadingSpinner").hide()
function hideSpinner() {
clearTimeout(spinnerTimeout);
const spinner = $("#loadingSpinner");
if (spinner.length) {
spinner.removeClass("visible");
spinner.fadeOut(animationTime);
spinnerTimeout = setTimeout(() => {
spinner.removeClass("visible");
spinner.fadeOut(animationTime); // optional remove or hide again
}, 300);
}
}
// --------------------------------------------------------
// Calls a backend function to add a front-end event to an execution queue
function updateApi(apiEndpoints)

View File

@@ -363,8 +363,6 @@ function removeAllOptions(element) {
function selectAll(element) {
settingsChanged();
// Get the <select> element with the class 'deviceSelector'
// var selectElement = $('.deviceSelector select');
var selectElement = $(`#${$(element).attr("my-input-to")}`);
// Iterate over each option within the select element
@@ -381,8 +379,6 @@ function selectAll(element) {
// UN-Select All
function unselectAll(element) {
settingsChanged();
// Get the <select> element with the class 'deviceSelector'
// var selectElement = $('.deviceSelector select');
var selectElement = $(`#${$(element).attr("my-input-to")}`);
// Iterate over each option within the select element
@@ -399,8 +395,7 @@ function unselectAll(element) {
// Trigger change to open up the dropdown filed
function selectChange(element) {
settingsChanged();
// Get the <select> element with the class 'deviceSelector'
// var selectElement = $('.deviceSelector select');
var selectElement = $(`#${$(element).attr("my-input-to")}`);
selectElement.parent().find("input").focus().click();
@@ -624,6 +619,7 @@ function generateOptionsOrSetOptions(
// console.log( setKey);
// NOTE {value} options to replace with a setting or SQL value are handled in the cacheSettings() function
// obj.push({ id: item, name: item })
options = arrayToObject(createArray(overrideOptions ? overrideOptions : getSettingOptions(setKey)))
@@ -689,6 +685,13 @@ function reverseTransformers(val, transformers) {
// retrieve string
val = getString(val);
break;
case "deviceChip":
mac = val // value is mac
val = `${getDevDataByMac(mac, "devName")}`
break;
case "deviceRelType":
val = val; // nothing to do
break;
default:
console.warn(`Unknown transformer: ${transformer}`);
}
@@ -822,13 +825,14 @@ function arrayToObject(array) {
// -----------------------------------------------------------------------------
// Processor to generate options
// options - available options
// valuesArray - values = selected options
function generateOptions(options, valuesArray, targetField, transformers, placeholder) {
var optionsHtml = "";
resultArray = []
selectedArray = []
cssClass = ""
cssClass = ""
// determine if options or values are used in the listing
if (valuesArray.length > 0 && options.length > 0){
@@ -847,7 +851,6 @@ function generateOptions(options, valuesArray, targetField, transformers, placeh
// dropdown -> options only (value == 1 STRING not ARRAY)
resultArray = options;
}
// Create a map to track the index of each item in valuesArray
const orderMap = new Map(valuesArray.map((item, index) => [item, index]));
@@ -1007,10 +1010,12 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
class="form-control ${addCss} ${cssClasses}"
name="${setKey}"
id="${setKey}"
my-transformers=${transformers}
my-customparams="${customParams}"
my-customid="${customId}"
my-originalSetKey="${originalSetKey}"
${multi}>
${multi}
${readOnly ? "disabled" : ""}>
<option value="" id="${setKey + "_temp_"}"></option>
</select>`;
@@ -1188,22 +1193,49 @@ function generateFormHtml(settingsData, set, overrideValue, overrideOptions, ori
const eventsList = createArray(set['setEvents']);
// inline buttons events
if (eventsList.length > 0) {
eventsList.forEach(event => {
let eventIcon = "fa-play";
if (eventsList.length > 0) {
eventsList.forEach(event => {
switch (event) {
case "select_icon":
eventIcon = "fa-chevron-down";
break;
case "add_icon":
case "add_option":
eventIcon = "fa-square-plus";
break;
case "copy_icons":
eventIcon = "fa-copy";
break;
case "go_to_device":
eventIcon = "fa-square-up-right";
break;
case "go_to_node":
eventIcon = "fa-sitemap fa-rotate-270";
break;
case "run":
eventIcon = "fa-play";
break;
case "test":
eventIcon = "fa-vial-circle-check";
break;
default:
eventIcon = "fa-play";
break;
}
eventsHtml += `<span class="input-group-addon pointer"
id="${`${event}_${setKey}`}"
data-myparam-setkey="${setKey}"
data-myparam="${setKey}"
data-myparam-plugin="${setKey.split('_')[0] || ''}"
data-myevent="${event}"
onclick="execute_settingEvent(this)">
<i title="${getString(event + "_event_tooltip")}" class="fa ${getString(event + "_event_icon")}"></i>
</span>`;
});
}
eventsHtml += `<span class="input-group-addon pointer"
id="${`${event}_${setKey}`}"
data-myparam-setkey="${setKey}"
data-myparam="${setKey}"
data-myparam-plugin="${setKey.split('_')[0] || ''}"
data-myevent="${event}"
onclick="execute_settingEvent(this)">
<i title="${getString(event + "_event_tooltip")}" class="fa ${eventIcon}"></i>
</span>`;
});
}
// Combine and return the final HTML
return inputHtml + eventsHtml;

View File

@@ -8,64 +8,6 @@
----------------------------------------------------------------------------- */
// -----------------------------------------------------------------------------
// Initialize device selectors / pickers fields
// -----------------------------------------------------------------------------
function initDeviceSelectors(devicesListAll_JSON) {
// Check if both device list exists
if (devicesListAll_JSON) {
// Parse the JSON string to get the device list array
var devicesList = JSON.parse(devicesListAll_JSON);
var selectorFieldsHTML = ''
// Loop through the devices list
devicesList.forEach(function(device) {
selectorFieldsHTML += `<option value="${device.devMac}">${device.devName}</option>`;
});
selector = `<div class="db_info_table_row col-sm-12" >
<div class="form-group" >
<div class="input-group col-sm-12 " >
<select class="form-control select2 select2-hidden-accessible" multiple="" style="width: 100%;" tabindex="-1" aria-hidden="true">
${selectorFieldsHTML}
</select>
</div>
</div>
</div>`
// Find HTML elements with class "deviceSelector" and append selector field
$('.deviceSelector').append(selector);
}
// Initialize selected items after a delay so selected macs are available in the context
setTimeout(function(){
// Retrieve MAC addresses from query string or cache
var macs = getQueryString('macs') || getCache('selectedDevices');
if(macs)
{
// Split MAC addresses if they are comma-separated
macs = macs.split(',');
console.log(macs)
// Loop through macs to be selected list
macs.forEach(function(mac) {
// Create the option and append to Select2
var option = new Option($('.deviceSelector select option[value="' + mac + '"]').html(), mac, true, true);
$('.deviceSelector select').append(option).trigger('change');
});
}
}, 10);
}
// -------------------------------------------------------------------
// Utility function to generate a random API token in the format t_<random string of specified length>
@@ -128,9 +70,6 @@ function getRandomBytes(elem, length) {
targetElement.val(formattedHex);
}
// ----------------------------------------------
// Updates the icon preview
function updateAllIconPreviews() {
@@ -342,6 +281,7 @@ function execute_settingEvent(element) {
feSetKey = $(element).attr('data-myparam-setkey');
feParam = $(element).attr('data-myparam');
feSourceId = $(element).attr('id');
feValue = $("#"+feSetKey).val();
if (["test", "run"].includes(feEvent)) {
// Calls a backend function to add a front-end event (specified by the attributes 'data-myevent' and 'data-myparam-plugin' on the passed element) to an execution queue
@@ -383,8 +323,12 @@ function execute_settingEvent(element) {
() => addIconAsBase64(element), // Wrap in an arrow function
feSourceId // triggered by id
);
} else if (["copy_icons"].includes(feEvent)) {
} else if (["select_icon"].includes(feEvent)) {
showIconSelection(feSetKey)
// myparam-setkey
} else if (["copy_icons"].includes(feEvent)) {
// Ask overwrite icon types
showModalWarning (
@@ -394,9 +338,12 @@ function execute_settingEvent(element) {
getString('Gen_Okay'),
'overwriteIconType'
);
} else if (["go_to_node"].includes(feEvent)) {
} else if (["go_to_device"].includes(feEvent)) {
goToNetworkNode('NEWDEV_devParentMAC');
goToDevice(feValue);
} else if (["go_to_node"].includes(feEvent)) {
goToNetworkNode(feValue);
} else {
console.warn(`🔺Not implemented: ${feEvent}`)
@@ -408,12 +355,24 @@ function execute_settingEvent(element) {
// -----------------------------------------------------------------------------
// Go to the correct network node in the Network section
function goToNetworkNode(dropdownId)
{
setCache('activeNetworkTab', $('#'+dropdownId).val().replaceAll(":","_")+'_id');
function goToNetworkNode(mac)
{
setCache('activeNetworkTab', mac.replaceAll(":","_")+'_id');
window.location.href = './network.php';
}
// -----------------------------------------------------------------------------
// Go to the device
function goToDevice(mac, newtab = false) {
const url = './deviceDetails.php?mac=' + encodeURIComponent(mac);
if (newtab) {
window.open(url, '_blank');
} else {
window.location.href = url;
}
}
// --------------------------------------------------------
@@ -494,10 +453,11 @@ function addIconAsBase64 (el) {
}
// -----------------------------------------------
// modal pop up for icon selection
function showIconSelection(setKey) {
function showIconSelection() {
const selectElement = document.getElementById('NEWDEV_devIcon');
const selectElement = document.getElementById(setKey);
const modalId = 'dynamicIconModal';
// Create modal HTML dynamically
@@ -574,19 +534,9 @@ function showIconSelection() {
}
// "Device_TableHead_Owner",
// "Device_TableHead_Type",
// "Device_TableHead_Group",
// "Device_TableHead_Status",
// "Device_TableHead_Location",
// "Device_TableHead_Vendor",
// "Device_TableHead_SyncHubNodeName",
// "Device_TableHead_NetworkSite",
// "Device_TableHead_SSID",
// "Device_TableHead_SourcePlugin"
// -----------------------------------------------------------------------------
// Get teh correct db column code name based on table header title string
// Get the correct db column code name based on table header title string
function getColumnNameFromLangString(headStringKey) {
columnNameMap = {
"Device_TableHead_Name": "devName",
@@ -615,12 +565,96 @@ function getColumnNameFromLangString(headStringKey) {
"Device_TableHead_SourcePlugin": "devSourcePlugin",
"Device_TableHead_PresentLastScan": "devPresentLastScan",
"Device_TableHead_AlertDown": "devAlertDown",
"Device_TableHead_CustomProps": "devCustomProps"
"Device_TableHead_CustomProps": "devCustomProps",
"Device_TableHead_FQDN": "devFQDN",
"Device_TableHead_ParentRelType": "devParentRelType",
"Device_TableHead_ReqNicsOnline": "devReqNicsOnline"
};
return columnNameMap[headStringKey] || "";
}
//--------------------------------------------------------------
// Generating the device status chip
function getStatusBadgeParts(devPresentLastScan, devAlertDown, devMac, statusText = '') {
let css = 'bg-gray text-white statusUnknown';
let icon = '<i class="fa-solid fa-question"></i>';
let status = 'unknown';
let cssText = '';
if (devPresentLastScan == 1) {
css = 'bg-green text-white statusOnline';
cssText = 'text-green';
icon = '<i class="fa-solid fa-plug"></i>';
status = 'online';
} else if (devAlertDown == 1) {
css = 'bg-red text-white statusDown';
cssText = 'text-red';
icon = '<i class="fa-solid fa-triangle-exclamation"></i>';
status = 'down';
} else if (devPresentLastScan != 1) {
css = 'bg-gray text-white statusOffline';
cssText = 'text-gray50';
icon = '<i class="fa-solid fa-xmark"></i>';
status = 'offline';
}
const cleanedText = statusText.replace(/-/g, '');
const url = `deviceDetails.php?mac=${encodeURIComponent(devMac)}`;
return {
cssClass: css,
cssText: cssText,
iconHtml: icon,
mac: devMac,
text: cleanedText,
status: status,
url: url
};
}
//--------------------------------------------------------------
// Getting the color and css class for device relationships
function getRelationshipConf(relType) {
let cssClass = '';
let color = '';
// --color-aqua: #00c0ef;
// --color-blue: #0060df;
// --color-green: #00a65a;
// --color-yellow: #f39c12;
// --color-red: #dd4b39;
switch (relType) {
case "child":
color = "#f39c12"; // yellow
cssClass = "text-yellow";
break;
case "nic":
color = "#dd4b39"; // red
cssClass = "text-red";
break;
case "virtual":
color = "#0060df"; // blue
cssClass = "text-blue";
break;
case "logical":
color = "#00a65a"; // green
cssClass = "text-green";
break;
default:
color = "#5B5B66"; // grey
cssClass = "text-light-grey";
break;
}
return {
cssClass: cssClass,
color: color
};
}
// -----------------------------------------------------------------------------
// initialize
@@ -634,17 +668,90 @@ function initSelect2() {
// check if cache ready
if(isValidJSON(devicesListAll_JSON))
{
// prepare HTML DOM before initializing the frotend
initDeviceSelectors(devicesListAll_JSON)
// --------------------------------------------------------
//Initialize Select2 Elements and make them sortable
$(function () {
// Iterate over each Select2 dropdown
$('.select2').each(function() {
var selectEl = $(this).select2();
$('.select2').each(function() {
// handle Device chips, if my-transformers="deviceChip"
if($(this).attr("my-transformers") == "deviceChip")
{
var selectEl = $(this).select2({
templateSelection: function (data, container) {
if (!data.id) return data.text; // default for placeholder etc.
const device = getDevDataByMac(data.id);
const badge = getStatusBadgeParts(
device.devPresentLastScan,
device.devAlertDown,
device.devMac
)
$(container).addClass(badge.cssClass);
// Custom HTML
const html = $(`
<a href="${badge.url}" target="_blank">
<span class="custom-chip hover-node-info"
data-name="${device.devName}"
data-ip="${device.devLastIP}"
data-mac="${device.devMac}"
data-vendor="${device.devVendor}"
data-type="${device.devType}"
data-lastseen="${device.devLastConnection}"
data-firstseen="${device.devFirstConnection}"
data-relationship="${device.devParentRelType}"
data-status="${device.devStatus}"
data-present="${device.devPresentLastScan}"
data-alert="${device.devAlertDown}"
data-icon="${device.devIcon}"
>
<span class="iconPreview">${atob(device.devIcon)}</span>
${data.text}
<span>
(${badge.iconHtml})
</span
</span>
</a>
`);
return html;
},
escapeMarkup: function (m) {
return m; // Allow HTML
}
});
} else if($(this).attr("my-transformers") == "deviceRelType") // handling dropdown for relationships
{
var selectEl = $(this).select2({
minimumResultsForSearch: Infinity,
templateSelection: function (data, container) {
if (!data.id) return data.text; // default for placeholder etc.
const relConf = getRelationshipConf(data.text);
// Custom HTML
const html = $(`
<span class="custom-chip ${relConf.cssClass}" >
${data.text}
</span>
`);
return html;
},
escapeMarkup: function (m) {
return m; // Allow HTML
}
});
} else // default handling - default template
{
var selectEl = $(this).select2();
}
// Apply sortable functionality to the dropdown's dropdown-container
selectEl.next().children().children().children().sortable({
@@ -675,14 +782,127 @@ function initSelect2() {
}
}
// init functions after dom loaded
window.addEventListener("load", function() {
// try to initialize
setTimeout(() => {
initSelect2()
// initializeiCheck();
}, 1000);
});
// ------------------------------------------
// Display device info on hover (attach only once)
function initHoverNodeInfo() {
if ($('#hover-box').length === 0) {
$('<div id="hover-box"></div>').appendTo('body').hide().css({
position: 'absolute',
zIndex: 9999,
border: '1px solid #ccc',
borderRadius: '8px',
padding: '10px',
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
minWidth: '200px',
maxWidth: '300px',
fontSize: '14px',
pointerEvents: 'none',
backgroundColor: '#fff'
});
}
// check if handlers already attached to prevent flickering
if (initHoverNodeInfo._handlersAttached) return;
initHoverNodeInfo._handlersAttached = true;
let hoverTimeout = null;
let lastTarget = null;
// remove title as it's replaced by the hover-box
$(document).on('mouseover', '.hover-node-info', function () {
this.removeAttribute('title');
$(this).attr("title", ""); // remove title as it's replaced by the hover-box
});
$(document).on('mouseenter', '.hover-node-info', function (e) {
const $el = $(this);
lastTarget = this;
// use timeout to prevent a quick hover and exit toi flash a card when navigating to a target node with your mouse
clearTimeout(hoverTimeout);
hoverTimeout = setTimeout(() => {
if (lastTarget !== this) return;
const icon = $el.data('icon');
const name = $el.data('name') || 'Unknown';
const ip = $el.data('ip') || 'N/A';
const mac = $el.data('mac') || 'N/A';
const vendor = $el.data('vendor') || 'Unknown';
const type = $el.data('type') || 'Unknown';
const lastseen = $el.data('lastseen') || 'Unknown';
const firstseen = $el.data('firstseen') || 'Unknown';
const relationship = $el.data('relationship') || 'Unknown';
const badge = getStatusBadgeParts( $el.data('present'), $el.data('alert'), $el.data('mac'))
const status =`<span class="badge ${badge.cssClass}">${badge.iconHtml} ${badge.status}</span>`
const html = `
<div>
<b> <div class="iconPreview">${atob(icon)}</div> </b><b class="devName"> ${name}</b><br>
</div>
<hr/>
<div class="line">
<b>Status:</b> <span>${status}</span><br>
</div>
<div class="line">
<b>IP:</b> <span>${ip}</span><br>
</div>
<div class="line">
<b>MAC:</b> <span>${mac}</span><br>
</div>
<div class="line">
<b>Vendor:</b> <span>${vendor}</span><br>
</div>
<div class="line">
<b>Type:</b> <span>${type}</span><br>
</div>
<div class="line">
<b>First seen:</b> <span>${firstseen}</span><br>
</div>
<div class="line">
<b>Last seen:</b> <span>${lastseen}</span><br>
</div>
<div class="line">
<b>Relationship:</b> <span class="${getRelationshipConf(relationship).cssClass}">${relationship}</span>
</div>
`;
$('#hover-box').html(html).fadeIn(150);
}, 300);
});
$(document).on('mousemove', '.hover-node-info', function (e) {
const hoverBox = $('#hover-box');
const boxWidth = hoverBox.outerWidth();
const boxHeight = hoverBox.outerHeight();
const padding = 15;
const winWidth = $(window).width();
const winHeight = $(window).height();
let left = e.pageX + padding;
let top = e.pageY + padding;
// Position leftward if close to right edge
if (e.pageX + boxWidth + padding > winWidth) {
left = e.pageX - boxWidth - padding;
}
// Position upward if close to bottom edge
if (e.pageY + boxHeight + padding > winHeight) {
top = e.pageY - boxHeight - padding;
}
hoverBox.css({ top: top + 'px', left: left + 'px' });
});
$(document).on('mouseleave', '.hover-node-info', function () {
clearTimeout(hoverTimeout);
lastTarget = null;
$('#hover-box').fadeOut(100);
});
}
console.log("init ui_components.js")

Binary file not shown.

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 326 KiB

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

Binary file not shown.

BIN
front/lib/fonts/ionicons.woff2 Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -17,18 +17,21 @@
<h3 class="box-title"><?= lang('Gen_Selected_Devices');?></h3>
</div>
<div class="deviceSelector col-md-11 col-sm-11" style="z-index:5"></div>
<div class="col-md-1">
<button type="button" class="btn btn-default col-md-12" onclick="markAllSelected()" title="<?= lang('Gen_Add_All');?>">
<i class="fa-solid fa-circle-check"></i>
</button>
<button type="button" class="btn btn-default col-md-12" onclick="markAllNotSelected()" title="<?= lang('Gen_Remove_All');?>">
<i class="fa-solid fa-circle-xmark"></i>
</button>
<div class="deviceSelector col-md-11 col-sm-11" style="z-index:5">
<div class="db_info_table_row col-sm-12" >
<div class="form-group" >
<div class="input-group col-sm-12 " >
<select class="form-control select2 select2-hidden-accessible" multiple="" style="width: 100%;" tabindex="-1" aria-hidden="true">
</select>
</div>
</div>
</div>
</div>
<div class="col-md-1 hoverHighlight">
<i class="fa-solid fa-circle-check hoverHighlight pointer" onclick="markAllSelected()" title="<?= lang('Gen_Add_All');?>"></i>
<i class="fa-solid fa-circle-xmark hoverHighlight pointer" onclick="markAllNotSelected()" title="<?= lang('Gen_Remove_All');?>"></i>
</div>
</div>
@@ -77,7 +80,7 @@
settingsData = res["data"];
excludedColumns = ["NEWDEV_devMac", "NEWDEV_devFirstConnection", "NEWDEV_devLastConnection", "NEWDEV_devLastNotification", "NEWDEV_devScan", "NEWDEV_devPresentLastScan", "NEWDEV_devCustomProps" ]
excludedColumns = ["NEWDEV_devMac", "NEWDEV_devFirstConnection", "NEWDEV_devLastConnection", "NEWDEV_devLastNotification", "NEWDEV_devScan", "NEWDEV_devPresentLastScan", "NEWDEV_devCustomProps", "NEWDEV_devChildrenNicsDynamic", "NEWDEV_devChildrenDynamic" ]
const relevantColumns = settingsData.filter(set =>
set.setGroup === "NEWDEV" &&
@@ -208,13 +211,64 @@
generateSimpleForm(relevantColumns);
initSelect2();
initDeviceSelectors();
})
}, 500);
}, 100);
}
// -----------------------------------------------------------------------------
// Initialize device selectors / pickers fields
function initDeviceSelectors() {
// Parse device list
devicesList = JSON.parse(getCache('devicesListAll_JSON'));
// Check if the device list exists and is an array
if (Array.isArray(devicesList)) {
const $select = $(".deviceSelector select");
$select.append(
devicesList
.filter(d => d.devMac && d.devName)
.map(d => `<option value="${d.devMac}">${d.devName}</option>`)
.join('')
).trigger('change');
}
// Initialize selected items after a delay so selected macs are available in the context
setTimeout(function(){
// Retrieve MAC addresses from query string or cache
var macs = getQueryString('macs') || getCache('selectedDevices');
if(macs)
{
// Split MAC addresses if they are comma-separated
macs = macs.split(',');
console.log(macs)
// Loop through macs to be selected list
macs.forEach(function(mac) {
// Create the option and append to Select2
var option = new Option($('.deviceSelector select option[value="' + mac + '"]').html(), mac, true, true);
$('.deviceSelector select').append(option).trigger('change');
});
}
}, 10);
}
// -----------------------------------------------------------------------------
// Get selected devices Macs

File diff suppressed because it is too large Load Diff

View File

@@ -63,7 +63,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
}
if (isset ($_REQUEST['rawSql'])) {
$rawSql = urldecode(base64_decode($_REQUEST['rawSql']));
$rawSql = urldecode(base64_decode($_REQUEST['rawSql'])); // base64 encoded SQL
}
if (isset ($_REQUEST['dbtable'])) {

View File

@@ -26,7 +26,7 @@
if (isset ($_REQUEST['action']) && !empty ($_REQUEST['action'])) {
$action = $_REQUEST['action'];
switch ($action) {
case 'getServerDeviceData': getServerDeviceData(); break;
case 'getServerDeviceData': getServerDeviceData(); break;
case 'setDeviceData': setDeviceData(); break;
case 'deleteDevice': deleteDevice(); break;
case 'deleteAllWithEmptyMACs': deleteAllWithEmptyMACs(); break;
@@ -45,8 +45,7 @@
case 'ImportCSV': ImportCSV(); break;
case 'getDevicesTotals': getDevicesTotals(); break;
case 'getDevicesList': getDevicesList(); break;
case 'getDevicesListCalendar': getDevicesListCalendar(); break;
case 'getDevicesListCalendar': getDevicesListCalendar(); break; //todo: slowly deprecate this
case 'updateNetworkLeaf': updateNetworkLeaf(); break;
case 'overwriteIconType': overwriteIconType(); break;
@@ -92,6 +91,8 @@ function getServerDeviceData() {
"devLogEvents" => 0,
"devAlertEvents" => 0,
"devAlertDown" => 0,
"devParentRelType" => "default",
"devReqNicsOnline" => 0,
"devSkipRepeated" => 0,
"devLastNotification" => "",
"devPresentLastScan" => 0,
@@ -120,69 +121,87 @@ function getServerDeviceData() {
}
// Device Data
$sql = 'SELECT rowid, *,
CASE WHEN devAlertDown !=0 AND devPresentLastScan=0 THEN "Down"
WHEN devPresentLastScan=1 THEN "On-line"
ELSE "Off-line" END as devStatus
FROM Devices
WHERE devMac="'. $mac .'" or cast(rowid as text)="'. $mac. '"';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_ASSOC);
// Get current date (used in presence calc)
$currentdate = date("Y-m-d H:i:s");
// Fetch Device Info + Children + Events Stats
$sql =<<<SQL
SELECT
d.rowid,
d.*,
CASE
WHEN d.devAlertDown != 0 AND d.devPresentLastScan = 0 THEN "Down"
WHEN d.devPresentLastScan = 1 THEN "On-line"
ELSE "Off-line"
END AS devStatus,
-- Event counters
(SELECT COUNT(*) FROM Sessions
WHERE ses_MAC = d.devMac AND (
ses_DateTimeConnection >= $periodDate OR
ses_DateTimeDisconnection >= $periodDate OR
ses_StillConnected = 1
)
) AS devSessions,
(SELECT COUNT(*) FROM Events
WHERE eve_MAC = d.devMac AND
eve_DateTime >= $periodDate AND
eve_EventType NOT IN ("Connected", "Disconnected")
) AS devEvents,
(SELECT COUNT(*) FROM Events
WHERE eve_MAC = d.devMac AND
eve_DateTime >= $periodDate AND
eve_EventType = "Device Down"
) AS devDownAlerts,
(SELECT CAST(( MAX (0, SUM (julianday (IFNULL (ses_DateTimeDisconnection,'$currentdate'))
- julianday (CASE WHEN ses_DateTimeConnection < $periodDate
THEN $periodDate
ELSE ses_DateTimeConnection END)) *24 )) AS INT)
FROM Sessions
WHERE ses_MAC = d.devMac AND
ses_DateTimeConnection IS NOT NULL AND
(ses_DateTimeDisconnection IS NOT NULL OR ses_StillConnected = 1) AND
(
ses_DateTimeConnection >= $periodDate OR
ses_DateTimeDisconnection >= $periodDate OR
ses_StillConnected = 1
)
) AS devPresenceHours
FROM Devices d
WHERE d.devMac = "$mac" OR CAST(d.rowid AS TEXT) = "$mac"
SQL;
$row = $db->query($sql)->fetchArray(SQLITE3_ASSOC);
$deviceData = $row;
$mac = $deviceData['devMac'];
$deviceData['devParentMAC'] = $row['devParentMAC'];
$deviceData['devParentPort'] = $row['devParentPort'];
$deviceData['devFirstConnection'] = formatDate ($row['devFirstConnection']); // Date formated
$deviceData['devLastConnection'] = formatDate ($row['devLastConnection']); // Date formated
$deviceData['devFirstConnection'] = formatDate($deviceData['devFirstConnection']);
$deviceData['devLastConnection'] = formatDate($deviceData['devLastConnection']);
$deviceData['devIsRandomMAC'] = isRandomMAC($mac);
$deviceData['devIsRandomMAC'] = isRandomMAC($mac);
// Count Totals
$condition = ' WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate;
// Connections
$sql = 'SELECT COUNT(*) FROM Sessions
WHERE ses_MAC="'. $mac .'"
AND ( ses_DateTimeConnection >= '. $periodDate .'
OR ses_DateTimeDisconnection >= '. $periodDate .'
OR ses_StillConnected = 1 )';
// Fetch children once and split in PHP
$sql = 'SELECT rowid, * FROM Devices WHERE devParentMAC = "' . $mac . '" ORDER BY devPresentLastScan DESC';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['devSessions'] = $row[0];
// Events
$sql = 'SELECT COUNT(*) FROM Events '. $condition .' AND eve_EventType <> "Connected" AND eve_EventType <> "Disconnected" ';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['devEvents'] = $row[0];
$children = [];
$childrenNics = [];
// Down Alerts
$sql = 'SELECT COUNT(*) FROM Events '. $condition .' AND eve_EventType = "Device Down"';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['devDownAlerts'] = $row[0];
while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
$children[] = $row;
if ($row['devParentRelType'] === 'nic') {
$childrenNics[] = $row;
}
}
// Get current date using php, sql datetime does not return time respective to timezone.
$currentdate = date("Y-m-d H:i:s");
// Presence hours
$sql = 'SELECT CAST(( MAX (0, SUM (julianday (IFNULL (ses_DateTimeDisconnection,"'. $currentdate .'" ))
- julianday (CASE WHEN ses_DateTimeConnection < '. $periodDate .' THEN '. $periodDate .'
ELSE ses_DateTimeConnection END)) *24 )) AS INT)
FROM Sessions
WHERE ses_MAC="'. $mac .'"
AND ses_DateTimeConnection IS NOT NULL
AND (ses_DateTimeDisconnection IS NOT NULL OR ses_StillConnected = 1 )
AND ( ses_DateTimeConnection >= '. $periodDate .'
OR ses_DateTimeDisconnection >= '. $periodDate .'
OR ses_StillConnected = 1 )';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
$deviceData['devPresenceHours'] = round ($row[0]);
$deviceData['devChildrenDynamic'] = $children;
$deviceData['devChildrenNicsDynamic'] = $childrenNics;
// Return JSON
echo json_encode($deviceData);
// Return json
echo (json_encode ($deviceData));
}
@@ -211,6 +230,8 @@ function setDeviceData() {
$scancycle = quotes($_POST['scancycle']);
$alertevents = quotes($_POST['alertevents']);
$alertdown = quotes($_POST['alertdown']);
$relType = quotes($_POST['relType']);
$reqNics = quotes($_POST['reqNics']);
$skiprepeated = quotes($_POST['skiprepeated']);
$newdevice = quotes($_POST['newdevice']);
$archived = quotes($_POST['archived']);
@@ -242,6 +263,8 @@ function setDeviceData() {
devScan = '$scancycle',
devAlertEvents = '$alertevents',
devAlertDown = '$alertdown',
devParentRelType = '$relType',
devReqNicsOnline = '$reqNics',
devSkipRepeated = '$skiprepeated',
devIsNew = '$newdevice',
devIsArchived = '$archived',
@@ -267,6 +290,8 @@ function setDeviceData() {
devScan,
devAlertEvents,
devAlertDown,
devParentRelType,
devReqNicsOnline,
devSkipRepeated,
devIsNew,
devIsArchived,
@@ -295,6 +320,8 @@ function setDeviceData() {
'$scancycle',
'$alertevents',
'$alertdown',
'$relType',
'$reqNics',
'$skiprepeated',
'$newdevice',
'$archived',
@@ -744,143 +771,6 @@ function getDevicesTotals() {
echo ($resultJSON);
}
//------------------------------------------------------------------------------
// Query the List of devices in a determined Status
//------------------------------------------------------------------------------
function getDevicesList() {
global $db;
$forceDefaultOrder = FALSE;
if (isset ($_REQUEST['forceDefaultOrder']) )
{
$forceDefaultOrder = TRUE;
}
// This object is used to map from the old order ( second parameter, first number) to the new mapping, that is represented by the 3rd parameter (Second number)
$columnOrderMapping = array(
array("devName", 0, 0),
array("devOwner", 1, 1),
array("devType", 2, 2),
array("devIcon", 3, 3),
array("devFavorite", 4, 4),
array("devGroup", 5, 5),
array("devFirstConnection", 6, 6),
array("devLastConnection", 7, 7),
array("devLastIP", 8, 8),
array("devMac", 9, 9),
array("devStatus", 10, 10),
array("devMac_full", 11, 11),
array("devLastIP_orderable", 12, 12),
array("rowid", 13, 13),
array("devParentMAC", 14, 14),
array("connected_devices", 15, 15),
array("devLocation", 16, 16),
array("devVendor", 17, 17),
array("devParentPort", 18, 18),
array("devGUID", 19, 19),
array("devSyncHubNode", 20, 20),
array("devSite", 21, 21),
array("devSSID", 22, 22),
array("devSourcePlugin", 23, 23)
);
if($forceDefaultOrder == FALSE)
{
// get device columns order
$sql = 'SELECT par_Value FROM Parameters where par_ID = "Front_Devices_Columns_Order"';
$result = $db->query($sql);
$row = $result -> fetchArray (SQLITE3_NUM);
if($row != NULL && count($row) == 1)
{
// ordered columns setting from the maintenance page
$orderedColumns = createArray($row[0]);
// init ordered columns
for($i = 0; $i < count($orderedColumns); $i++) {
$columnOrderMapping[$i][2] = $orderedColumns[$i];
}
}
}
// SQL
$condition = getDeviceCondition ($_REQUEST['status']);
$sql = 'SELECT * FROM (
SELECT rowid, *, CASE
WHEN t1.devAlertDown !=0 AND t1.devPresentLastScan=0 THEN "Down"
WHEN t1.devIsNew=1 THEN "New"
WHEN t1.devPresentLastScan=1 THEN "On-line"
ELSE "Off-line" END AS devStatus
FROM Devices t1 '.$condition.') t3
LEFT JOIN
(
SELECT devParentMAC as devParentMAC_t2, devMac as devMac_t2,
count() as connected_devices
FROM Devices b
WHERE b.devParentMAC NOT NULL group by b.devParentMAC
) t2
ON (t3.devMac = t2.devParentMAC_t2);';
$result = $db->query($sql);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_ASSOC)) {
$defaultOrder = array (
$row['devName'],
$row['devOwner'],
handleNull($row['devType']),
handleNull($row['devIcon'], "PGkgY2xhc3M9J2ZhIGZhLWxhcHRvcCc+PC9pPg=="), // laptop icon
$row['devFavorite'],
$row['devGroup'],
// ----
formatDate ($row['devFirstConnection']),
formatDate ($row['devLastConnection']),
$row['devLastIP'],
( isRandomMAC($row['devMac']) ),
$row['devStatus'],
$row['devMac'], // MAC (hidden)
formatIPlong ($row['devLastIP']), // IP orderable
$row['rowid'], // Rowid (hidden)
handleNull($row['devParentMAC']),
handleNull($row['connected_devices']),
handleNull($row['devLocation']),
handleNull($row['devVendor']),
handleNull($row['devParentPort']),
handleNull($row['devGUID']),
handleNull($row['devSyncHubNode']),
handleNull($row['devSite']),
handleNull($row['devSSID']),
handleNull($row['devSourcePlugin'])
);
$newOrder = array();
// reorder columns based on user settings
for($index = 0; $index < count($columnOrderMapping); $index++)
{
array_push($newOrder, $defaultOrder[$columnOrderMapping[$index][2]]);
}
$tableData['data'][] = $newOrder;
}
// Control no rows
if (empty($tableData['data'])) {
$tableData['data'] = '';
}
// Return json
echo (json_encode ($tableData));
}
//------------------------------------------------------------------------------
// Determine if Random MAC
//------------------------------------------------------------------------------

View File

@@ -29,7 +29,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/php/templates/security.php';
case 'getEvents': getEvents(); break;
case 'getDeviceSessions': getDeviceSessions(); break;
case 'getDevicePresence': getDevicePresence(); break;
case 'getDeviceEvents': getDeviceEvents(); break;
case 'getEventsCalendar': getEventsCalendar(); break;
default: logServerConsole ('Action: '. $action); break;
}
@@ -410,41 +409,4 @@ function getEventsCalendar() {
echo (json_encode($tableData));
}
//------------------------------------------------------------------------------
// Query Device events
//------------------------------------------------------------------------------
function getDeviceEvents() {
global $db;
// Request Parameters
$mac = $_REQUEST['mac'];
$periodDate = getDateFromPeriod();
$hideConnections = $_REQUEST ['hideConnections'];
// SQL
$SQL = 'SELECT eve_DateTime, eve_EventType, eve_IP, eve_AdditionalInfo
FROM Events
WHERE eve_MAC="'. $mac .'" AND eve_DateTime >= '. $periodDate .'
AND ( (eve_EventType <> "Connected" AND eve_EventType <> "Disconnected" AND
eve_EventType <> "VOIDED - Connected" AND eve_EventType <> "VOIDED - Disconnected")
OR "'. $hideConnections .'" = "false" ) ';
$result = $db->query($SQL);
// arrays of rows
$tableData = array();
while ($row = $result -> fetchArray (SQLITE3_NUM)) {
$row[0] = formatDate ($row[0]);
$tableData['data'][] = $row;
}
// Control no rows
if (empty($tableData['data'])) {
$tableData['data'] = '';
}
// Return json
echo (json_encode ($tableData));
}
?>

View File

@@ -587,7 +587,9 @@ function getDevicesColumns(){
"devSSID",
"devSourcePlugin",
"devCustomProps",
"devFQDN"
"devFQDN",
"devParentRelType",
"devReqNicsOnline"
];
return $columns;

View File

@@ -42,7 +42,6 @@
<script src="lib/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="lib/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
<script src="lib/datatables.net/js/dataTables.select.min.js"></script>
<script src="lib/popper_tooltip/popper.min.js"></script>
<script src="js/common.js?v=<?php include 'php/templates/version.php'; ?>"></script>
<script src="js/modal.js?v=<?php include 'php/templates/version.php'; ?>"></script>
@@ -51,8 +50,6 @@
<script src="js/settings_utils.js?v=<?php include 'php/templates/version.php'; ?>"></script>
<script src="js/device.js?v=<?php include 'php/templates/version.php'; ?>"></script>
<!-- iCheck -->
<link rel="stylesheet" href="lib/iCheck/all.css">
@@ -136,7 +133,21 @@
<!-- ----------------------------------------------------------------------- -->
<!-- Layout Boxed Yellow -->
<body class="hold-transition fixed <?php echo $pia_skin_selected;?> sidebar-mini" onLoad="update_servertime();" >
<!-- spinner -->
<body class="hold-transition fixed <?php echo $pia_skin_selected;?> theme-<?php echo $UI_THEME;?> sidebar-mini" onLoad="update_servertime();" >
<div id="loadingSpinner">
<div class="pa_semitransparent-panel"></div>
<div class="panel panel-default pa_spinner">
<table>
<td id="loadingSpinnerText" width="130px" ></td>
<td><i class="fa-solid fa-spinner fa-spin-pulse"></i></td>
</table>
</div>
</div>
<!-- Site wrapper -->
<div class="wrapper">
@@ -297,6 +308,12 @@
<li>
<a href="devices.php#archived" onclick="forceLoadUrl('devices.php#archived')" > <?= lang("Device_Shortcut_Archived");?> </a>
</li>
<li>
<a href="devices.php#all_devices" onclick="forceLoadUrl('devices.php#all_devices')" > <?= lang("Gen_All_Devices");?> </a>
</li>
<li>
<a href="devices.php#network_devices" onclick="forceLoadUrl('devices.php#network_devices')" > <?= lang("Network_Devices");?> </a>
</li>
</ul>
</li>
@@ -329,7 +346,7 @@
<!-- Network menu item -->
<li class=" <?php if (in_array (basename($_SERVER['SCRIPT_NAME']), array('network.php') ) ){ echo 'active'; } ?>">
<a href="network.php"><i class="fa fa-fw fa-network-wired"></i> <span><?= lang('Navigation_Network');?></span></a>
<a href="network.php"><i class="fa fa-fw fa-sitemap fa-rotate-270"></i> <span><?= lang('Navigation_Network');?></span></a>
</li>
<!-- Maintenance menu item -->

File diff suppressed because it is too large Load Diff

View File

@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Esborrar esdeveniments més vells de",
"DISCOVER_PLUGINS_description": "Desactiva aquesta opció per accelerar la inicialització i l'estalvi de configuració. Quan està desactivat, els connectors no es descobreixen, i no podeu afegir nous connectors a la configuració <code>LOADED_PLUGINS</code>.",
"DISCOVER_PLUGINS_name": "Descobreix els plugins",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "<i class=\"fa fa-copy\"></i> Copiar detalls des del dispositiu",
"DevDetail_Copy_Device_Tooltip": "Copiar detalls del dispositius des de la llista desplegable. Tot el d'aquesta pàgina es sobre-escriurà",
"DevDetail_CustomProperties_Title": "Propietats personalitzades",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "Tipus",
"DevDetail_MainInfo_Vendor": "Venedor",
"DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Seleccioneu el dispositiu de xarxa al qual aquest dispositiu està connectat, per poder omplir l'arbre de xarxa.",
"DevDetail_Network_Port_hover": "El port on el dispositiu està connectat al dispositiu de xarxa del pare. Si es deixa buit, sortirà una icona wifi a la representació de la Xarxa.",
"DevDetail_Nmap_Scans": "Escaneig manual Nmap",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "Atenció. Si feu clic a això s'aplicarà el valor de l'esquerra a tots els dispositius seleccionats a dalt.",
"Device_Searchbox": "Cerca",
"Device_Shortcut_AllDevices": "Els meus dispositius",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Arxivat",
"Device_Shortcut_Connected": "Connectat",
"Device_Shortcut_Devices": "Dispositius",
@@ -211,7 +214,7 @@
"Device_TableHead_AlertDown": "Cancel·lar alerta",
"Device_TableHead_Connected_Devices": "Connexions",
"Device_TableHead_CustomProps": "Props / Accions",
"Device_TableHead_FQDN": "",
"Device_TableHead_FQDN": "FQDN",
"Device_TableHead_Favorite": "Favorit",
"Device_TableHead_FirstSession": "Primera Sessió",
"Device_TableHead_GUID": "GUID",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Nom",
"Device_TableHead_NetworkSite": "Network Site",
"Device_TableHead_Owner": "Propietari",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Node pare de xarxa",
"Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Presència",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "ID de fila",
"Device_TableHead_Rowid": "ID de fila",
"Device_TableHead_SSID": "SSID",
@@ -304,6 +309,7 @@
"Gen_Filter": "Filtrar",
"Gen_Generate": "Generar",
"Gen_LockedDB": "ERROR - DB podria estar bloquejada - Fes servir F12 Eines desenvolupament -> Consola o provar-ho més tard.",
"Gen_NetworkMask": "",
"Gen_Offline": "Fora de línia",
"Gen_Okay": "Ok",
"Gen_Online": "En línia",
@@ -321,6 +327,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Seleccioneu la vista prèvia",
"Gen_Selected_Devices": "Dispositius seleccionats:",
"Gen_Subnet": "",
"Gen_Switch": "Switch",
"Gen_Upd": "Actualitzat correctament",
"Gen_Upd_Fail": "Actualització fallida",
@@ -359,11 +366,11 @@
"Maint_PurgeLog": "Registre de purga",
"Maint_RestartServer": "Reinici del servidor",
"Maint_Restart_Server_noti_text": "Estàs segur que vols reiniciar el servidor backend? Això pot causar incongruència a l'aplicació. Abans fes còpia de seguretat de la vostra configuració. <br/> <br/> Nota: Això pot durar uns quants minuts.",
"Maintenance_InitCheck": "",
"Maintenance_InitCheck_Checking": "",
"Maintenance_InitCheck_QuickSetupGuide": "",
"Maintenance_InitCheck_Success": "",
"Maintenance_ReCheck": "",
"Maintenance_InitCheck": "Init Check",
"Maintenance_InitCheck_Checking": "Comprovant…",
"Maintenance_InitCheck_QuickSetupGuide": "Assegureu-vos de seguir la guia <a href=\"https://jokob-sk.github.io/NetAlertX/INITIAL_SETUP/\" target=\"_blank\"> de configuració ràpida</a>.",
"Maintenance_InitCheck_Success": "Aplicació inicialitzada amb èxit!",
"Maintenance_ReCheck": "Tornar a comprovar",
"Maintenance_Running_Version": "Versió instal·lada",
"Maintenance_Status": "Estat",
"Maintenance_Title": "Eines de manteniment",
@@ -486,8 +493,10 @@
"Navigation_Workflows": "Workflows",
"Network_Assign": "Connecta el <i class=\"fa fa-server\"></i> node de Xarxa",
"Network_Cant_Assign": "No es pot assignar el node arrel d'Internet com a node fill.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Error de configuració",
"Network_Connected": "Dispositius connectats",
"Network_Devices": "",
"Network_ManageAdd": "Afegir dispositiu",
"Network_ManageAdd_Name": "Nom del dispositiu",
"Network_ManageAdd_Name_text": "Nom sense caràcters especials",
@@ -522,6 +531,8 @@
"Network_Root": "Node arrel",
"Network_Root_Not_Configured": "Seleccioneu un tipus de dispositiu de xarxa, per exemple un tipus <b>Gateway</b>, al camp <b>Tipus</b>del <a href=\"deviceDetails.php?mac=Internet\">dispositiu arrel d'Internet</a> per començar a configurar aquesta pantalla. <br/><br/>. Podeu trobar més documentació a la <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md\" target=\"_blank\">Guia de com configurar la vostra pàgina de xarxa</a>",
"Network_Root_Unconfigurable": "Arrel no configurable",
"Network_ShowArchived": "",
"Network_ShowOffline": "",
"Network_Table_Hostname": "Hostname",
"Network_Table_IP": "IP",
"Network_Table_State": "Estat",
@@ -565,8 +576,8 @@
"Presence_Shortcut_Favorites": "Favorits",
"Presence_Shortcut_NewDevices": "Nous dispositius",
"Presence_Title": "Detecció de dispositius",
"REFRESH_FQDN_description": "",
"REFRESH_FQDN_name": "",
"REFRESH_FQDN_description": "Re-escaneja tots dispositius i refresca el seu (FQDN). Si està desactivat, nomes s'escanegen els noms coneguts per fer-ho més ràpid. En aquest cas, FQDN s'actualitza només durant descoberta inicial de dispositius.",
"REFRESH_FQDN_name": "Refresc FQDN",
"REPORT_DASHBOARD_URL_description": "Aquesta URL s'utilitza com a base per generar enllaços en informes HTML (per exemple: correus electrònics). Introduïu la URL completa començant per <code>http://</code> incloent el número de port (sense barra inicial <code>/</code>).",
"REPORT_DASHBOARD_URL_name": "URL NetAlertX",
"REPORT_ERROR": "Si us plau, introdueix dins de la caixa de text els caràcters que veu a la imatge de sota. Això és requerit per evitar enviaments automàtics",
@@ -585,6 +596,7 @@
"Settings_device_Scanners_desync": "⚠ Els horaris d'escàner de dispositius no estan en sincronia.",
"Settings_device_Scanners_desync_popup": "Els horaris dels escàners de dispositius (<code>*_RUN_SCHD</code>) no són iguals. Això donarà lloc a notificacions inconsistents del dispositiu en línia / fora de línia. Si no és intencionat, utilitzeu el mateix horari per a tots els <b>🔍 escàners de dispositius</b>.",
"Speedtest_Results": "Speedtest Resultats",
"Systeminfo_AvailableIps": "",
"Systeminfo_CPU": "CPU",
"Systeminfo_CPU_Cores": "Nuclis de CPU:",
"Systeminfo_CPU_Name": "Nom de CPU:",
@@ -704,24 +716,21 @@
"WF_Trigger": "Disparador(Trigger)",
"WF_Trigger_event_type": "Tipus d'esdeveniment",
"WF_Trigger_type": "Tipus de disparador",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Afegir nova icona",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Afegir nou valor",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Sobreescriure icones de tots els dispositius amb el mateix tipus de dispositiu",
"devices_old": "Refrescant...",
"general_event_description": "L'esdeveniment que has desencadenat pot trigar un temps fins que acabin els processos de fons. L'execució acabarà una cop buida la cua d'execució (Comprova el registre d'errors <a href='/maintenance.php#tab_Logging'></a> si hi ha problemes). <br/> <br/> Cua d'execució:",
"general_event_title": "Execució d'un esdeveniment ad-hoc",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "Navegació a la pàgina de la Xarxa del node donat",
"new_version_available": "Ja està disponible una nova versió.",
"report_guid": "Notificació guid:",
"report_guid_missing": "No s'ha trobat la notificació enllaçada. Hi ha un petit retard entre les notificacions enviades recentment i que estiguin disponibles. Refresqui la pàgina i la memòria cau d'aquí uns segons. També és possible que la notificació seleccionada s'hagi esborrat durant el manteniment tal com s'especifica a la configuració <code>DBCLNP_NOTIFI_HIST</code>. <br/> <br/>L'última notificació es mostra en el seu lloc. La notificació perduda té el següent GUID:",
"report_select_format": "Seleccioneu Format:",
"report_time": "Data de recepció:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Habiliteu la configuració i deseu els canvis al principi abans d'executar-lo.",
"select_icon_event_tooltip": "",
"settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Nucli",
"settings_device_scanners": "Escàners de dispositius utilitzats per descobrir dispositius que escriuen a la taula de base de dades CurrentScan.",
@@ -748,6 +757,5 @@
"settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "Sistema",
"settings_update_item_warning": "Actualitza el valor sota. Sigues curós de seguir el format anterior. <b>No hi ha validació.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Deseu els canvis primer abans de comprovar la configuració."
}

View File

@@ -5,11 +5,11 @@
"API_TOKEN_name": "API token",
"API_display_name": "API",
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
"About_Design": "",
"About_Exit": "",
"About_Title": "",
"About_Design": "Designováno pro:",
"About_Exit": "Odhlásit",
"About_Title": "Scanner síťové bezpečnosti a framework pro upozornění",
"AppEvents_AppEventProcessed": "Zpracováno",
"AppEvents_DateTimeCreated": "Zalogováno",
"AppEvents_DateTimeCreated": "Objeveno",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "",
"AppEvents_Helper1": "",
@@ -66,6 +66,7 @@
"DAYS_TO_KEEP_EVENTS_name": "",
"DISCOVER_PLUGINS_description": "",
"DISCOVER_PLUGINS_name": "",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "",
"DevDetail_Copy_Device_Tooltip": "",
"DevDetail_CustomProperties_Title": "",
@@ -102,6 +103,7 @@
"DevDetail_MainInfo_Type": "",
"DevDetail_MainInfo_Vendor": "",
"DevDetail_MainInfo_mac": "",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "",
"DevDetail_Network_Port_hover": "",
"DevDetail_Nmap_Scans": "",
@@ -200,6 +202,7 @@
"Device_MultiEdit_Tooltip": "",
"Device_Searchbox": "",
"Device_Shortcut_AllDevices": "",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "",
"Device_Shortcut_Connected": "",
"Device_Shortcut_Devices": "",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "",
"Device_TableHead_NetworkSite": "",
"Device_TableHead_Owner": "",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "",
"Device_TableHead_Port": "",
"Device_TableHead_PresentLastScan": "",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "",
"Device_TableHead_Rowid": "",
"Device_TableHead_SSID": "",
@@ -289,45 +294,47 @@
"Gen_Action": "",
"Gen_Add": "",
"Gen_AddDevice": "",
"Gen_Add_All": "",
"Gen_All_Devices": "",
"Gen_AreYouSure": "",
"Gen_Backup": "",
"Gen_Cancel": "",
"Gen_Change": "",
"Gen_Copy": "",
"Gen_DataUpdatedUITakesTime": "",
"Gen_Delete": "",
"Gen_DeleteAll": "",
"Gen_Description": "",
"Gen_Error": "",
"Gen_Filter": "",
"Gen_Generate": "",
"Gen_LockedDB": "",
"Gen_Offline": "",
"Gen_Okay": "",
"Gen_Online": "",
"Gen_Purge": "",
"Gen_ReadDocs": "",
"Gen_Remove_All": "",
"Gen_Remove_Last": "",
"Gen_Reset": "",
"Gen_Restore": "",
"Gen_Run": "",
"Gen_Save": "",
"Gen_Saved": "",
"Gen_Search": "",
"Gen_Select": "",
"Gen_SelectIcon": "",
"Gen_SelectToPreview": "",
"Gen_Selected_Devices": "",
"Gen_Switch": "",
"Gen_Upd": "",
"Gen_Upd_Fail": "",
"Gen_Update": "",
"Gen_Update_Value": "",
"Gen_ValidIcon": "",
"Gen_Warning": "",
"Gen_Add_All": "Přidat vše",
"Gen_All_Devices": "Všechna zařízení",
"Gen_AreYouSure": "Jste si jistý?",
"Gen_Backup": "Spustit zálohování",
"Gen_Cancel": "Zrušit",
"Gen_Change": "Změnit",
"Gen_Copy": "Spustit",
"Gen_DataUpdatedUITakesTime": "OK - může zabrat chvíli aktualizovat rozhraní, pokud běží scan.",
"Gen_Delete": "Smazat",
"Gen_DeleteAll": "Smazat vše",
"Gen_Description": "Popis",
"Gen_Error": "Chyba",
"Gen_Filter": "Filtr",
"Gen_Generate": "Vygenerovat",
"Gen_LockedDB": "CHYBA - Databáze je možná zamčená - Zkontrolujte F12 -> Nástroje pro vývojáře -> Konzole. nebo to zkuste později.",
"Gen_NetworkMask": "",
"Gen_Offline": "Offline",
"Gen_Okay": "Ok",
"Gen_Online": "Online",
"Gen_Purge": "Vyčistit",
"Gen_ReadDocs": "Přečíst více v dokumentaci.",
"Gen_Remove_All": "Odstranit vše",
"Gen_Remove_Last": "Odstranit poslední",
"Gen_Reset": "Vyresetovat",
"Gen_Restore": "Spustit obnovu",
"Gen_Run": "Spustit",
"Gen_Save": "Uložit",
"Gen_Saved": "Uloženo",
"Gen_Search": "Hledat",
"Gen_Select": "Vybrat",
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Vybrat na náhled",
"Gen_Selected_Devices": "Vybraná zařízení:",
"Gen_Subnet": "",
"Gen_Switch": "Přepnout",
"Gen_Upd": "Úspěšně aktualizováno",
"Gen_Upd_Fail": "Aktualizace se nezdařila",
"Gen_Update": "Aktualizovat",
"Gen_Update_Value": "Aktualizovat hodnotu",
"Gen_ValidIcon": "<i class=\"fa-solid fa-chevron-right \"></i>",
"Gen_Warning": "Upozornění",
"Gen_Work_In_Progress": "",
"Gen_create_new_device": "",
"Gen_create_new_device_info": "",
@@ -486,8 +493,10 @@
"Navigation_Workflows": "",
"Network_Assign": "",
"Network_Cant_Assign": "",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "",
"Network_Connected": "",
"Network_Devices": "",
"Network_ManageAdd": "",
"Network_ManageAdd_Name": "",
"Network_ManageAdd_Name_text": "",
@@ -522,6 +531,8 @@
"Network_Root": "",
"Network_Root_Not_Configured": "",
"Network_Root_Unconfigurable": "",
"Network_ShowArchived": "",
"Network_ShowOffline": "",
"Network_Table_Hostname": "",
"Network_Table_IP": "",
"Network_Table_State": "",
@@ -585,6 +596,7 @@
"Settings_device_Scanners_desync": "",
"Settings_device_Scanners_desync_popup": "",
"Speedtest_Results": "",
"Systeminfo_AvailableIps": "",
"Systeminfo_CPU": "",
"Systeminfo_CPU_Cores": "",
"Systeminfo_CPU_Name": "",
@@ -704,24 +716,21 @@
"WF_Trigger": "",
"WF_Trigger_event_type": "",
"WF_Trigger_type": "",
"add_icon_event_icon": "",
"add_icon_event_tooltip": "",
"add_option_event_icon": "",
"add_option_event_tooltip": "",
"copy_icons_event_icon": "",
"copy_icons_event_tooltip": "",
"devices_old": "",
"add_icon_event_tooltip": "Přidat novou ikonu",
"add_option_event_tooltip": "Přidat novou hodnotu",
"copy_icons_event_tooltip": "Přepiš ikony všech zařízení za stejný typ zařízení",
"devices_old": "Obnovuji…",
"general_event_description": "",
"general_event_title": "",
"go_to_node_event_icon": "",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "",
"new_version_available": "",
"report_guid": "",
"report_guid_missing": "",
"report_select_format": "",
"report_time": "",
"run_event_icon": "",
"run_event_tooltip": "",
"select_icon_event_tooltip": "",
"settings_core_icon": "",
"settings_core_label": "",
"settings_device_scanners": "",
@@ -748,6 +757,5 @@
"settings_system_icon": "",
"settings_system_label": "",
"settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": ""
}

View File

@@ -5,19 +5,11 @@
"API_TOKEN_name": "API-Schlüssel",
"API_display_name": "API",
"API_icon": "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
"APPRISE_HOST_description": "Apprise host URL starting with <code>http://</code> or <code>https://</code>. (do not forget to include <code>/notify</code> at the end)",
"APPRISE_HOST_name": "Apprise host URL",
"APPRISE_PAYLOAD_description": "Select the payload type sent to Apprise. For example <code>html</code> works well with emails, <code>text</code> with chat apps, such as Telegram.",
"APPRISE_PAYLOAD_name": "Payload type",
"APPRISE_SIZE_description": "The maximum size of the apprise payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended.",
"APPRISE_SIZE_name": "Max payload size",
"APPRISE_URL_description": "Apprise notification target URL. For example for Telegram it would be <code>tgram://{bot_token}/{chat_id}</code>.",
"APPRISE_URL_name": "Apprise notification URL",
"About_Design": "Entworfen für:",
"About_Exit": "Abmelden",
"About_Title": "Netzwerksicherheitsscanner und Benachrichtigungsframework",
"AppEvents_AppEventProcessed": "Verarbeitet",
"AppEvents_DateTimeCreated": "Protokolliert",
"AppEvents_DateTimeCreated": "Entdeckt am",
"AppEvents_Extra": "Extra",
"AppEvents_GUID": "Anwendungsereignis-GUID",
"AppEvents_Helper1": "Helfer 1",
@@ -78,6 +70,7 @@
"DAYS_TO_KEEP_EVENTS_name": "Ereignisse löschen, die älter sind als",
"DISCOVER_PLUGINS_description": "Deaktiviere diese Option, um Initialisierung und Speichern der Einstellungen zu beschleunigen. Wenn es deaktiviert ist, werden keine neuen Plugins gefunden und es können keine manuell hinzugefügt werden.",
"DISCOVER_PLUGINS_name": "Entdecke Erweiterungen",
"DevDetail_Children_Title": "",
"DevDetail_Copy_Device_Title": "Details von Gerät kopieren",
"DevDetail_Copy_Device_Tooltip": "Details vom Gerät aus der Dropdown-Liste kopieren. Alles auf dieser Seite wird überschrieben",
"DevDetail_CustomProperties_Title": "Benutzerdefinierte Eigenschaften",
@@ -98,7 +91,7 @@
"DevDetail_GoToNetworkNode": "Zur Netzwerkseite des angegebenen Knotens navigieren.",
"DevDetail_Icon": "Icon",
"DevDetail_Icon_Descr": "Geben Sie einen Font Awesome Icon-Namen ohne das Präfix „fa-“ ein oder die vollständige Klasse, z. B.: fa fa-brands fa-apple.",
"DevDetail_Loading": "Laden ...",
"DevDetail_Loading": "Laden ",
"DevDetail_MainInfo_Comments": "Notiz",
"DevDetail_MainInfo_Favorite": "Favorit",
"DevDetail_MainInfo_Group": "Gruppe",
@@ -114,6 +107,7 @@
"DevDetail_MainInfo_Type": "Typ",
"DevDetail_MainInfo_Vendor": "Hersteller",
"DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "",
"DevDetail_Network_Node_hover": "Wählen Sie das Elternnetzgerät aus, an das das aktuelle Gerät angeschlossen ist, um den Netzwerkbaum zu erstellen.",
"DevDetail_Network_Port_hover": "Der Port, mit dem dieses Gerät am übergeordneten Netzwerkgerät verbunden ist. Bleibt er leer, wird ein WLAN-Symbol in der Netzwerkstruktur angezeigt.",
"DevDetail_Nmap_Scans": "Nmap Scans",
@@ -212,6 +206,7 @@
"Device_MultiEdit_Tooltip": "Achtung! Beim Drücken werden alle Werte auf die oben ausgewählten Geräte übertragen.",
"Device_Searchbox": "Suche",
"Device_Shortcut_AllDevices": "Meine Geräte",
"Device_Shortcut_AllNodes": "",
"Device_Shortcut_Archived": "Archiviert",
"Device_Shortcut_Connected": "Verbunden",
"Device_Shortcut_Devices": "Geräte",
@@ -238,9 +233,11 @@
"Device_TableHead_Name": "Name",
"Device_TableHead_NetworkSite": "Netzwerkseite",
"Device_TableHead_Owner": "Eigentümer",
"Device_TableHead_ParentRelType": "",
"Device_TableHead_Parent_MAC": "Übergeordneter Netzwerkknoten",
"Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Anwesenheit",
"Device_TableHead_ReqNicsOnline": "",
"Device_TableHead_RowID": "Zeilen ID",
"Device_TableHead_Rowid": "Zeilennummer",
"Device_TableHead_SSID": "SSID",
@@ -263,7 +260,7 @@
"ENCRYPTION_KEY_name": "Verschlüsselungsschlüssel",
"Email_display_name": "Email",
"Email_icon": "<i class=\"fa fa-at\"></i>",
"Events_Loading": "Laden...",
"Events_Loading": "Laden",
"Events_Periodselect_All": "Alle Ereignisse",
"Events_Periodselect_LastMonth": "Letzter Monat",
"Events_Periodselect_LastWeek": "Letzte Woche",
@@ -316,6 +313,7 @@
"Gen_Filter": "Filter",
"Gen_Generate": "Generieren",
"Gen_LockedDB": "ERROR - DB eventuell gesperrt - Nutze die Konsole in den Entwickler Werkzeugen (F12) zur Überprüfung oder probiere es später erneut.",
"Gen_NetworkMask": "",
"Gen_Offline": "Offline",
"Gen_Okay": "Ok",
"Gen_Online": "Online",
@@ -333,6 +331,7 @@
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Zur Vorschau auswählen",
"Gen_Selected_Devices": "Ausgewählte Geräte:",
"Gen_Subnet": "",
"Gen_Switch": "Umschalten",
"Gen_Upd": "Aktualisierung erfolgreich",
"Gen_Upd_Fail": "Aktualisierung fehlgeschlagen",
@@ -353,7 +352,7 @@
"LOADED_PLUGINS_name": "Geladene Plugins",
"LOG_LEVEL_description": "Diese Einstellung aktiviert die erweiterte Protokollierung. Nützlich fürs Debuggen von in die Datenbank geschriebenen Events.",
"LOG_LEVEL_name": "Erweiterte Protokollierung",
"Loading": "Laden...",
"Loading": "Laden",
"Login_Box": "Passwort eingeben",
"Login_Default_PWD": "Standardpasswort \"123456\" noch immer aktiv.",
"Login_Info": "",
@@ -386,28 +385,28 @@
"Maint_RestartServer": "Server neu starten",
"Maint_Restart_Server_noti_text": "Soll der Backend-Server wirklich neu gestartet werden? Das könnte Instabilitäten verursachen. Vorher ein Backup erstellen. <br/><br/>Hinweis: Das kann einige Minuten dauern.",
"Maintenance_InitCheck": "",
"Maintenance_InitCheck_Checking": "",
"Maintenance_InitCheck_Checking": "Prüfen …",
"Maintenance_InitCheck_QuickSetupGuide": "",
"Maintenance_InitCheck_Success": "",
"Maintenance_ReCheck": "",
"Maintenance_InitCheck_Success": "Anwendung erfolgreich initialisiert!",
"Maintenance_ReCheck": "Prüfung wiederholen",
"Maintenance_Running_Version": "Installierte Version",
"Maintenance_Status": "Status",
"Maintenance_Title": "Wartungswerkzeuge",
"Maintenance_Tool_DownloadConfig": "Einstellungen exportieren",
"Maintenance_Tool_DownloadConfig_text": "",
"Maintenance_Tool_DownloadWorkflows": "",
"Maintenance_Tool_DownloadWorkflows_text": "",
"Maintenance_Tool_ExportCSV": "CSV Export",
"Maintenance_Tool_ExportCSV_noti": "CSV Export",
"Maintenance_Tool_DownloadConfig_text": "Download eines Voll-Backup deiner Einstellungen. Konfiguration gespeichert in <code>app.conf</code> Datei.",
"Maintenance_Tool_DownloadWorkflows": "Workflows Export",
"Maintenance_Tool_DownloadWorkflows_text": "Download eines Voll-Backups deiner Worksflows. Gespeichert in <code>workflows.json</code> Datei.",
"Maintenance_Tool_ExportCSV": "Export Geräte (csv)",
"Maintenance_Tool_ExportCSV_noti": "Geräte Export (csv)",
"Maintenance_Tool_ExportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei erstellen wollen?",
"Maintenance_Tool_ExportCSV_text": "Generiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Dies kann auch durch das Besuchen der URL <code>your NetAlertX url/php/server/devices.php?action=ExportCSV</code> oder durch Aktivieren des <a href=\"settings.php#CSVBCKP_header\">CSV-Backups</a> ausgelöst werden.",
"Maintenance_Tool_ImportCSV": "CSV Import",
"Maintenance_Tool_ImportCSV_noti": "CSV Import",
"Maintenance_Tool_ImportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei importieren wollen? Dies wird <b>alle Geräte in der Datenbank überschreiben</b>.",
"Maintenance_Tool_ImportCSV_text": "Machen Sie ein Backup, bevor Sie diese Funk­tion nutzen. Importiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Um dies zu tun platziere die <b>devices.csv</b> benannte CSV-Datei in deinen <b>/config</b> Ordner.",
"Maintenance_Tool_ImportConfig_noti": "",
"Maintenance_Tool_ImportPastedCSV": "CSV-Import (Einfügen)",
"Maintenance_Tool_ImportPastedCSV_noti_text": "",
"Maintenance_Tool_ImportCSV": "Geräte Import (csv)",
"Maintenance_Tool_ImportCSV_noti": "Geräte Import (csv)",
"Maintenance_Tool_ImportCSV_noti_text": "Sind Sie sich sicher, dass Sie die CSV-Datei importieren wollen? Dies wird alle Geräte in der Datenbank <b>überschreiben</b>.",
"Maintenance_Tool_ImportCSV_text": "Mache ein Backup, bevor Du diese Funk­tion nutzt. Importiere eine CSV-Datei (comma separated values) mit einer Liste aller Geräte und deren Beziehungen zwischen Netzwerkknoten und verbundenen Geräten. Um dies zu tun platziere die <b>devices.csv</b> benannte CSV-Datei in deinen <b>/config</b> Ordner.",
"Maintenance_Tool_ImportConfig_noti": "Einstellungen importieren (app.conf)",
"Maintenance_Tool_ImportPastedCSV": "Geräte importieren (csv) (einfügen)",
"Maintenance_Tool_ImportPastedCSV_noti_text": "Bist Du dir sicher, dass Du die eingefügte CSV importieren willst? Es werden alle Geräte in deiner Datenbank <b>überschrieben</b>.",
"Maintenance_Tool_ImportPastedCSV_text": "",
"Maintenance_Tool_ImportPastedConfig": "",
"Maintenance_Tool_ImportPastedConfig_noti_text": "",
@@ -523,8 +522,10 @@
"Navigation_Workflows": "Arbeitsabläufe",
"Network_Assign": "Zum obigen <i class=\"fa fa-server\"></i> Netzwerkknoten zuweisen",
"Network_Cant_Assign": "Internet-Wurzelknoten kann nicht als äußerer Kindknoten zugewiesen werden.",
"Network_Cant_Assign_No_Node_Selected": "",
"Network_Configuration_Error": "Konfigurationsfehler",
"Network_Connected": "Verbundene Geräte",
"Network_Devices": "",
"Network_ManageAdd": "Gerät hinzufügen",
"Network_ManageAdd_Name": "Name des Gerätes",
"Network_ManageAdd_Name_text": "Name ohne Sonderzeichen",
@@ -559,6 +560,8 @@
"Network_Root": "Wurzelknoten",
"Network_Root_Not_Configured": "",
"Network_Root_Unconfigurable": "Nicht konfigurierbare Wurzel",
"Network_ShowArchived": "",
"Network_ShowOffline": "",
"Network_Table_Hostname": "Gerätename",
"Network_Table_IP": "IP",
"Network_Table_State": "Status",
@@ -597,7 +600,7 @@
"Presence_Key_OnlinePastMiss": "",
"Presence_Key_OnlinePastMiss_desc": "",
"Presence_Key_OnlinePast_desc": "",
"Presence_Loading": "Laden...",
"Presence_Loading": "Laden",
"Presence_Shortcut_AllDevices": "Meine Geräte",
"Presence_Shortcut_Archived": "Archiviert",
"Presence_Shortcut_Connected": "Verbunden",
@@ -654,6 +657,7 @@
"Settings_device_Scanners_desync": "⚠ Die Zeitpläne des Gerätescanners sind nicht synchronisiert.",
"Settings_device_Scanners_desync_popup": "",
"Speedtest_Results": "Ergebnisse des Geschwindigkeitstests",
"Systeminfo_AvailableIps": "",
"Systeminfo_CPU": "CPU",
"Systeminfo_CPU_Cores": "CPU-Kerne:",
"Systeminfo_CPU_Name": "CPU-Name:",
@@ -785,24 +789,21 @@
"WF_Trigger_type": "Auslösertyp",
"Webhooks_display_name": "Webhooks",
"Webhooks_icon": "<i class=\"fa fa-circle-nodes\"></i>",
"add_icon_event_icon": "",
"add_icon_event_tooltip": "Neues Symbol hinzufügen",
"add_option_event_icon": "",
"add_option_event_tooltip": "Neuen Wert hinzufügen",
"copy_icons_event_icon": "",
"copy_icons_event_tooltip": "Icons aller Geräte mit demselben Gerätetyp überschreiben",
"devices_old": "Aktualisiert...",
"general_event_description": "Das Ereignis, das Sie ausgelöst haben, könnte eine Weile dauern, bis Hintergrundprozesse abgeschlossen sind. Die Ausführung endet, wenn die unten ausgeführte Warteschlangen abgearbeitet ist. (Siehe <a href='/maintenance.php#tab_Logging'>error log</a>, wenn Probleme auftreten.)<br/> <br/> Ausführungsschlange:",
"general_event_title": "",
"go_to_node_event_icon": "",
"go_to_device_event_tooltip": "",
"go_to_node_event_tooltip": "",
"new_version_available": "Es ist eine neue Version verfügbar.",
"report_guid": "",
"report_guid_missing": "",
"report_select_format": "Format auswählen:",
"report_time": "Benachrichtigungszeit:",
"run_event_icon": "",
"run_event_tooltip": "Aktiviere die Einstellung und speichere deine Änderungen, bevor du sie ausführst.",
"select_icon_event_tooltip": "",
"settings_core_icon": "",
"settings_core_label": "Kern",
"settings_device_scanners": "",
@@ -829,6 +830,5 @@
"settings_system_icon": "",
"settings_system_label": "System",
"settings_update_item_warning": "",
"test_event_icon": "",
"test_event_tooltip": "Speichere die Änderungen, bevor Sie die Einstellungen testen."
}

View File

@@ -39,8 +39,8 @@
"BackDevices_Backup_CopError": "The original database could not be saved.",
"BackDevices_Backup_Failed": "The backup executed partially successfully. The archive could not be created or is empty.",
"BackDevices_Backup_okay": "The backup executed successfully with the new archive",
"BackDevices_DBTools_DelDevError_a": "Error deleting Device",
"BackDevices_DBTools_DelDevError_b": "Error deleting Devices",
"BackDevices_DBTools_DelDevError_a": "Error deleting device",
"BackDevices_DBTools_DelDevError_b": "Error deleting devices",
"BackDevices_DBTools_DelDev_a": "Device deleted",
"BackDevices_DBTools_DelDev_b": "Devices deleted",
"BackDevices_DBTools_DelEvents": "Events deleted",
@@ -66,27 +66,28 @@
"DAYS_TO_KEEP_EVENTS_name": "Delete events older than",
"DISCOVER_PLUGINS_description": "Disable this option to speed up initialization and settings saving. When disabled, plugins are not discovered, and you cannot add new plugins to the <code>LOADED_PLUGINS</code> setting.",
"DISCOVER_PLUGINS_name": "Discover plugins",
"DevDetail_Children_Title": "Children Relationships",
"DevDetail_Copy_Device_Title": "Copy details from device",
"DevDetail_Copy_Device_Tooltip": "Copy details from device from the dropdown list. Everything on this page will be overwritten",
"DevDetail_CustomProperties_Title": "Custom Properties",
"DevDetail_CustomProps_reset_info": "This will remove your custom properties on this device and reset them to the default value.",
"DevDetail_DisplayFields_Title": "Display",
"DevDetail_EveandAl_AlertAllEvents": "Alert Events",
"DevDetail_EveandAl_AlertDown": "Alert Down",
"DevDetail_EveandAl_AlertAllEvents": "Alert events",
"DevDetail_EveandAl_AlertDown": "Alert down",
"DevDetail_EveandAl_Archived": "Archived",
"DevDetail_EveandAl_NewDevice": "New Device",
"DevDetail_EveandAl_NewDevice_Tooltip": "Will show the New status for the device and include it in lists when the New Devices filter is active. Doesn't affect notifications.",
"DevDetail_EveandAl_NewDevice": "New device",
"DevDetail_EveandAl_NewDevice_Tooltip": "Will show the New status for the device and include it in lists when the New devices filter is active. Doesn't affect notifications.",
"DevDetail_EveandAl_RandomMAC": "Random MAC",
"DevDetail_EveandAl_ScanCycle": "Scan device",
"DevDetail_EveandAl_ScanCycle_a": "Scan Device",
"DevDetail_EveandAl_ScanCycle_z": "Don&#39;t Scan Device",
"DevDetail_EveandAl_ScanCycle_a": "Scan device",
"DevDetail_EveandAl_ScanCycle_z": "Don&#39;t scan device",
"DevDetail_EveandAl_Skip": "Skip repeated notifications for",
"DevDetail_EveandAl_Title": "Notifications config",
"DevDetail_Events_CheckBox": "Hide Connection Events",
"DevDetail_Events_CheckBox": "Hide connection events",
"DevDetail_GoToNetworkNode": "Navigate to the Network page of the given node.",
"DevDetail_Icon": "Icon",
"DevDetail_Icon_Descr": "Enter a font awesome icon name without the fa- prefix or with complete class, e.g.: fa fa-brands fa-apple.",
"DevDetail_Loading": "Loading...",
"DevDetail_Loading": "Loading",
"DevDetail_MainInfo_Comments": "Comments",
"DevDetail_MainInfo_Favorite": "Favorite",
"DevDetail_MainInfo_Group": "Group",
@@ -102,10 +103,11 @@
"DevDetail_MainInfo_Type": "Type",
"DevDetail_MainInfo_Vendor": "Vendor",
"DevDetail_MainInfo_mac": "MAC",
"DevDetail_NavToChildNode": "Open children node",
"DevDetail_Network_Node_hover": "Select the parent network device the current device is connected to, to populate the Network tree.",
"DevDetail_Network_Port_hover": "The port this device is connected to on the parent network device. If left empty a wifi icon is displayed in the Network tree.",
"DevDetail_Nmap_Scans": "Manual Nmap Scans",
"DevDetail_Nmap_Scans_desc": "Here you can execute manual NMAP scans. You can also schedule regular automatic NMAP scans via the Services & Ports (NMAP) plugin. Head to <a href='/settings.php' target='_blank'>Settings</a> to find out more",
"DevDetail_Nmap_Scans_desc": "Here you can execute manual NMAP scans. You can also schedule regular automatic NMAP scans via the Services & Ports (NMAP) plugin. Head to <a href=\"https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/nmap_scan\" target=\"_blank\">Docs</a> to find out more",
"DevDetail_Nmap_buttonDefault": "Default Scan",
"DevDetail_Nmap_buttonDefault_text": "Default Scan: Nmap scans the top 1,000 ports for each scan protocol requested. This catches roughly 93% of the TCP ports and 49% of the UDP ports. (about 5 seconds)",
"DevDetail_Nmap_buttonDetail": "Detailed Scan",
@@ -177,7 +179,7 @@
"DevDetail_Tools_WOL": "Send WoL command to ",
"DevDetail_Tools_WOL_noti": "Wake-on-LAN",
"DevDetail_Tools_WOL_noti_text": "The Wake-on-LAN command is sent to the broadcast address. If the target is not in the subnet/VLAN of NetAlertX, the target device will not respond.",
"DevDetail_Type_hover": "The Type of the device. If you select any of the pre-defined network devices (e.g.: AP, Firewall, Router, Switch...) they will show up in the Network tree configuration as possible parent network nodes.",
"DevDetail_Type_hover": "The Type of the device. If you select any of the pre-defined network devices (e.g.: AP, Firewall, Router, Switch) they will show up in the Network tree configuration as possible parent network nodes.",
"DevDetail_Vendor_hover": "Vendor should be auto-detected. You can overwrite or add your custom value.",
"DevDetail_WOL_Title": "<i class=\"fa fa-power-off\"></i> Wake-on-LAN",
"DevDetail_button_AddIcon": "Add new Icon",
@@ -194,19 +196,20 @@
"DevDetail_button_Save": "Save",
"DeviceEdit_ValidMacIp": "Enter a valid <b>Mac</b> and <b>IP</b> address.",
"Device_MultiEdit": "Multi-edit",
"Device_MultiEdit_Backup": "Careful, entering wrong values below will break your setup. Please backup your database or Devices configuration first (<a href=\"php/server/devices.php?action=ExportCSV\">click to download <i class=\"fa-solid fa-download fa-bounce\"></i></a>). Read how to recover Devices from this file in the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md#scenario-2-corrupted-database\" target=\"_blank\">Backups documentation</a>.",
"Device_MultiEdit_Backup": "Careful, entering wrong values below will break your setup. Please backup your database or Devices configuration first (<a href=\"php/server/devices.php?action=ExportCSV\">click to download <i class=\"fa-solid fa-download fa-bounce\"></i></a>). Read how to recover Devices from this file in the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/BACKUPS.md#scenario-2-corrupted-database\" target=\"_blank\">Backups documentation</a>. In order to apply your changes click the <b>Save<i class=\"fa-solid fa-save\"></i></b> icon on each field you want to update.",
"Device_MultiEdit_Fields": "Edit fields:",
"Device_MultiEdit_MassActions": "Mass actions:",
"Device_MultiEdit_Tooltip": "Careful. Clicking this will apply the value on the left to all devices selected above.",
"Device_Searchbox": "Search",
"Device_Shortcut_AllDevices": "My Devices",
"Device_Shortcut_AllDevices": "My devices",
"Device_Shortcut_AllNodes": "All Nodes",
"Device_Shortcut_Archived": "Archived",
"Device_Shortcut_Connected": "Connected",
"Device_Shortcut_Devices": "Devices",
"Device_Shortcut_DownAlerts": "Down & Offline",
"Device_Shortcut_DownOnly": "Down",
"Device_Shortcut_Favorites": "Favorites",
"Device_Shortcut_NewDevices": "New Devices",
"Device_Shortcut_NewDevices": "New devices",
"Device_Shortcut_OnlineChart": "Device presence",
"Device_TableHead_AlertDown": "Alert Down",
"Device_TableHead_Connected_Devices": "Connections",
@@ -226,9 +229,11 @@
"Device_TableHead_Name": "Name",
"Device_TableHead_NetworkSite": "Network Site",
"Device_TableHead_Owner": "Owner",
"Device_TableHead_ParentRelType": "Relationship Type",
"Device_TableHead_Parent_MAC": "Parent network node",
"Device_TableHead_Port": "Port",
"Device_TableHead_PresentLastScan": "Presence",
"Device_TableHead_ReqNicsOnline": "Require NICs Online",
"Device_TableHead_RowID": "Row ID",
"Device_TableHead_Rowid": "Row ID",
"Device_TableHead_SSID": "SSID",
@@ -251,7 +256,7 @@
"ENCRYPTION_KEY_name": "Encryption key",
"Email_display_name": "Email",
"Email_icon": "<i class=\"fa fa-at\"></i>",
"Events_Loading": "Loading...",
"Events_Loading": "Loading",
"Events_Periodselect_All": "All Info",
"Events_Periodselect_LastMonth": "Last Month",
"Events_Periodselect_LastWeek": "Last Week",
@@ -262,7 +267,7 @@
"Events_Shortcut_DownAlerts": "Down Alerts",
"Events_Shortcut_Events": "Events",
"Events_Shortcut_MissSessions": "Missing Sessions",
"Events_Shortcut_NewDevices": "New Devices",
"Events_Shortcut_NewDevices": "New devices",
"Events_Shortcut_Sessions": "Sessions",
"Events_Shortcut_VoidSessions": "Voided Sessions",
"Events_TableHead_AdditionalInfo": "Additional Info",
@@ -288,9 +293,9 @@
"GRAPHQL_PORT_name": "GraphQL port",
"Gen_Action": "Action",
"Gen_Add": "Add",
"Gen_AddDevice": "Add Device",
"Gen_AddDevice": "Add device",
"Gen_Add_All": "Add all",
"Gen_All_Devices": "All Devices",
"Gen_All_Devices": "All devices",
"Gen_AreYouSure": "Are you sure?",
"Gen_Backup": "Run Backup",
"Gen_Cancel": "Cancel",
@@ -304,6 +309,7 @@
"Gen_Filter": "Filter",
"Gen_Generate": "Generate",
"Gen_LockedDB": "ERROR - DB might be locked - Check F12 Dev tools -> Console or try later.",
"Gen_NetworkMask": "Network mask",
"Gen_Offline": "Offline",
"Gen_Okay": "Ok",
"Gen_Online": "Online",
@@ -320,7 +326,8 @@
"Gen_Select": "Select",
"Gen_SelectIcon": "<i class=\"fa-solid fa-chevron-down fa-fade\"></i>",
"Gen_SelectToPreview": "Select to preview",
"Gen_Selected_Devices": "Selected Devices:",
"Gen_Selected_Devices": "Selected devices:",
"Gen_Subnet": "Subnet",
"Gen_Switch": "Switch",
"Gen_Upd": "Updated successfully",
"Gen_Upd_Fail": "Update failed",
@@ -333,15 +340,15 @@
"Gen_create_new_device_info": "Devices are typically discovered using <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">plugins</a>. However, in certain cases, you may need to add devices manually. To explore specific scenarios check the <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/REMOTE_NETWORKS.md\">Remote Networks documentation</a>.",
"General_display_name": "General",
"General_icon": "<i class=\"fa fa-gears\"></i>",
"HRS_TO_KEEP_NEWDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices marked as <b>New Device</b> will be deleted if their <b>First Session</b> time was older than the specified hours in this setting. Use this setting if you want to auto-delete <b>New Devices</b> after <code>X</code> hours.",
"HRS_TO_KEEP_NEWDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices marked as <b>New device</b> will be deleted if their <b>First Session</b> time was older than the specified hours in this setting. Use this setting if you want to auto-delete <b>New devices</b> after <code>X</code> hours.",
"HRS_TO_KEEP_NEWDEV_name": "Delete new devices after",
"HRS_TO_KEEP_OFFDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices that are <b>Offline</b> and their <b>Last Connection</b> date time is older than the specified hours in this setting, will be deleted. Use this setting if you want to auto-delete <b>Offline Devices</b> after <code>X</code> hours being offline.",
"HRS_TO_KEEP_OFFDEV_description": "This is a maintenance setting <b>DELETING devices</b>. If enabled (<code>0</code> is disabled), devices that are <b>Offline</b> and their <b>Last Connection</b> date time is older than the specified hours in this setting, will be deleted. Use this setting if you want to auto-delete <b>Offline devices</b> after <code>X</code> hours being offline.",
"HRS_TO_KEEP_OFFDEV_name": "Delete offline devices after",
"LOADED_PLUGINS_description": "Which Plugins to load. Adding plugins might slow the application. Read more about which plugins need to be enabled, types, or scanning options in the <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/docs/PLUGINS.md\">plugins docs</a>. Unloaded plugins will lose your settings. Only <code>disabled</code> plugins can be unloaded.",
"LOADED_PLUGINS_name": "Loaded plugins",
"LOG_LEVEL_description": "This setting will enable more verbose logging. Useful for debugging events writing into the database.",
"LOG_LEVEL_name": "Print additional logging",
"Loading": "Loading...",
"Loading": "Loading",
"Login_Box": "Enter your password",
"Login_Default_PWD": "Default password \"123456\" is still active.",
"Login_Info": "Passwords are set via the Set Password plugin. Check the <a target=\"_blank\" href=\"https://github.com/jokob-sk/NetAlertX/tree/main/front/plugins/set_password\">SETPWD docs</a> if you have issues logging in.",
@@ -359,20 +366,20 @@
"Maint_PurgeLog": "Purge log",
"Maint_RestartServer": "Restart server",
"Maint_Restart_Server_noti_text": "Are you sure you want to restart the backend server? This may casue app inconsistency. Backup your setup first. <br/> <br/> Note: This may take a few minutes.",
"Maintenance_InitCheck": "Init Check",
"Maintenance_InitCheck_Checking": "Checking...",
"Maintenance_InitCheck": "Init check",
"Maintenance_InitCheck_Checking": "Checking",
"Maintenance_InitCheck_QuickSetupGuide": "Make sure you followed the <a href=\"https://jokob-sk.github.io/NetAlertX/INITIAL_SETUP/\" target=\"_blank\">quick setup guide</a>.",
"Maintenance_InitCheck_Success": "Application initialized succesfully!",
"Maintenance_ReCheck": "Retry Check",
"Maintenance_ReCheck": "Retry check",
"Maintenance_Running_Version": "Installed version",
"Maintenance_Status": "Status",
"Maintenance_Title": "Maintenance tools",
"Maintenance_Tool_DownloadConfig": "Settings Export",
"Maintenance_Tool_DownloadConfig": "Settings export",
"Maintenance_Tool_DownloadConfig_text": "Download a full backup of your Settings configuration stored in the <code>app.conf</code> file.",
"Maintenance_Tool_DownloadWorkflows": "Workflows Export",
"Maintenance_Tool_DownloadWorkflows": "Workflows export",
"Maintenance_Tool_DownloadWorkflows_text": "Download a full backup of your Workflows stored in the <code>workflows.json</code> file.",
"Maintenance_Tool_ExportCSV": "Devices Export (csv)",
"Maintenance_Tool_ExportCSV_noti": "Devices Export (csv)",
"Maintenance_Tool_ExportCSV": "Devices export (csv)",
"Maintenance_Tool_ExportCSV_noti": "Devices export (csv)",
"Maintenance_Tool_ExportCSV_noti_text": "Are you sure you want to generate a CSV file?",
"Maintenance_Tool_ExportCSV_text": "Generate a CSV (comma separated value) file containing the list of Devices including the Network relationships between Network Nodes and connected devices. You can also trigger this by accessing this URL <code>your_NetAlertX_url/php/server/devices.php?action=ExportCSV</code> or by enabling the <a href=\"settings.php#CSVBCKP_header\">CSV Backup</a> plugin.",
"Maintenance_Tool_ImportCSV": "Devices Import (csv)",
@@ -403,26 +410,26 @@
"Maintenance_Tool_del_ActHistory_noti": "Delete network activity",
"Maintenance_Tool_del_ActHistory_noti_text": "Are you sure you want to reset the network activity?",
"Maintenance_Tool_del_ActHistory_text": "The network activity graph is reset. This does not affect the events.",
"Maintenance_Tool_del_alldev": "Delete all Devices",
"Maintenance_Tool_del_alldev_noti": "Delete Devices",
"Maintenance_Tool_del_alldev": "Delete all devices",
"Maintenance_Tool_del_alldev_noti": "Delete devices",
"Maintenance_Tool_del_alldev_noti_text": "Are you sure you want to delete all devices?",
"Maintenance_Tool_del_alldev_text": "Before using this function, please make a backup. The deletion cannot be undone. All devices will be deleted from the database.",
"Maintenance_Tool_del_allevents": "Delete Events (Reset Presence)",
"Maintenance_Tool_del_allevents30": "Delete all Events older than 30 days",
"Maintenance_Tool_del_allevents30_noti": "Delete Events",
"Maintenance_Tool_del_allevents30_noti_text": "Are you sure you want to delete all Events older than 30 days? This resets Presence of all Devices.",
"Maintenance_Tool_del_allevents30_noti_text": "Are you sure you want to delete all Events older than 30 days? This resets presence of all devices.",
"Maintenance_Tool_del_allevents30_text": "Before using this function, please make a backup. The deletion cannot be undone. All events older than 30 days in the database will be deleted. At that moment the presence of all devices will be reset. This can lead to invalid sessions. This means that devices are displayed as \"present\" although they are offline. A scan while the device in question is online solves the problem.",
"Maintenance_Tool_del_allevents_noti": "Delete Events",
"Maintenance_Tool_del_allevents_noti_text": "Are you sure you want to delete all Events? This resets Presence of all Devices.",
"Maintenance_Tool_del_allevents_noti_text": "Are you sure you want to delete all Events? This resets presence of all devices.",
"Maintenance_Tool_del_allevents_text": "Before using this function, please make a backup. The deletion cannot be undone. All events in the database will be deleted. At that moment the presence of all devices will be reset. This can lead to invalid sessions. This means that devices are displayed as \"present\" although they are offline. A scan while the device in question is online solves the problem.",
"Maintenance_Tool_del_empty_macs": "Delete Devices with empty MACs",
"Maintenance_Tool_del_empty_macs_noti": "Delete Devices",
"Maintenance_Tool_del_empty_macs": "Delete devices with empty MACs",
"Maintenance_Tool_del_empty_macs_noti": "Delete devices",
"Maintenance_Tool_del_empty_macs_noti_text": "Are you sure you want to delete all devices with empty MAC addresses?<br>(maybe you prefer to archive it)",
"Maintenance_Tool_del_empty_macs_text": "Before using this function, please make a backup. The deletion cannot be undone. All devices without MAC will be deleted from the database.",
"Maintenance_Tool_del_selecteddev": "Delete selected devices",
"Maintenance_Tool_del_selecteddev_text": "Before using this function, please make a backup. The deletion cannot be undone. Selected devices will be deleted from the database.",
"Maintenance_Tool_del_unknowndev": "Delete (unknown) Devices",
"Maintenance_Tool_del_unknowndev_noti": "Delete (unknown) Devices",
"Maintenance_Tool_del_unknowndev": "Delete (unknown) devices",
"Maintenance_Tool_del_unknowndev_noti": "Delete (unknown) devices",
"Maintenance_Tool_del_unknowndev_noti_text": "Are you sure you want to delete all (unknown) and (name not found) devices?",
"Maintenance_Tool_del_unknowndev_text": "Before using this function, please make a backup. The deletion cannot be undone. All devices named (unknown) will be deleted from the database.",
"Maintenance_Tool_displayed_columns_text": "Change the visibility and order of the columns in the <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Devices</b></a> page.",
@@ -446,7 +453,7 @@
"Maintenance_Tools_Tab_UISettings": "UI Settings",
"Maintenance_arp_status": "Scan Status",
"Maintenance_arp_status_off": "is currently disabled",
"Maintenance_arp_status_on": "scan(s) currently running",
"Maintenance_arp_status_on": "scanning in progress",
"Maintenance_built_on": "Built on",
"Maintenance_current_version": "You are up-to-date. Check out what <a href=\"https://github.com/jokob-sk/NetAlertX/issues/138\" target=\"_blank\">I am working on</a>.",
"Maintenance_database_backup": "DB Backups",
@@ -466,10 +473,10 @@
"Maintenance_themeselector_lable": "Select Skin",
"Maintenance_themeselector_text": "The change takes place on the server side, so it affects all devices in use.",
"Maintenance_version": "App updates",
"NETWORK_DEVICE_TYPES_description": "Which device types are allowed to be used as network devices in the Network view. The device type has to match exactly the <code>Type</code> setting on a specific device in Device details. Add it on the Device via the <code>+</code> button. Do not remove existing types, only add new ones.",
"NETWORK_DEVICE_TYPES_description": "Which device types are allowed to be used as network devices in the Network view. The device type has to match exactly the <code>Type</code> setting on a specific device in Device details. Add it on the device via the <code>+</code> button. Do not remove existing types, only add new ones.",
"NETWORK_DEVICE_TYPES_name": "Network device types",
"Navigation_About": "About",
"Navigation_AppEvents": "App Events",
"Navigation_AppEvents": "App events",
"Navigation_Devices": "Devices",
"Navigation_Donations": "Donations",
"Navigation_Events": "Events",
@@ -480,38 +487,40 @@
"Navigation_Notifications": "Notifications",
"Navigation_Plugins": "Plugins",
"Navigation_Presence": "Presence",
"Navigation_Report": "Sent Reports",
"Navigation_Report": "Sent reports",
"Navigation_Settings": "Settings",
"Navigation_SystemInfo": "System info",
"Navigation_Workflows": "Workflows",
"Network_Assign": "Connect to the above <i class=\"fa fa-server\"></i> Network node",
"Network_Cant_Assign": "Can't assign the root Internet node as a child leaf node.",
"Network_Cant_Assign_No_Node_Selected": "Can't assign, no parent node selected.",
"Network_Configuration_Error": "Configuration Error",
"Network_Connected": "Connected devices",
"Network_ManageAdd": "Add Device",
"Network_ManageAdd_Name": "Device Name",
"Network_Devices": "Network devices",
"Network_ManageAdd": "Add device",
"Network_ManageAdd_Name": "Device name",
"Network_ManageAdd_Name_text": "Name without special characters",
"Network_ManageAdd_Port": "Port Count",
"Network_ManageAdd_Port_text": "leave blank for wifi and powerline",
"Network_ManageAdd_Submit": "Add Device",
"Network_ManageAdd_Type": "Device Type",
"Network_ManageAdd_Submit": "Add device",
"Network_ManageAdd_Type": "Device type",
"Network_ManageAdd_Type_text": "-- Select Type --",
"Network_ManageAssign": "Assign",
"Network_ManageDel": "Delete Device",
"Network_ManageDel": "Delete device",
"Network_ManageDel_Name": "Device to delete",
"Network_ManageDel_Name_text": "-- Select Device --",
"Network_ManageDel_Name_text": "-- Select device --",
"Network_ManageDel_Submit": "Delete",
"Network_ManageDevices": "Manage Devices",
"Network_ManageEdit": "Update Device",
"Network_ManageDevices": "Manage devices",
"Network_ManageEdit": "Update device",
"Network_ManageEdit_ID": "Device to update",
"Network_ManageEdit_ID_text": "-- Select Device for editing --",
"Network_ManageEdit_Name": "New Device Name",
"Network_ManageEdit_ID_text": "-- Select device for editing --",
"Network_ManageEdit_Name": "New device name",
"Network_ManageEdit_Name_text": "Name without special characters",
"Network_ManageEdit_Port": " New Port Count",
"Network_ManageEdit_Port_text": "leave blank for wifi and powerline",
"Network_ManageEdit_Submit": "Save Changes",
"Network_ManageEdit_Type": "New Device Type",
"Network_ManageEdit_Type_text": "-- Select Type --",
"Network_ManageEdit_Type": "New device type",
"Network_ManageEdit_Type_text": "-- Select type --",
"Network_ManageLeaf": "Manage assignment",
"Network_ManageUnassign": "Unassign",
"Network_NoAssignedDevices": "This network node does not have any assigned devices (leaf nodes). Assign one from bellow or go to the <b><i class=\"fa fa-info-circle\"></i> Details</b> tab of any device in <a href=\"devices.php\"><b> <i class=\"fa fa-laptop\"></i> Devices</b></a>, and assign it to a network <b><i class=\"fa fa-server\"></i> Node (MAC)</b> and <b><i class=\"fa fa-ethernet\"></i> Port</b> there.",
@@ -522,13 +531,15 @@
"Network_Root": "Root node",
"Network_Root_Not_Configured": "Select a network device type, for example a <b>Gateway</b>, in the <b>Type</b> field of the <a href=\"deviceDetails.php?mac=Internet\">the Internet root device</a> to start configuring this screen. <br/><br/> More documentation can be found in the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/NETWORK_TREE.md\" target=\"_blank\">How to setup your Network page</a> guide",
"Network_Root_Unconfigurable": "Unconfigurable root",
"Network_ShowArchived": "Show archived",
"Network_ShowOffline": "Show offline",
"Network_Table_Hostname": "Hostname",
"Network_Table_IP": "IP",
"Network_Table_State": "State",
"Network_Title": "Network overview",
"Network_UnassignedDevices": "Unassigned devices",
"Notifications_All": "All Notifications",
"Notifications_Mark_All_Read": "Mark All Read",
"Notifications_All": "All notifications",
"Notifications_Mark_All_Read": "Mark all read",
"PIALERT_WEB_PASSWORD_description": "The default password is <code>123456</code>. To change the password run <code>/app/back/pialert-cli</code> in the container or use the <a onclick=\"toggleAllSettings()\" href=\"#SETPWD_RUN\"><code>SETPWD_RUN</code> Set password plugin</a>.",
"PIALERT_WEB_PASSWORD_name": "Login password",
"PIALERT_WEB_PROTECTION_description": "When enabled a login dialog is displayed. Read below carefully if you get locked out of your instance.",
@@ -554,17 +565,17 @@
"Presence_Key_OnlineNow_desc": "Device detected in the last scan as online.",
"Presence_Key_OnlinePast": "Past online",
"Presence_Key_OnlinePastMiss": "Past online (miss-match)",
"Presence_Key_OnlinePastMiss_desc": "Device online in the past, but currently offline, but the start session might be missing or has conflicting data. (might be a bug - please submit a PR if you know how to fix it - I'm a bit lost in code here)",
"Presence_Key_OnlinePastMiss_desc": "Device online in the past, but currently offline, but the start session might be missing or has conflicting data.",
"Presence_Key_OnlinePast_desc": "Device online in the past, but currently offline.",
"Presence_Loading": "Loading...",
"Presence_Shortcut_AllDevices": "My Devices",
"Presence_Loading": "Loading",
"Presence_Shortcut_AllDevices": "My devices",
"Presence_Shortcut_Archived": "Archived",
"Presence_Shortcut_Connected": "Connected",
"Presence_Shortcut_Devices": "Devices",
"Presence_Shortcut_DownAlerts": "Down Alerts",
"Presence_Shortcut_Favorites": "Favorites",
"Presence_Shortcut_NewDevices": "New Devices",
"Presence_Title": "Presence by Device",
"Presence_Shortcut_NewDevices": "New devices",
"Presence_Title": "Presence by device",
"REFRESH_FQDN_description": "Rescans all devices and refreshes their Fully Qualified Domain Name (FQDN). If disabled, only devices without a known name are scanned to improve performance. In this case, FQDN is updated only during initial device discovery.",
"REFRESH_FQDN_name": "Refresh FQDN",
"REPORT_DASHBOARD_URL_description": "This URL is used as the base for generating links in HTML reports (e.g.: emails). Enter full URL starting with <code>http://</code> including the port number (no trailing slash <code>/</code>).",
@@ -574,8 +585,8 @@
"REPORT_MAIL_name": "Enable email",
"REPORT_TITLE": "Report",
"RandomMAC_hover": "Autodetected - indicates if the device randomizes it's MAC address. You can exclude specific MACs with the UI_NOT_RANDOM_MAC setting. Click to find out more.",
"Reports_Sent_Log": "Sent Reports Log",
"SCAN_SUBNETS_description": "Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG) rely on scanning specific network interfaces and subnets. Check the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnets documentation</a> for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface. <br/> <br/> An alternative to on-network scanners is to enable some other Device scanners/importers that don't rely on NetAlert<sup>X</sup> having access to the network (UNIFI, dhcp.leases, PiHole, etc.). <br/> <br/> Note: The scan time itself depends on the number of IP addresses to check, so set this up carefully with the appropriate network mask and interface.",
"Reports_Sent_Log": "Sent reports log",
"SCAN_SUBNETS_description": "Most on-network scanners (ARP-SCAN, NMAP, NSLOOKUP, DIG) rely on scanning specific network interfaces and subnets. Check the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/SUBNETS.md\" target=\"_blank\">subnets documentation</a> for help on this setting, especially VLANs, what VLANs are supported, or how to figure out the network mask and your interface. <br/> <br/> An alternative to on-network scanners is to enable some other device scanners/importers that don't rely on NetAlert<sup>X</sup> having access to the network (UNIFI, dhcp.leases, PiHole, etc.). <br/> <br/> Note: The scan time itself depends on the number of IP addresses to check, so set this up carefully with the appropriate network mask and interface.",
"SCAN_SUBNETS_name": "Networks to scan",
"SYSTEM_TITLE": "System Information",
"Setting_Override": "Override value",
@@ -583,8 +594,9 @@
"Settings_Metadata_Toggle": "Show/hide metadata for the given setting.",
"Settings_Show_Description": "Show setting description.",
"Settings_device_Scanners_desync": "⚠ Device scanner schedules are out-of-sync.",
"Settings_device_Scanners_desync_popup": "Schedules of devices scanners (<code>*_RUN_SCHD</code>) are not the same. This will result into inconsistent device online/offline notifications. Unless this is intended, please use the same schedule for all enabled <b>🔍Device scanners</b>.",
"Settings_device_Scanners_desync_popup": "Schedules of devices scanners (<code>*_RUN_SCHD</code>) are not the same. This will result into inconsistent device online/offline notifications. Unless this is intended, please use the same schedule for all enabled <b>🔍device scanners</b>.",
"Speedtest_Results": "Speedtest Results",
"Systeminfo_AvailableIps": "Available IPs",
"Systeminfo_CPU": "CPU",
"Systeminfo_CPU_Cores": "CPU Cores:",
"Systeminfo_CPU_Name": "CPU Name:",
@@ -658,18 +670,18 @@
"Systeminfo_System_Uname": "Uname:",
"Systeminfo_System_Uptime": "Uptime:",
"Systeminfo_This_Client": "This Client",
"Systeminfo_USB_Devices": "USB Devices",
"Systeminfo_USB_Devices": "USB devices",
"TICKER_MIGRATE_TO_NETALERTX": "⚠ Old mount locations detected. Follow <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/MIGRATION.md\" target=\"_blank\">this guide</a> to migrate to the new <code>/app/config</code> and <code>/app/db</code> folders and the <code>netalertx</code> container.",
"TIMEZONE_description": "Time zone to display stats correctly. Find your time zone <a target=\"_blank\" href=\"https://en.wikipedia.org/wiki/List_of_tz_database_time_zones\" rel=\"nofollow\">here</a>.",
"TIMEZONE_name": "Time zone",
"UI_DEV_SECTIONS_description": "Select which UI elements to hide in the Devices pages.",
"UI_DEV_SECTIONS_name": "Hide Devices Sections",
"UI_DEV_SECTIONS_description": "Select which UI elements to hide in the devices pages.",
"UI_DEV_SECTIONS_name": "Hide devices sections",
"UI_ICONS_description": "A list of pre-defined icons. Proceed with caution, the preferred way to add icons is described in the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/ICONS.md\" target=\"_blank\">Icons documentation</a>. You can add a base64-encoded SVG HTML or Font-awesome HTML tag.",
"UI_ICONS_name": "Pre-defined icons",
"UI_LANG_description": "Select the preferred UI language. Help translating or suggest languages in the online portal of <a href=\"https://hosted.weblate.org/projects/pialert/core/\" target=\"_blank\">Weblate</a>.",
"UI_LANG_name": "UI Language",
"UI_MY_DEVICES_description": "Devices of which statuses should be shown in the default <b>My Devices</b> view.",
"UI_MY_DEVICES_name": "Show in My Devices view",
"UI_MY_DEVICES_description": "Devices of which statuses should be shown in the default <b>My devices</b> view.",
"UI_MY_DEVICES_name": "Show in My devices view",
"UI_NOT_RANDOM_MAC_description": "Mac prefixes which shouldn't be marked as Random devices. Enter for example <code>52</code> to exclude devices starting with <code>52:xx:xx:xx:xx:xx</code> from being marked as devices with a random MAC address.",
"UI_NOT_RANDOM_MAC_name": "Don't mark as Random",
"UI_PRESENCE_description": "Select what statuses should be shown in the <b>Device presence</b> chart in the <a href=\"/devices.php\" target=\"_blank\">Devices</a> page.",
@@ -704,29 +716,26 @@
"WF_Trigger": "Trigger",
"WF_Trigger_event_type": "Event type",
"WF_Trigger_type": "Trigger type",
"add_icon_event_icon": "fa-square-plus",
"add_icon_event_tooltip": "Add new icon",
"add_option_event_icon": "fa-square-plus",
"add_option_event_tooltip": "Add new value",
"copy_icons_event_icon": "fa-copy",
"copy_icons_event_tooltip": "Overwrite icons of all devices with the same device type",
"devices_old": "Refreshing...",
"devices_old": "Refreshing",
"general_event_description": "The event you have triggered might take a while until background processes finish. The execution ended once the below execution queue empties (Check the <a href='/maintenance.php#tab_Logging'>error log</a> if you encounter issues). <br/> <br/> Execution queue:",
"general_event_title": "Executing an ad-hoc event",
"go_to_node_event_icon": "fa-square-up-right",
"go_to_device_event_tooltip": "Navigate to the device",
"go_to_node_event_tooltip": "Navigate to the Network page of the given node",
"new_version_available": "A new version is available.",
"report_guid": "Notification guid:",
"report_guid_missing": "Linked notification not found. There is a small delay between recently sent notifications and them being available. Referesh your page and cache after a few seconds. It's also possible the selected notification have been deleted during maintenance as specified in the <code>DBCLNP_NOTIFI_HIST</code> setting. <br/> <br/>The latest notification is displayed instead. The missing notification has the following GUID:",
"report_select_format": "Select Format:",
"report_time": "Notification time:",
"run_event_icon": "fa-play",
"run_event_tooltip": "Enable the setting and save your changes at first before you run it.",
"select_icon_event_tooltip": "Select icon",
"settings_core_icon": "fa-solid fa-gem",
"settings_core_label": "Core",
"settings_device_scanners": "Device scanners used to discover devices that write into the CurrentScan database table.",
"settings_device_scanners_icon": "fa-solid fa-magnifying-glass-plus",
"settings_device_scanners_info": "Load even more Device Scanners with the <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a> setting",
"settings_device_scanners_info": "Load more device scanners with the <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a> setting",
"settings_device_scanners_label": "Device scanners",
"settings_enabled": "Enabled settings",
"settings_enabled_icon": "fa-solid fa-toggle-on",
@@ -735,7 +744,7 @@
"settings_imported_label": "Settings imported",
"settings_missing": "Not all settings loaded! High load on the database or app startup sequence. Click the 🔄 reload button in the top.",
"settings_missing_block": "Error: Settings not loaded correctly. Click the reload button 🔄 at the top, alternatively, check the browser log for details (F12).",
"settings_old": "Importing settings and re-initializing...",
"settings_old": "Importing settings and re-initializing",
"settings_other_scanners": "Other, non-device scanner plugins that are currently enabled.",
"settings_other_scanners_icon": "fa-solid fa-recycle",
"settings_other_scanners_label": "Other scanners",
@@ -744,10 +753,9 @@
"settings_publishers_info": "Load more Publishers with the <a href=\"/settings.php#LOADED_PLUGINS\">LOADED_PLUGINS</a> setting",
"settings_publishers_label": "Publishers",
"settings_readonly": "Can't READ or WRITE <code>app.conf</code>. Try restarting the container and read the <a href=\"https://github.com/jokob-sk/NetAlertX/blob/main/docs/FILE_PERMISSIONS.md\" target=\"_blank\">file permissions documentation</a>",
"settings_saved": "<br/>Settings saved. <br/> Reloading... <br/><i class=\"ion ion-ios-loop-strong fa-spin fa-2x fa-fw\"></i> <br/>",
"settings_saved": "<br/>Settings saved. <br/> Reloading <br/><i class=\"ion ion-ios-loop-strong fa-spin fa-2x fa-fw\"></i> <br/>",
"settings_system_icon": "fa-solid fa-gear",
"settings_system_label": "System",
"settings_update_item_warning": "Update the value below. Be careful to follow the previous format. <b>Validation is not performed.</b>",
"test_event_icon": "fa-vial-circle-check",
"test_event_tooltip": "Save your changes at first before you test your settings."
}

Some files were not shown because too many files have changed in this diff Show More