iobroker.eos-admin 7.9.96 → 7.9.98
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL_TEST_V7.9.98.md +39 -0
- package/MERGE_UPDATE_README_V7.9.98.md +29 -0
- package/NEXOWATT_EOS_BUILD_INFO.json +20 -18
- package/PUBLISH_STABLE_V7.9.98.md +33 -0
- package/README.md +16 -6
- package/README_STABILITY_V7.9.98.md +22 -0
- package/RELEASE_ACCEPTANCE_V7.9.98.md +48 -0
- package/RELEASE_NOTES_V7.9.98.md +32 -0
- package/adminWww/assets/Intro-DkwRiz1n-v84.js +1 -1
- package/adminWww/assets/bootstrap-COulQZax-v84.js +3 -3
- package/adminWww/assets/index-D2ymscJA-v84.js +1 -1
- package/adminWww/css/eos-ems-overview.css +21 -0
- package/adminWww/css/nexowatt-native-shell.css +174 -40
- package/adminWww/index.html +15 -15
- package/adminWww/js/eos-account-management.js +26 -13
- package/adminWww/js/eos-assistant.js +1 -1
- package/adminWww/js/eos-ems-overview.js +136 -39
- package/adminWww/js/eos-role-bootstrap.js +7 -7
- package/adminWww/js/eos-role-ui.js +2 -2
- package/adminWww/js/nexowatt-native-shell.js +9 -2
- package/adminWww/static/js/nexowatt-stable-login.js +28 -62
- package/adminWww/static/js/nexowatt-stable-v98.js +33 -0
- package/build/lib/web.js +112 -79
- package/build/main.js +1 -1
- package/io-package.json +15 -5
- package/package.json +14 -12
- package/tools/nexowatt-account-management-selftest.cjs +16 -57
- package/tools/nexowatt-account-password-flow-selftest.cjs +186 -0
- package/tools/nexowatt-clean-legacy-runtime.cjs +33 -10
- package/tools/nexowatt-login-layout-selftest.cjs +12 -81
- package/tools/nexowatt-merge-update-selftest.cjs +3 -1
- package/tools/nexowatt-modern-ui-selftest.cjs +2 -2
- package/tools/nexowatt-password-write-selftest.cjs +48 -0
- package/tools/nexowatt-runtime-cleanup-selftest.cjs +9 -1
- package/tools/nexowatt-stable-v98-selftest.cjs +14 -0
- package/tools/nexowatt-sync-release-version.cjs +42 -1
- package/tools/nexowatt-ui-overview-runtime-selftest.cjs +11 -11
- package/tools/nexowatt-validate-package.cjs +20 -11
- package/tools/nexowatt-version-sync-selftest.cjs +18 -1
- package/INSTALL_TEST_V7.9.96.md +0 -11
- package/MERGE_UPDATE_README_V7.9.96.md +0 -5
- package/PUBLISH_STABLE_V7.9.96.md +0 -10
- package/README_STABILITY_V7.9.96.md +0 -11
- package/RELEASE_ACCEPTANCE_V7.9.96.md +0 -10
- package/RELEASE_NOTES_V7.9.96.md +0 -12
- package/adminWww/static/js/nexowatt-stable-v96.js +0 -82
- package/tools/nexowatt-stable-v96-selftest.cjs +0 -13
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Installationstest – NexoWatt EOS Admin 7.9.98
|
|
2
|
+
|
|
3
|
+
## Installation nach der npm-Veröffentlichung
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
cd /opt/iobroker
|
|
7
|
+
iobroker stop eos-admin.0
|
|
8
|
+
npm install --no-save --omit=dev iobroker.eos-admin@7.9.98
|
|
9
|
+
iobroker upload eos-admin
|
|
10
|
+
iobroker restart eos-admin.0
|
|
11
|
+
iobroker restart nexowatt-ui.0
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Version prüfen:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
node -p "require('/opt/iobroker/node_modules/iobroker.eos-admin/package.json').version"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Erwartet:
|
|
21
|
+
|
|
22
|
+
```text
|
|
23
|
+
7.9.98
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Danach im Browser eine vollständige Aktualisierung mit `Strg + F5` durchführen.
|
|
27
|
+
|
|
28
|
+
## Installation des geprüften TGZ ohne Registry
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cd /opt/iobroker
|
|
32
|
+
iobroker stop eos-admin.0
|
|
33
|
+
npm install --no-save --omit=dev /PFAD/iobroker.eos-admin-7.9.98.tgz
|
|
34
|
+
iobroker upload eos-admin
|
|
35
|
+
iobroker restart eos-admin.0
|
|
36
|
+
iobroker restart nexowatt-ui.0
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Anschließend die vollständige Abnahme aus `RELEASE_ACCEPTANCE_V7.9.98.md` durchführen.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# NexoWatt EOS Admin 7.9.98 – Merge-Update
|
|
2
|
+
|
|
3
|
+
Die Datei `NexoWatt_EOS_Admin_7.9.98_STABLE_MERGE_FLAT.zip` ist absichtlich flach aufgebaut. `package.json`, `io-package.json`, `src-admin`, `adminWww`, `build` und alle übrigen Repository-Dateien liegen direkt auf der ersten ZIP-Ebene.
|
|
4
|
+
|
|
5
|
+
## Anwendung auf einem vorhandenen Windows-Arbeitsordner
|
|
6
|
+
|
|
7
|
+
1. Den bestehenden Repository-Ordner sichern oder committen.
|
|
8
|
+
2. Die flache Merge-ZIP direkt in den vorhandenen Ordner entpacken.
|
|
9
|
+
3. Bei der Windows-Abfrage **„Dateien im Ziel ersetzen“** wählen.
|
|
10
|
+
4. Anschließend im Repository ausführen:
|
|
11
|
+
|
|
12
|
+
```powershell
|
|
13
|
+
.\MERGE_UPDATE.cmd
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Alternativ:
|
|
17
|
+
|
|
18
|
+
```powershell
|
|
19
|
+
.\MERGE_UPDATE.ps1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Das Merge-Skript:
|
|
23
|
+
|
|
24
|
+
- synchronisiert alle Release-Versionen auf `7.9.98`;
|
|
25
|
+
- entfernt alte Stable-Laufzeitdateien wie v97;
|
|
26
|
+
- prüft Paketstruktur, Stabilität, Rollen, Login, Passwortablauf und EMS-Übersicht;
|
|
27
|
+
- führt abschließend einen npm-Pack-Dry-Run aus.
|
|
28
|
+
|
|
29
|
+
Erst nach der grünen Abschlussmeldung veröffentlichen. `.git`, lokale Commit-Historie und `node_modules` werden vom Merge-Skript nicht gelöscht.
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "7.9.
|
|
2
|
+
"version": "7.9.98",
|
|
3
3
|
"channel": "stable-latest",
|
|
4
|
-
"baseFrontend": "validated Admin 7 runtime with native
|
|
4
|
+
"baseFrontend": "validated Admin 7 runtime with scrollable native cockpit, clean placeholder login and verified ioBroker password writes",
|
|
5
5
|
"runtimeEntry": "v84",
|
|
6
|
-
"releaseType": "stable-
|
|
7
|
-
"release": "stable-
|
|
8
|
-
"label": "
|
|
6
|
+
"releaseType": "stable-scroll-login-password-write-fix",
|
|
7
|
+
"release": "stable-scroll-login-password-write-fix",
|
|
8
|
+
"label": "v98",
|
|
9
9
|
"notes": [
|
|
10
|
-
"
|
|
11
|
-
"The
|
|
12
|
-
"
|
|
13
|
-
"First
|
|
10
|
+
"The native cockpit keeps the fixed header and provides an explicit vertical content scrollbar.",
|
|
11
|
+
"The login uses clean placeholder fields without overlapping MUI outline labels and expands for errors.",
|
|
12
|
+
"Password reset writes the real ioBroker user password to nexowatt and forces personal password setup.",
|
|
13
|
+
"First-login password changes are verified through the ioBroker password API before success is shown.",
|
|
14
|
+
"EOS Assist remains disabled until its separate complete redesign."
|
|
14
15
|
],
|
|
15
16
|
"changes": [
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
17
|
+
"Normalized system.user.* ids to the short account names expected by setPasswordAsync and checkPasswordAsync.",
|
|
18
|
+
"Separated password hash writes from EOS native metadata updates to prevent stale object replacement.",
|
|
19
|
+
"Relaxed same-host origin handling for reverse proxies while rejecting cross-site requests.",
|
|
20
|
+
"Added a stable vertical scroll surface to the overview and preserved the working EMS live diagnosis.",
|
|
21
|
+
"Removed floating login labels from the productive bundle and introduced clean accessible placeholders."
|
|
20
22
|
],
|
|
21
|
-
"brandingCacheVersion":
|
|
22
|
-
"shellCacheVersion":
|
|
23
|
-
"nativeShellVersion":
|
|
24
|
-
"shellCacheTag": "
|
|
25
|
-
"repositoryEntry": "nexowatt-eos-admin-repository-entry-
|
|
23
|
+
"brandingCacheVersion": 98,
|
|
24
|
+
"shellCacheVersion": 98,
|
|
25
|
+
"nativeShellVersion": 98,
|
|
26
|
+
"shellCacheTag": "98",
|
|
27
|
+
"repositoryEntry": "nexowatt-eos-admin-repository-entry-v98.json"
|
|
26
28
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# NexoWatt EOS Admin 7.9.98 veröffentlichen
|
|
2
|
+
|
|
3
|
+
## Empfohlener Weg: geprüftes TGZ veröffentlichen
|
|
4
|
+
|
|
5
|
+
Dadurch können keine alten oder lokal zusätzlich vorhandenen Dateien in das npm-Paket gelangen.
|
|
6
|
+
|
|
7
|
+
```powershell
|
|
8
|
+
npm login
|
|
9
|
+
npm whoami
|
|
10
|
+
npm publish .\iobroker.eos-admin-7.9.98.tgz --dry-run --tag latest
|
|
11
|
+
npm publish .\iobroker.eos-admin-7.9.98.tgz --tag latest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Der Dry-Run muss mit folgendem Paket enden:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
+ iobroker.eos-admin@7.9.98
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Veröffentlichung direkt aus dem Repository
|
|
21
|
+
|
|
22
|
+
Nur aus einem sauberen Arbeitsordner ausführen:
|
|
23
|
+
|
|
24
|
+
```powershell
|
|
25
|
+
npm login
|
|
26
|
+
npm whoami
|
|
27
|
+
npm run sync:eos-version
|
|
28
|
+
npm run check:eos-release
|
|
29
|
+
npm publish --dry-run --tag latest
|
|
30
|
+
npm publish --tag latest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Bei einem Fehler nicht veröffentlichen. Insbesondere müssen `package.json`, `package-lock.json`, `io-package.json`, `src-admin/package.json` und `src-admin/src/version.json` dieselbe Version enthalten.
|
package/README.md
CHANGED
|
@@ -13,11 +13,15 @@ Standard-Port: 8081
|
|
|
13
13
|
|
|
14
14
|
Damit überschreibt der Adapter den offiziellen `admin`-Adapter nicht mehr. Die alte ioBroker-Admin-Oberfläche kann parallel vorhanden bleiben, während NexoWatt-Systeme über `eos-admin.0` die EOS-Oberfläche nutzen.
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## Aktueller Stable-Verkaufskandidat 7.9.98
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
Version 7.9.98 verwendet die native **Übersicht** als Startseite und ergänzt dort die ausschließlich lesende EMS-Live-Diagnose. Der Inhaltsbereich ist vertikal scrollbar, während Header und Hauptnavigation stehen bleiben.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Verwaltete Installateur- und Endkundenkonten verwenden das Startpasswort `nexowatt`. Nach der ersten Anmeldung beziehungsweise nach einem Reset muss unmittelbar ein persönliches Passwort vergeben werden. Der Reset und die persönliche Passwortvergabe schreiben das reale ioBroker-Benutzerkennwort; EOS-Metadaten werden davon getrennt aktualisiert.
|
|
21
|
+
|
|
22
|
+
Admin/Service darf verwaltete Installateur- und Endkundenkonten zurücksetzen. Installateure dürfen ausschließlich ausdrücklich zugeordnete Endkundenkonten zurücksetzen. Admin-, Eigen-, deaktivierte und nicht verwaltete Konten bleiben geschützt.
|
|
23
|
+
|
|
24
|
+
EOS Assist ist in diesem Stand bewusst deaktiviert. Der interne Admin und die interne BackItUp-Notfallreserve bleiben installiert und sind ausschließlich für Admin/Service sichtbar. Für den regulären Betrieb wird die NexoWatt Sicherung verwendet.
|
|
21
25
|
|
|
22
26
|
## Installation über das NexoWatt Repository
|
|
23
27
|
|
|
@@ -29,7 +33,7 @@ Minimaler Repository-Eintrag:
|
|
|
29
33
|
{
|
|
30
34
|
"eos-admin": {
|
|
31
35
|
"name": "eos-admin",
|
|
32
|
-
"version": "7.9.
|
|
36
|
+
"version": "7.9.98",
|
|
33
37
|
"title": "NexoWatt EOS Admin",
|
|
34
38
|
"desc": {
|
|
35
39
|
"de": "NexoWatt EOS Administrationsoberfläche als eigenständiger Adapter.",
|
|
@@ -126,12 +130,18 @@ iobroker restart eos-admin.0
|
|
|
126
130
|
|
|
127
131
|
## Veröffentlichung auf npm
|
|
128
132
|
|
|
133
|
+
Vor der Veröffentlichung müssen Paket- und Stabilitätsprüfung vollständig grün sein:
|
|
134
|
+
|
|
129
135
|
```bash
|
|
130
136
|
npm login
|
|
131
|
-
npm
|
|
137
|
+
npm whoami
|
|
138
|
+
npm run sync:eos-version
|
|
139
|
+
npm run check:eos-release
|
|
140
|
+
npm publish --dry-run --tag latest
|
|
141
|
+
npm publish --tag latest
|
|
132
142
|
```
|
|
133
143
|
|
|
134
|
-
Die Version muss vor jedem erneuten Publish erhöht werden.
|
|
144
|
+
Die Version muss vor jedem erneuten Publish erhöht werden. Für 7.9.98 ist die Veröffentlichung des separat geprüften `iobroker.eos-admin-7.9.98.tgz` der sicherste Weg.
|
|
135
145
|
|
|
136
146
|
## Lizenz
|
|
137
147
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# NexoWatt EOS Admin 7.9.98 – Stable-Verkaufskandidat
|
|
2
|
+
|
|
3
|
+
Version 7.9.98 beseitigt die vier zuletzt auf dem realen EOS-Testsystem festgestellten Verkaufsblocker, ohne die funktionierende EMS-Live-Diagnose oder die bestehenden Rollenrechte zu erweitern.
|
|
4
|
+
|
|
5
|
+
## Korrigierte Bereiche
|
|
6
|
+
|
|
7
|
+
- **Cockpit vollständig bedienbar:** Der Kopf- und Navigationsbereich bleibt stehen; ausschließlich der Inhaltsbereich der Übersicht erhält einen vertikalen Scrollbereich. Dadurch sind auch lange EMS-Ereignislisten und die unteren Adapterkarten erreichbar.
|
|
8
|
+
- **Saubere Anmeldung:** Loginname und Passwort verwenden feste Platzhalter statt kollidierender Floating Labels. Die Karte ist moderat größer, wächst bei Fehlermeldungen automatisch und besitzt keine innere horizontale oder vertikale Scrollleiste.
|
|
9
|
+
- **Reales Kontopasswort beim Reset:** Ein zulässiger Reset schreibt das Startpasswort `nexowatt` mit der ioBroker-Passwortschnittstelle in das tatsächliche Benutzerkonto. Die EOS-Erstanmeldungsmerkmale werden getrennt davon aktualisiert, damit der neue Passwort-Hash nicht wieder überschrieben wird.
|
|
10
|
+
- **Persönliches Passwort nach der ersten Anmeldung:** Das neue Kennwort wird serverseitig validiert, in das reale Benutzerkonto geschrieben, anschließend geprüft und erst danach wird der Erstanmeldungsstatus beendet.
|
|
11
|
+
- **Saubere Rollenbegrenzung:** Admin/Service darf verwaltete Installateur- und Endkundenkonten zurücksetzen. Installateure dürfen ausschließlich ausdrücklich zugeordnete Endkundenkonten zurücksetzen. Admin-, Eigen-, deaktivierte und nicht verwaltete Konten bleiben geschützt.
|
|
12
|
+
|
|
13
|
+
## Unveränderte Produktregeln
|
|
14
|
+
|
|
15
|
+
- Die EMS-Live-Kachel ist ausschließlich lesend und verändert keine Regelung, Geräte- oder Sollwerte.
|
|
16
|
+
- Der NexoWatt UI Adapter stellt die Diagnosewerte weiterhin unter `nexowatt-ui.*.info.adminOverview.*` bereit.
|
|
17
|
+
- EOS Assist bleibt bis zur vollständigen Neuimplementierung deaktiviert.
|
|
18
|
+
- Standardport des EOS Admin bleibt `8081`.
|
|
19
|
+
|
|
20
|
+
## Freigabestatus
|
|
21
|
+
|
|
22
|
+
Alle paketinternen Prüfungen, die isolierte Browser-Geometrieprüfung, der simulierte Passwortablauf und der npm-Publish-Dry-Run müssen erfolgreich sein. Vor dem Verkauf ist zusätzlich die Checkliste in `RELEASE_ACCEPTANCE_V7.9.98.md` einmal auf einem realen EOS-Testcontroller abzuarbeiten.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Release-Abnahme – NexoWatt EOS Admin 7.9.98
|
|
2
|
+
|
|
3
|
+
Diese Checkliste ist vor der Verkaufsfreigabe einmal vollständig auf einem realen EOS-Testcontroller abzuarbeiten.
|
|
4
|
+
|
|
5
|
+
## Installation und Versionsstand
|
|
6
|
+
|
|
7
|
+
- [ ] `iobroker.eos-admin` zeigt Version `7.9.98`.
|
|
8
|
+
- [ ] `eos-admin.0` startet ohne Fehler und ist auf Port `8081` erreichbar.
|
|
9
|
+
- [ ] Nach `Strg + F5` werden ausschließlich die v98-Laufzeitdateien geladen.
|
|
10
|
+
- [ ] Ein kompletter Neustart des EOS-Controllers führt wieder zu einer erreichbaren Oberfläche.
|
|
11
|
+
|
|
12
|
+
## Anmeldung
|
|
13
|
+
|
|
14
|
+
- [ ] Loginname und Passwort überlappen weder Rahmen noch Beschriftungen.
|
|
15
|
+
- [ ] Die Anmeldekarte besitzt keine innere horizontale oder vertikale Scrollleiste.
|
|
16
|
+
- [ ] Eine absichtlich falsche Anmeldung zeigt die vollständige Fehlermeldung innerhalb der Karte.
|
|
17
|
+
- [ ] Die Karte bleibt bei 1920 × 1080 und 1366 × 768 vollständig bedienbar.
|
|
18
|
+
|
|
19
|
+
## Übersicht und EMS
|
|
20
|
+
|
|
21
|
+
- [ ] Header und Navigation bleiben stehen.
|
|
22
|
+
- [ ] Der Cockpit-Inhalt lässt sich bis zur letzten Karte vertikal scrollen.
|
|
23
|
+
- [ ] EMS-Budget, Ladeleistung, Speicher, Regelentscheidungen und Ereignisse werden angezeigt.
|
|
24
|
+
- [ ] Die Kachel aktualisiert sich mit realen Werten aus `nexowatt-ui.*.info.adminOverview.*`.
|
|
25
|
+
- [ ] Die EMS-Kachel besitzt keine Schreibfunktion und verändert keine Sollwerte.
|
|
26
|
+
|
|
27
|
+
## Rollen und Passwort-Reset
|
|
28
|
+
|
|
29
|
+
- [ ] Admin/Service kann `guest`, `user` und `installer` zurücksetzen, sofern diese Konten ausdrücklich einer verwalteten EOS-Rolle zugeordnet sind.
|
|
30
|
+
- [ ] Installateur kann ausschließlich ausdrücklich zugeordnete Endkundenkonten zurücksetzen.
|
|
31
|
+
- [ ] Admin-Konto, eigenes Konto, deaktivierte und nicht verwaltete Konten werden abgewiesen.
|
|
32
|
+
- [ ] Nach dem Reset funktioniert die Anmeldung mit dem Startpasswort `nexowatt`.
|
|
33
|
+
- [ ] Das bisherige persönliche Kennwort ist nach dem Reset nicht mehr gültig.
|
|
34
|
+
|
|
35
|
+
## Persönliches Passwort
|
|
36
|
+
|
|
37
|
+
- [ ] Die Anmeldung mit `nexowatt` öffnet unmittelbar die Seite „Persönliches Passwort festlegen“.
|
|
38
|
+
- [ ] Zu kurze, nicht übereinstimmende oder zu einfache Kennwörter werden verständlich abgewiesen.
|
|
39
|
+
- [ ] Ein gültiges neues Kennwort wird gespeichert.
|
|
40
|
+
- [ ] Nach erfolgreichem Speichern wird die alte Sitzung beendet.
|
|
41
|
+
- [ ] Die erneute Anmeldung funktioniert ausschließlich mit dem neu vergebenen Kennwort.
|
|
42
|
+
- [ ] Im nativen Benutzereditor ist weiterhin ein Passwort-Hash für das richtige Benutzerkonto vorhanden.
|
|
43
|
+
|
|
44
|
+
## Abschluss
|
|
45
|
+
|
|
46
|
+
- [ ] EOS Assist bleibt ausgeblendet.
|
|
47
|
+
- [ ] Sicherung, Dienste, Module, Datenpunkte und Systemlogs bleiben erreichbar.
|
|
48
|
+
- [ ] Es treten während der Abnahme keine neuen Fehler im EOS-Admin-Log auf.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Release Notes – NexoWatt EOS Admin 7.9.98
|
|
2
|
+
|
|
3
|
+
## Übersicht und Bedienung
|
|
4
|
+
|
|
5
|
+
- Der Cockpit-Inhalt kann jetzt bis zum letzten Element vertikal gescrollt werden.
|
|
6
|
+
- Header und Hauptnavigation bleiben währenddessen stehen.
|
|
7
|
+
- Die EMS-Live-Diagnose, aktuelle Regelentscheidungen, Ereignisse und nachfolgende Adapterkarten werden nicht mehr am unteren Fensterrand abgeschnitten.
|
|
8
|
+
|
|
9
|
+
## Anmeldung
|
|
10
|
+
|
|
11
|
+
- Überlappende MUI-Feldbeschriftungen wurden entfernt.
|
|
12
|
+
- Loginname und Passwort verwenden klar erkennbare Platzhalter.
|
|
13
|
+
- Die Anmeldekarte wurde nur moderat vergrößert und wächst bei einer Fehlermeldung automatisch.
|
|
14
|
+
- Innere horizontale und vertikale Scrollleisten bleiben ausgeschlossen.
|
|
15
|
+
|
|
16
|
+
## Konten und Kennwörter
|
|
17
|
+
|
|
18
|
+
- Ein Kontoreset schreibt das reale ioBroker-Kontopasswort auf `nexowatt`.
|
|
19
|
+
- Der Passwortschreibvorgang wird mit der Controller-Passwortprüfung verifiziert, bevor Erfolg gemeldet wird.
|
|
20
|
+
- Die EOS-Erstanmeldungsmerkmale werden ausschließlich als Metadaten erweitert; der zuvor geschriebene Passwort-Hash wird nicht durch ein altes Benutzerobjekt überschrieben.
|
|
21
|
+
- Admin/Service darf verwaltete Installateur- und Endkundenkonten zurücksetzen.
|
|
22
|
+
- Installateure dürfen ausschließlich ausdrücklich zugeordnete Endkundenkonten zurücksetzen.
|
|
23
|
+
- Admin-, Eigen-, deaktivierte und nicht verwaltete Konten werden weiterhin abgewiesen.
|
|
24
|
+
- Die persönliche Passwortvergabe nach der Anmeldung mit `nexowatt` schreibt und prüft ebenfalls das reale Benutzerkennwort.
|
|
25
|
+
- Nach erfolgreicher Passwortvergabe werden vorhandene Anmeldesitzungen beendet und der Erstanmeldungsstatus entfernt.
|
|
26
|
+
|
|
27
|
+
## Stabilität und Aktualisierung
|
|
28
|
+
|
|
29
|
+
- Paket-, Lockfile-, io-package-, Frontend- und Repository-Versionen werden vor der Veröffentlichung auf `7.9.98` synchronisiert.
|
|
30
|
+
- Alte Stable-Laufzeitdateien wie v97 werden beim Merge-Update automatisch entfernt.
|
|
31
|
+
- Die EMS-Live-Diagnose bleibt read-only.
|
|
32
|
+
- EOS Assist bleibt deaktiviert.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{j as s}from"./DefaultPropsProvider-BiXBMQYQ.js";import{i as _,a as B}from"./iobroker_admin__loadShare__react__loadShare__-LM7uyL45.js";import{b as S,r as J,c as P,s as w}from"./bootstrap-COulQZax-v84.js";import{i as n,a as f}from"./iobroker_admin__loadShare___mf_0_mui_mf_1_icons_mf_2_material__loadShare__-CJO5yP3h.js";import{i as v}from"./iobroker_admin__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__-LFZoiUTt.js";import{b as $}from"./blue-CagzI6CQ.js";import{g as b,v as M}from"./createTheme-DFX8CY6F.js";import"./_commonjsHelpers-CE1G-McA.js";import"./iobroker_admin__mf_v__runtimeInit__mf_v__-g2X2zhAf.js";import"./emotion-serialize.esm-Q4o_CgeF.js";import"./iobroker_admin__loadShare___mf_0_emotion_mf_1_react__loadShare__-BywLg1Xe.js";import"./ace-DEUjyTIn.js";import"./iobroker_admin__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__-CpA7pnS5.js";import"./iobroker_admin__loadShare__leaflet__loadShare__-CNUAG3AH.js";import"./ext-language_tools-ylAoucDh.js";import"./iobroker_admin__loadShare__react_mf_2_dropzone__loadShare__-CwjnV48g.js";import"./iobroker_admin__loadShare__react_mf_2_dom__loadShare__-CVeAXnkk.js";import"./preload-helper-BDBacUwf.js";import"./sdk-C-e-e2gd.js";import"./extends-CF3RwP-h.js";import"./assertThisInitialized-B0aQ9eG_.js";import"./useTheme-Bl-M1DYp.js";import"./index-DcK0RDrH.js";import"./ThemeProvider-BOFFjWAF.js";import"./emotion-cache.browser.esm-BgJfNZJN.js";import"./setYear-3ufv5yRD.js";import"./en-US-DBFJNIH6.js";const L="0 2px 2px 0 rgba(0, 0, 0, .14),0 3px 1px -2px rgba(0, 0, 0, .12),0 1px 5px 0 rgba(0, 0, 0, .2)",A="0 8px 17px 0 rgba(0, 0, 0, .2),0 6px 20px 0 rgba(0, 0, 0, .19)",x={root:g=>({padding:".75rem",[g.breakpoints.up("xl")]:{flex:"0 1 20%"}}),card:{display:"flex",minHeight:"235px",position:"relative",overflow:"hidden",maxHeight:"235p","&:hover":{overflowY:"auto",boxShadow:A}},cardInfo:{display:"flex",minHeight:"235px",position:"relative",overflow:"initial",maxHeight:"235p",flexDirection:"column","&:hover":{boxShadow:A}},cardInfoHead:g=>({position:"sticky",top:0,background:g.palette.background.default,display:"flex",width:"100%",justifyContent:"space-between",borderBottom:"1px solid",padding:"5px 5px 0px 5px"}),edit:{opacity:.6,userSelect:"none",pointerEvents:"none"},media:g=>({backgroundColor:g.palette.mode==="dark"?"#535353":"#e2e2e2",maxWidth:"30%"}),img:{width:120,height:"auto",padding:"2rem .5rem",maxWidth:"100%"},contentContainer:{display:"flex",flexDirection:"column",flex:1},content:{height:"170px",flexGrow:1,overflowY:"hidden"},action:{minHeight:"49px",padding:"16px 24px"},expand:{position:"absolute",right:"10px",bottom:"10px"},collapse:{minHeight:"100%",backgroundColor:"#ffffff",position:"absolute",width:"100%"},enabled:{color:"#ffffff",backgroundColor:$[500],position:"absolute",top:8,right:8,boxShadow:L,"&:hover":{backgroundColor:$[300]},"&:focus":{backgroundColor:$[500]}},disabled:{color:"#ffffff",backgroundColor:b[500],position:"absolute",top:8,right:8,boxShadow:L,"&:hover":{backgroundColor:b[300]},"&:focus":{backgroundColor:b[500]}},editButton:{color:"#ffffff",backgroundColor:b[500],position:"absolute",top:64,right:8,boxShadow:L,"&:hover":{backgroundColor:b[300]},"&:focus":{backgroundColor:b[500]}},deleteButton:{color:"#ffffff",backgroundColor:M[500],position:"absolute",top:120,right:8,boxShadow:L,"&:hover":{backgroundColor:M[300]},"&:focus":{backgroundColor:M[500]}},contentGrid:{height:"100%"},colorOrange:{color:"#ffcc80"},tooltip:{pointerEvents:"none"}};class O extends _.Component{constructor(t){super(t),this.state={expanded:!1}}static getDerivedStateFromProps(t){return t.edit?{expanded:!1}:null}handleExpandClick(){this.setState({expanded:!this.state.expanded})}renderContent(){return this.props.children}openDialog(){}renderDialogs(){return null}render(){var o,i;const t=this.props.edit?x.edit:void 0;let e=this.props.action.text||this.props.t("Link");return typeof e=="object"&&(e=e[this.props.lang]||e.en),s.jsx(n.Grid2,{size:{xs:12,sm:6,md:4,lg:3,xl:2},sx:v.Utils.getStyle(this.props.theme,x.root,this.props.style),style:{maxWidth:500},children:s.jsx(n.Link,{href:!this.props.edit&&this.props.action&&this.props.action.link?this.props.action.link:null,underline:"none",target:"_blank",rel:"noopener noreferrer",children:s.jsxs(n.Card,{sx:x.card,onClick:d=>{d.stopPropagation(),this.openDialog()},children:[this.props.showInfo&&!this.props.offline&&s.jsx(n.Button,{style:{...x.expand,...t},variant:"contained",size:"small",disabled:this.props.disabled,onClick:()=>this.handleExpandClick(),color:"primary",children:this.props.t("Info")}),s.jsxs(n.Box,{component:"div",sx:v.Utils.getStyle(this.props.theme,x.media,t,this.props.color&&{backgroundColor:this.props.color},{display:"flex",flexDirection:"column"}),children:[s.jsx(n.CardMedia,{style:x.img,component:"img",image:this.props.image}),s.jsx("div",{style:{flex:1,display:"flex",paddingBottom:"5px",paddingLeft:"5px"},children:this.props.warning?s.jsx(n.Tooltip,{title:this.props.warning,slotProps:{popper:{sx:x.tooltip}},children:s.jsx(f.Warning,{style:{alignSelf:"end",fontSize:36}})}):null})]}),s.jsxs("div",{style:{...x.contentContainer,...t},children:[s.jsx(n.CardContent,{style:x.content,children:s.jsxs(n.Grid2,{container:!0,direction:"column",wrap:"nowrap",style:x.contentGrid,children:[s.jsx(n.Typography,{gutterBottom:!0,variant:"h5",component:"h5",children:this.props.title}),this.renderContent()]})}),((o=this.props.action)==null?void 0:o.link)&&s.jsx(n.Divider,{}),((i=this.props.action)==null?void 0:i.link)&&s.jsx(n.CardActions,{style:x.action,children:s.jsx("div",{style:x.colorOrange,children:S.getText(e,this.props.lang)})})]}),this.props.showInfo&&s.jsx(n.Collapse,{style:x.collapse,in:this.state.expanded,timeout:"auto",unmountOnExit:!0,children:s.jsxs(n.Card,{sx:x.cardInfo,children:[s.jsxs(n.Box,{component:"div",sx:x.cardInfoHead,children:[s.jsx(n.Typography,{gutterBottom:!0,variant:"h5",component:"h5",children:this.props.t("Info")}),s.jsxs("div",{children:[s.jsx(n.IconButton,{size:"small",onClick:()=>{this.props.getHostDescriptionAll&&v.Utils.copyToClipboard(this.props.getHostDescriptionAll().text),this.props.openSnackBarFunc&&this.props.openSnackBarFunc()},children:s.jsx(v.IconCopy,{})}),s.jsx(n.IconButton,{size:"small",onClick:()=>this.handleExpandClick(),children:s.jsx(f.Close,{})})]})]}),s.jsx(n.CardContent,{children:this.props.getHostDescriptionAll().el})]})}),this.props.edit&&this.props.toggleActivation&&s.jsx(n.IconButton,{size:"large",sx:this.props.enabled?x.enabled:x.disabled,onClick:()=>this.props.toggleActivation(),children:s.jsx(f.Check,{})}),this.props.edit&&this.props.onEdit&&s.jsx(n.IconButton,{size:"large",sx:x.editButton,onClick:()=>this.props.onEdit(),children:s.jsx(f.Create,{})}),this.props.edit&&this.props.onRemove&&s.jsx(n.IconButton,{size:"large",sx:x.deleteButton,onClick:()=>this.props.onRemove(),children:s.jsx(f.Delete,{})}),this.renderDialogs()]})})})}}const I={closeButton:g=>({position:"absolute",right:8,top:8,color:g.palette.grey[500]}),paper:{},typography:{paddingRight:30},img:{width:"100%",height:"100%",objectFit:"contain"}};class R extends _.Component{cameraUpdateTimer;cameraRef;constructor(t){super(t),this.cameraUpdateTimer=null,this.cameraRef=_.createRef()}componentDidMount(){this.props.camera&&this.props.camera!=="text"&&(this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500)),this.updateCamera())}componentWillUnmount(){this.cameraUpdateTimer&&(clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=null)}updateCamera(){if(this.cameraRef.current)if(this.props.camera==="custom"){let t=this.props.cameraUrl;this.props.addTs&&(t.includes("?")?t+=`&ts=${Date.now()}`:t+=`?ts=${Date.now()}`),this.cameraRef.current.src=t}else{const t=this.props.camera.split("."),e=t.shift(),o=t.shift();this.props.socket.sendTo(`${e}.${o}`,"image",{name:t.pop(),width:this.cameraRef.current.width}).then(i=>{i&&i.data&&this.cameraRef.current&&(this.cameraRef.current.src=`data:image/jpeg;base64,${i.data}`)})}}render(){return s.jsxs(n.Dialog,{onClose:()=>this.props.onClose(),open:!0,maxWidth:"xl",fullWidth:!0,fullScreen:!0,sx:{"& .MuiDialog-paper":I.paper},children:[s.jsx(n.DialogTitle,{children:s.jsxs(n.Typography,{component:"h2",variant:"h6",sx:{"&.MuiTypography-root":I.typography},children:[this.props.name,s.jsx(n.IconButton,{size:"large",sx:I.closeButton,onClick:()=>this.props.onClose(),children:s.jsx(f.Close,{})})]})}),s.jsx(n.DialogContent,{dividers:!0,children:s.jsx("img",{style:I.img,src:"",alt:"camera",ref:this.cameraRef})}),s.jsx(n.DialogActions,{children:s.jsx(n.Button,{variant:"contained",autoFocus:!0,onClick:t=>{t.stopPropagation(),this.props.onClose()},color:"primary",startIcon:s.jsx(f.Close,{}),children:this.props.t("Close")})})]})}}const D={cameraImg:{width:"100%",height:"100%",maxWidth:200,maxHeight:200,objectFit:"contain"},imgContainer:{height:"100%"},hidden:{display:"none"},imgSkeleton:{transform:"initial"}};class E extends O{cameraRef;cameraUpdateTimer;interval;constructor(t){super(t),Object.assign(this.state,{error:!1,dialog:!1,loaded:!1}),this.cameraRef=_.createRef(),this.cameraUpdateTimer=null,this.interval=t.interval}updateCamera(){if(this.cameraRef.current)if(this.props.camera==="custom"){let t=this.props.cameraUrl;this.props.addTs&&(t.includes("?")?t+=`&ts=${Date.now()}`:t+=`?ts=${Date.now()}`),this.cameraRef.current.src=t}else{const t=this.props.camera.split("."),e=t.shift(),o=t.shift();this.props.socket.sendTo(`${e}.${o}`,"image",{name:t.pop(),width:this.cameraRef.current.width}).then(i=>{i!=null&&i.data&&this.cameraRef.current&&(this.cameraRef.current.src=`data:image/jpeg;base64,${i.data}`)}).catch(i=>window.alert(`Cannot send to instance: ${i}`))}}componentDidMount(){this.props.camera&&this.props.camera!=="text"&&(this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500)),this.updateCamera())}componentWillUnmount(){this.cameraUpdateTimer&&(clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=null)}renderDialogs(){return this.state.dialog?s.jsx(R,{socket:this.props.socket,camera:this.props.camera,name:this.props.title,t:this.props.t,onClose:()=>{this.props.camera&&this.props.camera!=="text"&&(this.cameraUpdateTimer&&clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500)),this.updateCamera()),this.setState({dialog:!1})},cameraUrl:this.props.cameraUrl}):null}handleImageLoad(){this.state.loaded||this.setState({loaded:!0,error:!1})}handleImageError(){this.state.error||this.setState({loaded:!1,error:!0})}renderContent(){if(this.props.camera==="custom"){let t=this.props.cameraUrl;return this.props.addTs&&(t.includes("?")?t+=`&ts=${Date.now()}`:t+=`?ts=${Date.now()}`),s.jsxs(n.Grid2,{container:!0,style:D.imgContainer,justifyContent:"center",alignItems:"center",children:[s.jsx("img",{ref:this.cameraRef,src:t,alt:"Camera",style:this.state.loaded&&!this.state.error?D.cameraImg:D.hidden,onLoad:()=>this.handleImageLoad(),onError:()=>this.handleImageError()}),!this.state.loaded&&!this.state.error&&s.jsx(n.Skeleton,{height:"100%",width:"100%",animation:"wave",style:D.imgSkeleton}),this.state.error&&s.jsx(f.Error,{fontSize:"large"})]})}return this.props.camera.startsWith("cameras.")?s.jsx("img",{ref:this.cameraRef,src:"",alt:"camera",style:D.cameraImg}):null}render(){return this.props.camera&&this.props.camera!=="text"?this.interval!==this.props.interval&&(this.interval=this.props.interval,this.cameraUpdateTimer&&clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500))):this.cameraUpdateTimer&&(clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=null),super.render()}}const y={formControl:{marginTop:32},rootGrid:{flexGrow:1},closeButton:g=>({position:"absolute",right:8,top:8,color:g.palette.grey[500]}),paper:{},typography:{paddingRight:30},editItem:{marginTop:8},editItemSlider:{marginTop:24},labelSlider:{marginTop:16,fontSize:"1rem"},editColor:{width:"100%"}};class U extends _.Component{constructor(t){super(t),this.state={image:"",name:t.t("New link"),link:"http://",linkName:"",color:"",desc:"",addTs:!0,interval:5e3,camera:"text",cameraList:[],...t.link}}componentDidMount(){this.getCamerasInstances()}getCamerasInstances(){this.props.socket.getAdapterInstances("cameras",!0).then(t=>{const e=[],o=[];t.forEach(i=>{const d=i._id.replace("system.adapter.","");i.common&&i.common.enabled&&o.push(this.props.socket.getState(`${i._id}.alive`).then(r=>r&&r.val&&this.props.socket.sendTo(d,"list",null)).then(r=>r&&r.list&&r.list.forEach(a=>e.push({id:a.id,name:`${a.desc} [${d}/${a.name}]`}))))}),Promise.all(o).then(()=>this.setState({cameraList:e}))})}static getLinkNameFromLink(t){const e=t.trim().match(/^https?:\/\/([^/:]+)(:\d+)?/);return e?e[1]+(e[2]||""):""}render(){return s.jsxs(n.Dialog,{onClose:()=>this.props.onClose(),open:!0,maxWidth:"md",fullWidth:!0,sx:{"& .MuiDialog-paper":y.paper},children:[s.jsx(n.DialogTitle,{children:s.jsxs(n.Typography,{component:"h2",variant:"h6",sx:{"&.MuiTypography-root":y.typography},children:[this.props.isNew?this.props.t("Add new link: "):this.props.t("Edit link"),s.jsx(n.IconButton,{size:"large",sx:y.closeButton,onClick:()=>this.props.onClose(),children:s.jsx(f.Close,{})})]})}),s.jsx(n.DialogContent,{dividers:!0,children:s.jsxs(n.Grid2,{style:y.rootGrid,container:!0,direction:"row",children:[s.jsx(n.Grid2,{size:{xs:12,sm:6,md:8,lg:9},children:s.jsxs(n.Grid2,{container:!0,direction:"column",children:[s.jsxs(n.FormControl,{variant:"standard",style:y.formControl,children:[s.jsx(n.InputLabel,{id:"select-helper-label",children:this.props.t("Link type")}),s.jsxs(n.Select,{variant:"standard",labelId:"select-helper-label",value:this.state.camera,onChange:t=>this.setState({camera:t.target.value}),children:[s.jsx(n.MenuItem,{value:"text",children:s.jsx("em",{children:this.props.t("Description")})},"desc"),this.state.cameraList.map(t=>s.jsx(n.MenuItem,{value:t.id,children:t.name},t.id)),s.jsx(n.MenuItem,{value:"custom",children:this.props.t("Custom camera URL")},"custom")]})]}),s.jsx(n.TextField,{variant:"standard",label:this.props.t("URL"),value:this.state.link,style:y.editItem,onChange:t=>{const e=U.getLinkNameFromLink(this.state.link);e&&(!this.state.linkName||e===this.state.linkName)?this.setState({link:t.target.value,linkName:U.getLinkNameFromLink(t.target.value)}):this.setState({link:t.target.value})},slotProps:{input:{endAdornment:this.state.link?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({link:""}),children:s.jsx(f.Close,{})})}):null}}}),s.jsx(n.TextField,{variant:"standard",style:y.editItem,label:this.props.t("Name"),value:this.state.name||"",onChange:t=>this.setState({name:t.target.value}),slotProps:{input:{endAdornment:this.state.name?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({name:""}),children:s.jsx(f.Close,{})})}):null}}}),this.state.link?s.jsx(n.TextField,{variant:"standard",style:y.editItem,label:this.props.t("Link name"),value:this.state.linkName||"",onChange:t=>this.setState({linkName:t.target.value}),slotProps:{input:{endAdornment:this.state.linkName?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({linkName:""}),children:s.jsx(f.Close,{})})}):null}}}):null,this.state.camera==="custom"||this.state.camera==="text"?s.jsx(n.TextField,{variant:"standard",style:y.editItem,label:this.state.camera==="custom"?this.props.t("Camera URL"):this.props.t("Description"),value:this.state.desc||"",onChange:t=>this.setState({desc:t.target.value}),slotProps:{input:{endAdornment:this.state.desc?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({desc:""}),children:s.jsx(f.Close,{})})}):null}}}):null,this.state.camera==="custom"?s.jsx(n.FormControlLabel,{style:y.editItem,control:s.jsx(n.Checkbox,{checked:this.state.addTs,onChange:t=>this.setState({addTs:t.target.checked})}),label:this.props.t("Add timestamp to URL")}):null,this.state.camera!=="text"?s.jsx(n.Typography,{style:y.labelSlider,gutterBottom:!0,children:"Polling interval in ms"}):null,this.state.camera!=="text"?s.jsx(n.Slider,{style:y.editItemSlider,value:this.state.interval,getAriaValueText:()=>`${this.state.interval}ms`,onChange:(t,e)=>this.setState({interval:e}),step:100,min:500,max:6e4,valueLabelDisplay:"on"}):null,s.jsx("div",{style:{...y.editItem,width:50},children:s.jsx(n.TextField,{variant:"standard",fullWidth:!0,label:this.props.t("Color"),style:y.editColor,type:"color",value:this.state.color,onChange:t=>this.setState({color:t.target.value})})}),s.jsx(v.UploadImage,{disabled:!1,crop:!0,maxSize:256*1024,icon:this.state.image,removeIconFunc:()=>this.setState({image:""}),onChange:t=>this.setState({image:t})})]})}),s.jsx(n.Grid2,{size:{xs:12,sm:6,md:4,lg:3},children:this.state.camera==="text"?s.jsx(O,{image:this.state.image,title:this.state.name,action:{link:this.state.link,text:this.state.linkName},t:this.props.t,lang:this.props.lang,style:{width:"100% !important",maxWidth:"100% !important",marginLeft:"8px"},color:this.state.color,enabled:!0,theme:this.props.theme,children:this.state.desc}):s.jsx(E,{interval:this.state.interval,camera:this.state.camera,addTs:this.state.addTs,style:{width:"100% !important",maxWidth:"100% !important",marginLeft:"8px"},image:this.state.image,title:this.state.name,socket:this.props.socket,action:{link:this.state.link,text:this.state.linkName},t:this.props.t,lang:this.props.lang,color:this.state.color,enabled:!0,cameraUrl:this.state.desc,theme:this.props.theme})})]})}),s.jsxs(n.DialogActions,{children:[s.jsx(n.Button,{variant:"contained",autoFocus:!0,onClick:()=>{this.props.onClose({link:this.state.link,name:this.state.name,desc:this.state.desc,linkName:this.state.linkName,color:this.state.color,image:this.state.image,addTs:this.state.addTs,camera:this.state.camera,interval:this.state.interval})},color:"primary",startIcon:this.props.isNew?s.jsx(f.Add,{}):s.jsx(f.Check,{}),children:this.props.isNew?this.props.t("Add"):this.props.t("Save")}),s.jsx(n.Button,{variant:"contained",onClick:()=>this.props.onClose(),color:"grey",startIcon:s.jsx(f.Close,{}),children:this.props.t("Close")})]})]})}}class W extends B.Component{constructor(t){super(t),this.state={inProgress:!1,success:!1,error:"",finished:!1}}render(){return s.jsxs(n.Dialog,{open:!0,maxWidth:"lg",fullWidth:!0,children:[s.jsx(n.DialogTitle,{children:v.I18n.t("Node.js upgrade")}),s.jsxs(n.DialogContent,{style:{height:100,padding:"0 20px",overflow:"hidden"},children:[this.state.finished?null:s.jsx(n.Typography,{children:v.I18n.t("Performing this update will restart the js-controller afterwards!")}),this.state.inProgress?s.jsx(n.Box,{sx:{display:"flex",justifyContent:"center"},children:s.jsx(n.CircularProgress,{})}):null,this.state.success?s.jsx(n.Typography,{children:v.I18n.t("Node.js update successful, restarting controller now!")}):null,this.state.error?s.jsx(n.Typography,{sx:{color:"red"},children:v.I18n.t("Node.js update failed: %s",this.state.error)}):null]}),s.jsxs(n.DialogActions,{children:[s.jsx(n.Button,{disabled:this.state.inProgress||this.state.finished,color:"primary",variant:"contained",startIcon:s.jsx(f.Refresh,{}),onClick:()=>this.updateNodeJsVersion(),children:v.I18n.t("Upgrade")}),s.jsx(n.Button,{disabled:this.state.inProgress,variant:"contained",onClick:()=>{this.props.onClose()},color:"primary",startIcon:s.jsx(f.Close,{}),children:v.I18n.t("Close")})]})]})}async updateNodeJsVersion(){this.setState({inProgress:!0});const t=await this.props.socket.upgradeOsPackages(this.props.hostId,[{name:"nodejs"}],!0);this.setState({inProgress:!1,success:t.success,error:t.error,finished:!0})}}const m={button:{position:"absolute",bottom:16,right:16},saveButton:g=>({backgroundColor:g.palette.success.main,right:80,"&:hover":{backgroundColor:g.palette.success.dark}}),addButton:g=>({backgroundColor:g.palette.secondary.main,right:144,"&:hover":{backgroundColor:g.palette.secondary.dark}}),closeButton:g=>({backgroundColor:g.palette.error.main,"&:hover":{backgroundColor:g.palette.error.dark}}),bold:{fontWeight:"bold"},hostOffline:{color:"#bb0000"},updateExists:{color:"#c28700",marginRight:4},updateNo:{color:"#00b204",marginRight:4},nodeUpdate:{opacity:.6},instanceNumber:{opacity:.7,fontSize:16},updateIcon:{cursor:"pointer",fontSize:16},tooltip:{pointerEvents:"none"},viewModeDiv:{display:"flex",flexFlow:"wrap",overflow:"auto",justifyContent:"left"}},T={Uptime:S.formatSeconds,"System uptime":S.formatSeconds,RAM:S.formatRam,Speed:S.formatSpeed,"Disk size":S.formatBytes,"Disk free":S.formatBytes};class C extends B.Component{#t=1800*1e3;#e=300*1e3;#s=60*1e3;introLinksOriginal;deactivatedOriginal;t;getDataTimeout;constructor(t){super(t),this.state={instances:null,deactivated:[],edit:!1,link:null,introLinks:[],editLink:!1,editLinkIndex:-1,openSnackBar:!1,hasUnsavedChanges:!1,reverseProxy:null,alive:{},hostsData:{},hosts:null,hostTimeDiffMap:new Map,hostDataTimestampMap:new Map,nodeUpdateSupported:!1,nodeUpdateDialog:null},this.t=t.t}checkBackendTime(){const t=this.state.hostTimeDiffMap,e=this.state.hostDataTimestampMap,o=Date.now();for(const[i,d]of Object.entries(this.state.hostsData)){const r=Math.abs(d.time-o);t.set(i,r),e.set(i,o)}this.setState({hostTimeDiffMap:t,hostDataTimestampMap:e})}async componentDidMount(){var i;let t=null,e=!1;try{[t,e]=await Promise.all([this.props.socket.getObject(`system.adapter.${this.props.adminInstance}`),this.props.socket.checkFeatureSupported("CONTROLLER_OS_PACKAGE_UPGRADE")])}catch(d){if(String(window.NEXOWATT_EOS_ACCESS_ROLE||"unknown").toLowerCase()==="admin")throw d}const o=((i=t==null?void 0:t.native)==null?void 0:i.reverseProxy)||[];await new Promise(d=>this.setState({reverseProxy:o,nodeUpdateSupported:e},()=>d())),await this.getData(),this.props.instancesWorker.registerHandler(this.getDataDelayed),this.props.hostsWorker.registerHandler(this.updateHosts),this.props.hostsWorker.registerAliveHandler(this.updateHostsAlive),this.checkBackendTime()}componentWillUnmount(){this.getDataTimeout&&(clearTimeout(this.getDataTimeout),this.getDataTimeout=void 0),this.props.instancesWorker.unregisterHandler(this.getDataDelayed),this.props.hostsWorker.unregisterHandler(this.updateHosts),this.props.hostsWorker.unregisterAliveHandler(this.updateHostsAlive)}updateHostsAlive=async t=>{const e=JSON.parse(JSON.stringify(this.state.alive)),o=[];if(t.find(i=>i.type==="deleted")){this.getDataDelayed();return}if(t.forEach(i=>{!!e[i.id]!=!!i.alive&&(e[i.id]=i.alive,o.push(i.id))}),o.length){const i=JSON.parse(JSON.stringify(this.state.hostsData)),d=new Map(this.state.hostDataTimestampMap),r=Date.now();(await Promise.all(o.map(l=>this.getHostData(l,e[l])))).forEach(l=>{i[l.id]=C.preprocessHostData(l.data),d.set(l.id,r)}),this.setState({alive:e,hostsData:i,hostDataTimestampMap:d},()=>this.checkBackendTime())}};updateHosts=t=>{let e=[];if(t.find(o=>!o.obj)){this.getDataDelayed();return}if(e=t.map(o=>o.id),e.length){const o=JSON.parse(JSON.stringify(this.state.hostsData)),i=new Map(this.state.hostDataTimestampMap),d=Date.now();Promise.all(e.map(r=>this.getHostData(r))).then(r=>{r.forEach(a=>{o[a.id]=C.preprocessHostData(a.data),i.set(a.id,d)}),this.setState({hostsData:o,hostDataTimestampMap:i})})}};async activateEditMode(){var i;const t=await this.props.socket.getSystemConfig(!0),e=await this.getInstances(!0,null,t),o=(i=t==null?void 0:t.native)!=null&&i.introLinks?t.native.introLinks:[];this.introLinksOriginal=JSON.stringify(o),this.deactivatedOriginal=JSON.parse(JSON.stringify(e.deactivated)),this.setState({instances:e.instances,deactivated:e.deactivated,edit:!0,introLinks:o,hasUnsavedChanges:!1})}deactivateEditMode(){this.state.hasUnsavedChanges,this.setState({deactivated:this.deactivatedOriginal,introLinks:JSON.parse(this.introLinksOriginal),hasUnsavedChanges:!1,edit:!1},()=>{this.deactivatedOriginal=null,this.introLinksOriginal=null})}toggleCard(t,e){if(!this.state.instances||!this.state.instances.length)return;const o=JSON.parse(JSON.stringify(this.state.deactivated)),i=o.indexOf(`${t}_${e}`);i!==-1?o.splice(i,1):(o.push(`${t}_${e}`),o.sort());const d=JSON.stringify(o)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(this.state.introLinks)!==this.introLinksOriginal;this.setState({deactivated:o,hasUnsavedChanges:d})}getInstancesCards(){var t;return(t=this.state.instances)==null?void 0:t.map(e=>{var i,d;const o=!((i=this.state.deactivated)!=null&&i.includes(`${e.id}_${e.linkName}`));if(o||this.state.edit){let r=e.link?e.link.replace(/^https?:\/\//,""):"";if(r=r.split("/")[0],e.id===this.props.adminInstance)return null;let a=window.isFinite(e.id.split(".").pop());a&&(a=!!((d=this.state.instances)!=null&&d.find(k=>k.id!==e.id&&e.name===k.name&&e.id.split(".")[0]===k.id.split(".")[0])));const l=this.state.hostsData?this.state.hostsData[e.id]:null,h=this.state.hostTimeDiffMap.get(e.id)??0,p=this.state.hostDataTimestampMap.get(e.id)??0,u=Date.now()-p<this.#e;return s.jsx(O,{image:e.image,title:s.jsxs(s.Fragment,{children:[s.jsx("span",{style:e.name&&e.name.length>12?{fontSize:"1rem"}:void 0,children:e.name}),a?s.jsxs("span",{style:m.instanceNumber,children:[".",e.id.split(".").pop()]}):null]}),action:{link:e.link,text:r},t:this.props.t,lang:this.props.lang,color:e.color,showInfo:!!e.info,edit:this.state.edit,offline:l&&l.alive===!1,warning:h>this.#t&&u?this.t("Backend time differs by %s minutes",Math.round(h/this.#s).toString()):null,enabled:o,disabled:!l||typeof l!="object",getHostDescriptionAll:()=>this.getHostDescriptionAll(e.id),toggleActivation:()=>this.toggleCard(e.id,e.linkName),openSnackBarFunc:()=>this.setState({openSnackBar:!0}),theme:this.props.theme,children:e.description||this.getHostDescription(e.id)},`${e.id}_${e.link}`)}return null})}toggleLinkCard(t){const e=JSON.parse(JSON.stringify(this.state.introLinks));e[t].enabled=!e[t].enabled;const o=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(e)!==this.introLinksOriginal;this.setState({introLinks:e,hasUnsavedChanges:o})}getLinkCards(){var t;return(t=this.state.introLinks)==null?void 0:t.map((e,o)=>!e.enabled&&!this.state.edit?null:e.camera==="custom"?s.jsx(E,{image:e.image,title:e.name,action:{link:e.link,text:e.linkName},t:this.props.t,socket:this.props.socket,color:e.color,edit:this.state.edit,interval:e.interval,camera:e.camera,addTs:e.addTs,onEdit:()=>{var i;return this.setState({editLink:!0,editLinkIndex:o,link:JSON.parse(JSON.stringify((i=this.state.introLinks)==null?void 0:i[o]))})},onRemove:()=>{const i=JSON.parse(JSON.stringify(this.state.introLinks));i.splice(o,1);const d=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(i)!==this.introLinksOriginal;this.setState({introLinks:i,hasUnsavedChanges:d})},enabled:e.enabled,lang:this.props.lang,toggleActivation:()=>this.toggleLinkCard(o),cameraUrl:e.desc,theme:this.props.theme},`link${o}`):s.jsx(O,{image:e.image,title:e.name,action:{link:e.link,text:e.linkName},t:this.props.t,color:e.color,edit:this.state.edit,onEdit:()=>{var i;return this.setState({editLink:!0,editLinkIndex:o,link:JSON.parse(JSON.stringify((i=this.state.introLinks)==null?void 0:i[o]))})},onRemove:()=>{const i=JSON.parse(JSON.stringify(this.state.introLinks));i.splice(o,1);const d=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(i)!==this.introLinksOriginal;this.setState({introLinks:i,hasUnsavedChanges:d})},enabled:e.enabled,lang:this.props.lang,toggleActivation:()=>this.toggleLinkCard(o),theme:this.props.theme,children:e.desc||""},`link${o}`))}editLinkCard(){return this.state.editLink?s.jsx(U,{link:this.state.link,socket:this.props.socket,isNew:this.state.editLinkIndex===-1,t:this.props.t,lang:this.props.lang,theme:this.props.theme,onClose:t=>{if(t){const e=JSON.parse(JSON.stringify(this.state.introLinks));this.state.editLinkIndex===-1?(t.enabled=!0,e.push(t)):(t.enabled=e[this.state.editLinkIndex].enabled,e[this.state.editLinkIndex]=t);const o=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(e)!==this.introLinksOriginal;this.setState({introLinks:e,editLink:!1,hasUnsavedChanges:o,link:null})}else this.setState({editLink:!1})}}):null}getButtons(){const t=[];return this.state.edit?(t.push(s.jsx(n.Fab,{color:"primary",size:"small",sx:v.Utils.getStyle(this.props.theme,m.button,m.addButton),onClick:()=>this.setState({editLink:!0,editLinkIndex:-1,link:{}}),children:s.jsx(f.Add,{})},"add")),t.push(s.jsx(n.Fab,{size:"small",color:"primary",disabled:!this.state.hasUnsavedChanges,sx:v.Utils.getStyle(this.props.theme,m.button,m.saveButton),onClick:()=>this.saveCards(),children:s.jsx(f.Check,{})},"save")),t.push(s.jsx(n.Fab,{size:"small",color:"primary",sx:v.Utils.getStyle(this.props.theme,m.button,m.closeButton),onClick:()=>this.deactivateEditMode(),children:s.jsx(f.Close,{})},"close"))):t.push(s.jsx(n.Fab,{color:"primary",size:"small",style:m.button,onClick:()=>this.activateEditMode(),children:s.jsx(f.Create,{})},"edit")),t}async saveCards(){const t=await this.props.socket.getSystemConfig(!0);let e=!1;JSON.stringify(t.common.intro)!==JSON.stringify(this.state.deactivated)&&(t.common.intro=this.state.deactivated,e=!0),!e&&JSON.stringify(t.native.introLinks)!==JSON.stringify(this.state.introLinks)&&(e=!0,t.native.introLinks=this.state.introLinks),e?this.props.socket.setSystemConfig(t).then(()=>this.props.showAlert("Updated","success")).catch(o=>{console.log(o),this.props.showAlert(o,"error")}).then(()=>this.setState({edit:!1})):this.setState({edit:!1})}async getHostData(t,e){let o;if(e!==void 0)o={val:e};else try{o=await this.props.socket.getState(`${t}.alive`)}catch(r){console.error(`Cannot get state ${t}.alive: ${r}`),o={val:!1}}let i={alive:!1};if(o!=null&&o.val)try{i=await this.props.socket.getHostInfo(t,!1,1e4),i&&typeof i=="object"&&i.alive!==!1&&(i.alive=!0)}catch(r){console.error(`Cannot get host info for ${t}: ${r}`),i={alive:!1}}else i={alive:!1};const d=await this.props.socket.getForeignStates(`${t}.versions.*`);return Object.keys(d).forEach(r=>i[`_${r.split(".").pop()}`]=d[r].val),{id:t,data:i}}async getHostsData(t){const e=t.map(l=>this.getHostData(l._id)),o=await Promise.all(e),i={},d={},r=new Map(this.state.hostDataTimestampMap),a=Date.now();return o.forEach(l=>{i[l.id]=C.preprocessHostData(l.data),d[l.id]=l.data.alive,r.set(l.id,a)}),this.setState({hostDataTimestampMap:r}),{hostsData:i,alive:d}}addLinks(t,e,o,i,d,r){const a={id:t.id,name:t.name,description:t.description,color:t.color,image:t.icon,info:""},l=J(t.link,e.name,o,{instances:i,hostname:this.props.hostname,adminInstance:this.props.adminInstance,hosts:d}),h=this.state.reverseProxy;let p=null;if(h!=null&&h.length){const c=window.location.pathname;p=h.find(u=>{if(!u.globalPath)return!1;const k=u.globalPath.endsWith("/")?u.globalPath:`${u.globalPath}/`;return c===k||c.startsWith(k)})||null}if(l.length===1){a.link=l[0].url,a.port=l[0].port,a.link=P(a.link,a.id,i,p)||a.link;const c=r.find(u=>u.link===a.link);c?console.log(`Double links: "${a.id}" and "${c.id}"`):r.push(a)}else l.length>1&&l.forEach(c=>{const u=r.find(k=>k.link===c.url);if(u)console.log(`Double links: "${a.id}" and "${u.id}"`);else{const k={...a,link:c.url,port:c.port};k.link=P(k.link,a.id,i,p)||k.link,r.push(k)}})}static getText(t,e){return t?typeof t=="object"?t[e]||t.en||"":t||"":""}static normalizeLinks(t,e,o){if(!t.common.localLinks&&!t.common.localLink&&!t.common.welcomeScreen&&!t.common.welcomeScreenPro)return null;const i={id:t._id.replace("system.adapter.",""),link:"",name:C.getText(t.common.titleLang||t.common.title||t.common.name,e),order:t.common.order||1e3,intro:!0,description:C.getText(t.common.desc,e),icon:t.common.icon?`adapter/${t.common.name}/${t.common.icon}`:"img/no-image.svg"};let d=[];if(t.common.localLink)if(typeof t.common.localLink=="string")d.push({...i,link:t.common.localLink});else{const r=t.common.localLink;if(r.link){const a={...i,link:r.link};r.color&&(a.color=r.color),r.order!==void 0&&typeof r.order=="number"&&(a.order=r.order),r.icon&&r.img&&(a.icon=r.icon||r.img),d.push(a)}else console.warn(`Unknown localLink structure: ${JSON.stringify(t.common.localLink)}`)}if(t.common.localLinks&&typeof t.common.localLinks=="object"&&Object.keys(t.common.localLinks).forEach(r=>{const a=t.common.localLinks[r];if(typeof a=="string")d.push({...i,link:a});else{const l=a;if(l.link){const h={...i,id:t._id.replace("system.adapter.","")+(r==="_default"?"":` ${r}`),link:l.link,name:i.name+(r==="_default"?"":` ${r}`)};l.color&&(h.color=l.color),l.order!==void 0&&(h.order=parseInt(l.order,10)||1e3),l.icon&&l.img&&(h.icon=l.icon||l.img),l.description&&(h.description=C.getText(l.description,e)),l.pro!==void 0&&(typeof l.pro=="string"?h.pro=l.pro:h.pro=`${t.common.name}/index.html`),l.cloud!==void 0&&(h.cloud=l.cloud),l.intro!==void 0&&(h.intro=l.intro===!0),l.name&&(h.name=C.getText(l.name,e)),r==="_default"&&(h.default=!0),d.push(h)}else console.warn(`Unknown localLinks structure: ${JSON.stringify(a)}`)}}),t.common.welcomeScreen&&typeof t.common.welcomeScreen=="object"&&((Array.isArray(t.common.welcomeScreen)?t.common.welcomeScreen:[t.common.welcomeScreen]).forEach(a=>{if(a.link){const l={...i,id:`${t._id.replace("system.adapter.","")} cloud`,link:`%web_protocol%://%web_bind%:%web_port%/${a.link}`,cloud:a.link};if(a.color&&(l.color=a.color),a.order!==void 0&&typeof a.order=="number"&&(l.order=a.order),a.icon&&a.img&&(l.icon=a.icon||a.img),a.localLinks){const h=t.common.localLinks[a.localLinks];h&&typeof h=="string"?l.link=h:h&&typeof h=="object"&&h.link&&(l.link=h.link)}a.name&&(l.name=C.getText(a.name,e)),d.push(l)}}),t.common.welcomeScreenPro&&typeof t.common.welcomeScreenPro=="object"&&(Array.isArray(t.common.welcomeScreenPro)?t.common.welcomeScreenPro:[t.common.welcomeScreenPro]).forEach(l=>{if(l.link){const h={...i,id:`${t._id.replace("system.adapter.","")} pro`,link:`%web_protocol%://%web_bind%:%web_port%/${l.link}`,pro:l.link};if(l.color&&(h.color=l.color),l.order!==void 0&&typeof l.order=="number"&&(h.order=l.order),l.icon&&l.img&&(h.icon=l.icon||l.img),l.localLinks){const p=t.common.localLinks[l.localLinks];p&&typeof p=="string"?h.link=p:p&&typeof p=="object"&&p.link&&(h.link=p.link)}l.name&&(h.name=C.getText(l.name,e)),d.push(h)}})),d.forEach(r=>{!r.icon.startsWith("adapter/")&&!r.icon.startsWith("data:image/")&&!r.icon.startsWith("http://")&&!r.icon.startsWith("https://")&&r.icon!=="img/no-image.svg"&&(r.icon=`adapter/${t.common.name}/${r.icon}`)}),o){const r={};d.forEach(a=>{r[a.link]?(a.color&&(r[a.link].color=a.color),a.icon&&(r[a.link].icon=a.icon),a.cloud&&(r[a.link].cloud=a.cloud),a.pro&&(r[a.link].pro=a.pro),a.intro!==void 0&&(r[a.link].intro=a.intro),a.name&&typeof a.name=="object"&&(r[a.link].name=a.name),a.order!==void 0&&(r[a.link].order=a.order),a.default&&(r[a.link].default=a.default)):r[a.link]=a}),d=Object.values(r)}return d.sort((r,a)=>r.default===void 0&&a.default===void 0?r.order===void 0&&a.order===void 0?0:r.order===void 0?-1:a.order===void 0?1:r.order-a.order:r.default===void 0?-1:a.default===void 0?1:r.order===void 0&&a.order===void 0?0:r.order===void 0?-1:a.order===void 0?1:r.order-a.order),d}async getInstances(t,e,o){e=e||this.state.hosts;const i={};e.forEach(d=>i[d._id]=d);try{const d=await this.props.socket.getAdapterInstances("",t);let r=o.common.intro||[];Array.isArray(r)||(r=Object.keys(r),r.sort());const a=[],l={};d.forEach(p=>l[p._id]=p),d.forEach(p=>{if(!p)return;const c=p.common||null,u=p._id.split("."),k=parseInt(u.pop(),10);let j;if(c!=null&&c.name&&typeof c.name=="object"){const N=c==null?void 0:c.name;j=N[this.props.lang]||N.en}else j=(c==null?void 0:c.name)||"";if(!(j==="admin"&&c.localLink===(this.props.hostname||""))&&j!=="web"&&!(j&&j!=="vis-web-admin"&&j.match(/^vis-/)&&j!=="vis-2")&&!(j!=null&&j.match(/^icons-/))&&c&&(c.enabled||c.onlyWWW)){const N=C.normalizeLinks(p,this.props.lang,!0);N&&N.forEach(H=>this.addLinks(H,c,k,l,i,a))}}),a.forEach(p=>{p.link&&(p.linkName=p.link.replace("https://","").replace("http://","").replace(/^[^_]+:/,""))}),a.sort((p,c)=>{if(p.order!==void 0||c.order!==void 0){if(p.order=p.order===void 0?1e3:p.order,c.order=c.order===void 0?1e3:c.order,p.order<c.order)return-1;if(p.order>c.order)return 1}return p.id>c.id?1:p.id<c.id?-1:0}),e==null||e.forEach(p=>{const c=p==null?void 0:p.common;let u=c==null?void 0:c.name;if(typeof u=="object"&&u&&(u=u[this.props.lang]||u.en),c){const k={id:p._id,name:u||"",color:"",image:c.icon||"img/no-image.svg",info:this.t("Info"),linkName:""};a.push(k)}});const h=[];return r.forEach(p=>{a.find(c=>p===`${c.id}_${c.linkName}`)&&h.push(p)}),r=h,{instances:a,deactivated:r}}catch(d){return console.log(d),{instances:[],deactivated:[]}}}getHostDescription(t){const e=this.state.hostsData?this.state.hostsData[t]:null;if(e&&e.alive===!1)return s.jsx("div",{style:m.hostOffline,children:this.props.t("Offline")});let o="",i="";if(e){try{e._nodeNewest&&e["Node.js"]&&w.gt(e._nodeNewest,e["Node.js"].replace(/^v/,""))&&(o=e._nodeNewest)}catch{}try{e._nodeNewest!==e._nodeNewestNext&&e._nodeNewestNext&&e["Node.js"]&&e._nodeNewest&&w.gt(e._nodeNewestNext,e["Node.js"].replace(/^v/,""))&&w.gt(e._nodeNewestNext,e._nodeNewest)&&(o+=(o?" / ":"")+e._nodeNewestNext)}catch{}if(o){const d=this.state.nodeUpdateSupported&&e.Platform==="linux";o=s.jsx(n.Tooltip,{title:this.props.t("Some updates available"),slotProps:{popper:{sx:m.tooltip}},children:s.jsxs("span",{style:{...m.nodeUpdate,display:"inline-flex"},children:["(",o,")",d?s.jsx(f.Refresh,{style:m.updateIcon,onClick:()=>this.setState({nodeUpdateDialog:{hostId:t,version:e._nodeNewestNext}})}):null]})})}try{e._npmNewest&&e.NPM&&w.gt(e._npmNewest,e.NPM)&&(i=e._npmNewest)}catch{}try{e._npmNewest!==e._npmNewestNext&&e._npmNewestNext&&e.NPM&&e._npmNewest&&w.gt(e._npmNewestNext,e.NPM)&&w.gt(e._npmNewestNext,e._npmNewest)&&(i+=(i?" / ":"")+e._npmNewestNext)}catch{}i&&(i=s.jsx(n.Tooltip,{title:this.props.t("Some updates available"),slotProps:{popper:{sx:m.tooltip}},children:s.jsxs("span",{style:m.nodeUpdate,children:["(",i,")"]})}))}return e&&typeof e=="object"?s.jsxs("ul",{style:{textTransform:"none"},children:[s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("Platform"),": "]}),e.Platform||"--"]})}),s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("RAM"),": "]}),T.RAM(e.RAM)]})}),s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("Node.js"),": "]}),s.jsx("span",{style:o?m.updateExists:m.updateNo,children:e["Node.js"]||"--"}),o]})}),s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("NPM"),": "]}),s.jsx("span",{className:i?m.updateExists:m.updateNo,children:e.NPM||"--"}),i]})})]}):s.jsxs("ul",{children:[s.jsx(n.Skeleton,{}),s.jsx(n.Skeleton,{}),s.jsx(n.Skeleton,{}),s.jsx(n.Skeleton,{})]})}getHostDescriptionAll(t){const e=this.state.hostsData?this.state.hostsData[t]:null;return{el:s.jsx("ul",{style:{textTransform:"none"},children:e&&typeof e=="object"&&Object.keys(e).filter(o=>!o.startsWith("_")&&e[o]!==null&&e[o]!==void 0).map(o=>s.jsx("li",{children:e&&typeof e=="object"?s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t(o),": "]}),T[o]?T[o](e[o],this.t):(typeof e[o]=="object"?JSON.stringify(e[o]):e[o].toString())||"--"]}):s.jsx(n.Skeleton,{})},o))}),text:e&&typeof e=="object"?Object.keys(e).reduce((o,i)=>`${o}${this.t(i)}:${T[i]?T[i](e[i],this.t):(typeof e[i]=="object"?JSON.stringify(e[i]):e[i])||"--"}
|
|
1
|
+
import{j as s}from"./DefaultPropsProvider-BiXBMQYQ.js";import{i as _,a as B}from"./iobroker_admin__loadShare__react__loadShare__-LM7uyL45.js";import{b as S,r as J,c as P,s as w}from"./bootstrap-COulQZax-v84.js";import{i as n,a as f}from"./iobroker_admin__loadShare___mf_0_mui_mf_1_icons_mf_2_material__loadShare__-CJO5yP3h.js";import{i as v}from"./iobroker_admin__loadShare___mf_0_iobroker_mf_1_adapter_mf_2_react_mf_2_v5__loadShare__-LFZoiUTt.js";import{b as $}from"./blue-CagzI6CQ.js";import{g as b,v as M}from"./createTheme-DFX8CY6F.js";import"./_commonjsHelpers-CE1G-McA.js";import"./iobroker_admin__mf_v__runtimeInit__mf_v__-g2X2zhAf.js";import"./emotion-serialize.esm-Q4o_CgeF.js";import"./iobroker_admin__loadShare___mf_0_emotion_mf_1_react__loadShare__-BywLg1Xe.js";import"./ace-DEUjyTIn.js";import"./iobroker_admin__loadShare___mf_0_iobroker_mf_1_json_mf_2_config__loadShare__-CpA7pnS5.js";import"./iobroker_admin__loadShare__leaflet__loadShare__-CNUAG3AH.js";import"./ext-language_tools-ylAoucDh.js";import"./iobroker_admin__loadShare__react_mf_2_dropzone__loadShare__-CwjnV48g.js";import"./iobroker_admin__loadShare__react_mf_2_dom__loadShare__-CVeAXnkk.js";import"./preload-helper-BDBacUwf.js";import"./sdk-C-e-e2gd.js";import"./extends-CF3RwP-h.js";import"./assertThisInitialized-B0aQ9eG_.js";import"./useTheme-Bl-M1DYp.js";import"./index-DcK0RDrH.js";import"./ThemeProvider-BOFFjWAF.js";import"./emotion-cache.browser.esm-BgJfNZJN.js";import"./setYear-3ufv5yRD.js";import"./en-US-DBFJNIH6.js";const L="0 2px 2px 0 rgba(0, 0, 0, .14),0 3px 1px -2px rgba(0, 0, 0, .12),0 1px 5px 0 rgba(0, 0, 0, .2)",A="0 8px 17px 0 rgba(0, 0, 0, .2),0 6px 20px 0 rgba(0, 0, 0, .19)",x={root:g=>({padding:".75rem",[g.breakpoints.up("xl")]:{flex:"0 1 20%"}}),card:{display:"flex",minHeight:"235px",position:"relative",overflow:"hidden",maxHeight:"235p","&:hover":{overflowY:"auto",boxShadow:A}},cardInfo:{display:"flex",minHeight:"235px",position:"relative",overflow:"initial",maxHeight:"235p",flexDirection:"column","&:hover":{boxShadow:A}},cardInfoHead:g=>({position:"sticky",top:0,background:g.palette.background.default,display:"flex",width:"100%",justifyContent:"space-between",borderBottom:"1px solid",padding:"5px 5px 0px 5px"}),edit:{opacity:.6,userSelect:"none",pointerEvents:"none"},media:g=>({backgroundColor:g.palette.mode==="dark"?"#535353":"#e2e2e2",maxWidth:"30%"}),img:{width:120,height:"auto",padding:"2rem .5rem",maxWidth:"100%"},contentContainer:{display:"flex",flexDirection:"column",flex:1},content:{height:"170px",flexGrow:1,overflowY:"hidden"},action:{minHeight:"49px",padding:"16px 24px"},expand:{position:"absolute",right:"10px",bottom:"10px"},collapse:{minHeight:"100%",backgroundColor:"#ffffff",position:"absolute",width:"100%"},enabled:{color:"#ffffff",backgroundColor:$[500],position:"absolute",top:8,right:8,boxShadow:L,"&:hover":{backgroundColor:$[300]},"&:focus":{backgroundColor:$[500]}},disabled:{color:"#ffffff",backgroundColor:b[500],position:"absolute",top:8,right:8,boxShadow:L,"&:hover":{backgroundColor:b[300]},"&:focus":{backgroundColor:b[500]}},editButton:{color:"#ffffff",backgroundColor:b[500],position:"absolute",top:64,right:8,boxShadow:L,"&:hover":{backgroundColor:b[300]},"&:focus":{backgroundColor:b[500]}},deleteButton:{color:"#ffffff",backgroundColor:M[500],position:"absolute",top:120,right:8,boxShadow:L,"&:hover":{backgroundColor:M[300]},"&:focus":{backgroundColor:M[500]}},contentGrid:{height:"100%"},colorOrange:{color:"#ffcc80"},tooltip:{pointerEvents:"none"}};class O extends _.Component{constructor(t){super(t),this.state={expanded:!1}}static getDerivedStateFromProps(t){return t.edit?{expanded:!1}:null}handleExpandClick(){this.setState({expanded:!this.state.expanded})}renderContent(){return this.props.children}openDialog(){}renderDialogs(){return null}render(){var o,i;const t=this.props.edit?x.edit:void 0;let e=this.props.action.text||this.props.t("Link");return typeof e=="object"&&(e=e[this.props.lang]||e.en),s.jsx(n.Grid2,{size:{xs:12,sm:6,md:4,lg:3,xl:2},sx:v.Utils.getStyle(this.props.theme,x.root,this.props.style),style:{maxWidth:500},children:s.jsx(n.Link,{href:!this.props.edit&&this.props.action&&this.props.action.link?this.props.action.link:null,underline:"none",target:"_blank",rel:"noopener noreferrer",children:s.jsxs(n.Card,{sx:x.card,onClick:d=>{d.stopPropagation(),this.openDialog()},children:[this.props.showInfo&&!this.props.offline&&s.jsx(n.Button,{style:{...x.expand,...t},variant:"contained",size:"small",disabled:this.props.disabled,onClick:()=>this.handleExpandClick(),color:"primary",children:this.props.t("Info")}),s.jsxs(n.Box,{component:"div",sx:v.Utils.getStyle(this.props.theme,x.media,t,this.props.color&&{backgroundColor:this.props.color},{display:"flex",flexDirection:"column"}),children:[s.jsx(n.CardMedia,{style:x.img,component:"img",image:this.props.image}),s.jsx("div",{style:{flex:1,display:"flex",paddingBottom:"5px",paddingLeft:"5px"},children:this.props.warning?s.jsx(n.Tooltip,{title:this.props.warning,slotProps:{popper:{sx:x.tooltip}},children:s.jsx(f.Warning,{style:{alignSelf:"end",fontSize:36}})}):null})]}),s.jsxs("div",{style:{...x.contentContainer,...t},children:[s.jsx(n.CardContent,{style:x.content,children:s.jsxs(n.Grid2,{container:!0,direction:"column",wrap:"nowrap",style:x.contentGrid,children:[s.jsx(n.Typography,{gutterBottom:!0,variant:"h5",component:"h5",children:this.props.title}),this.renderContent()]})}),((o=this.props.action)==null?void 0:o.link)&&s.jsx(n.Divider,{}),((i=this.props.action)==null?void 0:i.link)&&s.jsx(n.CardActions,{style:x.action,children:s.jsx("div",{style:x.colorOrange,children:S.getText(e,this.props.lang)})})]}),this.props.showInfo&&s.jsx(n.Collapse,{style:x.collapse,in:this.state.expanded,timeout:"auto",unmountOnExit:!0,children:s.jsxs(n.Card,{sx:x.cardInfo,children:[s.jsxs(n.Box,{component:"div",sx:x.cardInfoHead,children:[s.jsx(n.Typography,{gutterBottom:!0,variant:"h5",component:"h5",children:this.props.t("Info")}),s.jsxs("div",{children:[s.jsx(n.IconButton,{size:"small",onClick:()=>{this.props.getHostDescriptionAll&&v.Utils.copyToClipboard(this.props.getHostDescriptionAll().text),this.props.openSnackBarFunc&&this.props.openSnackBarFunc()},children:s.jsx(v.IconCopy,{})}),s.jsx(n.IconButton,{size:"small",onClick:()=>this.handleExpandClick(),children:s.jsx(f.Close,{})})]})]}),s.jsx(n.CardContent,{children:this.props.getHostDescriptionAll().el})]})}),this.props.edit&&this.props.toggleActivation&&s.jsx(n.IconButton,{size:"large",sx:this.props.enabled?x.enabled:x.disabled,onClick:()=>this.props.toggleActivation(),children:s.jsx(f.Check,{})}),this.props.edit&&this.props.onEdit&&s.jsx(n.IconButton,{size:"large",sx:x.editButton,onClick:()=>this.props.onEdit(),children:s.jsx(f.Create,{})}),this.props.edit&&this.props.onRemove&&s.jsx(n.IconButton,{size:"large",sx:x.deleteButton,onClick:()=>this.props.onRemove(),children:s.jsx(f.Delete,{})}),this.renderDialogs()]})})})}}const I={closeButton:g=>({position:"absolute",right:8,top:8,color:g.palette.grey[500]}),paper:{},typography:{paddingRight:30},img:{width:"100%",height:"100%",objectFit:"contain"}};class R extends _.Component{cameraUpdateTimer;cameraRef;constructor(t){super(t),this.cameraUpdateTimer=null,this.cameraRef=_.createRef()}componentDidMount(){this.props.camera&&this.props.camera!=="text"&&(this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500)),this.updateCamera())}componentWillUnmount(){this.cameraUpdateTimer&&(clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=null)}updateCamera(){if(this.cameraRef.current)if(this.props.camera==="custom"){let t=this.props.cameraUrl;this.props.addTs&&(t.includes("?")?t+=`&ts=${Date.now()}`:t+=`?ts=${Date.now()}`),this.cameraRef.current.src=t}else{const t=this.props.camera.split("."),e=t.shift(),o=t.shift();this.props.socket.sendTo(`${e}.${o}`,"image",{name:t.pop(),width:this.cameraRef.current.width}).then(i=>{i&&i.data&&this.cameraRef.current&&(this.cameraRef.current.src=`data:image/jpeg;base64,${i.data}`)})}}render(){return s.jsxs(n.Dialog,{onClose:()=>this.props.onClose(),open:!0,maxWidth:"xl",fullWidth:!0,fullScreen:!0,sx:{"& .MuiDialog-paper":I.paper},children:[s.jsx(n.DialogTitle,{children:s.jsxs(n.Typography,{component:"h2",variant:"h6",sx:{"&.MuiTypography-root":I.typography},children:[this.props.name,s.jsx(n.IconButton,{size:"large",sx:I.closeButton,onClick:()=>this.props.onClose(),children:s.jsx(f.Close,{})})]})}),s.jsx(n.DialogContent,{dividers:!0,children:s.jsx("img",{style:I.img,src:"",alt:"camera",ref:this.cameraRef})}),s.jsx(n.DialogActions,{children:s.jsx(n.Button,{variant:"contained",autoFocus:!0,onClick:t=>{t.stopPropagation(),this.props.onClose()},color:"primary",startIcon:s.jsx(f.Close,{}),children:this.props.t("Close")})})]})}}const D={cameraImg:{width:"100%",height:"100%",maxWidth:200,maxHeight:200,objectFit:"contain"},imgContainer:{height:"100%"},hidden:{display:"none"},imgSkeleton:{transform:"initial"}};class E extends O{cameraRef;cameraUpdateTimer;interval;constructor(t){super(t),Object.assign(this.state,{error:!1,dialog:!1,loaded:!1}),this.cameraRef=_.createRef(),this.cameraUpdateTimer=null,this.interval=t.interval}updateCamera(){if(this.cameraRef.current)if(this.props.camera==="custom"){let t=this.props.cameraUrl;this.props.addTs&&(t.includes("?")?t+=`&ts=${Date.now()}`:t+=`?ts=${Date.now()}`),this.cameraRef.current.src=t}else{const t=this.props.camera.split("."),e=t.shift(),o=t.shift();this.props.socket.sendTo(`${e}.${o}`,"image",{name:t.pop(),width:this.cameraRef.current.width}).then(i=>{i!=null&&i.data&&this.cameraRef.current&&(this.cameraRef.current.src=`data:image/jpeg;base64,${i.data}`)}).catch(i=>window.alert(`Cannot send to instance: ${i}`))}}componentDidMount(){this.props.camera&&this.props.camera!=="text"&&(this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500)),this.updateCamera())}componentWillUnmount(){this.cameraUpdateTimer&&(clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=null)}renderDialogs(){return this.state.dialog?s.jsx(R,{socket:this.props.socket,camera:this.props.camera,name:this.props.title,t:this.props.t,onClose:()=>{this.props.camera&&this.props.camera!=="text"&&(this.cameraUpdateTimer&&clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500)),this.updateCamera()),this.setState({dialog:!1})},cameraUrl:this.props.cameraUrl}):null}handleImageLoad(){this.state.loaded||this.setState({loaded:!0,error:!1})}handleImageError(){this.state.error||this.setState({loaded:!1,error:!0})}renderContent(){if(this.props.camera==="custom"){let t=this.props.cameraUrl;return this.props.addTs&&(t.includes("?")?t+=`&ts=${Date.now()}`:t+=`?ts=${Date.now()}`),s.jsxs(n.Grid2,{container:!0,style:D.imgContainer,justifyContent:"center",alignItems:"center",children:[s.jsx("img",{ref:this.cameraRef,src:t,alt:"Camera",style:this.state.loaded&&!this.state.error?D.cameraImg:D.hidden,onLoad:()=>this.handleImageLoad(),onError:()=>this.handleImageError()}),!this.state.loaded&&!this.state.error&&s.jsx(n.Skeleton,{height:"100%",width:"100%",animation:"wave",style:D.imgSkeleton}),this.state.error&&s.jsx(f.Error,{fontSize:"large"})]})}return this.props.camera.startsWith("cameras.")?s.jsx("img",{ref:this.cameraRef,src:"",alt:"camera",style:D.cameraImg}):null}render(){return this.props.camera&&this.props.camera!=="text"?this.interval!==this.props.interval&&(this.interval=this.props.interval,this.cameraUpdateTimer&&clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=setInterval(()=>this.updateCamera(),Math.max(parseInt(this.props.interval,10),500))):this.cameraUpdateTimer&&(clearInterval(this.cameraUpdateTimer),this.cameraUpdateTimer=null),super.render()}}const y={formControl:{marginTop:32},rootGrid:{flexGrow:1},closeButton:g=>({position:"absolute",right:8,top:8,color:g.palette.grey[500]}),paper:{},typography:{paddingRight:30},editItem:{marginTop:8},editItemSlider:{marginTop:24},labelSlider:{marginTop:16,fontSize:"1rem"},editColor:{width:"100%"}};class U extends _.Component{constructor(t){super(t),this.state={image:"",name:t.t("New link"),link:"http://",linkName:"",color:"",desc:"",addTs:!0,interval:5e3,camera:"text",cameraList:[],...t.link}}componentDidMount(){this.getCamerasInstances()}getCamerasInstances(){this.props.socket.getAdapterInstances("cameras",!0).then(t=>{const e=[],o=[];t.forEach(i=>{const d=i._id.replace("system.adapter.","");i.common&&i.common.enabled&&o.push(this.props.socket.getState(`${i._id}.alive`).then(r=>r&&r.val&&this.props.socket.sendTo(d,"list",null)).then(r=>r&&r.list&&r.list.forEach(a=>e.push({id:a.id,name:`${a.desc} [${d}/${a.name}]`}))))}),Promise.all(o).then(()=>this.setState({cameraList:e}))})}static getLinkNameFromLink(t){const e=t.trim().match(/^https?:\/\/([^/:]+)(:\d+)?/);return e?e[1]+(e[2]||""):""}render(){return s.jsxs(n.Dialog,{onClose:()=>this.props.onClose(),open:!0,maxWidth:"md",fullWidth:!0,sx:{"& .MuiDialog-paper":y.paper},children:[s.jsx(n.DialogTitle,{children:s.jsxs(n.Typography,{component:"h2",variant:"h6",sx:{"&.MuiTypography-root":y.typography},children:[this.props.isNew?this.props.t("Add new link: "):this.props.t("Edit link"),s.jsx(n.IconButton,{size:"large",sx:y.closeButton,onClick:()=>this.props.onClose(),children:s.jsx(f.Close,{})})]})}),s.jsx(n.DialogContent,{dividers:!0,children:s.jsxs(n.Grid2,{style:y.rootGrid,container:!0,direction:"row",children:[s.jsx(n.Grid2,{size:{xs:12,sm:6,md:8,lg:9},children:s.jsxs(n.Grid2,{container:!0,direction:"column",children:[s.jsxs(n.FormControl,{variant:"standard",style:y.formControl,children:[s.jsx(n.InputLabel,{id:"select-helper-label",children:this.props.t("Link type")}),s.jsxs(n.Select,{variant:"standard",labelId:"select-helper-label",value:this.state.camera,onChange:t=>this.setState({camera:t.target.value}),children:[s.jsx(n.MenuItem,{value:"text",children:s.jsx("em",{children:this.props.t("Description")})},"desc"),this.state.cameraList.map(t=>s.jsx(n.MenuItem,{value:t.id,children:t.name},t.id)),s.jsx(n.MenuItem,{value:"custom",children:this.props.t("Custom camera URL")},"custom")]})]}),s.jsx(n.TextField,{variant:"standard",label:this.props.t("URL"),value:this.state.link,style:y.editItem,onChange:t=>{const e=U.getLinkNameFromLink(this.state.link);e&&(!this.state.linkName||e===this.state.linkName)?this.setState({link:t.target.value,linkName:U.getLinkNameFromLink(t.target.value)}):this.setState({link:t.target.value})},slotProps:{input:{endAdornment:this.state.link?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({link:""}),children:s.jsx(f.Close,{})})}):null}}}),s.jsx(n.TextField,{variant:"standard",style:y.editItem,label:this.props.t("Name"),value:this.state.name||"",onChange:t=>this.setState({name:t.target.value}),slotProps:{input:{endAdornment:this.state.name?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({name:""}),children:s.jsx(f.Close,{})})}):null}}}),this.state.link?s.jsx(n.TextField,{variant:"standard",style:y.editItem,label:this.props.t("Link name"),value:this.state.linkName||"",onChange:t=>this.setState({linkName:t.target.value}),slotProps:{input:{endAdornment:this.state.linkName?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({linkName:""}),children:s.jsx(f.Close,{})})}):null}}}):null,this.state.camera==="custom"||this.state.camera==="text"?s.jsx(n.TextField,{variant:"standard",style:y.editItem,label:this.state.camera==="custom"?this.props.t("Camera URL"):this.props.t("Description"),value:this.state.desc||"",onChange:t=>this.setState({desc:t.target.value}),slotProps:{input:{endAdornment:this.state.desc?s.jsx(n.InputAdornment,{position:"end",children:s.jsx(n.IconButton,{tabIndex:-1,size:"small",onClick:()=>this.setState({desc:""}),children:s.jsx(f.Close,{})})}):null}}}):null,this.state.camera==="custom"?s.jsx(n.FormControlLabel,{style:y.editItem,control:s.jsx(n.Checkbox,{checked:this.state.addTs,onChange:t=>this.setState({addTs:t.target.checked})}),label:this.props.t("Add timestamp to URL")}):null,this.state.camera!=="text"?s.jsx(n.Typography,{style:y.labelSlider,gutterBottom:!0,children:"Polling interval in ms"}):null,this.state.camera!=="text"?s.jsx(n.Slider,{style:y.editItemSlider,value:this.state.interval,getAriaValueText:()=>`${this.state.interval}ms`,onChange:(t,e)=>this.setState({interval:e}),step:100,min:500,max:6e4,valueLabelDisplay:"on"}):null,s.jsx("div",{style:{...y.editItem,width:50},children:s.jsx(n.TextField,{variant:"standard",fullWidth:!0,label:this.props.t("Color"),style:y.editColor,type:"color",value:this.state.color,onChange:t=>this.setState({color:t.target.value})})}),s.jsx(v.UploadImage,{disabled:!1,crop:!0,maxSize:256*1024,icon:this.state.image,removeIconFunc:()=>this.setState({image:""}),onChange:t=>this.setState({image:t})})]})}),s.jsx(n.Grid2,{size:{xs:12,sm:6,md:4,lg:3},children:this.state.camera==="text"?s.jsx(O,{image:this.state.image,title:this.state.name,action:{link:this.state.link,text:this.state.linkName},t:this.props.t,lang:this.props.lang,style:{width:"100% !important",maxWidth:"100% !important",marginLeft:"8px"},color:this.state.color,enabled:!0,theme:this.props.theme,children:this.state.desc}):s.jsx(E,{interval:this.state.interval,camera:this.state.camera,addTs:this.state.addTs,style:{width:"100% !important",maxWidth:"100% !important",marginLeft:"8px"},image:this.state.image,title:this.state.name,socket:this.props.socket,action:{link:this.state.link,text:this.state.linkName},t:this.props.t,lang:this.props.lang,color:this.state.color,enabled:!0,cameraUrl:this.state.desc,theme:this.props.theme})})]})}),s.jsxs(n.DialogActions,{children:[s.jsx(n.Button,{variant:"contained",autoFocus:!0,onClick:()=>{this.props.onClose({link:this.state.link,name:this.state.name,desc:this.state.desc,linkName:this.state.linkName,color:this.state.color,image:this.state.image,addTs:this.state.addTs,camera:this.state.camera,interval:this.state.interval})},color:"primary",startIcon:this.props.isNew?s.jsx(f.Add,{}):s.jsx(f.Check,{}),children:this.props.isNew?this.props.t("Add"):this.props.t("Save")}),s.jsx(n.Button,{variant:"contained",onClick:()=>this.props.onClose(),color:"grey",startIcon:s.jsx(f.Close,{}),children:this.props.t("Close")})]})]})}}class W extends B.Component{constructor(t){super(t),this.state={inProgress:!1,success:!1,error:"",finished:!1}}render(){return s.jsxs(n.Dialog,{open:!0,maxWidth:"lg",fullWidth:!0,children:[s.jsx(n.DialogTitle,{children:v.I18n.t("Node.js upgrade")}),s.jsxs(n.DialogContent,{style:{height:100,padding:"0 20px",overflow:"hidden"},children:[this.state.finished?null:s.jsx(n.Typography,{children:v.I18n.t("Performing this update will restart the js-controller afterwards!")}),this.state.inProgress?s.jsx(n.Box,{sx:{display:"flex",justifyContent:"center"},children:s.jsx(n.CircularProgress,{})}):null,this.state.success?s.jsx(n.Typography,{children:v.I18n.t("Node.js update successful, restarting controller now!")}):null,this.state.error?s.jsx(n.Typography,{sx:{color:"red"},children:v.I18n.t("Node.js update failed: %s",this.state.error)}):null]}),s.jsxs(n.DialogActions,{children:[s.jsx(n.Button,{disabled:this.state.inProgress||this.state.finished,color:"primary",variant:"contained",startIcon:s.jsx(f.Refresh,{}),onClick:()=>this.updateNodeJsVersion(),children:v.I18n.t("Upgrade")}),s.jsx(n.Button,{disabled:this.state.inProgress,variant:"contained",onClick:()=>{this.props.onClose()},color:"primary",startIcon:s.jsx(f.Close,{}),children:v.I18n.t("Close")})]})]})}async updateNodeJsVersion(){this.setState({inProgress:!0});const t=await this.props.socket.upgradeOsPackages(this.props.hostId,[{name:"nodejs"}],!0);this.setState({inProgress:!1,success:t.success,error:t.error,finished:!0})}}const m={button:{position:"absolute",bottom:16,right:16},saveButton:g=>({backgroundColor:g.palette.success.main,right:80,"&:hover":{backgroundColor:g.palette.success.dark}}),addButton:g=>({backgroundColor:g.palette.secondary.main,right:144,"&:hover":{backgroundColor:g.palette.secondary.dark}}),closeButton:g=>({backgroundColor:g.palette.error.main,"&:hover":{backgroundColor:g.palette.error.dark}}),bold:{fontWeight:"bold"},hostOffline:{color:"#bb0000"},updateExists:{color:"#c28700",marginRight:4},updateNo:{color:"#00b204",marginRight:4},nodeUpdate:{opacity:.6},instanceNumber:{opacity:.7,fontSize:16},updateIcon:{cursor:"pointer",fontSize:16},tooltip:{pointerEvents:"none"},viewModeDiv:{display:"flex",flexFlow:"wrap",overflow:"auto",justifyContent:"left"}},T={Uptime:S.formatSeconds,"System uptime":S.formatSeconds,RAM:S.formatRam,Speed:S.formatSpeed,"Disk size":S.formatBytes,"Disk free":S.formatBytes};class C extends B.Component{#t=1800*1e3;#e=300*1e3;#s=60*1e3;introLinksOriginal;deactivatedOriginal;t;getDataTimeout;constructor(t){super(t),this.state={instances:null,deactivated:[],edit:!1,link:null,introLinks:[],editLink:!1,editLinkIndex:-1,openSnackBar:!1,hasUnsavedChanges:!1,reverseProxy:null,alive:{},hostsData:{},hosts:null,hostTimeDiffMap:new Map,hostDataTimestampMap:new Map,nodeUpdateSupported:!1,nodeUpdateDialog:null},this.t=t.t}checkBackendTime(){const t=this.state.hostTimeDiffMap,e=this.state.hostDataTimestampMap,o=Date.now();for(const[i,d]of Object.entries(this.state.hostsData)){const r=Math.abs(d.time-o);t.set(i,r),e.set(i,o)}this.setState({hostTimeDiffMap:t,hostDataTimestampMap:e})}async componentDidMount(){var i;window.NEXOWATT_EOS_ADMIN_SOCKET=this.props.socket,window.NEXOWATT_EOS_SOCKET=this.props.socket,window.dispatchEvent(new CustomEvent("nexowatt-eos-admin-socket-ready"));let t=null,e=!1;try{[t,e]=await Promise.all([this.props.socket.getObject(`system.adapter.${this.props.adminInstance}`),this.props.socket.checkFeatureSupported("CONTROLLER_OS_PACKAGE_UPGRADE")])}catch(d){if(String(window.NEXOWATT_EOS_ACCESS_ROLE||"unknown").toLowerCase()==="admin")throw d}const o=((i=t==null?void 0:t.native)==null?void 0:i.reverseProxy)||[];await new Promise(d=>this.setState({reverseProxy:o,nodeUpdateSupported:e},()=>d())),await this.getData(),this.props.instancesWorker.registerHandler(this.getDataDelayed),this.props.hostsWorker.registerHandler(this.updateHosts),this.props.hostsWorker.registerAliveHandler(this.updateHostsAlive),this.checkBackendTime()}componentWillUnmount(){this.getDataTimeout&&(clearTimeout(this.getDataTimeout),this.getDataTimeout=void 0),this.props.instancesWorker.unregisterHandler(this.getDataDelayed),this.props.hostsWorker.unregisterHandler(this.updateHosts),this.props.hostsWorker.unregisterAliveHandler(this.updateHostsAlive)}updateHostsAlive=async t=>{const e=JSON.parse(JSON.stringify(this.state.alive)),o=[];if(t.find(i=>i.type==="deleted")){this.getDataDelayed();return}if(t.forEach(i=>{!!e[i.id]!=!!i.alive&&(e[i.id]=i.alive,o.push(i.id))}),o.length){const i=JSON.parse(JSON.stringify(this.state.hostsData)),d=new Map(this.state.hostDataTimestampMap),r=Date.now();(await Promise.all(o.map(l=>this.getHostData(l,e[l])))).forEach(l=>{i[l.id]=C.preprocessHostData(l.data),d.set(l.id,r)}),this.setState({alive:e,hostsData:i,hostDataTimestampMap:d},()=>this.checkBackendTime())}};updateHosts=t=>{let e=[];if(t.find(o=>!o.obj)){this.getDataDelayed();return}if(e=t.map(o=>o.id),e.length){const o=JSON.parse(JSON.stringify(this.state.hostsData)),i=new Map(this.state.hostDataTimestampMap),d=Date.now();Promise.all(e.map(r=>this.getHostData(r))).then(r=>{r.forEach(a=>{o[a.id]=C.preprocessHostData(a.data),i.set(a.id,d)}),this.setState({hostsData:o,hostDataTimestampMap:i})})}};async activateEditMode(){var i;const t=await this.props.socket.getSystemConfig(!0),e=await this.getInstances(!0,null,t),o=(i=t==null?void 0:t.native)!=null&&i.introLinks?t.native.introLinks:[];this.introLinksOriginal=JSON.stringify(o),this.deactivatedOriginal=JSON.parse(JSON.stringify(e.deactivated)),this.setState({instances:e.instances,deactivated:e.deactivated,edit:!0,introLinks:o,hasUnsavedChanges:!1})}deactivateEditMode(){this.state.hasUnsavedChanges,this.setState({deactivated:this.deactivatedOriginal,introLinks:JSON.parse(this.introLinksOriginal),hasUnsavedChanges:!1,edit:!1},()=>{this.deactivatedOriginal=null,this.introLinksOriginal=null})}toggleCard(t,e){if(!this.state.instances||!this.state.instances.length)return;const o=JSON.parse(JSON.stringify(this.state.deactivated)),i=o.indexOf(`${t}_${e}`);i!==-1?o.splice(i,1):(o.push(`${t}_${e}`),o.sort());const d=JSON.stringify(o)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(this.state.introLinks)!==this.introLinksOriginal;this.setState({deactivated:o,hasUnsavedChanges:d})}getInstancesCards(){var t;return(t=this.state.instances)==null?void 0:t.map(e=>{var i,d;const o=String(window.NEXOWATT_EOS_ACCESS_ROLE||"admin").toLowerCase()!=="admin"&&String(window.NEXOWATT_EOS_ACCESS_ROLE||"admin").toLowerCase()!=="service"&&/^nexowatt-ui(?:\.|$)/i.test(e.id)||!((i=this.state.deactivated)!=null&&i.includes(`${e.id}_${e.linkName}`));if(o||this.state.edit){let r=e.link?e.link.replace(/^https?:\/\//,""):"";if(r=r.split("/")[0],e.id===this.props.adminInstance)return null;let a=window.isFinite(e.id.split(".").pop());a&&(a=!!((d=this.state.instances)!=null&&d.find(k=>k.id!==e.id&&e.name===k.name&&e.id.split(".")[0]===k.id.split(".")[0])));const l=this.state.hostsData?this.state.hostsData[e.id]:null,h=this.state.hostTimeDiffMap.get(e.id)??0,p=this.state.hostDataTimestampMap.get(e.id)??0,u=Date.now()-p<this.#e;return s.jsx(O,{image:e.image,title:s.jsxs(s.Fragment,{children:[s.jsx("span",{style:e.name&&e.name.length>12?{fontSize:"1rem"}:void 0,children:e.name}),a?s.jsxs("span",{style:m.instanceNumber,children:[".",e.id.split(".").pop()]}):null]}),action:{link:e.link,text:r},t:this.props.t,lang:this.props.lang,color:e.color,showInfo:!!e.info,edit:this.state.edit,offline:l&&l.alive===!1,warning:h>this.#t&&u?this.t("Backend time differs by %s minutes",Math.round(h/this.#s).toString()):null,enabled:o,disabled:!l||typeof l!="object",getHostDescriptionAll:()=>this.getHostDescriptionAll(e.id),toggleActivation:()=>this.toggleCard(e.id,e.linkName),openSnackBarFunc:()=>this.setState({openSnackBar:!0}),theme:this.props.theme,children:e.description||this.getHostDescription(e.id)},`${e.id}_${e.link}`)}return null})}toggleLinkCard(t){const e=JSON.parse(JSON.stringify(this.state.introLinks));e[t].enabled=!e[t].enabled;const o=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(e)!==this.introLinksOriginal;this.setState({introLinks:e,hasUnsavedChanges:o})}getLinkCards(){var t;return(t=this.state.introLinks)==null?void 0:t.map((e,o)=>!e.enabled&&!this.state.edit?null:e.camera==="custom"?s.jsx(E,{image:e.image,title:e.name,action:{link:e.link,text:e.linkName},t:this.props.t,socket:this.props.socket,color:e.color,edit:this.state.edit,interval:e.interval,camera:e.camera,addTs:e.addTs,onEdit:()=>{var i;return this.setState({editLink:!0,editLinkIndex:o,link:JSON.parse(JSON.stringify((i=this.state.introLinks)==null?void 0:i[o]))})},onRemove:()=>{const i=JSON.parse(JSON.stringify(this.state.introLinks));i.splice(o,1);const d=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(i)!==this.introLinksOriginal;this.setState({introLinks:i,hasUnsavedChanges:d})},enabled:e.enabled,lang:this.props.lang,toggleActivation:()=>this.toggleLinkCard(o),cameraUrl:e.desc,theme:this.props.theme},`link${o}`):s.jsx(O,{image:e.image,title:e.name,action:{link:e.link,text:e.linkName},t:this.props.t,color:e.color,edit:this.state.edit,onEdit:()=>{var i;return this.setState({editLink:!0,editLinkIndex:o,link:JSON.parse(JSON.stringify((i=this.state.introLinks)==null?void 0:i[o]))})},onRemove:()=>{const i=JSON.parse(JSON.stringify(this.state.introLinks));i.splice(o,1);const d=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(i)!==this.introLinksOriginal;this.setState({introLinks:i,hasUnsavedChanges:d})},enabled:e.enabled,lang:this.props.lang,toggleActivation:()=>this.toggleLinkCard(o),theme:this.props.theme,children:e.desc||""},`link${o}`))}editLinkCard(){return this.state.editLink?s.jsx(U,{link:this.state.link,socket:this.props.socket,isNew:this.state.editLinkIndex===-1,t:this.props.t,lang:this.props.lang,theme:this.props.theme,onClose:t=>{if(t){const e=JSON.parse(JSON.stringify(this.state.introLinks));this.state.editLinkIndex===-1?(t.enabled=!0,e.push(t)):(t.enabled=e[this.state.editLinkIndex].enabled,e[this.state.editLinkIndex]=t);const o=JSON.stringify(this.state.deactivated)!==JSON.stringify(this.deactivatedOriginal)||JSON.stringify(e)!==this.introLinksOriginal;this.setState({introLinks:e,editLink:!1,hasUnsavedChanges:o,link:null})}else this.setState({editLink:!1})}}):null}getButtons(){const t=[];return this.state.edit?(t.push(s.jsx(n.Fab,{color:"primary",size:"small",sx:v.Utils.getStyle(this.props.theme,m.button,m.addButton),onClick:()=>this.setState({editLink:!0,editLinkIndex:-1,link:{}}),children:s.jsx(f.Add,{})},"add")),t.push(s.jsx(n.Fab,{size:"small",color:"primary",disabled:!this.state.hasUnsavedChanges,sx:v.Utils.getStyle(this.props.theme,m.button,m.saveButton),onClick:()=>this.saveCards(),children:s.jsx(f.Check,{})},"save")),t.push(s.jsx(n.Fab,{size:"small",color:"primary",sx:v.Utils.getStyle(this.props.theme,m.button,m.closeButton),onClick:()=>this.deactivateEditMode(),children:s.jsx(f.Close,{})},"close"))):t.push(s.jsx(n.Fab,{color:"primary",size:"small",style:m.button,onClick:()=>this.activateEditMode(),children:s.jsx(f.Create,{})},"edit")),t}async saveCards(){const t=await this.props.socket.getSystemConfig(!0);let e=!1;JSON.stringify(t.common.intro)!==JSON.stringify(this.state.deactivated)&&(t.common.intro=this.state.deactivated,e=!0),!e&&JSON.stringify(t.native.introLinks)!==JSON.stringify(this.state.introLinks)&&(e=!0,t.native.introLinks=this.state.introLinks),e?this.props.socket.setSystemConfig(t).then(()=>this.props.showAlert("Updated","success")).catch(o=>{console.log(o),this.props.showAlert(o,"error")}).then(()=>this.setState({edit:!1})):this.setState({edit:!1})}async getHostData(t,e){let o;if(e!==void 0)o={val:e};else try{o=await this.props.socket.getState(`${t}.alive`)}catch(r){console.error(`Cannot get state ${t}.alive: ${r}`),o={val:!1}}let i={alive:!1};if(o!=null&&o.val)try{i=await this.props.socket.getHostInfo(t,!1,1e4),i&&typeof i=="object"&&i.alive!==!1&&(i.alive=!0)}catch(r){console.error(`Cannot get host info for ${t}: ${r}`),i={alive:!1}}else i={alive:!1};const d=await this.props.socket.getForeignStates(`${t}.versions.*`);return Object.keys(d).forEach(r=>i[`_${r.split(".").pop()}`]=d[r].val),{id:t,data:i}}async getHostsData(t){const e=t.map(l=>this.getHostData(l._id)),o=await Promise.all(e),i={},d={},r=new Map(this.state.hostDataTimestampMap),a=Date.now();return o.forEach(l=>{i[l.id]=C.preprocessHostData(l.data),d[l.id]=l.data.alive,r.set(l.id,a)}),this.setState({hostDataTimestampMap:r}),{hostsData:i,alive:d}}addLinks(t,e,o,i,d,r){const a={id:t.id,name:t.name,description:t.description,color:t.color,image:t.icon,info:""},l=J(t.link,e.name,o,{instances:i,hostname:this.props.hostname,adminInstance:this.props.adminInstance,hosts:d}),h=this.state.reverseProxy;let p=null;if(h!=null&&h.length){const c=window.location.pathname;p=h.find(u=>{if(!u.globalPath)return!1;const k=u.globalPath.endsWith("/")?u.globalPath:`${u.globalPath}/`;return c===k||c.startsWith(k)})||null}if(l.length===1){a.link=l[0].url,a.port=l[0].port,a.link=P(a.link,a.id,i,p)||a.link;const c=r.find(u=>u.link===a.link);c?console.log(`Double links: "${a.id}" and "${c.id}"`):r.push(a)}else l.length>1&&l.forEach(c=>{const u=r.find(k=>k.link===c.url);if(u)console.log(`Double links: "${a.id}" and "${u.id}"`);else{const k={...a,link:c.url,port:c.port};k.link=P(k.link,a.id,i,p)||k.link,r.push(k)}})}static getText(t,e){return t?typeof t=="object"?t[e]||t.en||"":t||"":""}static normalizeLinks(t,e,o){if(!t.common.localLinks&&!t.common.localLink&&!t.common.welcomeScreen&&!t.common.welcomeScreenPro)return null;const i={id:t._id.replace("system.adapter.",""),link:"",name:C.getText(t.common.titleLang||t.common.title||t.common.name,e),order:t.common.order||1e3,intro:!0,description:C.getText(t.common.desc,e),icon:t.common.icon?`adapter/${t.common.name}/${t.common.icon}`:"img/no-image.svg"};let d=[];if(t.common.localLink)if(typeof t.common.localLink=="string")d.push({...i,link:t.common.localLink});else{const r=t.common.localLink;if(r.link){const a={...i,link:r.link};r.color&&(a.color=r.color),r.order!==void 0&&typeof r.order=="number"&&(a.order=r.order),r.icon&&r.img&&(a.icon=r.icon||r.img),d.push(a)}else console.warn(`Unknown localLink structure: ${JSON.stringify(t.common.localLink)}`)}if(t.common.localLinks&&typeof t.common.localLinks=="object"&&Object.keys(t.common.localLinks).forEach(r=>{const a=t.common.localLinks[r];if(typeof a=="string")d.push({...i,link:a});else{const l=a;if(l.link){const h={...i,id:t._id.replace("system.adapter.","")+(r==="_default"?"":` ${r}`),link:l.link,name:i.name+(r==="_default"?"":` ${r}`)};l.color&&(h.color=l.color),l.order!==void 0&&(h.order=parseInt(l.order,10)||1e3),l.icon&&l.img&&(h.icon=l.icon||l.img),l.description&&(h.description=C.getText(l.description,e)),l.pro!==void 0&&(typeof l.pro=="string"?h.pro=l.pro:h.pro=`${t.common.name}/index.html`),l.cloud!==void 0&&(h.cloud=l.cloud),l.intro!==void 0&&(h.intro=l.intro===!0),l.name&&(h.name=C.getText(l.name,e)),r==="_default"&&(h.default=!0),d.push(h)}else console.warn(`Unknown localLinks structure: ${JSON.stringify(a)}`)}}),t.common.welcomeScreen&&typeof t.common.welcomeScreen=="object"&&((Array.isArray(t.common.welcomeScreen)?t.common.welcomeScreen:[t.common.welcomeScreen]).forEach(a=>{if(a.link){const l={...i,id:`${t._id.replace("system.adapter.","")} cloud`,link:`%web_protocol%://%web_bind%:%web_port%/${a.link}`,cloud:a.link};if(a.color&&(l.color=a.color),a.order!==void 0&&typeof a.order=="number"&&(l.order=a.order),a.icon&&a.img&&(l.icon=a.icon||a.img),a.localLinks){const h=t.common.localLinks[a.localLinks];h&&typeof h=="string"?l.link=h:h&&typeof h=="object"&&h.link&&(l.link=h.link)}a.name&&(l.name=C.getText(a.name,e)),d.push(l)}}),t.common.welcomeScreenPro&&typeof t.common.welcomeScreenPro=="object"&&(Array.isArray(t.common.welcomeScreenPro)?t.common.welcomeScreenPro:[t.common.welcomeScreenPro]).forEach(l=>{if(l.link){const h={...i,id:`${t._id.replace("system.adapter.","")} pro`,link:`%web_protocol%://%web_bind%:%web_port%/${l.link}`,pro:l.link};if(l.color&&(h.color=l.color),l.order!==void 0&&typeof l.order=="number"&&(h.order=l.order),l.icon&&l.img&&(h.icon=l.icon||l.img),l.localLinks){const p=t.common.localLinks[l.localLinks];p&&typeof p=="string"?h.link=p:p&&typeof p=="object"&&p.link&&(h.link=p.link)}l.name&&(h.name=C.getText(l.name,e)),d.push(h)}})),d.forEach(r=>{!r.icon.startsWith("adapter/")&&!r.icon.startsWith("data:image/")&&!r.icon.startsWith("http://")&&!r.icon.startsWith("https://")&&r.icon!=="img/no-image.svg"&&(r.icon=`adapter/${t.common.name}/${r.icon}`)}),o){const r={};d.forEach(a=>{r[a.link]?(a.color&&(r[a.link].color=a.color),a.icon&&(r[a.link].icon=a.icon),a.cloud&&(r[a.link].cloud=a.cloud),a.pro&&(r[a.link].pro=a.pro),a.intro!==void 0&&(r[a.link].intro=a.intro),a.name&&typeof a.name=="object"&&(r[a.link].name=a.name),a.order!==void 0&&(r[a.link].order=a.order),a.default&&(r[a.link].default=a.default)):r[a.link]=a}),d=Object.values(r)}return d.sort((r,a)=>r.default===void 0&&a.default===void 0?r.order===void 0&&a.order===void 0?0:r.order===void 0?-1:a.order===void 0?1:r.order-a.order:r.default===void 0?-1:a.default===void 0?1:r.order===void 0&&a.order===void 0?0:r.order===void 0?-1:a.order===void 0?1:r.order-a.order),d}async getInstances(t,e,o){e=e||this.state.hosts;const i={};e.forEach(d=>i[d._id]=d);try{const d=await this.props.socket.getAdapterInstances("",t);let r=o.common.intro||[];Array.isArray(r)||(r=Object.keys(r),r.sort());const a=[],l={};d.forEach(p=>l[p._id]=p),d.forEach(p=>{if(!p)return;const c=p.common||null,u=p._id.split("."),k=parseInt(u.pop(),10);let j;if(c!=null&&c.name&&typeof c.name=="object"){const N=c==null?void 0:c.name;j=N[this.props.lang]||N.en}else j=(c==null?void 0:c.name)||"";if(!(j==="admin"&&c.localLink===(this.props.hostname||""))&&j!=="web"&&!(j&&j!=="vis-web-admin"&&j.match(/^vis-/)&&j!=="vis-2")&&!(j!=null&&j.match(/^icons-/))&&c&&(c.enabled||c.onlyWWW)){const N=C.normalizeLinks(p,this.props.lang,!0);N&&N.forEach(H=>this.addLinks(H,c,k,l,i,a))}}),a.forEach(p=>{p.link&&(p.linkName=p.link.replace("https://","").replace("http://","").replace(/^[^_]+:/,""))}),a.sort((p,c)=>{if(p.order!==void 0||c.order!==void 0){if(p.order=p.order===void 0?1e3:p.order,c.order=c.order===void 0?1e3:c.order,p.order<c.order)return-1;if(p.order>c.order)return 1}return p.id>c.id?1:p.id<c.id?-1:0}),e==null||e.forEach(p=>{const c=p==null?void 0:p.common;let u=c==null?void 0:c.name;if(typeof u=="object"&&u&&(u=u[this.props.lang]||u.en),c){const k={id:p._id,name:u||"",color:"",image:c.icon||"img/no-image.svg",info:this.t("Info"),linkName:""};a.push(k)}});const h=[];return r.forEach(p=>{a.find(c=>p===`${c.id}_${c.linkName}`)&&h.push(p)}),r=h,{instances:a,deactivated:r}}catch(d){return console.log(d),{instances:[],deactivated:[]}}}getHostDescription(t){const e=this.state.hostsData?this.state.hostsData[t]:null;if(e&&e.alive===!1)return s.jsx("div",{style:m.hostOffline,children:this.props.t("Offline")});let o="",i="";if(e){try{e._nodeNewest&&e["Node.js"]&&w.gt(e._nodeNewest,e["Node.js"].replace(/^v/,""))&&(o=e._nodeNewest)}catch{}try{e._nodeNewest!==e._nodeNewestNext&&e._nodeNewestNext&&e["Node.js"]&&e._nodeNewest&&w.gt(e._nodeNewestNext,e["Node.js"].replace(/^v/,""))&&w.gt(e._nodeNewestNext,e._nodeNewest)&&(o+=(o?" / ":"")+e._nodeNewestNext)}catch{}if(o){const d=this.state.nodeUpdateSupported&&e.Platform==="linux";o=s.jsx(n.Tooltip,{title:this.props.t("Some updates available"),slotProps:{popper:{sx:m.tooltip}},children:s.jsxs("span",{style:{...m.nodeUpdate,display:"inline-flex"},children:["(",o,")",d?s.jsx(f.Refresh,{style:m.updateIcon,onClick:()=>this.setState({nodeUpdateDialog:{hostId:t,version:e._nodeNewestNext}})}):null]})})}try{e._npmNewest&&e.NPM&&w.gt(e._npmNewest,e.NPM)&&(i=e._npmNewest)}catch{}try{e._npmNewest!==e._npmNewestNext&&e._npmNewestNext&&e.NPM&&e._npmNewest&&w.gt(e._npmNewestNext,e.NPM)&&w.gt(e._npmNewestNext,e._npmNewest)&&(i+=(i?" / ":"")+e._npmNewestNext)}catch{}i&&(i=s.jsx(n.Tooltip,{title:this.props.t("Some updates available"),slotProps:{popper:{sx:m.tooltip}},children:s.jsxs("span",{style:m.nodeUpdate,children:["(",i,")"]})}))}return e&&typeof e=="object"?s.jsxs("ul",{style:{textTransform:"none"},children:[s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("Platform"),": "]}),e.Platform||"--"]})}),s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("RAM"),": "]}),T.RAM(e.RAM)]})}),s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("Node.js"),": "]}),s.jsx("span",{style:o?m.updateExists:m.updateNo,children:e["Node.js"]||"--"}),o]})}),s.jsx("li",{children:s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t("NPM"),": "]}),s.jsx("span",{className:i?m.updateExists:m.updateNo,children:e.NPM||"--"}),i]})})]}):s.jsxs("ul",{children:[s.jsx(n.Skeleton,{}),s.jsx(n.Skeleton,{}),s.jsx(n.Skeleton,{}),s.jsx(n.Skeleton,{})]})}getHostDescriptionAll(t){const e=this.state.hostsData?this.state.hostsData[t]:null;return{el:s.jsx("ul",{style:{textTransform:"none"},children:e&&typeof e=="object"&&Object.keys(e).filter(o=>!o.startsWith("_")&&e[o]!==null&&e[o]!==void 0).map(o=>s.jsx("li",{children:e&&typeof e=="object"?s.jsxs("span",{children:[s.jsxs("span",{style:m.bold,children:[this.t(o),": "]}),T[o]?T[o](e[o],this.t):(typeof e[o]=="object"?JSON.stringify(e[o]):e[o].toString())||"--"]}):s.jsx(n.Skeleton,{})},o))}),text:e&&typeof e=="object"?Object.keys(e).reduce((o,i)=>`${o}${this.t(i)}:${T[i]?T[i](e[i],this.t):(typeof e[i]=="object"?JSON.stringify(e[i]):e[i])||"--"}
|
|
2
2
|
`):""}}getDataDelayed=t=>{this.getDataTimeout&&clearTimeout(this.getDataTimeout),this.getDataTimeout=setTimeout(()=>{this.getDataTimeout=void 0,this.getData(!0).catch(e=>console.error(`Cannot get data: ${e}`))},300)};async getData(t){try{const e=await this.props.socket.getSystemConfig(t),o=await this.props.socket.getCompactHosts(t),i=await this.getInstances(t,o,e);this.setState({instances:i.instances,hosts:o,deactivated:i.deactivated,introLinks:e&&e.native&&e.native.introLinks?e.native.introLinks:[]});const d=await this.getHostsData(o);await new Promise(r=>{this.setState(d,()=>r())})}catch(e){const o=String(window.NEXOWATT_EOS_ACCESS_ROLE||"unknown").toLowerCase();if(o!=="admin"){try{const i=await this.getInstances(t,[],{common:{intro:[]},native:{introLinks:[]}});this.setState({instances:i.instances,hosts:[],deactivated:i.deactivated,introLinks:[],hostsData:{},alive:{}});return}catch{}this.setState({instances:[],hosts:[],deactivated:[],introLinks:[],hostsData:{},alive:{}});return}window.alert(`Cannot get data: ${e}`)}}renderCopiedToast(){return s.jsx(n.Snackbar,{anchorOrigin:{vertical:"bottom",horizontal:"left"},open:this.state.openSnackBar,autoHideDuration:3e3,onClose:()=>this.setState({openSnackBar:!1}),message:this.t("copied")})}render(){return this.state.instances?s.jsxs(v.TabContainer,{elevation:0,overflow:"visible",children:[this.renderCopiedToast(),this.state.nodeUpdateDialog?s.jsx(W,{onClose:()=>this.setState({nodeUpdateDialog:null}),socket:this.props.socket,...this.state.nodeUpdateDialog}):null,s.jsxs("div",{style:m.viewModeDiv,children:[this.getInstancesCards(),this.getLinkCards()]}),String(window.NEXOWATT_EOS_ACCESS_ROLE||"admin").toLowerCase()==="admin"?this.getButtons():null,String(window.NEXOWATT_EOS_ACCESS_ROLE||"admin").toLowerCase()==="admin"?this.editLinkCard():null]}):s.jsx(n.LinearProgress,{})}static preprocessHostData(t){var e;if((e=t.dockerInformation)!=null&&e.isDocker){let o=t.dockerInformation.isOfficial?"official image":"unofficial image";t.dockerInformation.isOfficial&&(o+=` - ${t.dockerInformation.officialVersion}`),t.Platform=`${t.Platform} (${o})`}return delete t.dockerInformation,t}}export{C as default};
|