iobroker.eos-admin 7.9.98 → 7.9.99

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.
Files changed (52) hide show
  1. package/INSTALL_TEST_V7.9.99.md +11 -0
  2. package/MERGE_UPDATE_README_V7.9.99.md +5 -0
  3. package/NEXOWATT_EOS_BUILD_INFO.json +21 -20
  4. package/PUBLISH_STABLE_V7.9.99.md +15 -0
  5. package/README.md +6 -16
  6. package/README_STABILITY_V7.9.99.md +18 -0
  7. package/RELEASE_ACCEPTANCE_V7.9.99.md +11 -0
  8. package/RELEASE_NOTES_V7.9.99.md +9 -0
  9. package/adminWww/assets/Intro-DkwRiz1n-v84.js +2 -2
  10. package/adminWww/assets/bootstrap-COulQZax-v84.js +2 -2
  11. package/adminWww/css/eos-ems-overview.css +3 -5
  12. package/adminWww/css/nexowatt-native-shell.css +26 -112
  13. package/adminWww/index.html +19 -18
  14. package/adminWww/js/eos-account-management.js +19 -28
  15. package/adminWww/js/eos-assistant.js +1 -1
  16. package/adminWww/js/eos-ems-overview.js +2 -3
  17. package/adminWww/js/eos-release-watch.js +77 -0
  18. package/adminWww/js/eos-role-bootstrap.js +11 -8
  19. package/adminWww/js/eos-role-ui.js +2 -2
  20. package/adminWww/js/nexowatt-native-shell.js +1 -1
  21. package/adminWww/static/js/nexowatt-stable-login.js +3 -3
  22. package/adminWww/static/js/{nexowatt-stable-v98.js → nexowatt-stable-v99.js} +2 -2
  23. package/build/lib/eosPassword.js +62 -0
  24. package/build/lib/eosRequestSecurity.js +31 -0
  25. package/build/lib/web.js +149 -154
  26. package/build/main.js +2 -1
  27. package/io-package.json +5 -10
  28. package/package.json +17 -13
  29. package/tools/nexowatt-account-management-selftest.cjs +19 -15
  30. package/tools/nexowatt-apply-ems-overview.cjs +2 -4
  31. package/tools/nexowatt-cache-update-selftest.cjs +11 -0
  32. package/tools/nexowatt-clean-legacy-runtime.cjs +1 -1
  33. package/tools/nexowatt-ems-overview-selftest.cjs +1 -1
  34. package/tools/nexowatt-login-layout-selftest.cjs +11 -11
  35. package/tools/nexowatt-merge-update-selftest.cjs +1 -1
  36. package/tools/nexowatt-modern-ui-selftest.cjs +2 -2
  37. package/tools/nexowatt-password-write-selftest.cjs +42 -44
  38. package/tools/nexowatt-request-security-selftest.cjs +11 -0
  39. package/tools/nexowatt-runtime-cleanup-selftest.cjs +6 -6
  40. package/tools/nexowatt-stable-v99-selftest.cjs +25 -0
  41. package/tools/nexowatt-sync-release-version.cjs +1 -42
  42. package/tools/nexowatt-ui-overview-runtime-selftest.cjs +3 -1
  43. package/tools/nexowatt-validate-package.cjs +23 -23
  44. package/tools/nexowatt-version-sync-selftest.cjs +1 -18
  45. package/INSTALL_TEST_V7.9.98.md +0 -39
  46. package/MERGE_UPDATE_README_V7.9.98.md +0 -29
  47. package/PUBLISH_STABLE_V7.9.98.md +0 -33
  48. package/README_STABILITY_V7.9.98.md +0 -22
  49. package/RELEASE_ACCEPTANCE_V7.9.98.md +0 -48
  50. package/RELEASE_NOTES_V7.9.98.md +0 -32
  51. package/tools/nexowatt-account-password-flow-selftest.cjs +0 -186
  52. package/tools/nexowatt-stable-v98-selftest.cjs +0 -14
@@ -0,0 +1,11 @@
1
+ # Installationstest 7.9.99
2
+
3
+ ```bash
4
+ cd /opt/iobroker
5
+ iobroker stop eos-admin.0
6
+ npm install --no-save --omit=dev iobroker.eos-admin@7.9.99
7
+ iobroker upload eos-admin
8
+ iobroker restart eos-admin.0
9
+ ```
10
+
11
+ Danach Browser mit `Strg + F5` vollständig neu laden. Für EMS-Livedaten muss `iobroker.nexowatt-ui` mindestens `0.8.198` installiert und gestartet sein.
@@ -0,0 +1,5 @@
1
+ # NexoWatt EOS Admin 7.9.99 – Merge-Update
2
+
3
+ Die flache Merge-ZIP direkt in den vorhandenen Repository-Ordner entpacken und anschließend `MERGE_UPDATE.cmd` ausführen.
4
+
5
+ Enthalten sind alle Änderungen aus 7.9.96 einschließlich nativer Rollenübersicht, persönlicher Erstkennwortvergabe und EMS-Diagnose sowie die Korrekturen für Login-Geometrie und produktive AdminConnection.
@@ -1,28 +1,29 @@
1
1
  {
2
- "version": "7.9.98",
2
+ "version": "7.9.99",
3
3
  "channel": "stable-latest",
4
- "baseFrontend": "validated Admin 7 runtime with scrollable native cockpit, clean placeholder login and verified ioBroker password writes",
4
+ "baseFrontend": "validated Admin 7 runtime with truthful EMS overview, in-grid edit controls, short-name password API and release cache invalidation",
5
5
  "runtimeEntry": "v84",
6
- "releaseType": "stable-scroll-login-password-write-fix",
7
- "release": "stable-scroll-login-password-write-fix",
8
- "label": "v98",
6
+ "releaseType": "stable-truthful-ems-cache-password-fix",
7
+ "release": "stable-truthful-ems-cache-password-fix",
8
+ "label": "v99",
9
9
  "notes": [
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."
10
+ "The EMS overview exposes only destinations that exist in the installed product.",
11
+ "The Intro edit controls are anchored inside the lowest card grid.",
12
+ "EOS password changes use the ioBroker user-name API and verify persistence before clearing first-login flags.",
13
+ "EOS entrypoints, overlays and patched bundles are served with no-store headers.",
14
+ "A release watcher detects future server version changes and reloads without a browser hard reset."
15
15
  ],
16
16
  "changes": [
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."
17
+ "Removed the unsupported full EMS diagnosis link from source and productive runtime.",
18
+ "Moved the pencil/FAB into the bottom Intro card grid.",
19
+ "Changed password writes from system.user.* IDs to the documented short user name.",
20
+ "Replaced stale full-user writes after password changes with native-only object extensions.",
21
+ "Added explicit password persistence, credential and first-login metadata verification.",
22
+ "Added versioned entrypoints, no-store response headers and an automatic release watcher."
22
23
  ],
23
- "brandingCacheVersion": 98,
24
- "shellCacheVersion": 98,
25
- "nativeShellVersion": 98,
26
- "shellCacheTag": "98",
27
- "repositoryEntry": "nexowatt-eos-admin-repository-entry-v98.json"
24
+ "brandingCacheVersion": 99,
25
+ "shellCacheVersion": 99,
26
+ "nativeShellVersion": 99,
27
+ "shellCacheTag": "99",
28
+ "repositoryEntry": "nexowatt-eos-admin-repository-entry-v99.json"
28
29
  }
@@ -0,0 +1,15 @@
1
+ # Stable-Veröffentlichung 7.9.99
2
+
3
+ ```powershell
4
+ npm login
5
+ npm whoami
6
+ npm run check:eos-release
7
+ npm publish --dry-run --tag latest
8
+ npm publish --tag latest
9
+ ```
10
+
11
+ Das geprüfte Tarball kann alternativ direkt veröffentlicht werden:
12
+
13
+ ```powershell
14
+ npm publish .\iobroker.eos-admin-7.9.99.tgz --tag latest
15
+ ```
package/README.md CHANGED
@@ -13,15 +13,11 @@ 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
- ## Aktueller Stable-Verkaufskandidat 7.9.98
16
+ ## Aktuelle Stable 7.9.89
17
17
 
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.
18
+ Die Verkaufsversion 7.9.89 verwendet die aktuelle **Übersicht** als Startseite, integriert EOS Assist in den Header und führt Zugangsverwaltung ausschließlich unter **Zugänge & Rechte**. Installer und Guest aktivieren ihr Konto beim ersten Login im normalen Anmeldeformular einmalig ohne Startpasswort und vergeben anschließend ein persönliches Passwort. Admin / Service bleibt unverändert.
19
19
 
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.
20
+ Der interne Admin und die interne BackItUp-Notfallreserve bleiben installiert, sind aber ausschließlich für Admin / Service sichtbar. Für den regulären Betrieb wird die NexoWatt Sicherung verwendet.
25
21
 
26
22
  ## Installation über das NexoWatt Repository
27
23
 
@@ -33,7 +29,7 @@ Minimaler Repository-Eintrag:
33
29
  {
34
30
  "eos-admin": {
35
31
  "name": "eos-admin",
36
- "version": "7.9.98",
32
+ "version": "7.9.89",
37
33
  "title": "NexoWatt EOS Admin",
38
34
  "desc": {
39
35
  "de": "NexoWatt EOS Administrationsoberfläche als eigenständiger Adapter.",
@@ -130,18 +126,12 @@ iobroker restart eos-admin.0
130
126
 
131
127
  ## Veröffentlichung auf npm
132
128
 
133
- Vor der Veröffentlichung müssen Paket- und Stabilitätsprüfung vollständig grün sein:
134
-
135
129
  ```bash
136
130
  npm login
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
131
+ npm publish
142
132
  ```
143
133
 
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.
134
+ Die Version muss vor jedem erneuten Publish erhöht werden.
145
135
 
146
136
  ## Lizenz
147
137
 
@@ -0,0 +1,18 @@
1
+ # NexoWatt EOS Admin 7.9.99 – Stable
2
+
3
+ Diese Version behebt die sichtbaren Regressionen aus 7.9.96 und ist für den anschließenden Feldtest als Verkaufsfassung vorbereitet.
4
+
5
+ ## Korrigiert
6
+
7
+ - Ordentliche NexoWatt-Anmeldekarte im bewährten Verhältnis, nur moderat größer.
8
+ - Keine innere horizontale oder vertikale Scrollleiste – auch nicht bei „Falsches Passwort“ oder der persönlichen Erstanmeldung.
9
+ - Keine doppelte Karten-Geometrie auf einem inneren Formular-/Grid-Container.
10
+ - Native Übersicht für Admin, Installateur und Endkunde.
11
+ - Read-only EMS-Live-Diagnose über die echte authentifizierte AdminConnection.
12
+ - Konkrete Hinweise bei fehlendem UI-Adapter, zu alter UI-Version, fehlendem Diagnosevertrag oder fehlender Leseberechtigung.
13
+
14
+ ## Kompatibilität
15
+
16
+ Für vollständige EMS-Livedaten wird `iobroker.nexowatt-ui` ab `0.8.198` benötigt. Der Diagnosevertrag liegt unter `nexowatt-ui.*.info.adminOverview.*` und besitzt keine Schreibhoheit.
17
+
18
+ Erstkennwort `nexowatt`, verpflichtende persönliche Kennwortvergabe, Rollenmodell, geschützte EOS-Adapter, interne Notfallreserven und Standardport `8081` bleiben unverändert.
@@ -0,0 +1,11 @@
1
+ # Release-Abnahme 7.9.99
2
+
3
+ - [ ] Login-Karte ist ordentlich proportioniert und nur moderat größer als vor 7.9.96.
4
+ - [ ] Normale Anmeldung, falsches Passwort und persönliche Erstkennwortvergabe erzeugen keine innere Scrollleiste.
5
+ - [ ] Erstkennwort `nexowatt` führt zur verpflichtenden persönlichen Kennwortvergabe.
6
+ - [ ] Native Adapterkarten sind bei Admin, Installateur und Endkunde sichtbar, soweit die Rolle sie freigibt.
7
+ - [ ] NexoWatt-UI-Karte ist in der Übersicht vorhanden.
8
+ - [ ] EMS-Kachel zeigt nach Verbindungsaufbau Livewerte aus `nexowatt-ui.*.info.adminOverview.*`.
9
+ - [ ] UI-Version unter `0.8.198` wird verständlich gemeldet.
10
+ - [ ] Die EMS-Kachel enthält keinen Schreibpfad.
11
+ - [ ] `npm run check:eos-release` und `npm publish --dry-run --tag latest` sind vollständig grün.
@@ -0,0 +1,9 @@
1
+ # NexoWatt EOS Admin 7.9.99 – Stable Candidate
2
+
3
+ - Nicht vorhandenen Link „Vollständige EMS-Diagnose öffnen“ entfernt.
4
+ - Bearbeitungsstift in den untersten Intro-Kartenbereich verschoben.
5
+ - Passwortvergabe nach Erstanmeldung nutzt den kurzen ioBroker-Benutzernamen und prüft das neue Kennwort.
6
+ - Passwort-Metadaten werden nur über `native` erweitert; der neue Passwort-Hash wird nicht mit einem alten Benutzerobjekt überschrieben.
7
+ - Konto-Reset und sichtbare Kontoliste verwenden dieselbe Rollenfreigabe.
8
+ - EOS-Overlays und gepatchte Bundles werden mit `no-store` ausgeliefert.
9
+ - Release-Watcher erkennt zukünftige Versionswechsel und lädt die Oberfläche neu.
@@ -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;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
- `):""}}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};
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:"static",margin:0},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:{position:"relative",display:"flex",flexFlow:"wrap",width:"100%",minHeight:80,paddingBottom:80,overflow:"visible",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
+ `):""}}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,className:"eos-native-intro-grid",children:[this.getInstancesCards(),this.getLinkCards(),String(window.NEXOWATT_EOS_ACCESS_ROLE||"admin").toLowerCase()==="admin"?s.jsx("div",{className:"eos-overview-edit-controls",children: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};