iobroker.eos-admin 7.9.96 → 7.9.98

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/INSTALL_TEST_V7.9.98.md +39 -0
  2. package/MERGE_UPDATE_README_V7.9.98.md +29 -0
  3. package/NEXOWATT_EOS_BUILD_INFO.json +20 -18
  4. package/PUBLISH_STABLE_V7.9.98.md +33 -0
  5. package/README.md +16 -6
  6. package/README_STABILITY_V7.9.98.md +22 -0
  7. package/RELEASE_ACCEPTANCE_V7.9.98.md +48 -0
  8. package/RELEASE_NOTES_V7.9.98.md +32 -0
  9. package/adminWww/assets/Intro-DkwRiz1n-v84.js +1 -1
  10. package/adminWww/assets/bootstrap-COulQZax-v84.js +3 -3
  11. package/adminWww/assets/index-D2ymscJA-v84.js +1 -1
  12. package/adminWww/css/eos-ems-overview.css +21 -0
  13. package/adminWww/css/nexowatt-native-shell.css +174 -40
  14. package/adminWww/index.html +15 -15
  15. package/adminWww/js/eos-account-management.js +26 -13
  16. package/adminWww/js/eos-assistant.js +1 -1
  17. package/adminWww/js/eos-ems-overview.js +136 -39
  18. package/adminWww/js/eos-role-bootstrap.js +7 -7
  19. package/adminWww/js/eos-role-ui.js +2 -2
  20. package/adminWww/js/nexowatt-native-shell.js +9 -2
  21. package/adminWww/static/js/nexowatt-stable-login.js +28 -62
  22. package/adminWww/static/js/nexowatt-stable-v98.js +33 -0
  23. package/build/lib/web.js +112 -79
  24. package/build/main.js +1 -1
  25. package/io-package.json +15 -5
  26. package/package.json +14 -12
  27. package/tools/nexowatt-account-management-selftest.cjs +16 -57
  28. package/tools/nexowatt-account-password-flow-selftest.cjs +186 -0
  29. package/tools/nexowatt-clean-legacy-runtime.cjs +33 -10
  30. package/tools/nexowatt-login-layout-selftest.cjs +12 -81
  31. package/tools/nexowatt-merge-update-selftest.cjs +3 -1
  32. package/tools/nexowatt-modern-ui-selftest.cjs +2 -2
  33. package/tools/nexowatt-password-write-selftest.cjs +48 -0
  34. package/tools/nexowatt-runtime-cleanup-selftest.cjs +9 -1
  35. package/tools/nexowatt-stable-v98-selftest.cjs +14 -0
  36. package/tools/nexowatt-sync-release-version.cjs +42 -1
  37. package/tools/nexowatt-ui-overview-runtime-selftest.cjs +11 -11
  38. package/tools/nexowatt-validate-package.cjs +20 -11
  39. package/tools/nexowatt-version-sync-selftest.cjs +18 -1
  40. package/INSTALL_TEST_V7.9.96.md +0 -11
  41. package/MERGE_UPDATE_README_V7.9.96.md +0 -5
  42. package/PUBLISH_STABLE_V7.9.96.md +0 -10
  43. package/README_STABILITY_V7.9.96.md +0 -11
  44. package/RELEASE_ACCEPTANCE_V7.9.96.md +0 -10
  45. package/RELEASE_NOTES_V7.9.96.md +0 -12
  46. package/adminWww/static/js/nexowatt-stable-v96.js +0 -82
  47. package/tools/nexowatt-stable-v96-selftest.cjs +0 -13
@@ -60,3 +60,24 @@
60
60
  .eos-ems-overview-columns { grid-template-columns:1fr; }
61
61
  .eos-ems-overview-footer { display:grid; }
62
62
  }
63
+
64
+ /* v98: startup and compatibility messages stay compact. */
65
+ .eos-ems-overview-card.is-loading,
66
+ .eos-ems-overview-card.is-unavailable {
67
+ min-height: 0;
68
+ padding-block: 20px;
69
+ }
70
+ .eos-ems-overview-card.is-loading .eos-ems-overview-header,
71
+ .eos-ems-overview-card.is-unavailable .eos-ems-overview-header { align-items: center; }
72
+ .eos-ems-overview-help {
73
+ display: block;
74
+ margin-top: 8px;
75
+ color: #6fcba1;
76
+ font-size: .73rem;
77
+ line-height: 1.45;
78
+ }
79
+ .eos-ems-overview-state-dot--pulse { animation: eos-ems-overview-pulse 1.15s ease-in-out infinite; }
80
+ @keyframes eos-ems-overview-pulse {
81
+ 0%, 100% { opacity: .45; transform: scale(.85); }
82
+ 50% { opacity: 1; transform: scale(1.12); }
83
+ }
@@ -75,8 +75,8 @@ html.eos-login main.MuiPaper-root::before {
75
75
  left: 50%;
76
76
  top: 50%;
77
77
  box-sizing: border-box;
78
- width: min(520px, calc(100vw - 24px)) !important;
79
- height: min(640px, calc(100dvh - 24px)) !important;
78
+ width: min(440px, calc(100vw - 20px)) !important;
79
+ height: min(580px, calc(100dvh - 20px)) !important;
80
80
  transform: translate(-50%, -50%);
81
81
  border: 1px solid rgba(0, 229, 138, .34);
82
82
  border-radius: 26px;
@@ -90,12 +90,12 @@ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) {
90
90
  position: relative;
91
91
  z-index: 1;
92
92
  box-sizing: border-box !important;
93
- width: min(460px, calc(100vw - 56px)) !important;
93
+ width: min(380px, calc(100vw - 52px)) !important;
94
94
  height: auto !important;
95
- min-height: 540px !important;
96
- max-width: 460px !important;
95
+ min-height: 510px !important;
96
+ max-width: 380px !important;
97
97
  max-height: none !important;
98
- padding: 34px 36px 32px !important;
98
+ padding: 28px 30px 26px !important;
99
99
  overflow: visible !important;
100
100
  border-radius: 24px !important;
101
101
  color: var(--nx-text) !important;
@@ -886,10 +886,10 @@ html.eos-login .eos-login-card-modern {
886
886
  /* Compact product login: the form remains the proven inner card while the
887
887
  decorative rear frame keeps a fixed, restrained footprint. */
888
888
  box-sizing: border-box !important;
889
- width: min(460px, calc(100vw - 56px)) !important;
889
+ width: min(380px, calc(100vw - 52px)) !important;
890
890
  height: auto !important;
891
- min-height: 540px !important;
892
- max-width: 460px !important;
891
+ min-height: 510px !important;
892
+ max-width: 380px !important;
893
893
  max-height: none !important;
894
894
  overflow: visible !important;
895
895
  }
@@ -1292,8 +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
-
1296
- /* NexoWatt EOS 7.9.96 – spacious login card without inner scrollbars. */
1295
+ /* NexoWatt EOS 7.9.97 – orderly login, moderately enlarged. */
1297
1296
  html.eos-login,
1298
1297
  html.eos-login body {
1299
1298
  min-height: 100%;
@@ -1304,31 +1303,51 @@ html.eos-login body {
1304
1303
  html.eos-login #root {
1305
1304
  min-height: 100dvh;
1306
1305
  box-sizing: border-box;
1307
- padding: 24px 12px;
1306
+ display: grid;
1307
+ place-items: center;
1308
+ padding: 12px 8px;
1308
1309
  }
1309
1310
  html.eos-login main.MuiPaper-root {
1310
1311
  box-sizing: border-box !important;
1311
- min-height: calc(100dvh - 48px) !important;
1312
- padding: 28px 0 !important;
1312
+ min-height: calc(100dvh - 24px) !important;
1313
+ display: grid !important;
1314
+ place-items: center !important;
1315
+ padding: 0 !important;
1313
1316
  overflow: visible !important;
1314
1317
  }
1315
1318
  html.eos-login main.MuiPaper-root::before {
1316
- width: min(520px, calc(100vw - 24px)) !important;
1317
- height: min(640px, calc(100dvh - 24px)) !important;
1318
- min-height: 590px !important;
1319
+ width: min(440px, calc(100vw - 20px)) !important;
1320
+ height: min(580px, calc(100dvh - 20px)) !important;
1321
+ min-height: 0 !important;
1322
+ border-radius: 25px !important;
1319
1323
  }
1320
1324
  html.eos-login main.MuiPaper-root > .eos-login-card-modern,
1321
1325
  html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username),
1322
- html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password),
1323
- html.eos-login [data-nw-login-card="true"] {
1326
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) {
1324
1327
  box-sizing: border-box !important;
1325
- width: min(460px, calc(100vw - 56px)) !important;
1328
+ width: min(380px, calc(100vw - 52px)) !important;
1326
1329
  min-width: 0 !important;
1327
- min-height: 540px !important;
1330
+ min-height: 510px !important;
1328
1331
  height: auto !important;
1329
- max-width: 460px !important;
1332
+ max-width: 380px !important;
1330
1333
  max-height: none !important;
1331
- padding: 34px 36px 32px !important;
1334
+ padding: 28px 30px 26px !important;
1335
+ overflow: visible !important;
1336
+ border-radius: 23px !important;
1337
+ }
1338
+ /* A cached older runtime may still leave data attributes on a Grid/form
1339
+ ancestor. They must never become a second full-size login card. */
1340
+ html.eos-login [data-nw-login-card="true"]:not(.MuiPaper-root):not(.eos-login-card-modern),
1341
+ html.eos-login [data-nw-login-shell="true"]:not(main):not(.MuiPaper-root) {
1342
+ box-sizing: border-box !important;
1343
+ width: 100% !important;
1344
+ min-width: 0 !important;
1345
+ max-width: 100% !important;
1346
+ min-height: 0 !important;
1347
+ height: auto !important;
1348
+ max-height: none !important;
1349
+ margin: 0 !important;
1350
+ padding: 0 !important;
1332
1351
  overflow: visible !important;
1333
1352
  }
1334
1353
  html.eos-login main.MuiPaper-root > .eos-login-card-modern *,
@@ -1342,6 +1361,7 @@ html.eos-login [role="alert"],
1342
1361
  html.eos-login .eos-login-first-status,
1343
1362
  html.eos-login .eos-login-first-hint {
1344
1363
  position: static !important;
1364
+ box-sizing: border-box !important;
1345
1365
  width: 100% !important;
1346
1366
  max-width: 100% !important;
1347
1367
  max-height: none !important;
@@ -1353,39 +1373,153 @@ html.eos-login .eos-login-first-hint {
1353
1373
  }
1354
1374
  html.eos-login input,
1355
1375
  html.eos-login button,
1356
- html.eos-login form {
1357
- max-width: 100% !important;
1358
- }
1359
- @media (max-width: 560px) {
1360
- html.eos-login #root { padding: 10px 8px; }
1361
- html.eos-login main.MuiPaper-root { min-height: calc(100dvh - 20px) !important; padding: 14px 0 !important; }
1376
+ html.eos-login form { max-width: 100% !important; }
1377
+ @media (max-width: 500px) {
1378
+ html.eos-login #root { padding: 8px; }
1379
+ html.eos-login main.MuiPaper-root { min-height: calc(100dvh - 16px) !important; }
1362
1380
  html.eos-login main.MuiPaper-root::before {
1363
- width: calc(100vw - 16px) !important;
1364
- min-height: 0 !important;
1381
+ width: calc(100vw - 12px) !important;
1365
1382
  height: calc(100% - 4px) !important;
1366
1383
  border-radius: 20px !important;
1367
1384
  }
1368
1385
  html.eos-login main.MuiPaper-root > .eos-login-card-modern,
1369
1386
  html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username),
1370
- html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password),
1371
- html.eos-login [data-nw-login-card="true"] {
1387
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) {
1372
1388
  width: calc(100vw - 38px) !important;
1373
1389
  max-width: none !important;
1374
1390
  min-height: 0 !important;
1375
- padding: 26px 22px !important;
1391
+ padding: 24px 22px !important;
1392
+ border-radius: 18px !important;
1376
1393
  }
1377
1394
  }
1378
- @media (max-height: 690px) {
1379
- html.eos-login main.MuiPaper-root::before { min-height: 0 !important; height: calc(100% - 12px) !important; }
1395
+ @media (max-height: 620px) {
1396
+ html.eos-login #root { place-items: start center; }
1397
+ html.eos-login main.MuiPaper-root { min-height: 0 !important; padding: 10px 0 !important; }
1398
+ html.eos-login main.MuiPaper-root::before { height: calc(100% - 6px) !important; }
1380
1399
  html.eos-login main.MuiPaper-root > .eos-login-card-modern,
1381
1400
  html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username),
1382
- html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password),
1383
- html.eos-login [data-nw-login-card="true"] { min-height: 0 !important; }
1401
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) { min-height: 0 !important; }
1384
1402
  }
1385
1403
 
1386
-
1387
- /* 7.9.96: native Intro owns the overview for every EOS role. */
1404
+ /* Native Intro owns the overview for every EOS role. */
1388
1405
  #eos-role-safe-overview,
1389
1406
  .eos-role-safe-overview { display: none !important; }
1390
1407
  html.eos-safe-overview-active #app-paper > :not(.MuiSnackbar-root):not([role="presentation"]) { pointer-events: auto !important; }
1391
1408
  .eos-intro-admin-edit-hidden { display: none !important; }
1409
+
1410
+ /* NexoWatt EOS 7.9.98 – stable scrolling, clean login fields and expandable errors. */
1411
+ html.eos-app,
1412
+ html.eos-app body,
1413
+ html.eos-app #root {
1414
+ height: 100% !important;
1415
+ max-height: 100% !important;
1416
+ overflow: hidden !important;
1417
+ }
1418
+ html.eos-app #app-paper {
1419
+ height: calc(100vh - var(--nx-content-top) - 12px) !important;
1420
+ height: calc(100dvh - var(--nx-content-top) - 12px) !important;
1421
+ min-height: 0 !important;
1422
+ max-height: calc(100vh - var(--nx-content-top) - 12px) !important;
1423
+ max-height: calc(100dvh - var(--nx-content-top) - 12px) !important;
1424
+ overflow-x: hidden !important;
1425
+ overflow-y: auto !important;
1426
+ overscroll-behavior: contain;
1427
+ scrollbar-gutter: stable;
1428
+ scrollbar-width: thin;
1429
+ scrollbar-color: rgba(0, 229, 138, .88) rgba(3, 18, 29, .72);
1430
+ }
1431
+ html.eos-app #app-paper::-webkit-scrollbar { width: 11px; }
1432
+ html.eos-app #app-paper::-webkit-scrollbar-track {
1433
+ border-radius: 12px;
1434
+ background: rgba(3, 18, 29, .72);
1435
+ }
1436
+ html.eos-app #app-paper::-webkit-scrollbar-thumb {
1437
+ min-height: 46px;
1438
+ border: 2px solid rgba(3, 18, 29, .72);
1439
+ border-radius: 12px;
1440
+ background: linear-gradient(180deg, #00e58a, #39c9ef);
1441
+ }
1442
+ html.eos-app #app-paper::-webkit-scrollbar-thumb:hover {
1443
+ background: linear-gradient(180deg, #21f2a1, #60dcff);
1444
+ }
1445
+
1446
+ html.eos-login main.MuiPaper-root::before {
1447
+ width: min(456px, calc(100vw - 20px)) !important;
1448
+ height: min(536px, calc(100dvh - 20px)) !important;
1449
+ border-radius: 24px !important;
1450
+ }
1451
+ html.eos-login main.MuiPaper-root > .eos-login-card-modern,
1452
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username),
1453
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) {
1454
+ width: min(400px, calc(100vw - 48px)) !important;
1455
+ max-width: 400px !important;
1456
+ min-height: 0 !important;
1457
+ height: auto !important;
1458
+ padding: 30px 32px 28px !important;
1459
+ gap: 0 !important;
1460
+ overflow: visible !important;
1461
+ border-radius: 22px !important;
1462
+ }
1463
+ html.eos-login .eos-login-card-modern > .MuiGrid2-root,
1464
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username) > .MuiGrid2-root,
1465
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) > .MuiGrid2-root {
1466
+ width: 100% !important;
1467
+ min-width: 0 !important;
1468
+ }
1469
+ html.eos-login .MuiFormControl-root {
1470
+ width: 100% !important;
1471
+ margin: 13px 0 3px !important;
1472
+ }
1473
+ html.eos-login .MuiInputLabel-root { display: none !important; }
1474
+ html.eos-login .MuiOutlinedInput-root {
1475
+ min-height: 46px !important;
1476
+ border-radius: 6px !important;
1477
+ background: rgba(4, 19, 31, .76) !important;
1478
+ }
1479
+ html.eos-login .MuiOutlinedInput-input {
1480
+ min-height: 0 !important;
1481
+ padding: 11px 14px !important;
1482
+ line-height: 22px !important;
1483
+ }
1484
+ html.eos-login .MuiOutlinedInput-input::placeholder {
1485
+ color: rgba(245, 251, 255, .92) !important;
1486
+ opacity: 1 !important;
1487
+ }
1488
+ html.eos-login .MuiOutlinedInput-notchedOutline legend {
1489
+ width: 0 !important;
1490
+ max-width: 0 !important;
1491
+ padding: 0 !important;
1492
+ }
1493
+ html.eos-login .MuiFormControlLabel-root {
1494
+ margin: 7px 0 5px !important;
1495
+ }
1496
+ html.eos-login .MuiButton-root[type="submit"] {
1497
+ min-height: 44px !important;
1498
+ margin: 8px 0 0 !important;
1499
+ }
1500
+ html.eos-login .eos-login-card-modern > .MuiBox-root:last-child,
1501
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username) > .MuiBox-root:last-child,
1502
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) > .MuiBox-root:last-child {
1503
+ margin-top: 28px !important;
1504
+ }
1505
+ html.eos-login .MuiAlert-root,
1506
+ html.eos-login [role="alert"] {
1507
+ margin: 14px 0 1px !important;
1508
+ padding: 9px 11px !important;
1509
+ line-height: 1.35 !important;
1510
+ }
1511
+ @media (max-width: 500px) {
1512
+ html.eos-login main.MuiPaper-root::before {
1513
+ width: calc(100vw - 12px) !important;
1514
+ height: auto !important;
1515
+ min-height: min(520px, calc(100dvh - 12px)) !important;
1516
+ }
1517
+ html.eos-login main.MuiPaper-root > .eos-login-card-modern,
1518
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#username),
1519
+ html.eos-login main.MuiPaper-root > .MuiPaper-root:has(#password) {
1520
+ width: calc(100vw - 38px) !important;
1521
+ max-width: none !important;
1522
+ padding: 25px 22px 23px !important;
1523
+ }
1524
+ }
1525
+
@@ -8,7 +8,7 @@
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-manual-write-policy.js?v=96"></script>
11
+ <script src="./js/eos-manual-write-policy.js?v=98"></script>
12
12
  <script type="module" src="./assets/hostInit-v84.js?v=84"></script>
13
13
 
14
14
  <meta charset="utf-8" />
@@ -36,8 +36,8 @@
36
36
  rel="stylesheet"
37
37
  href="css/leaflet.css"
38
38
  />
39
- <link rel="stylesheet" href="./css/nexowatt-native-shell.css?v=96" />
40
- <link rel="stylesheet" href="./css/eos-ems-overview.css?v=96" />
39
+ <link rel="stylesheet" href="./css/nexowatt-native-shell.css?v=98" />
40
+ <link rel="stylesheet" href="./css/eos-ems-overview.css?v=98" />
41
41
  <link
42
42
  rel="manifest"
43
43
  href="manifest.json"
@@ -159,21 +159,21 @@
159
159
  </script>
160
160
  <link rel="modulepreload" crossorigin href="./assets/preload-helper-BDBacUwf.js">
161
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=96" data-eos-entry="./assets/index-CQZugZ1z-v84.js?v=84"></script>
163
- <script defer src="./js/eos-policy-client.js?v=96"></script>
164
- <script defer src="./js/eos-branding-sanitizer.js?v=96"></script>
165
- <script defer src="./js/nexowatt-native-shell.js?v=96"></script>
166
- <script defer src="./js/eos-native-security.js?v=96"></script>
167
- <script defer src="./js/eos-basic-settings.js?v=96"></script>
168
- <script defer src="./js/eos-role-ui.js?v=96"></script>
169
- <script defer src="./js/eos-ems-overview.js?v=96"></script>
170
- <script defer src="./js/eos-account-management.js?v=96"></script>
171
- <script defer src="./js/eos-assistant.js?v=96"></script>
162
+ <script defer src="./js/eos-role-bootstrap.js?v=98" data-eos-entry="./assets/index-CQZugZ1z-v84.js?v=84"></script>
163
+ <script defer src="./js/eos-policy-client.js?v=98"></script>
164
+ <script defer src="./js/eos-branding-sanitizer.js?v=98"></script>
165
+ <script defer src="./js/nexowatt-native-shell.js?v=98"></script>
166
+ <script defer src="./js/eos-native-security.js?v=98"></script>
167
+ <script defer src="./js/eos-basic-settings.js?v=98"></script>
168
+ <script defer src="./js/eos-role-ui.js?v=98"></script>
169
+ <script defer src="./js/eos-ems-overview.js?v=98"></script>
170
+ <script defer src="./js/eos-account-management.js?v=98"></script>
171
+ <script defer src="./js/eos-assistant.js?v=98"></script>
172
172
  </head>
173
173
  <body>
174
174
  <noscript>Für NexoWatt EOS muss JavaScript aktiviert sein.</noscript>
175
175
  <div id="root"></div>
176
- <script defer src="static/js/nexowatt-stable-login.js?v=96"></script>
177
- <script defer src="static/js/nexowatt-stable-v96.js?v=96"></script>
176
+ <script defer src="static/js/nexowatt-stable-login.js?v=98"></script>
177
+ <script defer src="static/js/nexowatt-stable-v98.js?v=98"></script>
178
178
  </body>
179
179
  </html>
@@ -1,7 +1,7 @@
1
1
  (() => {
2
2
  'use strict';
3
3
 
4
- const VERSION = 'v91-account-management-under-access-rights';
4
+ const VERSION = 'v98-account-management-real-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,9 +19,9 @@
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? Das bisherige Passwort wird ungültig und bei der nächsten Erstanmeldung muss ein neues Passwort vergeben werden.`,
23
- resetDone: name => `Der Zugang „${name}“ ist zurückgesetzt. Bei der nächsten Anmeldung wird im normalen Anmeldefeld einmalig ohne Passwort gestartet und anschließend ein neues Passwort vergeben.`,
24
- resetFailed: 'Der Zugang konnte nicht zurückgesetzt werden.', lastSet: 'Letzte Passwortvergabe', lastReset: 'Letzter Reset', by: 'durch',
22
+ reset: 'Passwort zurücksetzen', resetting: 'Wird zurückgesetzt …', resetConfirm: name => `Soll der Zugang „${name}“ wirklich zurückgesetzt werden? Das bisherige Passwort wird ungültig. Danach gilt einmalig das Startpasswort „nexowatt“ und beim nächsten Login muss sofort ein persönliches Passwort vergeben werden.`,
23
+ resetDone: name => `Der Zugang „${name}“ ist zurückgesetzt. Einmalig mit dem Startpasswort „nexowatt“ anmelden und anschließend direkt ein persönliches Passwort festlegen.`,
24
+ resetFailed: 'Der Zugang konnte nicht zurückgesetzt werden.', permissionError: 'Für dieses Konto ist das Zurücksetzen nicht erlaubt.', originError: 'Die Sicherheitsprüfung der Anfrage ist fehlgeschlagen. Seite mit Strg+F5 neu laden.', disabledError: 'Das Konto ist deaktiviert und kann nicht zurückgesetzt werden.', notFoundError: 'Das Konto wurde nicht gefunden.', writeError: 'Das neue Startpasswort konnte nicht in das Benutzerkonto geschrieben 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
26
  },
27
27
  en: {
@@ -30,9 +30,9 @@
30
30
  introInstaller: 'You may reset end-user accounts. Admin and installer accounts remain reserved for NexoWatt Service.',
31
31
  loading: 'Loading accounts …', empty: 'No matching accounts found.', close: 'Close', refresh: 'Refresh',
32
32
  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 current password will become invalid and a new password must be created during the next first activation.`,
34
- resetDone: name => `Account “${name}” was reset. At the next sign-in the normal login form is used once with an empty password, followed by creation of a new password.`,
35
- resetFailed: 'The account could not be reset.', lastSet: 'Last password setup', lastReset: 'Last reset', by: 'by',
33
+ reset: 'Reset password', resetting: 'Resetting …', resetConfirm: name => `Reset account “${name}”? The current password becomes invalid. Sign in once with the initial password “nexowatt”, then create a personal password immediately.`,
34
+ resetDone: name => `Account “${name}” was reset. Sign in once with “nexowatt” and then create a personal password.`,
35
+ resetFailed: 'The account could not be reset.', permissionError: 'Reset is not permitted for this account.', originError: 'The request security check failed. Reload the page with Ctrl+F5.', disabledError: 'The account is disabled and cannot be reset.', notFoundError: 'The account was not found.', writeError: 'The initial password could not be written to the user account.', lastSet: 'Last password setup', lastReset: 'Last reset', by: 'by',
36
36
  security: 'Admin/Service may reset installer and end-user accounts. Installers may reset end-user accounts only.',
37
37
  },
38
38
  nl: {
@@ -41,13 +41,26 @@
41
41
  introInstaller: 'Je kunt eindgebruikersaccounts resetten. Admin- en installateurstoegang blijft voor NexoWatt Service.',
42
42
  loading: 'Toegangen worden geladen …', empty: 'Geen passende accounts gevonden.', close: 'Sluiten', refresh: 'Vernieuwen',
43
43
  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? Het huidige wachtwoord wordt ongeldig en bij de volgende eerste activering moet een nieuw wachtwoord worden ingesteld.`,
45
- resetDone: name => `Account „${name}“ is gereset. Bij de volgende aanmelding wordt het normale formulier één keer met een leeg wachtwoord gebruikt, waarna een nieuw wachtwoord wordt ingesteld.`,
46
- resetFailed: 'Het account kon niet worden gereset.', lastSet: 'Laatste wachtwoordinstelling', lastReset: 'Laatste reset', by: 'door',
44
+ reset: 'Wachtwoord resetten', resetting: 'Wordt gereset …', resetConfirm: name => `Account „${name}“ resetten? Het huidige wachtwoord wordt ongeldig. Meld één keer aan met het startwachtwoord „nexowatt“ en stel daarna direct een persoonlijk wachtwoord in.`,
45
+ resetDone: name => `Account „${name}“ is gereset. Meld één keer aan met „nexowatt“ en stel daarna een persoonlijk wachtwoord in.`,
46
+ resetFailed: 'Het account kon niet worden gereset.', permissionError: 'Resetten is voor dit account niet toegestaan.', originError: 'De veiligheidscontrole van het verzoek is mislukt. Herlaad de pagina met Ctrl+F5.', disabledError: 'Het account is uitgeschakeld en kan niet worden gereset.', notFoundError: 'Het account werd niet gevonden.', writeError: 'Het startwachtwoord kon niet naar het gebruikersaccount worden geschreven.', lastSet: 'Laatste wachtwoordinstelling', lastReset: 'Laatste reset', by: 'door',
47
47
  security: 'Admin/service mag installateur- en eindgebruikersaccounts resetten. Installateurs alleen eindgebruikers.',
48
48
  },
49
49
  };
50
50
  const t = () => i18n[language()];
51
+ const accountErrorText = code => {
52
+ const text = t();
53
+ return ({
54
+ permissionError: text.permissionError,
55
+ invalidRequestOrigin: text.originError,
56
+ accountDisabled: text.disabledError,
57
+ accountNotFound: text.notFoundError,
58
+ passwordApiUnavailable: text.writeError,
59
+ passwordWriteFailed: text.writeError,
60
+ passwordVerificationFailed: text.writeError,
61
+ userObjectUnavailableAfterPasswordChange: text.writeError,
62
+ })[String(code || '')] || text.resetFailed;
63
+ };
51
64
  const roleFromPolicy = policy => {
52
65
  const raw = normalize(policy?.role || '');
53
66
  if (policy?.isAdmin || policy?.isEosAdminGroup || /admin|service/.test(raw)) return 'admin';
@@ -144,12 +157,12 @@
144
157
  reset.disabled = true; reset.textContent = t().resetting; setStatus('', '');
145
158
  try {
146
159
  const response = await fetch(new URL('nexowatt/account/reset', base).href, {
147
- method: 'POST', credentials: 'same-origin', cache: 'no-store',
160
+ method: 'POST', credentials: 'include', cache: 'no-store',
148
161
  headers: { 'Content-Type': 'application/json', Accept: 'application/json', 'X-NexoWatt-EOS-Account-Reset': '1' },
149
162
  body: JSON.stringify({ user: account.id }),
150
163
  });
151
164
  const payload = await response.json().catch(() => ({}));
152
- if (!response.ok || payload.error) throw new Error(payload.error || t().resetFailed);
165
+ if (!response.ok || payload.error) throw new Error(accountErrorText(payload.error));
153
166
  setStatus(t().resetDone(label), 'success');
154
167
  await loadAccounts();
155
168
  } catch (error) {
@@ -176,7 +189,7 @@
176
189
  if (!state.overlay) return;
177
190
  setStatus(t().loading, '');
178
191
  try {
179
- const response = await fetch(new URL('nexowatt/account/manage', base).href, { credentials: 'same-origin', cache: 'no-store', headers: { Accept: 'application/json' } });
192
+ const response = await fetch(new URL('nexowatt/account/manage', base).href, { credentials: 'include', cache: 'no-store', headers: { Accept: 'application/json' } });
180
193
  const data = await response.json().catch(() => ({}));
181
194
  if (!response.ok || data.error) throw new Error(data.error || t().resetFailed);
182
195
  renderAccounts(data); setStatus('', '');
@@ -1,6 +1,6 @@
1
1
  (() => {
2
2
  'use strict';
3
- // NexoWatt EOS stable 7.9.96: EOS Assist remains disabled until the
3
+ // NexoWatt EOS stable 7.9.97: 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');