iobroker.eos-admin 7.9.97 → 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.
- package/{INSTALL_TEST_V7.9.97.md → INSTALL_TEST_V7.9.99.md} +2 -2
- package/{MERGE_UPDATE_README_V7.9.97.md → MERGE_UPDATE_README_V7.9.99.md} +1 -1
- package/NEXOWATT_EOS_BUILD_INFO.json +21 -20
- package/{PUBLISH_STABLE_V7.9.97.md → PUBLISH_STABLE_V7.9.99.md} +2 -2
- package/{README_STABILITY_V7.9.97.md → README_STABILITY_V7.9.99.md} +1 -1
- package/{RELEASE_ACCEPTANCE_V7.9.97.md → RELEASE_ACCEPTANCE_V7.9.99.md} +1 -1
- package/RELEASE_NOTES_V7.9.99.md +9 -0
- package/adminWww/assets/Intro-DkwRiz1n-v84.js +2 -2
- package/adminWww/css/eos-ems-overview.css +3 -5
- package/adminWww/css/nexowatt-native-shell.css +32 -1
- package/adminWww/index.html +19 -18
- package/adminWww/js/eos-account-management.js +13 -9
- package/adminWww/js/eos-assistant.js +1 -1
- package/adminWww/js/eos-ems-overview.js +2 -3
- package/adminWww/js/eos-release-watch.js +77 -0
- package/adminWww/js/eos-role-bootstrap.js +7 -4
- package/adminWww/js/eos-role-ui.js +2 -2
- package/adminWww/js/nexowatt-native-shell.js +1 -1
- package/adminWww/static/js/nexowatt-stable-login.js +3 -3
- package/adminWww/static/js/{nexowatt-stable-v97.js → nexowatt-stable-v99.js} +2 -2
- package/build/lib/eosPassword.js +62 -0
- package/build/lib/eosRequestSecurity.js +31 -0
- package/build/lib/web.js +99 -71
- package/build/main.js +2 -1
- package/io-package.json +5 -5
- package/package.json +18 -12
- package/tools/nexowatt-account-management-selftest.cjs +20 -57
- package/tools/nexowatt-apply-ems-overview.cjs +2 -4
- package/tools/nexowatt-cache-update-selftest.cjs +11 -0
- package/tools/nexowatt-clean-legacy-runtime.cjs +1 -1
- package/tools/nexowatt-ems-overview-selftest.cjs +1 -1
- package/tools/nexowatt-login-layout-selftest.cjs +11 -11
- package/tools/nexowatt-merge-update-selftest.cjs +1 -1
- package/tools/nexowatt-modern-ui-selftest.cjs +1 -1
- package/tools/nexowatt-password-write-selftest.cjs +46 -0
- package/tools/nexowatt-request-security-selftest.cjs +11 -0
- package/tools/nexowatt-runtime-cleanup-selftest.cjs +6 -6
- package/tools/nexowatt-stable-v99-selftest.cjs +25 -0
- package/tools/nexowatt-ui-overview-runtime-selftest.cjs +3 -1
- package/tools/nexowatt-validate-package.cjs +23 -14
- package/RELEASE_NOTES_V7.9.97.md +0 -19
- package/tools/nexowatt-stable-v97-selftest.cjs +0 -16
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
# Installationstest 7.9.
|
|
1
|
+
# Installationstest 7.9.99
|
|
2
2
|
|
|
3
3
|
```bash
|
|
4
4
|
cd /opt/iobroker
|
|
5
5
|
iobroker stop eos-admin.0
|
|
6
|
-
npm install --no-save --omit=dev iobroker.eos-admin@7.9.
|
|
6
|
+
npm install --no-save --omit=dev iobroker.eos-admin@7.9.99
|
|
7
7
|
iobroker upload eos-admin
|
|
8
8
|
iobroker restart eos-admin.0
|
|
9
9
|
```
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "7.9.
|
|
2
|
+
"version": "7.9.99",
|
|
3
3
|
"channel": "stable-latest",
|
|
4
|
-
"baseFrontend": "validated Admin 7 runtime with
|
|
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-
|
|
7
|
-
"release": "stable-
|
|
8
|
-
"label": "
|
|
6
|
+
"releaseType": "stable-truthful-ems-cache-password-fix",
|
|
7
|
+
"release": "stable-truthful-ems-cache-password-fix",
|
|
8
|
+
"label": "v99",
|
|
9
9
|
"notes": [
|
|
10
|
-
"The
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
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
|
-
"Removed the
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
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":
|
|
24
|
-
"shellCacheVersion":
|
|
25
|
-
"nativeShellVersion":
|
|
26
|
-
"shellCacheTag": "
|
|
27
|
-
"repositoryEntry": "nexowatt-eos-admin-repository-entry-
|
|
24
|
+
"brandingCacheVersion": 99,
|
|
25
|
+
"shellCacheVersion": 99,
|
|
26
|
+
"nativeShellVersion": 99,
|
|
27
|
+
"shellCacheTag": "99",
|
|
28
|
+
"repositoryEntry": "nexowatt-eos-admin-repository-entry-v99.json"
|
|
28
29
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Stable-Veröffentlichung 7.9.
|
|
1
|
+
# Stable-Veröffentlichung 7.9.99
|
|
2
2
|
|
|
3
3
|
```powershell
|
|
4
4
|
npm login
|
|
@@ -11,5 +11,5 @@ npm publish --tag latest
|
|
|
11
11
|
Das geprüfte Tarball kann alternativ direkt veröffentlicht werden:
|
|
12
12
|
|
|
13
13
|
```powershell
|
|
14
|
-
npm publish .\iobroker.eos-admin-7.9.
|
|
14
|
+
npm publish .\iobroker.eos-admin-7.9.99.tgz --tag latest
|
|
15
15
|
```
|
|
@@ -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()
|
|
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};
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
}
|
|
18
18
|
#eos-ems-overview-runtime { width: calc(100% - 32px); max-width: none; margin: 0 16px 20px; }
|
|
19
19
|
.eos-ems-overview-card * { box-sizing: border-box; }
|
|
20
|
-
.eos-ems-overview-header { display:flex; align-items:flex-start; justify-content:
|
|
20
|
+
.eos-ems-overview-header { display:flex; align-items:flex-start; justify-content:flex-start; gap:20px; }
|
|
21
21
|
.eos-ems-overview-header h2 { margin:5px 0 6px; font-size:clamp(1.2rem,2vw,1.65rem); color:#f5fbff; }
|
|
22
22
|
.eos-ems-overview-header p { margin:0; max-width:760px; color:#9eb2c2; line-height:1.45; }
|
|
23
23
|
.eos-ems-overview-eyebrow { color:#49e39e; font-size:.72rem; font-weight:900; letter-spacing:.13em; text-transform:uppercase; }
|
|
@@ -48,9 +48,7 @@
|
|
|
48
48
|
.eos-ems-overview-event time { color:#6f8799; font-size:.68rem; font-variant-numeric:tabular-nums; }
|
|
49
49
|
.eos-ems-overview-event div { display:grid; gap:2px; min-width:0; }
|
|
50
50
|
.eos-ems-overview-empty { color:#718797; font-size:.76rem; }
|
|
51
|
-
.eos-ems-overview-footer { display:flex; justify-content:
|
|
52
|
-
.eos-ems-overview-footer a { color:#5ee0c2; font-weight:800; text-decoration:none; }
|
|
53
|
-
.eos-ems-overview-footer a:hover,.eos-ems-overview-footer a:focus-visible { color:#9af2dd; text-decoration:underline; }
|
|
51
|
+
.eos-ems-overview-footer { display:flex; justify-content:flex-start; gap:12px; margin-top:12px; color:#60798a; font-size:.67rem; }
|
|
54
52
|
@media (max-width: 1100px) { .eos-ems-overview-card { flex-basis:100%; max-width:none; } }
|
|
55
53
|
@media (max-width: 760px) {
|
|
56
54
|
#eos-ems-overview-runtime,.eos-ems-overview-card { min-width:0; width:calc(100% - 16px); margin:8px; padding:16px; }
|
|
@@ -61,7 +59,7 @@
|
|
|
61
59
|
.eos-ems-overview-footer { display:grid; }
|
|
62
60
|
}
|
|
63
61
|
|
|
64
|
-
/*
|
|
62
|
+
/* v99: startup and compatibility messages stay compact. */
|
|
65
63
|
.eos-ems-overview-card.is-loading,
|
|
66
64
|
.eos-ems-overview-card.is-unavailable {
|
|
67
65
|
min-height: 0;
|
|
@@ -1292,7 +1292,7 @@ html.eos-route-intro #app-paper [class*="card"] {
|
|
|
1292
1292
|
.eos-assist-header-root .eos-assist-panel { right: 8px !important; width: calc(100vw - 16px); }
|
|
1293
1293
|
}
|
|
1294
1294
|
|
|
1295
|
-
/* NexoWatt EOS 7.9.
|
|
1295
|
+
/* NexoWatt EOS 7.9.99 – orderly login, moderately enlarged. */
|
|
1296
1296
|
html.eos-login,
|
|
1297
1297
|
html.eos-login body {
|
|
1298
1298
|
min-height: 100%;
|
|
@@ -1406,3 +1406,34 @@ html.eos-login form { max-width: 100% !important; }
|
|
|
1406
1406
|
.eos-role-safe-overview { display: none !important; }
|
|
1407
1407
|
html.eos-safe-overview-active #app-paper > :not(.MuiSnackbar-root):not([role="presentation"]) { pointer-events: auto !important; }
|
|
1408
1408
|
.eos-intro-admin-edit-hidden { display: none !important; }
|
|
1409
|
+
|
|
1410
|
+
|
|
1411
|
+
/* NexoWatt EOS 7.9.99 – edit controls belong to the lowest Intro card grid. */
|
|
1412
|
+
html.eos-route-intro .eos-native-intro-grid {
|
|
1413
|
+
position: relative !important;
|
|
1414
|
+
width: 100% !important;
|
|
1415
|
+
min-height: 80px !important;
|
|
1416
|
+
padding-bottom: 80px !important;
|
|
1417
|
+
overflow: visible !important;
|
|
1418
|
+
}
|
|
1419
|
+
html.eos-route-intro .eos-overview-edit-controls {
|
|
1420
|
+
position: absolute !important;
|
|
1421
|
+
right: 16px !important;
|
|
1422
|
+
bottom: 16px !important;
|
|
1423
|
+
z-index: 3 !important;
|
|
1424
|
+
display: flex !important;
|
|
1425
|
+
align-items: center !important;
|
|
1426
|
+
gap: 8px !important;
|
|
1427
|
+
min-width: 52px !important;
|
|
1428
|
+
min-height: 52px !important;
|
|
1429
|
+
padding: 6px !important;
|
|
1430
|
+
border: 1px solid rgba(0, 229, 138, .24) !important;
|
|
1431
|
+
border-radius: 16px !important;
|
|
1432
|
+
background: rgba(3, 23, 34, .94) !important;
|
|
1433
|
+
box-shadow: 0 12px 30px rgba(0, 0, 0, .26) !important;
|
|
1434
|
+
}
|
|
1435
|
+
html.eos-route-intro .eos-overview-edit-controls .MuiFab-root {
|
|
1436
|
+
position: static !important;
|
|
1437
|
+
inset: auto !important;
|
|
1438
|
+
margin: 0 !important;
|
|
1439
|
+
}
|
package/adminWww/index.html
CHANGED
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
<meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate" />
|
|
9
9
|
<meta http-equiv="Pragma" content="no-cache" />
|
|
10
10
|
<meta http-equiv="Expires" content="0" />
|
|
11
|
-
<script src="./js/eos-
|
|
12
|
-
<script
|
|
11
|
+
<script src="./js/eos-release-watch.js?v=99"></script>
|
|
12
|
+
<script src="./js/eos-manual-write-policy.js?v=99"></script>
|
|
13
|
+
<script type="module" src="./assets/hostInit-v84.js?v=99"></script>
|
|
13
14
|
|
|
14
15
|
<meta charset="utf-8" />
|
|
15
16
|
<link
|
|
@@ -36,8 +37,8 @@
|
|
|
36
37
|
rel="stylesheet"
|
|
37
38
|
href="css/leaflet.css"
|
|
38
39
|
/>
|
|
39
|
-
<link rel="stylesheet" href="./css/nexowatt-native-shell.css?v=
|
|
40
|
-
<link rel="stylesheet" href="./css/eos-ems-overview.css?v=
|
|
40
|
+
<link rel="stylesheet" href="./css/nexowatt-native-shell.css?v=99" />
|
|
41
|
+
<link rel="stylesheet" href="./css/eos-ems-overview.css?v=99" />
|
|
41
42
|
<link
|
|
42
43
|
rel="manifest"
|
|
43
44
|
href="manifest.json"
|
|
@@ -157,23 +158,23 @@
|
|
|
157
158
|
false,
|
|
158
159
|
);
|
|
159
160
|
</script>
|
|
160
|
-
<link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js">
|
|
161
|
-
<link rel="modulepreload" crossorigin href="./assets/iobroker_admin__mf_v__runtimeInit__mf_v__-g2X2zhAf.js">
|
|
162
|
-
<script defer src="./js/eos-role-bootstrap.js?v=
|
|
163
|
-
<script defer src="./js/eos-policy-client.js?v=
|
|
164
|
-
<script defer src="./js/eos-branding-sanitizer.js?v=
|
|
165
|
-
<script defer src="./js/nexowatt-native-shell.js?v=
|
|
166
|
-
<script defer src="./js/eos-native-security.js?v=
|
|
167
|
-
<script defer src="./js/eos-basic-settings.js?v=
|
|
168
|
-
<script defer src="./js/eos-role-ui.js?v=
|
|
169
|
-
<script defer src="./js/eos-ems-overview.js?v=
|
|
170
|
-
<script defer src="./js/eos-account-management.js?v=
|
|
171
|
-
<script defer src="./js/eos-assistant.js?v=
|
|
161
|
+
<link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js?v=99">
|
|
162
|
+
<link rel="modulepreload" crossorigin href="./assets/iobroker_admin__mf_v__runtimeInit__mf_v__-g2X2zhAf.js?v=99">
|
|
163
|
+
<script defer src="./js/eos-role-bootstrap.js?v=99" data-eos-entry="./assets/index-CQZugZ1z-v84.js?v=99"></script>
|
|
164
|
+
<script defer src="./js/eos-policy-client.js?v=99"></script>
|
|
165
|
+
<script defer src="./js/eos-branding-sanitizer.js?v=99"></script>
|
|
166
|
+
<script defer src="./js/nexowatt-native-shell.js?v=99"></script>
|
|
167
|
+
<script defer src="./js/eos-native-security.js?v=99"></script>
|
|
168
|
+
<script defer src="./js/eos-basic-settings.js?v=99"></script>
|
|
169
|
+
<script defer src="./js/eos-role-ui.js?v=99"></script>
|
|
170
|
+
<script defer src="./js/eos-ems-overview.js?v=99"></script>
|
|
171
|
+
<script defer src="./js/eos-account-management.js?v=99"></script>
|
|
172
|
+
<script defer src="./js/eos-assistant.js?v=99"></script>
|
|
172
173
|
</head>
|
|
173
174
|
<body>
|
|
174
175
|
<noscript>Für NexoWatt EOS muss JavaScript aktiviert sein.</noscript>
|
|
175
176
|
<div id="root"></div>
|
|
176
|
-
<script defer src="static/js/nexowatt-stable-login.js?v=
|
|
177
|
-
<script defer src="static/js/nexowatt-stable-
|
|
177
|
+
<script defer src="static/js/nexowatt-stable-login.js?v=99"></script>
|
|
178
|
+
<script defer src="static/js/nexowatt-stable-v99.js?v=99"></script>
|
|
178
179
|
</body>
|
|
179
180
|
</html>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
const VERSION = '
|
|
4
|
+
const VERSION = 'v99-account-management-password-write';
|
|
5
5
|
const script = document.currentScript || document.querySelector('script[src*="eos-account-management.js"]');
|
|
6
6
|
const base = new URL('../', script?.src || window.location.href);
|
|
7
7
|
const abort = new AbortController();
|
|
@@ -19,10 +19,11 @@
|
|
|
19
19
|
introInstaller: 'Du kannst Endkundenzugänge zurücksetzen. Admin- und Installateurzugänge bleiben NexoWatt Service vorbehalten.',
|
|
20
20
|
loading: 'Zugänge werden geladen …', empty: 'Keine passenden Konten gefunden.', close: 'Schließen', refresh: 'Aktualisieren',
|
|
21
21
|
installer: 'Installateur', enduser: 'Endkunde / Gast', active: 'Passwort aktiv', first: 'Erstanmeldung offen', disabled: 'Deaktiviert',
|
|
22
|
-
reset: 'Passwort zurücksetzen', resetting: 'Wird zurückgesetzt …', resetConfirm: name => `Soll der Zugang „${name}“ wirklich zurückgesetzt werden?
|
|
23
|
-
resetDone: name => `Der Zugang „${name}“
|
|
22
|
+
reset: 'Passwort zurücksetzen', resetting: 'Wird zurückgesetzt …', resetConfirm: name => `Soll der Zugang „${name}“ wirklich zurückgesetzt werden? Danach gilt einmalig das Startpasswort „nexowatt“ und anschließend muss ein persönliches Passwort vergeben werden.`,
|
|
23
|
+
resetDone: name => `Der Zugang „${name}“ wurde im EOS-Benutzerkonto auf „nexowatt“ zurückgesetzt. Nach der nächsten Anmeldung muss sofort ein persönliches Passwort vergeben werden.`,
|
|
24
24
|
resetFailed: 'Der Zugang konnte nicht zurückgesetzt werden.', lastSet: 'Letzte Passwortvergabe', lastReset: 'Letzter Reset', by: 'durch',
|
|
25
25
|
security: 'Admin/Service darf Installateur und Endkunde zurücksetzen. Installateure dürfen ausschließlich Endkunden zurücksetzen.',
|
|
26
|
+
errors: { permissionError: 'Die Admin-/Installateurberechtigung konnte nicht bestätigt werden. Bitte neu anmelden.', invalidRequest: 'Die Sicherheitsbestätigung fehlt. Bitte die Seite neu laden.', invalidRequestOrigin: 'Die Sitzung oder Adresse hat sich geändert. Bitte die Seite neu laden.', invalidTarget: 'Dieses Konto darf nicht über EOS zurückgesetzt werden.', accountDisabled: 'Das Konto ist deaktiviert.', accountNotFound: 'Das Benutzerkonto wurde nicht gefunden.', passwordApiUnavailable: 'Die EOS-Passwortverwaltung ist nicht verfügbar.', passwordNotPersisted: 'Das Startpasswort wurde nicht gespeichert.', passwordVerificationFailed: 'Das Startpasswort wurde geschrieben, aber nicht als gültige Anmeldung bestätigt.', passwordMetadataNotPersisted: 'Der Erstanmeldungsstatus wurde nicht gespeichert.', accountResetFailed: 'Das Konto konnte serverseitig nicht zurückgesetzt werden.' },
|
|
26
27
|
},
|
|
27
28
|
en: {
|
|
28
29
|
launcher: 'Accounts', titleAdmin: 'Accounts & roles', titleInstaller: 'End-user accounts',
|
|
@@ -30,10 +31,11 @@
|
|
|
30
31
|
introInstaller: 'You may reset end-user accounts. Admin and installer accounts remain reserved for NexoWatt Service.',
|
|
31
32
|
loading: 'Loading accounts …', empty: 'No matching accounts found.', close: 'Close', refresh: 'Refresh',
|
|
32
33
|
installer: 'Installer', enduser: 'End user / Guest', active: 'Password active', first: 'First activation open', disabled: 'Disabled',
|
|
33
|
-
reset: 'Reset password', resetting: 'Resetting …', resetConfirm: name => `Reset account “${name}”? The
|
|
34
|
-
resetDone: name => `Account “${name}” was reset
|
|
34
|
+
reset: 'Reset password', resetting: 'Resetting …', resetConfirm: name => `Reset account “${name}”? The one-time initial password will be “nexowatt”; a personal password must then be created immediately.`,
|
|
35
|
+
resetDone: name => `Account “${name}” was reset in the EOS user account to “nexowatt”. The next sign-in requires an immediate personal password change.`,
|
|
35
36
|
resetFailed: 'The account could not be reset.', lastSet: 'Last password setup', lastReset: 'Last reset', by: 'by',
|
|
36
37
|
security: 'Admin/Service may reset installer and end-user accounts. Installers may reset end-user accounts only.',
|
|
38
|
+
errors: { permissionError: 'Admin/Installer permission could not be confirmed. Sign in again.', invalidRequest: 'The security confirmation is missing. Reload the page.', invalidRequestOrigin: 'The session or address changed. Reload the page.', invalidTarget: 'This account cannot be reset through EOS.', accountDisabled: 'The account is disabled.', accountNotFound: 'The user account was not found.', passwordApiUnavailable: 'The EOS password service is unavailable.', passwordNotPersisted: 'The initial password was not saved.', passwordVerificationFailed: 'The initial password was written but could not be verified.', passwordMetadataNotPersisted: 'The first-login status was not saved.', accountResetFailed: 'The account could not be reset on the server.' },
|
|
37
39
|
},
|
|
38
40
|
nl: {
|
|
39
41
|
launcher: 'Toegangen', titleAdmin: 'Toegangen & rollen', titleInstaller: 'Eindgebruikerstoegangen',
|
|
@@ -41,13 +43,15 @@
|
|
|
41
43
|
introInstaller: 'Je kunt eindgebruikersaccounts resetten. Admin- en installateurstoegang blijft voor NexoWatt Service.',
|
|
42
44
|
loading: 'Toegangen worden geladen …', empty: 'Geen passende accounts gevonden.', close: 'Sluiten', refresh: 'Vernieuwen',
|
|
43
45
|
installer: 'Installateur', enduser: 'Eindgebruiker / Guest', active: 'Wachtwoord actief', first: 'Eerste activering open', disabled: 'Uitgeschakeld',
|
|
44
|
-
reset: 'Wachtwoord resetten', resetting: 'Wordt gereset …', resetConfirm: name => `Account „${name}“ resetten?
|
|
45
|
-
resetDone: name => `Account „${name}“ is
|
|
46
|
+
reset: 'Wachtwoord resetten', resetting: 'Wordt gereset …', resetConfirm: name => `Account „${name}“ resetten? Eenmalig geldt het startwachtwoord „nexowatt“, waarna direct een persoonlijk wachtwoord moet worden ingesteld.`,
|
|
47
|
+
resetDone: name => `Account „${name}“ is in het EOS-gebruikersaccount teruggezet op „nexowatt“. Bij de volgende aanmelding moet direct een persoonlijk wachtwoord worden ingesteld.`,
|
|
46
48
|
resetFailed: 'Het account kon niet worden gereset.', lastSet: 'Laatste wachtwoordinstelling', lastReset: 'Laatste reset', by: 'door',
|
|
47
49
|
security: 'Admin/service mag installateur- en eindgebruikersaccounts resetten. Installateurs alleen eindgebruikers.',
|
|
50
|
+
errors: { permissionError: 'De Admin-/Installateurrechten konden niet worden bevestigd. Meld opnieuw aan.', invalidRequest: 'De beveiligingsbevestiging ontbreekt. Herlaad de pagina.', invalidRequestOrigin: 'De sessie of het adres is gewijzigd. Herlaad de pagina.', invalidTarget: 'Dit account kan niet via EOS worden gereset.', accountDisabled: 'Het account is uitgeschakeld.', accountNotFound: 'Het gebruikersaccount is niet gevonden.', passwordApiUnavailable: 'De EOS-wachtwoordservice is niet beschikbaar.', passwordNotPersisted: 'Het startwachtwoord is niet opgeslagen.', passwordVerificationFailed: 'Het startwachtwoord is geschreven maar kon niet worden geverifieerd.', passwordMetadataNotPersisted: 'De eerste-aanmeldstatus is niet opgeslagen.', accountResetFailed: 'Het account kon server-side niet worden gereset.' },
|
|
48
51
|
},
|
|
49
52
|
};
|
|
50
53
|
const t = () => i18n[language()];
|
|
54
|
+
const errorText = code => t().errors?.[String(code || '')] || String(code || t().resetFailed);
|
|
51
55
|
const roleFromPolicy = policy => {
|
|
52
56
|
const raw = normalize(policy?.role || '');
|
|
53
57
|
if (policy?.isAdmin || policy?.isEosAdminGroup || /admin|service/.test(raw)) return 'admin';
|
|
@@ -154,7 +158,7 @@
|
|
|
154
158
|
await loadAccounts();
|
|
155
159
|
} catch (error) {
|
|
156
160
|
reset.disabled = false; reset.textContent = t().reset;
|
|
157
|
-
setStatus(error?.message
|
|
161
|
+
setStatus(errorText(error?.message), 'error');
|
|
158
162
|
}
|
|
159
163
|
});
|
|
160
164
|
actions.appendChild(reset);
|
|
@@ -181,7 +185,7 @@
|
|
|
181
185
|
if (!response.ok || data.error) throw new Error(data.error || t().resetFailed);
|
|
182
186
|
renderAccounts(data); setStatus('', '');
|
|
183
187
|
} catch (error) {
|
|
184
|
-
setStatus(error?.message
|
|
188
|
+
setStatus(errorText(error?.message), 'error');
|
|
185
189
|
}
|
|
186
190
|
};
|
|
187
191
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
(() => {
|
|
2
2
|
'use strict';
|
|
3
|
-
// NexoWatt EOS stable 7.9.
|
|
3
|
+
// NexoWatt EOS stable 7.9.99: EOS Assist remains disabled until the
|
|
4
4
|
// read-only system assistant is rebuilt and accepted separately.
|
|
5
5
|
window.NEXOWATT_EOS_ASSIST_DISABLED = true;
|
|
6
6
|
document.documentElement.classList.add('eos-assist-disabled');
|