myio-js-library 0.1.169 → 0.1.173
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/dist/index.cjs +1905 -335
- package/dist/index.d.cts +207 -4
- package/dist/index.js +1901 -335
- package/dist/myio-js-library.umd.js +1900 -335
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
|
@@ -1324,7 +1324,8 @@
|
|
|
1324
1324
|
FAILURE: "failure",
|
|
1325
1325
|
MAINTENANCE: "maintenance",
|
|
1326
1326
|
NO_INFO: "no_info",
|
|
1327
|
-
NOT_INSTALLED: "not_installed"
|
|
1327
|
+
NOT_INSTALLED: "not_installed",
|
|
1328
|
+
OFFLINE: "offline"
|
|
1328
1329
|
};
|
|
1329
1330
|
var ConnectionStatusType = {
|
|
1330
1331
|
CONNECTED: "connected",
|
|
@@ -1333,39 +1334,42 @@
|
|
|
1333
1334
|
var deviceStatusIcons = {
|
|
1334
1335
|
[DeviceStatusType.POWER_ON]: "\u26A1",
|
|
1335
1336
|
[DeviceStatusType.STANDBY]: "\u{1F50C}",
|
|
1336
|
-
[DeviceStatusType.POWER_OFF]: "\
|
|
1337
|
+
[DeviceStatusType.POWER_OFF]: "\u26AB",
|
|
1337
1338
|
[DeviceStatusType.WARNING]: "\u26A0\uFE0F",
|
|
1338
1339
|
[DeviceStatusType.FAILURE]: "\u{1F6A8}",
|
|
1339
1340
|
[DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
|
|
1340
1341
|
[DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
|
|
1341
|
-
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
|
|
1342
|
+
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
|
|
1343
|
+
[DeviceStatusType.OFFLINE]: "\u{1F534}"
|
|
1342
1344
|
};
|
|
1343
1345
|
var waterDeviceStatusIcons = {
|
|
1344
1346
|
[DeviceStatusType.POWER_ON]: "\u{1F4A7}",
|
|
1345
1347
|
[DeviceStatusType.STANDBY]: "\u{1F6B0}",
|
|
1346
|
-
[DeviceStatusType.POWER_OFF]: "\
|
|
1348
|
+
[DeviceStatusType.POWER_OFF]: "\u26AB",
|
|
1347
1349
|
[DeviceStatusType.WARNING]: "\u26A0\uFE0F",
|
|
1348
1350
|
[DeviceStatusType.FAILURE]: "\u{1F6A8}",
|
|
1349
1351
|
[DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
|
|
1350
1352
|
[DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
|
|
1351
|
-
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
|
|
1353
|
+
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
|
|
1354
|
+
[DeviceStatusType.OFFLINE]: "\u{1F534}"
|
|
1352
1355
|
};
|
|
1353
1356
|
var temperatureDeviceStatusIcons = {
|
|
1354
1357
|
[DeviceStatusType.POWER_ON]: "\u{1F321}\uFE0F",
|
|
1355
1358
|
[DeviceStatusType.STANDBY]: "\u{1F321}\uFE0F",
|
|
1356
|
-
[DeviceStatusType.POWER_OFF]: "\
|
|
1359
|
+
[DeviceStatusType.POWER_OFF]: "\u26AB",
|
|
1357
1360
|
[DeviceStatusType.WARNING]: "\u26A0\uFE0F",
|
|
1358
1361
|
[DeviceStatusType.FAILURE]: "\u{1F6A8}",
|
|
1359
1362
|
[DeviceStatusType.MAINTENANCE]: "\u{1F6E0}\uFE0F",
|
|
1360
1363
|
[DeviceStatusType.NO_INFO]: "\u2753\uFE0F",
|
|
1361
|
-
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}"
|
|
1364
|
+
[DeviceStatusType.NOT_INSTALLED]: "\u{1F4E6}",
|
|
1365
|
+
[DeviceStatusType.OFFLINE]: "\u{1F534}"
|
|
1362
1366
|
};
|
|
1363
1367
|
var connectionStatusIcons = {
|
|
1364
1368
|
[ConnectionStatusType.CONNECTED]: "\u{1F7E2}",
|
|
1365
1369
|
[ConnectionStatusType.OFFLINE]: "\u{1F6AB}"
|
|
1366
1370
|
};
|
|
1367
1371
|
function mapDeviceToConnectionStatus(deviceStatus) {
|
|
1368
|
-
if (deviceStatus === DeviceStatusType.NO_INFO) {
|
|
1372
|
+
if (deviceStatus === DeviceStatusType.NO_INFO || deviceStatus === DeviceStatusType.OFFLINE) {
|
|
1369
1373
|
return ConnectionStatusType.OFFLINE;
|
|
1370
1374
|
}
|
|
1371
1375
|
return ConnectionStatusType.CONNECTED;
|
|
@@ -1389,15 +1393,16 @@
|
|
|
1389
1393
|
[DeviceStatusType.FAILURE]: "fail",
|
|
1390
1394
|
[DeviceStatusType.MAINTENANCE]: "alert",
|
|
1391
1395
|
[DeviceStatusType.NO_INFO]: "unknown",
|
|
1392
|
-
[DeviceStatusType.NOT_INSTALLED]: "not_installed"
|
|
1396
|
+
[DeviceStatusType.NOT_INSTALLED]: "not_installed",
|
|
1397
|
+
[DeviceStatusType.OFFLINE]: "offline"
|
|
1393
1398
|
};
|
|
1394
1399
|
return statusMap[deviceStatus] || "unknown";
|
|
1395
1400
|
}
|
|
1396
1401
|
function shouldFlashIcon(deviceStatus) {
|
|
1397
|
-
return deviceStatus === DeviceStatusType.POWER_OFF || deviceStatus === DeviceStatusType.WARNING || deviceStatus === DeviceStatusType.FAILURE || deviceStatus === DeviceStatusType.MAINTENANCE;
|
|
1402
|
+
return deviceStatus === DeviceStatusType.POWER_OFF || deviceStatus === DeviceStatusType.WARNING || deviceStatus === DeviceStatusType.FAILURE || deviceStatus === DeviceStatusType.MAINTENANCE || deviceStatus === DeviceStatusType.OFFLINE;
|
|
1398
1403
|
}
|
|
1399
1404
|
function isDeviceOffline(deviceStatus) {
|
|
1400
|
-
return deviceStatus === DeviceStatusType.NO_INFO;
|
|
1405
|
+
return deviceStatus === DeviceStatusType.NO_INFO || deviceStatus === DeviceStatusType.OFFLINE;
|
|
1401
1406
|
}
|
|
1402
1407
|
function getDeviceStatusIcon(deviceStatus, deviceType = null) {
|
|
1403
1408
|
const normalizedType = deviceType?.toUpperCase() || "";
|
|
@@ -3953,15 +3958,30 @@
|
|
|
3953
3958
|
--myio-chip-alert-fg: #b45309;
|
|
3954
3959
|
--myio-border-alert: rgba(245, 158, 11, 0.5);
|
|
3955
3960
|
|
|
3956
|
-
/* Status colors - Failure (red) */
|
|
3961
|
+
/* Status colors - Failure (dark red) */
|
|
3957
3962
|
--myio-chip-failure-bg: #fee2e2;
|
|
3958
3963
|
--myio-chip-failure-fg: #b91c1c;
|
|
3959
|
-
--myio-border-failure: rgba(
|
|
3964
|
+
--myio-border-failure: rgba(153, 27, 27, 0.6);
|
|
3965
|
+
|
|
3966
|
+
/* Status colors - Power Off (light red) */
|
|
3967
|
+
--myio-chip-power-off-bg: #fecaca;
|
|
3968
|
+
--myio-chip-power-off-fg: #dc2626;
|
|
3969
|
+
--myio-border-power-off: rgba(239, 68, 68, 0.5);
|
|
3970
|
+
|
|
3971
|
+
/* Status colors - Offline (dark gray) */
|
|
3972
|
+
--myio-chip-offline-bg: #e2e8f0;
|
|
3973
|
+
--myio-chip-offline-fg: #475569;
|
|
3974
|
+
--myio-border-offline: rgba(71, 85, 105, 0.6);
|
|
3975
|
+
|
|
3976
|
+
/* Status colors - No Info (dark orange) */
|
|
3977
|
+
--myio-chip-no-info-bg: #fed7aa;
|
|
3978
|
+
--myio-chip-no-info-fg: #c2410c;
|
|
3979
|
+
--myio-border-no-info: rgba(194, 65, 12, 0.5);
|
|
3960
3980
|
|
|
3961
|
-
/* Status colors -
|
|
3962
|
-
--myio-chip-
|
|
3963
|
-
--myio-chip-
|
|
3964
|
-
--myio-border-
|
|
3981
|
+
/* Status colors - Not Installed (purple) */
|
|
3982
|
+
--myio-chip-not-installed-bg: #e9d5ff;
|
|
3983
|
+
--myio-chip-not-installed-fg: #7c3aed;
|
|
3984
|
+
--myio-border-not-installed: rgba(124, 58, 237, 0.5);
|
|
3965
3985
|
|
|
3966
3986
|
--myio-text-1: #0f172a;
|
|
3967
3987
|
--myio-text-2: #4b5563;
|
|
@@ -4017,26 +4037,55 @@
|
|
|
4017
4037
|
}
|
|
4018
4038
|
|
|
4019
4039
|
/* Card border states based on device status */
|
|
4020
|
-
|
|
4040
|
+
|
|
4041
|
+
/* POWER_ON - Blue */
|
|
4042
|
+
.myio-ho-card.is-power-on {
|
|
4021
4043
|
border-color: var(--myio-border-ok);
|
|
4022
4044
|
box-shadow: 0 0 0 2px var(--myio-border-ok), var(--myio-card-shadow);
|
|
4023
4045
|
}
|
|
4024
4046
|
|
|
4047
|
+
/* STANDBY - Green */
|
|
4025
4048
|
.myio-ho-card.is-standby {
|
|
4026
4049
|
border-color: var(--myio-border-standby);
|
|
4027
4050
|
box-shadow: 0 0 0 2px var(--myio-border-standby), var(--myio-card-shadow);
|
|
4028
4051
|
}
|
|
4029
4052
|
|
|
4030
|
-
|
|
4053
|
+
/* WARNING - Yellow */
|
|
4054
|
+
.myio-ho-card.is-warning {
|
|
4055
|
+
border-color: var(--myio-border-alert);
|
|
4056
|
+
box-shadow: 0 0 0 2px var(--myio-border-alert), var(--myio-card-shadow);
|
|
4057
|
+
}
|
|
4058
|
+
|
|
4059
|
+
/* MAINTENANCE - Yellow */
|
|
4060
|
+
.myio-ho-card.is-maintenance {
|
|
4031
4061
|
border-color: var(--myio-border-alert);
|
|
4032
4062
|
box-shadow: 0 0 0 2px var(--myio-border-alert), var(--myio-card-shadow);
|
|
4033
4063
|
}
|
|
4034
4064
|
|
|
4065
|
+
/* FAILURE - Dark Red */
|
|
4035
4066
|
.myio-ho-card.is-failure {
|
|
4036
4067
|
border-color: var(--myio-border-failure);
|
|
4037
4068
|
box-shadow: 0 0 0 2px var(--myio-border-failure), var(--myio-card-shadow);
|
|
4038
4069
|
}
|
|
4039
4070
|
|
|
4071
|
+
/* POWER_OFF - Light Red */
|
|
4072
|
+
.myio-ho-card.is-power-off {
|
|
4073
|
+
border-color: var(--myio-border-power-off);
|
|
4074
|
+
box-shadow: 0 0 0 2px var(--myio-border-power-off), var(--myio-card-shadow);
|
|
4075
|
+
}
|
|
4076
|
+
|
|
4077
|
+
/* NO_INFO - Dark Orange */
|
|
4078
|
+
.myio-ho-card.is-no-info {
|
|
4079
|
+
border-color: var(--myio-border-no-info);
|
|
4080
|
+
box-shadow: 0 0 0 2px var(--myio-border-no-info), var(--myio-card-shadow);
|
|
4081
|
+
}
|
|
4082
|
+
|
|
4083
|
+
/* NOT_INSTALLED - Purple */
|
|
4084
|
+
.myio-ho-card.is-not-installed {
|
|
4085
|
+
border-color: var(--myio-border-not-installed);
|
|
4086
|
+
box-shadow: 0 0 0 2px var(--myio-border-not-installed), var(--myio-card-shadow);
|
|
4087
|
+
}
|
|
4088
|
+
|
|
4040
4089
|
/* Header section */
|
|
4041
4090
|
.myio-ho-card__header {
|
|
4042
4091
|
display: flex;
|
|
@@ -4054,7 +4103,9 @@
|
|
|
4054
4103
|
margin-top: 2px;
|
|
4055
4104
|
}
|
|
4056
4105
|
|
|
4057
|
-
|
|
4106
|
+
/* Icon colors based on status */
|
|
4107
|
+
.myio-ho-card.is-warning .myio-ho-card__icon,
|
|
4108
|
+
.myio-ho-card.is-maintenance .myio-ho-card__icon {
|
|
4058
4109
|
color: var(--myio-chip-alert-fg);
|
|
4059
4110
|
}
|
|
4060
4111
|
|
|
@@ -4062,14 +4113,28 @@
|
|
|
4062
4113
|
color: var(--myio-chip-failure-fg);
|
|
4063
4114
|
}
|
|
4064
4115
|
|
|
4116
|
+
.myio-ho-card.is-power-off .myio-ho-card__icon {
|
|
4117
|
+
color: var(--myio-chip-power-off-fg);
|
|
4118
|
+
}
|
|
4119
|
+
|
|
4120
|
+
.myio-ho-card.is-offline .myio-ho-card__icon {
|
|
4121
|
+
color: var(--myio-chip-offline-fg);
|
|
4122
|
+
}
|
|
4123
|
+
|
|
4124
|
+
.myio-ho-card.is-no-info .myio-ho-card__icon {
|
|
4125
|
+
color: var(--myio-chip-no-info-fg);
|
|
4126
|
+
}
|
|
4127
|
+
|
|
4128
|
+
.myio-ho-card.is-not-installed .myio-ho-card__icon {
|
|
4129
|
+
color: var(--myio-chip-not-installed-fg);
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4065
4132
|
.myio-ho-card__title {
|
|
4066
4133
|
flex: 1;
|
|
4067
4134
|
min-width: 0;
|
|
4068
4135
|
}
|
|
4069
4136
|
|
|
4070
|
-
/*
|
|
4071
|
-
|
|
4072
|
-
/* Estado Offline - borda cinza */
|
|
4137
|
+
/* OFFLINE - Dark Gray */
|
|
4073
4138
|
.myio-ho-card.is-offline {
|
|
4074
4139
|
border-color: var(--myio-border-offline);
|
|
4075
4140
|
box-shadow: 0 0 0 2px var(--myio-border-offline), var(--myio-card-shadow);
|
|
@@ -4464,6 +4529,37 @@
|
|
|
4464
4529
|
color: var(--myio-chip-offline-fg);
|
|
4465
4530
|
}
|
|
4466
4531
|
|
|
4532
|
+
/* New chip classes aligned with getCardStateClass */
|
|
4533
|
+
.chip--power-on {
|
|
4534
|
+
background: var(--myio-chip-ok-bg);
|
|
4535
|
+
color: var(--myio-chip-ok-fg);
|
|
4536
|
+
}
|
|
4537
|
+
|
|
4538
|
+
.chip--warning {
|
|
4539
|
+
background: var(--myio-chip-alert-bg);
|
|
4540
|
+
color: var(--myio-chip-alert-fg);
|
|
4541
|
+
}
|
|
4542
|
+
|
|
4543
|
+
.chip--maintenance {
|
|
4544
|
+
background: var(--myio-chip-alert-bg);
|
|
4545
|
+
color: var(--myio-chip-alert-fg);
|
|
4546
|
+
}
|
|
4547
|
+
|
|
4548
|
+
.chip--power-off {
|
|
4549
|
+
background: var(--myio-chip-power-off-bg);
|
|
4550
|
+
color: var(--myio-chip-power-off-fg);
|
|
4551
|
+
}
|
|
4552
|
+
|
|
4553
|
+
.chip--no-info {
|
|
4554
|
+
background: var(--myio-chip-no-info-bg);
|
|
4555
|
+
color: var(--myio-chip-no-info-fg);
|
|
4556
|
+
}
|
|
4557
|
+
|
|
4558
|
+
.chip--not-installed {
|
|
4559
|
+
background: var(--myio-chip-not-installed-bg);
|
|
4560
|
+
color: var(--myio-chip-not-installed-fg);
|
|
4561
|
+
}
|
|
4562
|
+
|
|
4467
4563
|
/* Status indicator dot for power metric */
|
|
4468
4564
|
.status-dot {
|
|
4469
4565
|
width: 8px;
|
|
@@ -4497,6 +4593,31 @@
|
|
|
4497
4593
|
background: var(--myio-muted);
|
|
4498
4594
|
}
|
|
4499
4595
|
|
|
4596
|
+
/* New dot classes aligned with getCardStateClass */
|
|
4597
|
+
.status-dot.dot--power-on {
|
|
4598
|
+
background: var(--myio-chip-ok-fg);
|
|
4599
|
+
}
|
|
4600
|
+
|
|
4601
|
+
.status-dot.dot--warning {
|
|
4602
|
+
background: var(--myio-chip-alert-fg);
|
|
4603
|
+
}
|
|
4604
|
+
|
|
4605
|
+
.status-dot.dot--maintenance {
|
|
4606
|
+
background: var(--myio-chip-alert-fg);
|
|
4607
|
+
}
|
|
4608
|
+
|
|
4609
|
+
.status-dot.dot--power-off {
|
|
4610
|
+
background: var(--myio-chip-power-off-fg);
|
|
4611
|
+
}
|
|
4612
|
+
|
|
4613
|
+
.status-dot.dot--no-info {
|
|
4614
|
+
background: var(--myio-chip-no-info-fg);
|
|
4615
|
+
}
|
|
4616
|
+
|
|
4617
|
+
.status-dot.dot--not-installed {
|
|
4618
|
+
background: var(--myio-chip-not-installed-fg);
|
|
4619
|
+
}
|
|
4620
|
+
|
|
4500
4621
|
/* Primary metric */
|
|
4501
4622
|
.myio-ho-card__primary {
|
|
4502
4623
|
margin-bottom: 14px;
|
|
@@ -4679,6 +4800,215 @@
|
|
|
4679
4800
|
transition: none;
|
|
4680
4801
|
}
|
|
4681
4802
|
}
|
|
4803
|
+
|
|
4804
|
+
/* ============================================
|
|
4805
|
+
DEBUG TOOLTIP STYLES (Premium)
|
|
4806
|
+
============================================ */
|
|
4807
|
+
|
|
4808
|
+
.has-debug-tooltip {
|
|
4809
|
+
cursor: help !important;
|
|
4810
|
+
}
|
|
4811
|
+
|
|
4812
|
+
.has-debug-tooltip::after {
|
|
4813
|
+
content: '\u{1F41B}';
|
|
4814
|
+
position: absolute;
|
|
4815
|
+
top: -4px;
|
|
4816
|
+
right: -4px;
|
|
4817
|
+
font-size: 10px;
|
|
4818
|
+
z-index: 1;
|
|
4819
|
+
}
|
|
4820
|
+
|
|
4821
|
+
.debug-tooltip-container {
|
|
4822
|
+
position: absolute;
|
|
4823
|
+
bottom: calc(100% + 8px);
|
|
4824
|
+
left: 50%;
|
|
4825
|
+
transform: translateX(-50%);
|
|
4826
|
+
z-index: 10000;
|
|
4827
|
+
pointer-events: none;
|
|
4828
|
+
opacity: 0;
|
|
4829
|
+
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
4830
|
+
}
|
|
4831
|
+
|
|
4832
|
+
.has-debug-tooltip:hover .debug-tooltip-container {
|
|
4833
|
+
opacity: 1;
|
|
4834
|
+
pointer-events: auto;
|
|
4835
|
+
}
|
|
4836
|
+
|
|
4837
|
+
.debug-tooltip {
|
|
4838
|
+
background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%);
|
|
4839
|
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
|
4840
|
+
border-radius: 12px;
|
|
4841
|
+
box-shadow:
|
|
4842
|
+
0 20px 40px rgba(0, 0, 0, 0.4),
|
|
4843
|
+
0 0 0 1px rgba(255, 255, 255, 0.05),
|
|
4844
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
|
4845
|
+
min-width: 340px;
|
|
4846
|
+
max-width: 420px;
|
|
4847
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
4848
|
+
font-size: 12px;
|
|
4849
|
+
color: #e2e8f0;
|
|
4850
|
+
overflow: hidden;
|
|
4851
|
+
}
|
|
4852
|
+
|
|
4853
|
+
.debug-tooltip__header {
|
|
4854
|
+
display: flex;
|
|
4855
|
+
align-items: center;
|
|
4856
|
+
gap: 8px;
|
|
4857
|
+
padding: 12px 16px;
|
|
4858
|
+
background: linear-gradient(90deg, rgba(99, 102, 241, 0.2) 0%, rgba(139, 92, 246, 0.1) 100%);
|
|
4859
|
+
border-bottom: 1px solid rgba(99, 102, 241, 0.2);
|
|
4860
|
+
}
|
|
4861
|
+
|
|
4862
|
+
.debug-tooltip__icon {
|
|
4863
|
+
font-size: 16px;
|
|
4864
|
+
}
|
|
4865
|
+
|
|
4866
|
+
.debug-tooltip__title {
|
|
4867
|
+
font-weight: 700;
|
|
4868
|
+
font-size: 13px;
|
|
4869
|
+
color: #f1f5f9;
|
|
4870
|
+
letter-spacing: 0.5px;
|
|
4871
|
+
text-transform: uppercase;
|
|
4872
|
+
}
|
|
4873
|
+
|
|
4874
|
+
.debug-tooltip__content {
|
|
4875
|
+
padding: 12px 16px;
|
|
4876
|
+
max-height: 400px;
|
|
4877
|
+
overflow-y: auto;
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4880
|
+
.debug-tooltip__section {
|
|
4881
|
+
margin-bottom: 14px;
|
|
4882
|
+
padding-bottom: 12px;
|
|
4883
|
+
border-bottom: 1px solid rgba(148, 163, 184, 0.1);
|
|
4884
|
+
}
|
|
4885
|
+
|
|
4886
|
+
.debug-tooltip__section:last-child {
|
|
4887
|
+
margin-bottom: 0;
|
|
4888
|
+
padding-bottom: 0;
|
|
4889
|
+
border-bottom: none;
|
|
4890
|
+
}
|
|
4891
|
+
|
|
4892
|
+
.debug-tooltip__section-title {
|
|
4893
|
+
font-size: 11px;
|
|
4894
|
+
font-weight: 600;
|
|
4895
|
+
color: #94a3b8;
|
|
4896
|
+
text-transform: uppercase;
|
|
4897
|
+
letter-spacing: 0.8px;
|
|
4898
|
+
margin-bottom: 10px;
|
|
4899
|
+
display: flex;
|
|
4900
|
+
align-items: center;
|
|
4901
|
+
gap: 6px;
|
|
4902
|
+
}
|
|
4903
|
+
|
|
4904
|
+
.debug-tooltip__row {
|
|
4905
|
+
display: flex;
|
|
4906
|
+
justify-content: space-between;
|
|
4907
|
+
align-items: flex-start;
|
|
4908
|
+
padding: 4px 0;
|
|
4909
|
+
gap: 12px;
|
|
4910
|
+
}
|
|
4911
|
+
|
|
4912
|
+
.debug-tooltip__row--full {
|
|
4913
|
+
flex-direction: column;
|
|
4914
|
+
gap: 4px;
|
|
4915
|
+
}
|
|
4916
|
+
|
|
4917
|
+
.debug-tooltip__label {
|
|
4918
|
+
color: #94a3b8;
|
|
4919
|
+
font-size: 11px;
|
|
4920
|
+
flex-shrink: 0;
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4923
|
+
.debug-tooltip__value {
|
|
4924
|
+
color: #f1f5f9;
|
|
4925
|
+
font-weight: 500;
|
|
4926
|
+
text-align: right;
|
|
4927
|
+
word-break: break-all;
|
|
4928
|
+
}
|
|
4929
|
+
|
|
4930
|
+
.debug-tooltip__row--full .debug-tooltip__value {
|
|
4931
|
+
text-align: left;
|
|
4932
|
+
background: rgba(0, 0, 0, 0.3);
|
|
4933
|
+
padding: 6px 10px;
|
|
4934
|
+
border-radius: 6px;
|
|
4935
|
+
font-size: 11px;
|
|
4936
|
+
width: 100%;
|
|
4937
|
+
box-sizing: border-box;
|
|
4938
|
+
}
|
|
4939
|
+
|
|
4940
|
+
.debug-tooltip__value--mono {
|
|
4941
|
+
font-family: 'SF Mono', 'Fira Code', 'Consolas', monospace;
|
|
4942
|
+
font-size: 11px;
|
|
4943
|
+
background: rgba(0, 0, 0, 0.3);
|
|
4944
|
+
padding: 2px 6px;
|
|
4945
|
+
border-radius: 4px;
|
|
4946
|
+
}
|
|
4947
|
+
|
|
4948
|
+
.debug-tooltip__value--highlight {
|
|
4949
|
+
color: #a5b4fc;
|
|
4950
|
+
font-style: italic;
|
|
4951
|
+
}
|
|
4952
|
+
|
|
4953
|
+
.debug-tooltip__badge {
|
|
4954
|
+
display: inline-block;
|
|
4955
|
+
padding: 2px 8px;
|
|
4956
|
+
border-radius: 4px;
|
|
4957
|
+
font-size: 10px;
|
|
4958
|
+
font-weight: 600;
|
|
4959
|
+
text-transform: uppercase;
|
|
4960
|
+
letter-spacing: 0.5px;
|
|
4961
|
+
background: rgba(99, 102, 241, 0.3);
|
|
4962
|
+
color: #a5b4fc;
|
|
4963
|
+
}
|
|
4964
|
+
|
|
4965
|
+
.debug-tooltip__badge--energy {
|
|
4966
|
+
background: rgba(59, 130, 246, 0.3);
|
|
4967
|
+
color: #93c5fd;
|
|
4968
|
+
}
|
|
4969
|
+
|
|
4970
|
+
.debug-tooltip__badge--water {
|
|
4971
|
+
background: rgba(6, 182, 212, 0.3);
|
|
4972
|
+
color: #67e8f9;
|
|
4973
|
+
}
|
|
4974
|
+
|
|
4975
|
+
.debug-tooltip__badge--temperature {
|
|
4976
|
+
background: rgba(249, 115, 22, 0.3);
|
|
4977
|
+
color: #fdba74;
|
|
4978
|
+
}
|
|
4979
|
+
|
|
4980
|
+
/* Tooltip arrow */
|
|
4981
|
+
.debug-tooltip::after {
|
|
4982
|
+
content: '';
|
|
4983
|
+
position: absolute;
|
|
4984
|
+
bottom: -6px;
|
|
4985
|
+
left: 50%;
|
|
4986
|
+
transform: translateX(-50%) rotate(45deg);
|
|
4987
|
+
width: 12px;
|
|
4988
|
+
height: 12px;
|
|
4989
|
+
background: #0f172a;
|
|
4990
|
+
border-right: 1px solid rgba(99, 102, 241, 0.3);
|
|
4991
|
+
border-bottom: 1px solid rgba(99, 102, 241, 0.3);
|
|
4992
|
+
}
|
|
4993
|
+
|
|
4994
|
+
/* Scrollbar styling for tooltip content */
|
|
4995
|
+
.debug-tooltip__content::-webkit-scrollbar {
|
|
4996
|
+
width: 6px;
|
|
4997
|
+
}
|
|
4998
|
+
|
|
4999
|
+
.debug-tooltip__content::-webkit-scrollbar-track {
|
|
5000
|
+
background: rgba(0, 0, 0, 0.2);
|
|
5001
|
+
border-radius: 3px;
|
|
5002
|
+
}
|
|
5003
|
+
|
|
5004
|
+
.debug-tooltip__content::-webkit-scrollbar-thumb {
|
|
5005
|
+
background: rgba(99, 102, 241, 0.4);
|
|
5006
|
+
border-radius: 3px;
|
|
5007
|
+
}
|
|
5008
|
+
|
|
5009
|
+
.debug-tooltip__content::-webkit-scrollbar-thumb:hover {
|
|
5010
|
+
background: rgba(99, 102, 241, 0.6);
|
|
5011
|
+
}
|
|
4682
5012
|
`;
|
|
4683
5013
|
|
|
4684
5014
|
// src/thingsboard/main-dashboard-shopping/v-4.0.0/head-office/card-head-office.icons.ts
|
|
@@ -4819,46 +5149,295 @@
|
|
|
4819
5149
|
menu_settings: "Configura\xE7\xF5es"
|
|
4820
5150
|
};
|
|
4821
5151
|
|
|
4822
|
-
// src/
|
|
4823
|
-
var
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
5152
|
+
// src/components/temperature/utils.ts
|
|
5153
|
+
var DAY_PERIODS = [
|
|
5154
|
+
{ id: "madrugada", label: "Madrugada (00h-06h)", startHour: 0, endHour: 6 },
|
|
5155
|
+
{ id: "manha", label: "Manh\xE3 (06h-12h)", startHour: 6, endHour: 12 },
|
|
5156
|
+
{ id: "tarde", label: "Tarde (12h-18h)", startHour: 12, endHour: 18 },
|
|
5157
|
+
{ id: "noite", label: "Noite (18h-24h)", startHour: 18, endHour: 24 }
|
|
5158
|
+
];
|
|
5159
|
+
var DEFAULT_CLAMP_RANGE = { min: 15, max: 40 };
|
|
5160
|
+
function getTodaySoFar() {
|
|
5161
|
+
const now = /* @__PURE__ */ new Date();
|
|
5162
|
+
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
|
|
5163
|
+
return {
|
|
5164
|
+
startTs: startOfDay.getTime(),
|
|
5165
|
+
endTs: now.getTime()
|
|
5166
|
+
};
|
|
4831
5167
|
}
|
|
4832
|
-
|
|
4833
|
-
|
|
4834
|
-
|
|
5168
|
+
var CHART_COLORS = [
|
|
5169
|
+
"#1976d2",
|
|
5170
|
+
// Blue
|
|
5171
|
+
"#FF6B6B",
|
|
5172
|
+
// Red
|
|
5173
|
+
"#4CAF50",
|
|
5174
|
+
// Green
|
|
5175
|
+
"#FF9800",
|
|
5176
|
+
// Orange
|
|
5177
|
+
"#9C27B0",
|
|
5178
|
+
// Purple
|
|
5179
|
+
"#00BCD4",
|
|
5180
|
+
// Cyan
|
|
5181
|
+
"#E91E63",
|
|
5182
|
+
// Pink
|
|
5183
|
+
"#795548"
|
|
5184
|
+
// Brown
|
|
5185
|
+
];
|
|
5186
|
+
async function fetchTemperatureData(token, deviceId, startTs, endTs) {
|
|
5187
|
+
const url = `/api/plugins/telemetry/DEVICE/${deviceId}/values/timeseries?keys=temperature&startTs=${encodeURIComponent(startTs)}&endTs=${encodeURIComponent(endTs)}&limit=50000&agg=NONE`;
|
|
5188
|
+
const response = await fetch(url, {
|
|
5189
|
+
headers: {
|
|
5190
|
+
"X-Authorization": `Bearer ${token}`,
|
|
5191
|
+
"Content-Type": "application/json"
|
|
5192
|
+
}
|
|
5193
|
+
});
|
|
5194
|
+
if (!response.ok) {
|
|
5195
|
+
throw new Error(`Failed to fetch temperature data: ${response.status}`);
|
|
4835
5196
|
}
|
|
4836
|
-
const
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
|
|
5197
|
+
const data = await response.json();
|
|
5198
|
+
return data?.temperature || [];
|
|
5199
|
+
}
|
|
5200
|
+
function clampTemperature(value, range = DEFAULT_CLAMP_RANGE) {
|
|
5201
|
+
const num = Number(value || 0);
|
|
5202
|
+
if (num < range.min) return range.min;
|
|
5203
|
+
if (num > range.max) return range.max;
|
|
5204
|
+
return num;
|
|
5205
|
+
}
|
|
5206
|
+
function calculateStats(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
5207
|
+
if (data.length === 0) {
|
|
5208
|
+
return { avg: 0, min: 0, max: 0, count: 0 };
|
|
4840
5209
|
}
|
|
5210
|
+
const values = data.map((item) => clampTemperature(item.value, clampRange));
|
|
5211
|
+
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
4841
5212
|
return {
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
useNewComponents: Boolean(params.useNewComponents),
|
|
4847
|
-
// RFC-0091: Configurable delay time for connection status check (default 15 minutes)
|
|
4848
|
-
delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? 15,
|
|
4849
|
-
callbacks: {
|
|
4850
|
-
handleActionDashboard: params.handleActionDashboard,
|
|
4851
|
-
handleActionReport: params.handleActionReport,
|
|
4852
|
-
handleActionSettings: params.handleActionSettings,
|
|
4853
|
-
handleSelect: params.handleSelect,
|
|
4854
|
-
handInfo: params.handInfo,
|
|
4855
|
-
handleClickCard: params.handleClickCard
|
|
4856
|
-
}
|
|
5213
|
+
avg: sum / values.length,
|
|
5214
|
+
min: Math.min(...values),
|
|
5215
|
+
max: Math.max(...values),
|
|
5216
|
+
count: values.length
|
|
4857
5217
|
};
|
|
4858
5218
|
}
|
|
4859
|
-
function
|
|
4860
|
-
|
|
4861
|
-
|
|
5219
|
+
function interpolateTemperature(data, options) {
|
|
5220
|
+
const { intervalMinutes, startTs, endTs, clampRange = DEFAULT_CLAMP_RANGE } = options;
|
|
5221
|
+
const intervalMs = intervalMinutes * 60 * 1e3;
|
|
5222
|
+
if (data.length === 0) {
|
|
5223
|
+
return [];
|
|
5224
|
+
}
|
|
5225
|
+
const sortedData = [...data].sort((a, b) => a.ts - b.ts);
|
|
5226
|
+
const result = [];
|
|
5227
|
+
let lastKnownValue = clampTemperature(sortedData[0].value, clampRange);
|
|
5228
|
+
let dataIndex = 0;
|
|
5229
|
+
for (let ts = startTs; ts <= endTs; ts += intervalMs) {
|
|
5230
|
+
while (dataIndex < sortedData.length - 1 && sortedData[dataIndex + 1].ts <= ts) {
|
|
5231
|
+
dataIndex++;
|
|
5232
|
+
}
|
|
5233
|
+
const currentData = sortedData[dataIndex];
|
|
5234
|
+
if (currentData && Math.abs(currentData.ts - ts) < intervalMs) {
|
|
5235
|
+
lastKnownValue = clampTemperature(currentData.value, clampRange);
|
|
5236
|
+
}
|
|
5237
|
+
result.push({
|
|
5238
|
+
ts,
|
|
5239
|
+
value: lastKnownValue
|
|
5240
|
+
});
|
|
5241
|
+
}
|
|
5242
|
+
return result;
|
|
5243
|
+
}
|
|
5244
|
+
function aggregateByDay(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
5245
|
+
if (data.length === 0) {
|
|
5246
|
+
return [];
|
|
5247
|
+
}
|
|
5248
|
+
const dayMap = /* @__PURE__ */ new Map();
|
|
5249
|
+
data.forEach((item) => {
|
|
5250
|
+
const date = new Date(item.ts);
|
|
5251
|
+
const dateKey = date.toISOString().split("T")[0];
|
|
5252
|
+
if (!dayMap.has(dateKey)) {
|
|
5253
|
+
dayMap.set(dateKey, []);
|
|
5254
|
+
}
|
|
5255
|
+
dayMap.get(dateKey).push(item);
|
|
5256
|
+
});
|
|
5257
|
+
const result = [];
|
|
5258
|
+
dayMap.forEach((dayData, dateKey) => {
|
|
5259
|
+
const values = dayData.map((item) => clampTemperature(item.value, clampRange));
|
|
5260
|
+
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
5261
|
+
result.push({
|
|
5262
|
+
date: dateKey,
|
|
5263
|
+
dateTs: new Date(dateKey).getTime(),
|
|
5264
|
+
avg: sum / values.length,
|
|
5265
|
+
min: Math.min(...values),
|
|
5266
|
+
max: Math.max(...values),
|
|
5267
|
+
count: values.length
|
|
5268
|
+
});
|
|
5269
|
+
});
|
|
5270
|
+
return result.sort((a, b) => a.dateTs - b.dateTs);
|
|
5271
|
+
}
|
|
5272
|
+
function filterByDayPeriods(data, selectedPeriods) {
|
|
5273
|
+
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
5274
|
+
return data;
|
|
5275
|
+
}
|
|
5276
|
+
return data.filter((item) => {
|
|
5277
|
+
const date = new Date(item.ts);
|
|
5278
|
+
const hour = date.getHours();
|
|
5279
|
+
return selectedPeriods.some((periodId) => {
|
|
5280
|
+
const period = DAY_PERIODS.find((p) => p.id === periodId);
|
|
5281
|
+
if (!period) return false;
|
|
5282
|
+
return hour >= period.startHour && hour < period.endHour;
|
|
5283
|
+
});
|
|
5284
|
+
});
|
|
5285
|
+
}
|
|
5286
|
+
function getSelectedPeriodsLabel(selectedPeriods) {
|
|
5287
|
+
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
5288
|
+
return "Todos os per\xEDodos";
|
|
5289
|
+
}
|
|
5290
|
+
if (selectedPeriods.length === 1) {
|
|
5291
|
+
const period = DAY_PERIODS.find((p) => p.id === selectedPeriods[0]);
|
|
5292
|
+
return period?.label || "";
|
|
5293
|
+
}
|
|
5294
|
+
return `${selectedPeriods.length} per\xEDodos selecionados`;
|
|
5295
|
+
}
|
|
5296
|
+
function formatTemperature(value, decimals = 1) {
|
|
5297
|
+
if (value === null || value === void 0 || isNaN(value)) {
|
|
5298
|
+
return "\u2014";
|
|
5299
|
+
}
|
|
5300
|
+
return `${value.toFixed(decimals)}\xB0C`;
|
|
5301
|
+
}
|
|
5302
|
+
function exportTemperatureCSV(data, deviceLabel, stats, startDate, endDate) {
|
|
5303
|
+
if (data.length === 0) {
|
|
5304
|
+
console.warn("No data to export");
|
|
5305
|
+
return;
|
|
5306
|
+
}
|
|
5307
|
+
const BOM = "\uFEFF";
|
|
5308
|
+
let csvContent = BOM;
|
|
5309
|
+
csvContent += `Relat\xF3rio de Temperatura - ${deviceLabel}
|
|
5310
|
+
`;
|
|
5311
|
+
csvContent += `Per\xEDodo: ${startDate} at\xE9 ${endDate}
|
|
5312
|
+
`;
|
|
5313
|
+
csvContent += `M\xE9dia: ${formatTemperature(stats.avg)}
|
|
5314
|
+
`;
|
|
5315
|
+
csvContent += `M\xEDnima: ${formatTemperature(stats.min)}
|
|
5316
|
+
`;
|
|
5317
|
+
csvContent += `M\xE1xima: ${formatTemperature(stats.max)}
|
|
5318
|
+
`;
|
|
5319
|
+
csvContent += `Total de leituras: ${stats.count}
|
|
5320
|
+
`;
|
|
5321
|
+
csvContent += "\n";
|
|
5322
|
+
csvContent += "Data/Hora,Temperatura (\xB0C)\n";
|
|
5323
|
+
data.forEach((item) => {
|
|
5324
|
+
const date = new Date(item.ts).toLocaleString("pt-BR");
|
|
5325
|
+
const temp = Number(item.value).toFixed(2);
|
|
5326
|
+
csvContent += `"${date}",${temp}
|
|
5327
|
+
`;
|
|
5328
|
+
});
|
|
5329
|
+
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
5330
|
+
const url = URL.createObjectURL(blob);
|
|
5331
|
+
const link = document.createElement("a");
|
|
5332
|
+
link.href = url;
|
|
5333
|
+
link.download = `temperatura_${deviceLabel.replace(/\s+/g, "_")}_${startDate}_${endDate}.csv`;
|
|
5334
|
+
document.body.appendChild(link);
|
|
5335
|
+
link.click();
|
|
5336
|
+
document.body.removeChild(link);
|
|
5337
|
+
URL.revokeObjectURL(url);
|
|
5338
|
+
}
|
|
5339
|
+
var DARK_THEME = {
|
|
5340
|
+
background: "rgba(0, 0, 0, 0.85)",
|
|
5341
|
+
surface: "#1a1f28",
|
|
5342
|
+
text: "#ffffff",
|
|
5343
|
+
textMuted: "rgba(255, 255, 255, 0.7)",
|
|
5344
|
+
border: "rgba(255, 255, 255, 0.1)",
|
|
5345
|
+
primary: "#1976d2",
|
|
5346
|
+
success: "#4CAF50",
|
|
5347
|
+
warning: "#FF9800",
|
|
5348
|
+
danger: "#f44336",
|
|
5349
|
+
chartLine: "#1976d2",
|
|
5350
|
+
chartGrid: "rgba(255, 255, 255, 0.1)"
|
|
5351
|
+
};
|
|
5352
|
+
var LIGHT_THEME = {
|
|
5353
|
+
background: "rgba(0, 0, 0, 0.6)",
|
|
5354
|
+
surface: "#ffffff",
|
|
5355
|
+
text: "#333333",
|
|
5356
|
+
textMuted: "#666666",
|
|
5357
|
+
border: "#e0e0e0",
|
|
5358
|
+
primary: "#1976d2",
|
|
5359
|
+
success: "#4CAF50",
|
|
5360
|
+
warning: "#FF9800",
|
|
5361
|
+
danger: "#f44336",
|
|
5362
|
+
chartLine: "#1976d2",
|
|
5363
|
+
chartGrid: "#e0e0e0"
|
|
5364
|
+
};
|
|
5365
|
+
function getThemeColors(theme) {
|
|
5366
|
+
return theme === "dark" ? DARK_THEME : LIGHT_THEME;
|
|
5367
|
+
}
|
|
5368
|
+
|
|
5369
|
+
// src/utils/logHelper.js
|
|
5370
|
+
function createLogHelper(debugActive = false) {
|
|
5371
|
+
return {
|
|
5372
|
+
log: function(...args) {
|
|
5373
|
+
if (debugActive) {
|
|
5374
|
+
console.log(...args);
|
|
5375
|
+
}
|
|
5376
|
+
},
|
|
5377
|
+
warn: function(...args) {
|
|
5378
|
+
if (debugActive) {
|
|
5379
|
+
console.warn(...args);
|
|
5380
|
+
}
|
|
5381
|
+
},
|
|
5382
|
+
error: function(...args) {
|
|
5383
|
+
console.error(...args);
|
|
5384
|
+
}
|
|
5385
|
+
};
|
|
5386
|
+
}
|
|
5387
|
+
|
|
5388
|
+
// src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
|
|
5389
|
+
var LABEL_CHAR_LIMIT = 18;
|
|
5390
|
+
var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
|
|
5391
|
+
var CSS_TAG = "head-office-card-v1";
|
|
5392
|
+
function ensureCss() {
|
|
5393
|
+
if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
|
|
5394
|
+
const style = document.createElement("style");
|
|
5395
|
+
style.setAttribute("data-myio-css", CSS_TAG);
|
|
5396
|
+
style.textContent = CSS_STRING;
|
|
5397
|
+
document.head.appendChild(style);
|
|
5398
|
+
}
|
|
5399
|
+
}
|
|
5400
|
+
function normalizeParams(params) {
|
|
5401
|
+
if (!params || !params.entityObject) {
|
|
5402
|
+
throw new Error("renderCardCompenteHeadOffice: entityObject is required");
|
|
5403
|
+
}
|
|
5404
|
+
const LogHelper2 = createLogHelper(params.debugActive ?? false);
|
|
5405
|
+
const entityObject = params.entityObject;
|
|
5406
|
+
if (!entityObject.entityId) {
|
|
5407
|
+
LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
|
|
5408
|
+
entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
5409
|
+
}
|
|
5410
|
+
if (!params.delayTimeConnectionInMins) {
|
|
5411
|
+
LogHelper2.warn(
|
|
5412
|
+
`[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
|
|
5413
|
+
);
|
|
5414
|
+
}
|
|
5415
|
+
return {
|
|
5416
|
+
entityObject,
|
|
5417
|
+
i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
|
|
5418
|
+
enableSelection: Boolean(params.enableSelection),
|
|
5419
|
+
enableDragDrop: Boolean(params.enableDragDrop),
|
|
5420
|
+
useNewComponents: Boolean(params.useNewComponents),
|
|
5421
|
+
// RFC-0091: Configurable delay time for connection status check (default 15 minutes)
|
|
5422
|
+
delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
|
|
5423
|
+
// Debug options
|
|
5424
|
+
debugActive: params.debugActive ?? false,
|
|
5425
|
+
activeTooltipDebug: params.activeTooltipDebug ?? false,
|
|
5426
|
+
// LogHelper instance for this card
|
|
5427
|
+
LogHelper: LogHelper2,
|
|
5428
|
+
callbacks: {
|
|
5429
|
+
handleActionDashboard: params.handleActionDashboard,
|
|
5430
|
+
handleActionReport: params.handleActionReport,
|
|
5431
|
+
handleActionSettings: params.handleActionSettings,
|
|
5432
|
+
handleSelect: params.handleSelect,
|
|
5433
|
+
handInfo: params.handInfo,
|
|
5434
|
+
handleClickCard: params.handleClickCard
|
|
5435
|
+
}
|
|
5436
|
+
};
|
|
5437
|
+
}
|
|
5438
|
+
function getIconSvg(deviceType, domain) {
|
|
5439
|
+
if (domain === "water") {
|
|
5440
|
+
return Icons.waterDrop;
|
|
4862
5441
|
}
|
|
4863
5442
|
if (domain === "temperature") {
|
|
4864
5443
|
return Icons.thermometer;
|
|
@@ -4883,16 +5462,10 @@
|
|
|
4883
5462
|
return formatWaterVolumeM3(value);
|
|
4884
5463
|
}
|
|
4885
5464
|
if (domain === "temperature") {
|
|
4886
|
-
return formatTemperature(value);
|
|
5465
|
+
return formatTemperature(value, 0);
|
|
4887
5466
|
}
|
|
4888
5467
|
return formatEnergy(value);
|
|
4889
5468
|
}
|
|
4890
|
-
function formatTemperature(temp) {
|
|
4891
|
-
if (temp === null || temp === void 0 || isNaN(temp)) {
|
|
4892
|
-
return "\u2014";
|
|
4893
|
-
}
|
|
4894
|
-
return `${temp.toFixed(0)}\xB0C`;
|
|
4895
|
-
}
|
|
4896
5469
|
function calculateConsumptionPercentage(target, consumption) {
|
|
4897
5470
|
const numericTarget = Number(target);
|
|
4898
5471
|
const numericConsumption = Number(consumption);
|
|
@@ -4907,32 +5480,32 @@
|
|
|
4907
5480
|
// --- Novos Status de Temperatura ---
|
|
4908
5481
|
case "normal":
|
|
4909
5482
|
return { chipClass: "chip--ok", label: "Normal" };
|
|
4910
|
-
// Verde/Azul
|
|
4911
5483
|
case "cold":
|
|
4912
5484
|
return { chipClass: "chip--standby", label: "Frio" };
|
|
4913
|
-
// Azul claro/Ciano
|
|
4914
5485
|
case "hot":
|
|
4915
5486
|
return { chipClass: "chip--alert", label: "Quente" };
|
|
4916
|
-
//
|
|
4917
|
-
// --- Status Existentes ---
|
|
5487
|
+
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
4918
5488
|
case DeviceStatusType.POWER_ON:
|
|
4919
5489
|
if (domain === "water") {
|
|
4920
|
-
return { chipClass: "chip--
|
|
5490
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation_water };
|
|
4921
5491
|
}
|
|
4922
|
-
return { chipClass: "chip--
|
|
5492
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation };
|
|
4923
5493
|
case DeviceStatusType.STANDBY:
|
|
4924
5494
|
return { chipClass: "chip--standby", label: i18n.standby };
|
|
4925
5495
|
case DeviceStatusType.WARNING:
|
|
4926
|
-
return { chipClass: "chip--
|
|
5496
|
+
return { chipClass: "chip--warning", label: i18n.alert };
|
|
5497
|
+
case DeviceStatusType.MAINTENANCE:
|
|
5498
|
+
return { chipClass: "chip--maintenance", label: i18n.maintenance };
|
|
4927
5499
|
case DeviceStatusType.FAILURE:
|
|
4928
|
-
case DeviceStatusType.POWER_OFF:
|
|
4929
5500
|
return { chipClass: "chip--failure", label: i18n.failure };
|
|
4930
|
-
case DeviceStatusType.
|
|
4931
|
-
return { chipClass: "chip--
|
|
4932
|
-
case DeviceStatusType.
|
|
4933
|
-
return { chipClass: "chip--offline", label: i18n.
|
|
4934
|
-
// Default (Cai aqui se não achar 'normal', 'hot' etc)
|
|
5501
|
+
case DeviceStatusType.POWER_OFF:
|
|
5502
|
+
return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
|
|
5503
|
+
case DeviceStatusType.OFFLINE:
|
|
5504
|
+
return { chipClass: "chip--offline", label: i18n.offline };
|
|
4935
5505
|
case DeviceStatusType.NO_INFO:
|
|
5506
|
+
return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
|
|
5507
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
5508
|
+
return { chipClass: "chip--not-installed", label: i18n.not_installed };
|
|
4936
5509
|
default:
|
|
4937
5510
|
return { chipClass: "chip--offline", label: i18n.offline };
|
|
4938
5511
|
}
|
|
@@ -4940,23 +5513,32 @@
|
|
|
4940
5513
|
function getCardStateClass(deviceStatus) {
|
|
4941
5514
|
switch (deviceStatus) {
|
|
4942
5515
|
case DeviceStatusType.POWER_ON:
|
|
4943
|
-
return "is-
|
|
5516
|
+
return "is-power-on";
|
|
4944
5517
|
// Blue border
|
|
4945
5518
|
case DeviceStatusType.STANDBY:
|
|
4946
5519
|
return "is-standby";
|
|
4947
5520
|
// Green border
|
|
4948
5521
|
case DeviceStatusType.WARNING:
|
|
5522
|
+
return "is-warning";
|
|
5523
|
+
// Yellow border
|
|
4949
5524
|
case DeviceStatusType.MAINTENANCE:
|
|
4950
|
-
return "is-
|
|
5525
|
+
return "is-maintenance";
|
|
4951
5526
|
// Yellow border
|
|
4952
5527
|
case DeviceStatusType.FAILURE:
|
|
4953
|
-
case DeviceStatusType.POWER_OFF:
|
|
4954
5528
|
return "is-failure";
|
|
4955
|
-
// Red border
|
|
5529
|
+
// Dark Red border
|
|
5530
|
+
case DeviceStatusType.POWER_OFF:
|
|
5531
|
+
return "is-power-off";
|
|
5532
|
+
// Light Red border
|
|
5533
|
+
case DeviceStatusType.OFFLINE:
|
|
5534
|
+
return "is-offline";
|
|
5535
|
+
// Dark Gray border
|
|
4956
5536
|
case DeviceStatusType.NO_INFO:
|
|
5537
|
+
return "is-no-info";
|
|
5538
|
+
// Dark Orange border
|
|
4957
5539
|
case DeviceStatusType.NOT_INSTALLED:
|
|
4958
|
-
return "is-
|
|
4959
|
-
//
|
|
5540
|
+
return "is-not-installed";
|
|
5541
|
+
// Purple border
|
|
4960
5542
|
default:
|
|
4961
5543
|
return "";
|
|
4962
5544
|
}
|
|
@@ -4970,17 +5552,25 @@
|
|
|
4970
5552
|
return "dot--standby";
|
|
4971
5553
|
case "hot":
|
|
4972
5554
|
return "dot--alert";
|
|
4973
|
-
// --- Status Existentes ---
|
|
5555
|
+
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
4974
5556
|
case DeviceStatusType.POWER_ON:
|
|
4975
|
-
return "dot--
|
|
5557
|
+
return "dot--power-on";
|
|
4976
5558
|
case DeviceStatusType.STANDBY:
|
|
4977
5559
|
return "dot--standby";
|
|
4978
5560
|
case DeviceStatusType.WARNING:
|
|
5561
|
+
return "dot--warning";
|
|
4979
5562
|
case DeviceStatusType.MAINTENANCE:
|
|
4980
|
-
return "dot--
|
|
5563
|
+
return "dot--maintenance";
|
|
4981
5564
|
case DeviceStatusType.FAILURE:
|
|
4982
|
-
case DeviceStatusType.POWER_OFF:
|
|
4983
5565
|
return "dot--failure";
|
|
5566
|
+
case DeviceStatusType.POWER_OFF:
|
|
5567
|
+
return "dot--power-off";
|
|
5568
|
+
case DeviceStatusType.OFFLINE:
|
|
5569
|
+
return "dot--offline";
|
|
5570
|
+
case DeviceStatusType.NO_INFO:
|
|
5571
|
+
return "dot--no-info";
|
|
5572
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
5573
|
+
return "dot--not-installed";
|
|
4984
5574
|
default:
|
|
4985
5575
|
return "dot--offline";
|
|
4986
5576
|
}
|
|
@@ -5004,7 +5594,13 @@
|
|
|
5004
5594
|
titleSection.className = "myio-ho-card__title";
|
|
5005
5595
|
const nameEl = document.createElement("div");
|
|
5006
5596
|
nameEl.className = "myio-ho-card__name";
|
|
5007
|
-
|
|
5597
|
+
const fullName = entityObject.labelOrName || "Unknown Device";
|
|
5598
|
+
if (fullName.length > LABEL_CHAR_LIMIT) {
|
|
5599
|
+
nameEl.textContent = fullName.slice(0, LABEL_CHAR_LIMIT) + "\u2026";
|
|
5600
|
+
nameEl.title = fullName;
|
|
5601
|
+
} else {
|
|
5602
|
+
nameEl.textContent = fullName;
|
|
5603
|
+
}
|
|
5008
5604
|
titleSection.appendChild(nameEl);
|
|
5009
5605
|
if (entityObject.deviceIdentifier) {
|
|
5010
5606
|
const codeEl = document.createElement("div");
|
|
@@ -5133,29 +5729,207 @@
|
|
|
5133
5729
|
root.appendChild(footer);
|
|
5134
5730
|
return root;
|
|
5135
5731
|
}
|
|
5136
|
-
function
|
|
5732
|
+
function buildDebugTooltipInfo(entityObject, statusInfo, stateClass, statusDecisionSource, delayTimeConnectionInMins) {
|
|
5733
|
+
const formatTimestamp = (ts) => {
|
|
5734
|
+
if (!ts) return "N/A";
|
|
5735
|
+
const d = new Date(ts);
|
|
5736
|
+
return d.toLocaleString("pt-BR", {
|
|
5737
|
+
day: "2-digit",
|
|
5738
|
+
month: "2-digit",
|
|
5739
|
+
year: "numeric",
|
|
5740
|
+
hour: "2-digit",
|
|
5741
|
+
minute: "2-digit",
|
|
5742
|
+
second: "2-digit"
|
|
5743
|
+
});
|
|
5744
|
+
};
|
|
5745
|
+
return {
|
|
5746
|
+
// Entity identification
|
|
5747
|
+
entityId: entityObject.entityId || "N/A",
|
|
5748
|
+
name: entityObject.name || entityObject.nameEl || "N/A",
|
|
5749
|
+
domain: entityObject.domain || "energy",
|
|
5750
|
+
// Status decision chain
|
|
5751
|
+
originalDeviceStatus: entityObject._originalDeviceStatus || entityObject.deviceStatus,
|
|
5752
|
+
finalDeviceStatus: entityObject.deviceStatus,
|
|
5753
|
+
connectionStatus: entityObject.connectionStatus || "N/A",
|
|
5754
|
+
statusDecisionSource,
|
|
5755
|
+
// Visual output
|
|
5756
|
+
stateClass,
|
|
5757
|
+
chipClass: statusInfo.chipClass,
|
|
5758
|
+
chipLabel: statusInfo.label,
|
|
5759
|
+
// Connection timestamps
|
|
5760
|
+
lastConnectTime: formatTimestamp(entityObject.lastConnectTime),
|
|
5761
|
+
lastDisconnectTime: formatTimestamp(entityObject.lastDisconnectTime),
|
|
5762
|
+
delayTimeConnectionInMins,
|
|
5763
|
+
// Raw values
|
|
5764
|
+
val: entityObject.val,
|
|
5765
|
+
consumptionTargetValue: entityObject.consumptionTargetValue,
|
|
5766
|
+
deviceType: entityObject.deviceType || "N/A"
|
|
5767
|
+
};
|
|
5768
|
+
}
|
|
5769
|
+
function attachDebugTooltip(element, debugInfo) {
|
|
5770
|
+
const existingTooltip = element.querySelector(".debug-tooltip-container");
|
|
5771
|
+
if (existingTooltip) {
|
|
5772
|
+
existingTooltip.remove();
|
|
5773
|
+
}
|
|
5774
|
+
const tooltipContainer = document.createElement("div");
|
|
5775
|
+
tooltipContainer.className = "debug-tooltip-container";
|
|
5776
|
+
const tooltip = document.createElement("div");
|
|
5777
|
+
tooltip.className = "debug-tooltip";
|
|
5778
|
+
tooltip.innerHTML = `
|
|
5779
|
+
<div class="debug-tooltip__header">
|
|
5780
|
+
<span class="debug-tooltip__icon">\u{1F50D}</span>
|
|
5781
|
+
<span class="debug-tooltip__title">Debug Info</span>
|
|
5782
|
+
</div>
|
|
5783
|
+
<div class="debug-tooltip__content">
|
|
5784
|
+
<div class="debug-tooltip__section">
|
|
5785
|
+
<div class="debug-tooltip__section-title">\u{1F4CB} Identifica\xE7\xE3o</div>
|
|
5786
|
+
<div class="debug-tooltip__row">
|
|
5787
|
+
<span class="debug-tooltip__label">Entity ID:</span>
|
|
5788
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.entityId}</span>
|
|
5789
|
+
</div>
|
|
5790
|
+
<div class="debug-tooltip__row">
|
|
5791
|
+
<span class="debug-tooltip__label">Nome:</span>
|
|
5792
|
+
<span class="debug-tooltip__value">${debugInfo.name}</span>
|
|
5793
|
+
</div>
|
|
5794
|
+
<div class="debug-tooltip__row">
|
|
5795
|
+
<span class="debug-tooltip__label">Dom\xEDnio:</span>
|
|
5796
|
+
<span class="debug-tooltip__value debug-tooltip__badge debug-tooltip__badge--${debugInfo.domain}">${debugInfo.domain}</span>
|
|
5797
|
+
</div>
|
|
5798
|
+
</div>
|
|
5799
|
+
|
|
5800
|
+
<div class="debug-tooltip__section">
|
|
5801
|
+
<div class="debug-tooltip__section-title">\u26A1 Decis\xE3o de Status</div>
|
|
5802
|
+
<div class="debug-tooltip__row">
|
|
5803
|
+
<span class="debug-tooltip__label">connectionStatus:</span>
|
|
5804
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.connectionStatus}</span>
|
|
5805
|
+
</div>
|
|
5806
|
+
<div class="debug-tooltip__row">
|
|
5807
|
+
<span class="debug-tooltip__label">deviceStatus (final):</span>
|
|
5808
|
+
<span class="debug-tooltip__value debug-tooltip__badge">${debugInfo.finalDeviceStatus}</span>
|
|
5809
|
+
</div>
|
|
5810
|
+
<div class="debug-tooltip__row debug-tooltip__row--full">
|
|
5811
|
+
<span class="debug-tooltip__label">Fonte da decis\xE3o:</span>
|
|
5812
|
+
<span class="debug-tooltip__value debug-tooltip__value--highlight">${debugInfo.statusDecisionSource}</span>
|
|
5813
|
+
</div>
|
|
5814
|
+
</div>
|
|
5815
|
+
|
|
5816
|
+
<div class="debug-tooltip__section">
|
|
5817
|
+
<div class="debug-tooltip__section-title">\u{1F3A8} Output Visual</div>
|
|
5818
|
+
<div class="debug-tooltip__row">
|
|
5819
|
+
<span class="debug-tooltip__label">stateClass:</span>
|
|
5820
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.stateClass}</span>
|
|
5821
|
+
</div>
|
|
5822
|
+
<div class="debug-tooltip__row">
|
|
5823
|
+
<span class="debug-tooltip__label">chipClass:</span>
|
|
5824
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.chipClass}</span>
|
|
5825
|
+
</div>
|
|
5826
|
+
<div class="debug-tooltip__row">
|
|
5827
|
+
<span class="debug-tooltip__label">chipLabel:</span>
|
|
5828
|
+
<span class="debug-tooltip__value">${debugInfo.chipLabel}</span>
|
|
5829
|
+
</div>
|
|
5830
|
+
</div>
|
|
5831
|
+
|
|
5832
|
+
<div class="debug-tooltip__section">
|
|
5833
|
+
<div class="debug-tooltip__section-title">\u{1F550} Timestamps de Conex\xE3o</div>
|
|
5834
|
+
<div class="debug-tooltip__row">
|
|
5835
|
+
<span class="debug-tooltip__label">lastConnectTime:</span>
|
|
5836
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.lastConnectTime}</span>
|
|
5837
|
+
</div>
|
|
5838
|
+
<div class="debug-tooltip__row">
|
|
5839
|
+
<span class="debug-tooltip__label">lastDisconnectTime:</span>
|
|
5840
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.lastDisconnectTime}</span>
|
|
5841
|
+
</div>
|
|
5842
|
+
<div class="debug-tooltip__row">
|
|
5843
|
+
<span class="debug-tooltip__label">delayTime:</span>
|
|
5844
|
+
<span class="debug-tooltip__value">${debugInfo.delayTimeConnectionInMins} mins</span>
|
|
5845
|
+
</div>
|
|
5846
|
+
</div>
|
|
5847
|
+
|
|
5848
|
+
<div class="debug-tooltip__section">
|
|
5849
|
+
<div class="debug-tooltip__section-title">\u{1F4CA} Valores</div>
|
|
5850
|
+
<div class="debug-tooltip__row">
|
|
5851
|
+
<span class="debug-tooltip__label">val (consumo):</span>
|
|
5852
|
+
<span class="debug-tooltip__value">${debugInfo.val ?? "N/A"}</span>
|
|
5853
|
+
</div>
|
|
5854
|
+
<div class="debug-tooltip__row">
|
|
5855
|
+
<span class="debug-tooltip__label">target (meta):</span>
|
|
5856
|
+
<span class="debug-tooltip__value">${debugInfo.consumptionTargetValue ?? "N/A"}</span>
|
|
5857
|
+
</div>
|
|
5858
|
+
<div class="debug-tooltip__row">
|
|
5859
|
+
<span class="debug-tooltip__label">deviceType:</span>
|
|
5860
|
+
<span class="debug-tooltip__value debug-tooltip__value--mono">${debugInfo.deviceType}</span>
|
|
5861
|
+
</div>
|
|
5862
|
+
</div>
|
|
5863
|
+
</div>
|
|
5864
|
+
`;
|
|
5865
|
+
tooltipContainer.appendChild(tooltip);
|
|
5866
|
+
element.style.position = "relative";
|
|
5867
|
+
element.style.cursor = "help";
|
|
5868
|
+
element.appendChild(tooltipContainer);
|
|
5869
|
+
element.classList.add("has-debug-tooltip");
|
|
5870
|
+
}
|
|
5871
|
+
function verifyOfflineStatus(entityObject, delayTimeInMins = 15, LogHelper2) {
|
|
5137
5872
|
const lastConnectionTime = new Date(entityObject.lastConnectTime || 0);
|
|
5138
5873
|
const lastDisconnectTime = new Date(entityObject.lastDisconnectTime || 0);
|
|
5139
5874
|
const now = /* @__PURE__ */ new Date();
|
|
5140
5875
|
const delayTimeInMs = delayTimeInMins * 60 * 1e3;
|
|
5141
5876
|
const timeSinceConnection = now.getTime() - lastConnectionTime.getTime();
|
|
5877
|
+
let isOffline = false;
|
|
5142
5878
|
if (lastDisconnectTime.getTime() > lastConnectionTime.getTime()) {
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5879
|
+
isOffline = true;
|
|
5880
|
+
LogHelper2.log(
|
|
5881
|
+
"[CardHeadOffice][ConnectionStatus Verify] Device is OFFLINE because lastDisconnectTime is more recent than lastConnectTime",
|
|
5882
|
+
entityObject.nameEl
|
|
5883
|
+
);
|
|
5884
|
+
} else if (timeSinceConnection > delayTimeInMs) {
|
|
5885
|
+
isOffline = true;
|
|
5886
|
+
LogHelper2.log(
|
|
5887
|
+
"[CardHeadOffice][ConnectionStatus Verify] Device is OFFLINE because lastConnectTime is older than configured delayTimeConnectionInMins:",
|
|
5888
|
+
delayTimeInMins,
|
|
5889
|
+
"for device",
|
|
5890
|
+
entityObject.nameEl
|
|
5891
|
+
);
|
|
5892
|
+
} else {
|
|
5893
|
+
isOffline = false;
|
|
5894
|
+
LogHelper2.log(
|
|
5895
|
+
"[CardHeadOffice][ConnectionStatus Verify] Device is ONLINE because lastConnectTime is within configured delayTimeConnectionInMins:",
|
|
5896
|
+
delayTimeInMins,
|
|
5897
|
+
"for device",
|
|
5898
|
+
entityObject.nameEl
|
|
5899
|
+
);
|
|
5147
5900
|
}
|
|
5148
|
-
return
|
|
5901
|
+
return isOffline;
|
|
5149
5902
|
}
|
|
5150
5903
|
function paint(root, state) {
|
|
5151
|
-
const { entityObject, i18n, delayTimeConnectionInMins, isSelected } = state;
|
|
5904
|
+
const { entityObject, i18n, delayTimeConnectionInMins, isSelected, LogHelper: LogHelper2, activeTooltipDebug } = state;
|
|
5905
|
+
let statusDecisionSource = "unknown";
|
|
5152
5906
|
if (entityObject.connectionStatus) {
|
|
5153
5907
|
if (entityObject.connectionStatus === "offline") {
|
|
5154
|
-
|
|
5908
|
+
LogHelper2.log(
|
|
5909
|
+
"[CardHeadOffice][ConnectionStatus Verify 01] Setting deviceStatus to OFFLINE based on connectionStatus"
|
|
5910
|
+
);
|
|
5911
|
+
entityObject.deviceStatus = DeviceStatusType.OFFLINE;
|
|
5912
|
+
statusDecisionSource = 'connectionStatus === "offline"';
|
|
5913
|
+
} else {
|
|
5914
|
+
LogHelper2.log(
|
|
5915
|
+
"[CardHeadOffice] Device is ONLINE or WAITING based on connectionStatus for device",
|
|
5916
|
+
entityObject.nameEl
|
|
5917
|
+
);
|
|
5918
|
+
statusDecisionSource = `connectionStatus === "${entityObject.connectionStatus}" (kept original deviceStatus)`;
|
|
5155
5919
|
}
|
|
5156
5920
|
} else {
|
|
5157
|
-
if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
|
|
5158
|
-
|
|
5921
|
+
if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins, LogHelper2) === false) {
|
|
5922
|
+
LogHelper2.log(
|
|
5923
|
+
"[CardHeadOffice][ConnectionStatus Verify 02] Setting deviceStatus to OFFLINE based on timestamp verification by verifyOfflineStatus METHOD with delayTimeConnectionInMins:",
|
|
5924
|
+
delayTimeConnectionInMins
|
|
5925
|
+
);
|
|
5926
|
+
entityObject.deviceStatus = DeviceStatusType.OFFLINE;
|
|
5927
|
+
statusDecisionSource = `verifyOfflineStatus() returned false (delay: ${delayTimeConnectionInMins} mins)`;
|
|
5928
|
+
} else {
|
|
5929
|
+
LogHelper2.log(
|
|
5930
|
+
`[CardHeadOffice][ConnectionStatus Verify 03] Device is ONLINE with deviceStatus = ${entityObject.deviceStatus} based on timestamp verification for device ${entityObject.nameEl}`
|
|
5931
|
+
);
|
|
5932
|
+
statusDecisionSource = `verifyOfflineStatus() returned true (delay: ${delayTimeConnectionInMins} mins)`;
|
|
5159
5933
|
}
|
|
5160
5934
|
}
|
|
5161
5935
|
const stateClass = getCardStateClass(entityObject.deviceStatus);
|
|
@@ -5164,6 +5938,10 @@
|
|
|
5164
5938
|
const chip = root.querySelector(".chip");
|
|
5165
5939
|
chip.className = `chip ${statusInfo.chipClass}`;
|
|
5166
5940
|
chip.innerHTML = statusInfo.label;
|
|
5941
|
+
if (activeTooltipDebug) {
|
|
5942
|
+
const debugInfo = buildDebugTooltipInfo(entityObject, statusInfo, stateClass, statusDecisionSource, delayTimeConnectionInMins);
|
|
5943
|
+
attachDebugTooltip(chip, debugInfo);
|
|
5944
|
+
}
|
|
5167
5945
|
const primaryValue = formatValueByDomain(entityObject.val, entityObject.domain);
|
|
5168
5946
|
const numSpan = root.querySelector(".myio-ho-card__value .num");
|
|
5169
5947
|
root.querySelector(".myio-ho-card__value .unit");
|
|
@@ -5376,6 +6154,7 @@
|
|
|
5376
6154
|
}
|
|
5377
6155
|
|
|
5378
6156
|
// src/thingsboard/main-dashboard-shopping/v-5.2.0/card/template-card-v5.js
|
|
6157
|
+
var LABEL_CHAR_LIMIT2 = 18;
|
|
5379
6158
|
function renderCardComponentV5({
|
|
5380
6159
|
entityObject,
|
|
5381
6160
|
handleActionDashboard,
|
|
@@ -5892,7 +6671,7 @@ ${rangeText}`;
|
|
|
5892
6671
|
|
|
5893
6672
|
<div class="device-title-row" style="flex-direction: column; min-height: 38px; text-align: center; width: 100%;">
|
|
5894
6673
|
<span class="device-title" title="${cardEntity.name}">
|
|
5895
|
-
${cardEntity.name.length >
|
|
6674
|
+
${cardEntity.name.length > LABEL_CHAR_LIMIT2 ? cardEntity.name.slice(0, LABEL_CHAR_LIMIT2) + "\u2026" : cardEntity.name}
|
|
5896
6675
|
</span>
|
|
5897
6676
|
${deviceIdentifier ? `
|
|
5898
6677
|
<span class="device-subtitle" title="${deviceIdentifier}">
|
|
@@ -15658,23 +16437,1019 @@ ${rangeText}`;
|
|
|
15658
16437
|
if (isNaN(level) || level < 0 || level > 100) {
|
|
15659
16438
|
errors.push("currentLevel must be a number between 0 and 100");
|
|
15660
16439
|
}
|
|
15661
|
-
}
|
|
15662
|
-
if (options.limit !== void 0) {
|
|
15663
|
-
const limit = Number(options.limit);
|
|
15664
|
-
if (isNaN(limit) || limit < 1 || limit > 1e4) {
|
|
15665
|
-
errors.push("limit must be a number between 1 and 10000");
|
|
16440
|
+
}
|
|
16441
|
+
if (options.limit !== void 0) {
|
|
16442
|
+
const limit = Number(options.limit);
|
|
16443
|
+
if (isNaN(limit) || limit < 1 || limit > 1e4) {
|
|
16444
|
+
errors.push("limit must be a number between 1 and 10000");
|
|
16445
|
+
}
|
|
16446
|
+
}
|
|
16447
|
+
if (options.aggregation !== void 0) {
|
|
16448
|
+
const validAggregations = ["NONE", "MIN", "MAX", "AVG", "SUM", "COUNT"];
|
|
16449
|
+
if (!validAggregations.includes(options.aggregation)) {
|
|
16450
|
+
errors.push(`aggregation must be one of: ${validAggregations.join(", ")}`);
|
|
16451
|
+
}
|
|
16452
|
+
}
|
|
16453
|
+
if (errors.length > 0) {
|
|
16454
|
+
throw new Error(`Validation failed:
|
|
16455
|
+
- ${errors.join("\n- ")}`);
|
|
16456
|
+
}
|
|
16457
|
+
}
|
|
16458
|
+
|
|
16459
|
+
// src/components/premium-modals/power-limits/types.ts
|
|
16460
|
+
var DEVICE_TYPES = [
|
|
16461
|
+
{ value: "ELEVADOR", label: "Elevator" },
|
|
16462
|
+
{ value: "ESCADA_ROLANTE", label: "Escalator" },
|
|
16463
|
+
{ value: "MOTOR", label: "Motor" },
|
|
16464
|
+
{ value: "BOMBA", label: "Pump" },
|
|
16465
|
+
{ value: "CHILLER", label: "Chiller" },
|
|
16466
|
+
{ value: "AR_CONDICIONADO", label: "Air Conditioner" },
|
|
16467
|
+
{ value: "HVAC", label: "HVAC" },
|
|
16468
|
+
{ value: "FANCOIL", label: "Fancoil" },
|
|
16469
|
+
{ value: "3F_MEDIDOR", label: "Three-phase Meter" }
|
|
16470
|
+
];
|
|
16471
|
+
var TELEMETRY_TYPES2 = [
|
|
16472
|
+
{ value: "consumption", label: "Consumption (kW)", unit: "kW" },
|
|
16473
|
+
{ value: "voltage_a", label: "Voltage A (V)", unit: "V" },
|
|
16474
|
+
{ value: "voltage_b", label: "Voltage B (V)", unit: "V" },
|
|
16475
|
+
{ value: "voltage_c", label: "Voltage C (V)", unit: "V" },
|
|
16476
|
+
{ value: "current_a", label: "Current A (A)", unit: "A" },
|
|
16477
|
+
{ value: "current_b", label: "Current B (A)", unit: "A" },
|
|
16478
|
+
{ value: "current_c", label: "Current C (A)", unit: "A" },
|
|
16479
|
+
{ value: "total_current", label: "Total Current (A)", unit: "A" },
|
|
16480
|
+
{ value: "fp_a", label: "Power Factor A", unit: "" },
|
|
16481
|
+
{ value: "fp_b", label: "Power Factor B", unit: "" },
|
|
16482
|
+
{ value: "fp_c", label: "Power Factor C", unit: "" }
|
|
16483
|
+
];
|
|
16484
|
+
var STATUS_CONFIG = {
|
|
16485
|
+
standBy: { label: "StandBy", color: "#22c55e", bgColor: "rgba(34, 197, 94, 0.1)" },
|
|
16486
|
+
normal: { label: "Normal", color: "#3b82f6", bgColor: "rgba(59, 130, 246, 0.1)" },
|
|
16487
|
+
alert: { label: "Alert", color: "#f59e0b", bgColor: "rgba(245, 158, 11, 0.1)" },
|
|
16488
|
+
failure: { label: "Failure", color: "#ef4444", bgColor: "rgba(239, 68, 68, 0.1)" }
|
|
16489
|
+
};
|
|
16490
|
+
|
|
16491
|
+
// src/components/premium-modals/power-limits/PowerLimitsModalView.ts
|
|
16492
|
+
var PowerLimitsModalView = class {
|
|
16493
|
+
container = null;
|
|
16494
|
+
overlayEl = null;
|
|
16495
|
+
config;
|
|
16496
|
+
formData;
|
|
16497
|
+
isLoading = false;
|
|
16498
|
+
isSaving = false;
|
|
16499
|
+
constructor(config) {
|
|
16500
|
+
this.config = config;
|
|
16501
|
+
this.formData = {
|
|
16502
|
+
deviceType: config.deviceType,
|
|
16503
|
+
telemetryType: config.telemetryType,
|
|
16504
|
+
standby: { baseValue: null, topValue: null },
|
|
16505
|
+
normal: { baseValue: null, topValue: null },
|
|
16506
|
+
alert: { baseValue: null, topValue: null },
|
|
16507
|
+
failure: { baseValue: null, topValue: null }
|
|
16508
|
+
};
|
|
16509
|
+
}
|
|
16510
|
+
render(targetContainer) {
|
|
16511
|
+
this.overlayEl = document.createElement("div");
|
|
16512
|
+
this.overlayEl.className = "myio-power-limits-overlay";
|
|
16513
|
+
this.overlayEl.innerHTML = `
|
|
16514
|
+
<style>${this.getStyles()}</style>
|
|
16515
|
+
<div class="myio-power-limits-card">
|
|
16516
|
+
${this.renderHeader()}
|
|
16517
|
+
${this.renderSelectors()}
|
|
16518
|
+
${this.renderStatusCards()}
|
|
16519
|
+
${this.renderLoadingState()}
|
|
16520
|
+
${this.renderErrorState()}
|
|
16521
|
+
${this.renderSuccessState()}
|
|
16522
|
+
</div>
|
|
16523
|
+
`;
|
|
16524
|
+
const target = targetContainer || document.body;
|
|
16525
|
+
target.appendChild(this.overlayEl);
|
|
16526
|
+
this.container = this.overlayEl.querySelector(".myio-power-limits-card");
|
|
16527
|
+
this.setupEventListeners();
|
|
16528
|
+
requestAnimationFrame(() => {
|
|
16529
|
+
this.overlayEl?.classList.add("active");
|
|
16530
|
+
});
|
|
16531
|
+
return this.overlayEl;
|
|
16532
|
+
}
|
|
16533
|
+
renderHeader() {
|
|
16534
|
+
return `
|
|
16535
|
+
<div class="myio-power-limits-header">
|
|
16536
|
+
<div class="myio-power-limits-title-section">
|
|
16537
|
+
<span class="myio-power-limits-icon">⚙</span>
|
|
16538
|
+
<h2 class="myio-power-limits-title">Power Limits Setup</h2>
|
|
16539
|
+
</div>
|
|
16540
|
+
<div class="myio-power-limits-actions">
|
|
16541
|
+
<button class="myio-btn myio-btn-primary" id="plm-save-btn" type="button">
|
|
16542
|
+
<span class="myio-btn-text">Save</span>
|
|
16543
|
+
<span class="myio-btn-spinner" style="display: none;"></span>
|
|
16544
|
+
</button>
|
|
16545
|
+
<button class="myio-btn myio-btn-secondary" id="plm-reset-btn" type="button">Reset</button>
|
|
16546
|
+
<button class="myio-btn myio-btn-close" id="plm-close-btn" type="button" aria-label="Close">×</button>
|
|
16547
|
+
</div>
|
|
16548
|
+
</div>
|
|
16549
|
+
`;
|
|
16550
|
+
}
|
|
16551
|
+
renderSelectors() {
|
|
16552
|
+
const deviceOptions = DEVICE_TYPES.map(
|
|
16553
|
+
(dt) => `<option value="${dt.value}" ${dt.value === this.config.deviceType ? "selected" : ""}>${dt.label}</option>`
|
|
16554
|
+
).join("");
|
|
16555
|
+
const telemetryOptions = TELEMETRY_TYPES2.map(
|
|
16556
|
+
(tt) => `<option value="${tt.value}" ${tt.value === this.config.telemetryType ? "selected" : ""}>${tt.label}</option>`
|
|
16557
|
+
).join("");
|
|
16558
|
+
return `
|
|
16559
|
+
<div class="myio-power-limits-selectors">
|
|
16560
|
+
<div class="myio-form-group">
|
|
16561
|
+
<label for="plm-device-type">Device Type</label>
|
|
16562
|
+
<select id="plm-device-type" class="myio-select">
|
|
16563
|
+
${deviceOptions}
|
|
16564
|
+
</select>
|
|
16565
|
+
</div>
|
|
16566
|
+
<div class="myio-form-group">
|
|
16567
|
+
<label for="plm-telemetry-type">Telemetry Type</label>
|
|
16568
|
+
<select id="plm-telemetry-type" class="myio-select">
|
|
16569
|
+
${telemetryOptions}
|
|
16570
|
+
</select>
|
|
16571
|
+
</div>
|
|
16572
|
+
</div>
|
|
16573
|
+
`;
|
|
16574
|
+
}
|
|
16575
|
+
renderStatusCards() {
|
|
16576
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
16577
|
+
const cards = statuses.map((status) => {
|
|
16578
|
+
const config = STATUS_CONFIG[status === "standby" ? "standBy" : status];
|
|
16579
|
+
const formValues = this.formData[status];
|
|
16580
|
+
return `
|
|
16581
|
+
<div class="myio-power-limits-card-item myio-status-${status}" style="--status-color: ${config.color}; --status-bg: ${config.bgColor};">
|
|
16582
|
+
<div class="myio-card-header">
|
|
16583
|
+
<span class="myio-status-indicator"></span>
|
|
16584
|
+
<span class="myio-status-label">${config.label}</span>
|
|
16585
|
+
</div>
|
|
16586
|
+
<div class="myio-card-inputs">
|
|
16587
|
+
<div class="myio-input-group">
|
|
16588
|
+
<label for="plm-${status}-base">Base Value</label>
|
|
16589
|
+
<input
|
|
16590
|
+
type="number"
|
|
16591
|
+
id="plm-${status}-base"
|
|
16592
|
+
class="myio-input"
|
|
16593
|
+
min="0"
|
|
16594
|
+
step="0.01"
|
|
16595
|
+
value="${formValues.baseValue ?? ""}"
|
|
16596
|
+
placeholder="0"
|
|
16597
|
+
>
|
|
16598
|
+
</div>
|
|
16599
|
+
<div class="myio-input-group">
|
|
16600
|
+
<label for="plm-${status}-top">Top Value</label>
|
|
16601
|
+
<input
|
|
16602
|
+
type="number"
|
|
16603
|
+
id="plm-${status}-top"
|
|
16604
|
+
class="myio-input"
|
|
16605
|
+
min="0"
|
|
16606
|
+
step="0.01"
|
|
16607
|
+
value="${formValues.topValue ?? ""}"
|
|
16608
|
+
placeholder="0"
|
|
16609
|
+
>
|
|
16610
|
+
</div>
|
|
16611
|
+
</div>
|
|
16612
|
+
</div>
|
|
16613
|
+
`;
|
|
16614
|
+
}).join("");
|
|
16615
|
+
return `
|
|
16616
|
+
<div class="myio-power-limits-grid" id="plm-grid">
|
|
16617
|
+
${cards}
|
|
16618
|
+
</div>
|
|
16619
|
+
`;
|
|
16620
|
+
}
|
|
16621
|
+
renderLoadingState() {
|
|
16622
|
+
return `
|
|
16623
|
+
<div class="myio-power-limits-loading" id="plm-loading" style="display: none;">
|
|
16624
|
+
<div class="myio-spinner"></div>
|
|
16625
|
+
<span>Loading configuration...</span>
|
|
16626
|
+
</div>
|
|
16627
|
+
`;
|
|
16628
|
+
}
|
|
16629
|
+
renderErrorState() {
|
|
16630
|
+
return `
|
|
16631
|
+
<div class="myio-power-limits-error" id="plm-error" style="display: none;">
|
|
16632
|
+
<span class="myio-error-icon">⚠</span>
|
|
16633
|
+
<span class="myio-error-message" id="plm-error-msg"></span>
|
|
16634
|
+
</div>
|
|
16635
|
+
`;
|
|
16636
|
+
}
|
|
16637
|
+
renderSuccessState() {
|
|
16638
|
+
return `
|
|
16639
|
+
<div class="myio-power-limits-success" id="plm-success" style="display: none;">
|
|
16640
|
+
<span class="myio-success-icon">✓</span>
|
|
16641
|
+
<span class="myio-success-message">Configuration saved successfully!</span>
|
|
16642
|
+
</div>
|
|
16643
|
+
`;
|
|
16644
|
+
}
|
|
16645
|
+
setupEventListeners() {
|
|
16646
|
+
if (!this.overlayEl) return;
|
|
16647
|
+
const closeBtn = this.overlayEl.querySelector("#plm-close-btn");
|
|
16648
|
+
closeBtn?.addEventListener("click", () => this.close());
|
|
16649
|
+
this.overlayEl.addEventListener("click", (e) => {
|
|
16650
|
+
if (e.target === this.overlayEl) {
|
|
16651
|
+
this.close();
|
|
16652
|
+
}
|
|
16653
|
+
});
|
|
16654
|
+
document.addEventListener("keydown", this.handleKeyDown);
|
|
16655
|
+
const saveBtn = this.overlayEl.querySelector("#plm-save-btn");
|
|
16656
|
+
saveBtn?.addEventListener("click", () => this.handleSave());
|
|
16657
|
+
const resetBtn = this.overlayEl.querySelector("#plm-reset-btn");
|
|
16658
|
+
resetBtn?.addEventListener("click", () => this.handleReset());
|
|
16659
|
+
const deviceSelect = this.overlayEl.querySelector("#plm-device-type");
|
|
16660
|
+
deviceSelect?.addEventListener("change", (e) => {
|
|
16661
|
+
const value = e.target.value;
|
|
16662
|
+
this.formData.deviceType = value;
|
|
16663
|
+
this.config.onDeviceTypeChange(value);
|
|
16664
|
+
});
|
|
16665
|
+
const telemetrySelect = this.overlayEl.querySelector("#plm-telemetry-type");
|
|
16666
|
+
telemetrySelect?.addEventListener("change", (e) => {
|
|
16667
|
+
const value = e.target.value;
|
|
16668
|
+
this.formData.telemetryType = value;
|
|
16669
|
+
this.config.onTelemetryTypeChange(value);
|
|
16670
|
+
});
|
|
16671
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
16672
|
+
statuses.forEach((status) => {
|
|
16673
|
+
const baseInput = this.overlayEl?.querySelector(`#plm-${status}-base`);
|
|
16674
|
+
const topInput = this.overlayEl?.querySelector(`#plm-${status}-top`);
|
|
16675
|
+
baseInput?.addEventListener("input", (e) => {
|
|
16676
|
+
const value = e.target.value;
|
|
16677
|
+
this.formData[status].baseValue = value ? parseFloat(value) : null;
|
|
16678
|
+
});
|
|
16679
|
+
topInput?.addEventListener("input", (e) => {
|
|
16680
|
+
const value = e.target.value;
|
|
16681
|
+
this.formData[status].topValue = value ? parseFloat(value) : null;
|
|
16682
|
+
});
|
|
16683
|
+
});
|
|
16684
|
+
}
|
|
16685
|
+
handleKeyDown = (e) => {
|
|
16686
|
+
if (e.key === "Escape") {
|
|
16687
|
+
this.close();
|
|
16688
|
+
}
|
|
16689
|
+
};
|
|
16690
|
+
async handleSave() {
|
|
16691
|
+
if (this.isSaving) return;
|
|
16692
|
+
const validationError = this.validateForm();
|
|
16693
|
+
if (validationError) {
|
|
16694
|
+
this.showError(validationError);
|
|
16695
|
+
return;
|
|
16696
|
+
}
|
|
16697
|
+
this.isSaving = true;
|
|
16698
|
+
this.showSaveLoading(true);
|
|
16699
|
+
this.hideError();
|
|
16700
|
+
this.hideSuccess();
|
|
16701
|
+
try {
|
|
16702
|
+
await this.config.onSave();
|
|
16703
|
+
this.showSuccess();
|
|
16704
|
+
setTimeout(() => this.hideSuccess(), 3e3);
|
|
16705
|
+
} catch (error) {
|
|
16706
|
+
this.showError(error.message || "Failed to save configuration");
|
|
16707
|
+
} finally {
|
|
16708
|
+
this.isSaving = false;
|
|
16709
|
+
this.showSaveLoading(false);
|
|
16710
|
+
}
|
|
16711
|
+
}
|
|
16712
|
+
handleReset() {
|
|
16713
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
16714
|
+
statuses.forEach((status) => {
|
|
16715
|
+
const baseInput = this.overlayEl?.querySelector(`#plm-${status}-base`);
|
|
16716
|
+
const topInput = this.overlayEl?.querySelector(`#plm-${status}-top`);
|
|
16717
|
+
if (baseInput) baseInput.value = "";
|
|
16718
|
+
if (topInput) topInput.value = "";
|
|
16719
|
+
this.formData[status] = { baseValue: null, topValue: null };
|
|
16720
|
+
});
|
|
16721
|
+
this.hideError();
|
|
16722
|
+
this.hideSuccess();
|
|
16723
|
+
}
|
|
16724
|
+
validateForm() {
|
|
16725
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
16726
|
+
for (const status of statuses) {
|
|
16727
|
+
const base = this.formData[status].baseValue;
|
|
16728
|
+
const top = this.formData[status].topValue;
|
|
16729
|
+
if (base !== null && base < 0) {
|
|
16730
|
+
return `${STATUS_CONFIG[status === "standby" ? "standBy" : status].label}: Base value cannot be negative`;
|
|
16731
|
+
}
|
|
16732
|
+
if (top !== null && top < 0) {
|
|
16733
|
+
return `${STATUS_CONFIG[status === "standby" ? "standBy" : status].label}: Top value cannot be negative`;
|
|
16734
|
+
}
|
|
16735
|
+
if (base !== null && top !== null && base > top) {
|
|
16736
|
+
return `${STATUS_CONFIG[status === "standby" ? "standBy" : status].label}: Base value should not exceed top value`;
|
|
16737
|
+
}
|
|
16738
|
+
}
|
|
16739
|
+
return null;
|
|
16740
|
+
}
|
|
16741
|
+
close() {
|
|
16742
|
+
document.removeEventListener("keydown", this.handleKeyDown);
|
|
16743
|
+
if (this.overlayEl) {
|
|
16744
|
+
this.overlayEl.classList.remove("active");
|
|
16745
|
+
setTimeout(() => {
|
|
16746
|
+
this.overlayEl?.remove();
|
|
16747
|
+
this.overlayEl = null;
|
|
16748
|
+
this.container = null;
|
|
16749
|
+
this.config.onClose();
|
|
16750
|
+
}, 300);
|
|
16751
|
+
}
|
|
16752
|
+
}
|
|
16753
|
+
destroy() {
|
|
16754
|
+
document.removeEventListener("keydown", this.handleKeyDown);
|
|
16755
|
+
this.overlayEl?.remove();
|
|
16756
|
+
this.overlayEl = null;
|
|
16757
|
+
this.container = null;
|
|
16758
|
+
}
|
|
16759
|
+
showLoading() {
|
|
16760
|
+
this.isLoading = true;
|
|
16761
|
+
const loadingEl = this.overlayEl?.querySelector("#plm-loading");
|
|
16762
|
+
const gridEl = this.overlayEl?.querySelector("#plm-grid");
|
|
16763
|
+
if (loadingEl) loadingEl.style.display = "flex";
|
|
16764
|
+
if (gridEl) gridEl.style.opacity = "0.5";
|
|
16765
|
+
}
|
|
16766
|
+
hideLoading() {
|
|
16767
|
+
this.isLoading = false;
|
|
16768
|
+
const loadingEl = this.overlayEl?.querySelector("#plm-loading");
|
|
16769
|
+
const gridEl = this.overlayEl?.querySelector("#plm-grid");
|
|
16770
|
+
if (loadingEl) loadingEl.style.display = "none";
|
|
16771
|
+
if (gridEl) gridEl.style.opacity = "1";
|
|
16772
|
+
}
|
|
16773
|
+
showSaveLoading(show) {
|
|
16774
|
+
const saveBtn = this.overlayEl?.querySelector("#plm-save-btn");
|
|
16775
|
+
const btnText = saveBtn?.querySelector(".myio-btn-text");
|
|
16776
|
+
const btnSpinner = saveBtn?.querySelector(".myio-btn-spinner");
|
|
16777
|
+
if (saveBtn) saveBtn.disabled = show;
|
|
16778
|
+
if (btnText) btnText.style.display = show ? "none" : "inline";
|
|
16779
|
+
if (btnSpinner) btnSpinner.style.display = show ? "inline-block" : "none";
|
|
16780
|
+
}
|
|
16781
|
+
showError(message) {
|
|
16782
|
+
const errorEl = this.overlayEl?.querySelector("#plm-error");
|
|
16783
|
+
const errorMsg = this.overlayEl?.querySelector("#plm-error-msg");
|
|
16784
|
+
if (errorEl) errorEl.style.display = "flex";
|
|
16785
|
+
if (errorMsg) errorMsg.textContent = message;
|
|
16786
|
+
}
|
|
16787
|
+
hideError() {
|
|
16788
|
+
const errorEl = this.overlayEl?.querySelector("#plm-error");
|
|
16789
|
+
if (errorEl) errorEl.style.display = "none";
|
|
16790
|
+
}
|
|
16791
|
+
showSuccess() {
|
|
16792
|
+
const successEl = this.overlayEl?.querySelector("#plm-success");
|
|
16793
|
+
if (successEl) successEl.style.display = "flex";
|
|
16794
|
+
}
|
|
16795
|
+
hideSuccess() {
|
|
16796
|
+
const successEl = this.overlayEl?.querySelector("#plm-success");
|
|
16797
|
+
if (successEl) successEl.style.display = "none";
|
|
16798
|
+
}
|
|
16799
|
+
getFormData() {
|
|
16800
|
+
return { ...this.formData };
|
|
16801
|
+
}
|
|
16802
|
+
setFormData(data) {
|
|
16803
|
+
if (data.deviceType) this.formData.deviceType = data.deviceType;
|
|
16804
|
+
if (data.telemetryType) this.formData.telemetryType = data.telemetryType;
|
|
16805
|
+
if (data.standby) this.formData.standby = { ...data.standby };
|
|
16806
|
+
if (data.normal) this.formData.normal = { ...data.normal };
|
|
16807
|
+
if (data.alert) this.formData.alert = { ...data.alert };
|
|
16808
|
+
if (data.failure) this.formData.failure = { ...data.failure };
|
|
16809
|
+
this.updateInputValues();
|
|
16810
|
+
}
|
|
16811
|
+
updateInputValues() {
|
|
16812
|
+
const statuses = ["standby", "normal", "alert", "failure"];
|
|
16813
|
+
statuses.forEach((status) => {
|
|
16814
|
+
const baseInput = this.overlayEl?.querySelector(`#plm-${status}-base`);
|
|
16815
|
+
const topInput = this.overlayEl?.querySelector(`#plm-${status}-top`);
|
|
16816
|
+
if (baseInput) {
|
|
16817
|
+
baseInput.value = this.formData[status].baseValue?.toString() ?? "";
|
|
16818
|
+
}
|
|
16819
|
+
if (topInput) {
|
|
16820
|
+
topInput.value = this.formData[status].topValue?.toString() ?? "";
|
|
16821
|
+
}
|
|
16822
|
+
});
|
|
16823
|
+
const deviceSelect = this.overlayEl?.querySelector("#plm-device-type");
|
|
16824
|
+
const telemetrySelect = this.overlayEl?.querySelector("#plm-telemetry-type");
|
|
16825
|
+
if (deviceSelect) deviceSelect.value = this.formData.deviceType;
|
|
16826
|
+
if (telemetrySelect) telemetrySelect.value = this.formData.telemetryType;
|
|
16827
|
+
}
|
|
16828
|
+
getStyles() {
|
|
16829
|
+
const styles = this.config.styles || {};
|
|
16830
|
+
const primaryColor = styles.primaryColor || "#4A148C";
|
|
16831
|
+
const successColor = styles.successColor || "#22c55e";
|
|
16832
|
+
styles.warningColor || "#f59e0b";
|
|
16833
|
+
const dangerColor = styles.dangerColor || "#ef4444";
|
|
16834
|
+
styles.infoColor || "#3b82f6";
|
|
16835
|
+
return `
|
|
16836
|
+
.myio-power-limits-overlay {
|
|
16837
|
+
position: fixed;
|
|
16838
|
+
top: 0;
|
|
16839
|
+
left: 0;
|
|
16840
|
+
right: 0;
|
|
16841
|
+
bottom: 0;
|
|
16842
|
+
background: rgba(0, 0, 0, 0.6);
|
|
16843
|
+
display: flex;
|
|
16844
|
+
align-items: center;
|
|
16845
|
+
justify-content: center;
|
|
16846
|
+
z-index: ${styles.zIndex || 1e4};
|
|
16847
|
+
opacity: 0;
|
|
16848
|
+
visibility: hidden;
|
|
16849
|
+
transition: all 0.3s ease;
|
|
16850
|
+
font-family: ${styles.fontFamily || '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'};
|
|
16851
|
+
}
|
|
16852
|
+
|
|
16853
|
+
.myio-power-limits-overlay.active {
|
|
16854
|
+
opacity: 1;
|
|
16855
|
+
visibility: visible;
|
|
16856
|
+
}
|
|
16857
|
+
|
|
16858
|
+
.myio-power-limits-card {
|
|
16859
|
+
background: ${styles.backgroundColor || "#ffffff"};
|
|
16860
|
+
border-radius: ${styles.borderRadius || "12px"};
|
|
16861
|
+
width: 90%;
|
|
16862
|
+
max-width: 700px;
|
|
16863
|
+
max-height: 90vh;
|
|
16864
|
+
overflow-y: auto;
|
|
16865
|
+
transform: scale(0.9);
|
|
16866
|
+
transition: transform 0.3s ease;
|
|
16867
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
|
|
16868
|
+
}
|
|
16869
|
+
|
|
16870
|
+
.myio-power-limits-overlay.active .myio-power-limits-card {
|
|
16871
|
+
transform: scale(1);
|
|
16872
|
+
}
|
|
16873
|
+
|
|
16874
|
+
.myio-power-limits-header {
|
|
16875
|
+
display: flex;
|
|
16876
|
+
align-items: center;
|
|
16877
|
+
justify-content: space-between;
|
|
16878
|
+
padding: 20px 24px;
|
|
16879
|
+
background: linear-gradient(135deg, ${primaryColor}, ${this.lightenColor(primaryColor, 20)});
|
|
16880
|
+
color: white;
|
|
16881
|
+
border-radius: 12px 12px 0 0;
|
|
16882
|
+
}
|
|
16883
|
+
|
|
16884
|
+
.myio-power-limits-title-section {
|
|
16885
|
+
display: flex;
|
|
16886
|
+
align-items: center;
|
|
16887
|
+
gap: 12px;
|
|
16888
|
+
}
|
|
16889
|
+
|
|
16890
|
+
.myio-power-limits-icon {
|
|
16891
|
+
font-size: 24px;
|
|
16892
|
+
}
|
|
16893
|
+
|
|
16894
|
+
.myio-power-limits-title {
|
|
16895
|
+
font-size: 1.25rem;
|
|
16896
|
+
font-weight: 600;
|
|
16897
|
+
margin: 0;
|
|
16898
|
+
}
|
|
16899
|
+
|
|
16900
|
+
.myio-power-limits-actions {
|
|
16901
|
+
display: flex;
|
|
16902
|
+
align-items: center;
|
|
16903
|
+
gap: 8px;
|
|
16904
|
+
}
|
|
16905
|
+
|
|
16906
|
+
.myio-btn {
|
|
16907
|
+
padding: 8px 16px;
|
|
16908
|
+
border-radius: ${styles.buttonRadius || "6px"};
|
|
16909
|
+
font-size: 14px;
|
|
16910
|
+
font-weight: 500;
|
|
16911
|
+
cursor: pointer;
|
|
16912
|
+
border: none;
|
|
16913
|
+
transition: all 0.2s;
|
|
16914
|
+
display: inline-flex;
|
|
16915
|
+
align-items: center;
|
|
16916
|
+
gap: 6px;
|
|
16917
|
+
}
|
|
16918
|
+
|
|
16919
|
+
.myio-btn:disabled {
|
|
16920
|
+
opacity: 0.6;
|
|
16921
|
+
cursor: not-allowed;
|
|
16922
|
+
}
|
|
16923
|
+
|
|
16924
|
+
.myio-btn-primary {
|
|
16925
|
+
background: white;
|
|
16926
|
+
color: ${primaryColor};
|
|
16927
|
+
}
|
|
16928
|
+
|
|
16929
|
+
.myio-btn-primary:hover:not(:disabled) {
|
|
16930
|
+
background: #f3f4f6;
|
|
16931
|
+
}
|
|
16932
|
+
|
|
16933
|
+
.myio-btn-secondary {
|
|
16934
|
+
background: rgba(255, 255, 255, 0.2);
|
|
16935
|
+
color: white;
|
|
16936
|
+
}
|
|
16937
|
+
|
|
16938
|
+
.myio-btn-secondary:hover:not(:disabled) {
|
|
16939
|
+
background: rgba(255, 255, 255, 0.3);
|
|
16940
|
+
}
|
|
16941
|
+
|
|
16942
|
+
.myio-btn-close {
|
|
16943
|
+
background: transparent;
|
|
16944
|
+
color: white;
|
|
16945
|
+
font-size: 24px;
|
|
16946
|
+
padding: 4px 8px;
|
|
16947
|
+
line-height: 1;
|
|
16948
|
+
}
|
|
16949
|
+
|
|
16950
|
+
.myio-btn-close:hover {
|
|
16951
|
+
background: rgba(255, 255, 255, 0.1);
|
|
16952
|
+
}
|
|
16953
|
+
|
|
16954
|
+
.myio-btn-spinner {
|
|
16955
|
+
width: 16px;
|
|
16956
|
+
height: 16px;
|
|
16957
|
+
border: 2px solid ${primaryColor};
|
|
16958
|
+
border-top-color: transparent;
|
|
16959
|
+
border-radius: 50%;
|
|
16960
|
+
animation: spin 0.8s linear infinite;
|
|
16961
|
+
}
|
|
16962
|
+
|
|
16963
|
+
@keyframes spin {
|
|
16964
|
+
to { transform: rotate(360deg); }
|
|
16965
|
+
}
|
|
16966
|
+
|
|
16967
|
+
.myio-power-limits-selectors {
|
|
16968
|
+
display: grid;
|
|
16969
|
+
grid-template-columns: 1fr 1fr;
|
|
16970
|
+
gap: 16px;
|
|
16971
|
+
padding: 20px 24px;
|
|
16972
|
+
background: #f9fafb;
|
|
16973
|
+
border-bottom: 1px solid #e5e7eb;
|
|
16974
|
+
}
|
|
16975
|
+
|
|
16976
|
+
.myio-form-group {
|
|
16977
|
+
display: flex;
|
|
16978
|
+
flex-direction: column;
|
|
16979
|
+
gap: 6px;
|
|
16980
|
+
}
|
|
16981
|
+
|
|
16982
|
+
.myio-form-group label {
|
|
16983
|
+
font-size: 13px;
|
|
16984
|
+
font-weight: 500;
|
|
16985
|
+
color: #374151;
|
|
16986
|
+
}
|
|
16987
|
+
|
|
16988
|
+
.myio-select, .myio-input {
|
|
16989
|
+
padding: 10px 12px;
|
|
16990
|
+
border: 1px solid #d1d5db;
|
|
16991
|
+
border-radius: 6px;
|
|
16992
|
+
font-size: 14px;
|
|
16993
|
+
background: white;
|
|
16994
|
+
color: #1f2937;
|
|
16995
|
+
transition: border-color 0.2s, box-shadow 0.2s;
|
|
16996
|
+
}
|
|
16997
|
+
|
|
16998
|
+
.myio-select:focus, .myio-input:focus {
|
|
16999
|
+
outline: none;
|
|
17000
|
+
border-color: ${primaryColor};
|
|
17001
|
+
box-shadow: 0 0 0 3px ${this.hexToRgba(primaryColor, 0.1)};
|
|
17002
|
+
}
|
|
17003
|
+
|
|
17004
|
+
.myio-power-limits-grid {
|
|
17005
|
+
display: grid;
|
|
17006
|
+
grid-template-columns: repeat(2, 1fr);
|
|
17007
|
+
gap: 16px;
|
|
17008
|
+
padding: 24px;
|
|
17009
|
+
transition: opacity 0.3s;
|
|
17010
|
+
}
|
|
17011
|
+
|
|
17012
|
+
.myio-power-limits-card-item {
|
|
17013
|
+
background: var(--status-bg);
|
|
17014
|
+
border: 1px solid var(--status-color);
|
|
17015
|
+
border-radius: 8px;
|
|
17016
|
+
padding: 16px;
|
|
17017
|
+
transition: transform 0.2s, box-shadow 0.2s;
|
|
17018
|
+
}
|
|
17019
|
+
|
|
17020
|
+
.myio-power-limits-card-item:hover {
|
|
17021
|
+
transform: translateY(-2px);
|
|
17022
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
17023
|
+
}
|
|
17024
|
+
|
|
17025
|
+
.myio-card-header {
|
|
17026
|
+
display: flex;
|
|
17027
|
+
align-items: center;
|
|
17028
|
+
gap: 8px;
|
|
17029
|
+
margin-bottom: 12px;
|
|
17030
|
+
}
|
|
17031
|
+
|
|
17032
|
+
.myio-status-indicator {
|
|
17033
|
+
width: 12px;
|
|
17034
|
+
height: 12px;
|
|
17035
|
+
border-radius: 50%;
|
|
17036
|
+
background: var(--status-color);
|
|
17037
|
+
}
|
|
17038
|
+
|
|
17039
|
+
.myio-status-label {
|
|
17040
|
+
font-weight: 600;
|
|
17041
|
+
font-size: 14px;
|
|
17042
|
+
color: #1f2937;
|
|
17043
|
+
}
|
|
17044
|
+
|
|
17045
|
+
.myio-card-inputs {
|
|
17046
|
+
display: grid;
|
|
17047
|
+
grid-template-columns: 1fr 1fr;
|
|
17048
|
+
gap: 12px;
|
|
17049
|
+
}
|
|
17050
|
+
|
|
17051
|
+
.myio-input-group {
|
|
17052
|
+
display: flex;
|
|
17053
|
+
flex-direction: column;
|
|
17054
|
+
gap: 4px;
|
|
17055
|
+
}
|
|
17056
|
+
|
|
17057
|
+
.myio-input-group label {
|
|
17058
|
+
font-size: 11px;
|
|
17059
|
+
font-weight: 500;
|
|
17060
|
+
color: #6b7280;
|
|
17061
|
+
text-transform: uppercase;
|
|
17062
|
+
}
|
|
17063
|
+
|
|
17064
|
+
.myio-power-limits-loading,
|
|
17065
|
+
.myio-power-limits-error,
|
|
17066
|
+
.myio-power-limits-success {
|
|
17067
|
+
display: flex;
|
|
17068
|
+
align-items: center;
|
|
17069
|
+
justify-content: center;
|
|
17070
|
+
gap: 12px;
|
|
17071
|
+
padding: 16px 24px;
|
|
17072
|
+
margin: 0 24px 24px;
|
|
17073
|
+
border-radius: 8px;
|
|
17074
|
+
}
|
|
17075
|
+
|
|
17076
|
+
.myio-power-limits-loading {
|
|
17077
|
+
background: #f3f4f6;
|
|
17078
|
+
color: #6b7280;
|
|
17079
|
+
}
|
|
17080
|
+
|
|
17081
|
+
.myio-power-limits-error {
|
|
17082
|
+
background: #fef2f2;
|
|
17083
|
+
color: ${dangerColor};
|
|
17084
|
+
border: 1px solid ${dangerColor};
|
|
17085
|
+
}
|
|
17086
|
+
|
|
17087
|
+
.myio-power-limits-success {
|
|
17088
|
+
background: #f0fdf4;
|
|
17089
|
+
color: ${successColor};
|
|
17090
|
+
border: 1px solid ${successColor};
|
|
17091
|
+
}
|
|
17092
|
+
|
|
17093
|
+
.myio-spinner {
|
|
17094
|
+
width: 24px;
|
|
17095
|
+
height: 24px;
|
|
17096
|
+
border: 3px solid #e5e7eb;
|
|
17097
|
+
border-top-color: ${primaryColor};
|
|
17098
|
+
border-radius: 50%;
|
|
17099
|
+
animation: spin 0.8s linear infinite;
|
|
17100
|
+
}
|
|
17101
|
+
|
|
17102
|
+
.myio-error-icon, .myio-success-icon {
|
|
17103
|
+
font-size: 20px;
|
|
17104
|
+
}
|
|
17105
|
+
|
|
17106
|
+
@media (max-width: 600px) {
|
|
17107
|
+
.myio-power-limits-selectors,
|
|
17108
|
+
.myio-power-limits-grid {
|
|
17109
|
+
grid-template-columns: 1fr;
|
|
17110
|
+
}
|
|
17111
|
+
|
|
17112
|
+
.myio-power-limits-header {
|
|
17113
|
+
flex-direction: column;
|
|
17114
|
+
gap: 12px;
|
|
17115
|
+
text-align: center;
|
|
17116
|
+
}
|
|
17117
|
+
|
|
17118
|
+
.myio-power-limits-actions {
|
|
17119
|
+
width: 100%;
|
|
17120
|
+
justify-content: center;
|
|
17121
|
+
}
|
|
17122
|
+
}
|
|
17123
|
+
`;
|
|
17124
|
+
}
|
|
17125
|
+
lightenColor(hex, percent) {
|
|
17126
|
+
const num = parseInt(hex.replace("#", ""), 16);
|
|
17127
|
+
const amt = Math.round(2.55 * percent);
|
|
17128
|
+
const R = (num >> 16) + amt;
|
|
17129
|
+
const G = (num >> 8 & 255) + amt;
|
|
17130
|
+
const B = (num & 255) + amt;
|
|
17131
|
+
return "#" + (16777216 + (R < 255 ? R < 1 ? 0 : R : 255) * 65536 + (G < 255 ? G < 1 ? 0 : G : 255) * 256 + (B < 255 ? B < 1 ? 0 : B : 255)).toString(16).slice(1);
|
|
17132
|
+
}
|
|
17133
|
+
hexToRgba(hex, alpha) {
|
|
17134
|
+
const num = parseInt(hex.replace("#", ""), 16);
|
|
17135
|
+
const R = num >> 16;
|
|
17136
|
+
const G = num >> 8 & 255;
|
|
17137
|
+
const B = num & 255;
|
|
17138
|
+
return `rgba(${R}, ${G}, ${B}, ${alpha})`;
|
|
17139
|
+
}
|
|
17140
|
+
};
|
|
17141
|
+
|
|
17142
|
+
// src/components/premium-modals/power-limits/PowerLimitsPersister.ts
|
|
17143
|
+
var PowerLimitsPersister = class {
|
|
17144
|
+
jwtToken;
|
|
17145
|
+
tbBaseUrl;
|
|
17146
|
+
constructor(jwtToken, tbBaseUrl) {
|
|
17147
|
+
this.jwtToken = jwtToken;
|
|
17148
|
+
this.tbBaseUrl = tbBaseUrl || window.location.origin;
|
|
17149
|
+
}
|
|
17150
|
+
/**
|
|
17151
|
+
* Load existing mapInstantaneousPower from customer server_scope attributes
|
|
17152
|
+
*/
|
|
17153
|
+
async loadCustomerPowerLimits(customerId) {
|
|
17154
|
+
try {
|
|
17155
|
+
const url = `${this.tbBaseUrl}/api/plugins/telemetry/CUSTOMER/${customerId}/values/attributes/SERVER_SCOPE?keys=mapInstantaneousPower`;
|
|
17156
|
+
const response = await fetch(url, {
|
|
17157
|
+
method: "GET",
|
|
17158
|
+
headers: {
|
|
17159
|
+
"X-Authorization": `Bearer ${this.jwtToken}`,
|
|
17160
|
+
"Content-Type": "application/json"
|
|
17161
|
+
}
|
|
17162
|
+
});
|
|
17163
|
+
if (!response.ok) {
|
|
17164
|
+
if (response.status === 404) {
|
|
17165
|
+
console.log("[PowerLimitsPersister] No existing mapInstantaneousPower found");
|
|
17166
|
+
return null;
|
|
17167
|
+
}
|
|
17168
|
+
throw this.createHttpError(response.status, await response.text().catch(() => ""));
|
|
17169
|
+
}
|
|
17170
|
+
const data = await response.json();
|
|
17171
|
+
if (!data || data.length === 0) {
|
|
17172
|
+
console.log("[PowerLimitsPersister] No mapInstantaneousPower attribute found");
|
|
17173
|
+
return null;
|
|
17174
|
+
}
|
|
17175
|
+
const attr = data.find((item) => item.key === "mapInstantaneousPower");
|
|
17176
|
+
if (!attr || !attr.value) {
|
|
17177
|
+
return null;
|
|
17178
|
+
}
|
|
17179
|
+
const parsedValue = typeof attr.value === "string" ? JSON.parse(attr.value) : attr.value;
|
|
17180
|
+
console.log("[PowerLimitsPersister] Loaded mapInstantaneousPower:", parsedValue);
|
|
17181
|
+
return parsedValue;
|
|
17182
|
+
} catch (error) {
|
|
17183
|
+
console.error("[PowerLimitsPersister] Error loading power limits:", error);
|
|
17184
|
+
throw this.mapError(error);
|
|
17185
|
+
}
|
|
17186
|
+
}
|
|
17187
|
+
/**
|
|
17188
|
+
* Save mapInstantaneousPower to customer server_scope attributes
|
|
17189
|
+
*/
|
|
17190
|
+
async saveCustomerPowerLimits(customerId, limits) {
|
|
17191
|
+
try {
|
|
17192
|
+
const url = `${this.tbBaseUrl}/api/plugins/telemetry/CUSTOMER/${customerId}/attributes/SERVER_SCOPE`;
|
|
17193
|
+
const payload = {
|
|
17194
|
+
mapInstantaneousPower: limits
|
|
17195
|
+
};
|
|
17196
|
+
console.log("[PowerLimitsPersister] Saving power limits:", payload);
|
|
17197
|
+
const response = await fetch(url, {
|
|
17198
|
+
method: "POST",
|
|
17199
|
+
headers: {
|
|
17200
|
+
"X-Authorization": `Bearer ${this.jwtToken}`,
|
|
17201
|
+
"Content-Type": "application/json"
|
|
17202
|
+
},
|
|
17203
|
+
body: JSON.stringify(payload)
|
|
17204
|
+
});
|
|
17205
|
+
if (!response.ok) {
|
|
17206
|
+
throw this.createHttpError(response.status, await response.text().catch(() => ""));
|
|
17207
|
+
}
|
|
17208
|
+
console.log("[PowerLimitsPersister] Successfully saved power limits");
|
|
17209
|
+
return { ok: true };
|
|
17210
|
+
} catch (error) {
|
|
17211
|
+
console.error("[PowerLimitsPersister] Error saving power limits:", error);
|
|
17212
|
+
return { ok: false, error: this.mapError(error) };
|
|
17213
|
+
}
|
|
17214
|
+
}
|
|
17215
|
+
/**
|
|
17216
|
+
* Extract form data for a specific device type and telemetry type
|
|
17217
|
+
*/
|
|
17218
|
+
extractFormData(limits, deviceType, telemetryType) {
|
|
17219
|
+
const defaultFormData = {
|
|
17220
|
+
deviceType,
|
|
17221
|
+
telemetryType,
|
|
17222
|
+
standby: { baseValue: null, topValue: null },
|
|
17223
|
+
normal: { baseValue: null, topValue: null },
|
|
17224
|
+
alert: { baseValue: null, topValue: null },
|
|
17225
|
+
failure: { baseValue: null, topValue: null }
|
|
17226
|
+
};
|
|
17227
|
+
if (!limits || !limits.limitsByInstantaneoustPowerType) {
|
|
17228
|
+
return defaultFormData;
|
|
17229
|
+
}
|
|
17230
|
+
const telemetryEntry = limits.limitsByInstantaneoustPowerType.find(
|
|
17231
|
+
(t) => t.telemetryType === telemetryType
|
|
17232
|
+
);
|
|
17233
|
+
if (!telemetryEntry || !telemetryEntry.itemsByDeviceType) {
|
|
17234
|
+
return defaultFormData;
|
|
17235
|
+
}
|
|
17236
|
+
const deviceEntry = telemetryEntry.itemsByDeviceType.find(
|
|
17237
|
+
(d) => d.deviceType === deviceType
|
|
17238
|
+
);
|
|
17239
|
+
if (!deviceEntry || !deviceEntry.limitsByDeviceStatus) {
|
|
17240
|
+
return defaultFormData;
|
|
17241
|
+
}
|
|
17242
|
+
const statusMap = {
|
|
17243
|
+
"standBy": "standby",
|
|
17244
|
+
"normal": "normal",
|
|
17245
|
+
"alert": "alert",
|
|
17246
|
+
"failure": "failure"
|
|
17247
|
+
};
|
|
17248
|
+
deviceEntry.limitsByDeviceStatus.forEach((status) => {
|
|
17249
|
+
const formKey = statusMap[status.deviceStatusName];
|
|
17250
|
+
if (formKey && defaultFormData[formKey]) {
|
|
17251
|
+
defaultFormData[formKey] = {
|
|
17252
|
+
baseValue: status.limitsValues.baseValue,
|
|
17253
|
+
topValue: status.limitsValues.topValue
|
|
17254
|
+
};
|
|
17255
|
+
}
|
|
17256
|
+
});
|
|
17257
|
+
return defaultFormData;
|
|
17258
|
+
}
|
|
17259
|
+
/**
|
|
17260
|
+
* Merge form data into existing limits JSON
|
|
17261
|
+
* Creates new entries if they don't exist
|
|
17262
|
+
*/
|
|
17263
|
+
mergeFormDataIntoLimits(existingLimits, formData) {
|
|
17264
|
+
const result = existingLimits ? JSON.parse(JSON.stringify(existingLimits)) : { version: "1.0.0", limitsByInstantaneoustPowerType: [] };
|
|
17265
|
+
const statusLimits = [
|
|
17266
|
+
{
|
|
17267
|
+
deviceStatusName: "standBy",
|
|
17268
|
+
limitsValues: {
|
|
17269
|
+
baseValue: formData.standby.baseValue ?? 0,
|
|
17270
|
+
topValue: formData.standby.topValue ?? 0
|
|
17271
|
+
}
|
|
17272
|
+
},
|
|
17273
|
+
{
|
|
17274
|
+
deviceStatusName: "normal",
|
|
17275
|
+
limitsValues: {
|
|
17276
|
+
baseValue: formData.normal.baseValue ?? 0,
|
|
17277
|
+
topValue: formData.normal.topValue ?? 0
|
|
17278
|
+
}
|
|
17279
|
+
},
|
|
17280
|
+
{
|
|
17281
|
+
deviceStatusName: "alert",
|
|
17282
|
+
limitsValues: {
|
|
17283
|
+
baseValue: formData.alert.baseValue ?? 0,
|
|
17284
|
+
topValue: formData.alert.topValue ?? 0
|
|
17285
|
+
}
|
|
17286
|
+
},
|
|
17287
|
+
{
|
|
17288
|
+
deviceStatusName: "failure",
|
|
17289
|
+
limitsValues: {
|
|
17290
|
+
baseValue: formData.failure.baseValue ?? 0,
|
|
17291
|
+
topValue: formData.failure.topValue ?? 0
|
|
17292
|
+
}
|
|
17293
|
+
}
|
|
17294
|
+
];
|
|
17295
|
+
let telemetryEntry = result.limitsByInstantaneoustPowerType.find(
|
|
17296
|
+
(t) => t.telemetryType === formData.telemetryType
|
|
17297
|
+
);
|
|
17298
|
+
if (!telemetryEntry) {
|
|
17299
|
+
telemetryEntry = {
|
|
17300
|
+
telemetryType: formData.telemetryType,
|
|
17301
|
+
itemsByDeviceType: []
|
|
17302
|
+
};
|
|
17303
|
+
result.limitsByInstantaneoustPowerType.push(telemetryEntry);
|
|
17304
|
+
}
|
|
17305
|
+
let deviceEntry = telemetryEntry.itemsByDeviceType.find(
|
|
17306
|
+
(d) => d.deviceType === formData.deviceType
|
|
17307
|
+
);
|
|
17308
|
+
if (!deviceEntry) {
|
|
17309
|
+
deviceEntry = {
|
|
17310
|
+
deviceType: formData.deviceType,
|
|
17311
|
+
name: `mapInstantaneousPower${this.formatDeviceTypeName(formData.deviceType)}`,
|
|
17312
|
+
description: `Power limits for ${formData.deviceType}`,
|
|
17313
|
+
limitsByDeviceStatus: []
|
|
17314
|
+
};
|
|
17315
|
+
telemetryEntry.itemsByDeviceType.push(deviceEntry);
|
|
17316
|
+
}
|
|
17317
|
+
deviceEntry.limitsByDeviceStatus = statusLimits;
|
|
17318
|
+
deviceEntry.name = `mapInstantaneousPower${this.formatDeviceTypeName(formData.deviceType)}`;
|
|
17319
|
+
deviceEntry.description = `Power limits for ${formData.deviceType} - ${formData.telemetryType}`;
|
|
17320
|
+
return result;
|
|
17321
|
+
}
|
|
17322
|
+
/**
|
|
17323
|
+
* Format device type name for the JSON name field
|
|
17324
|
+
*/
|
|
17325
|
+
formatDeviceTypeName(deviceType) {
|
|
17326
|
+
if (!deviceType) return "";
|
|
17327
|
+
return deviceType.toLowerCase().split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
17328
|
+
}
|
|
17329
|
+
createHttpError(status, body) {
|
|
17330
|
+
const error = new Error(`HTTP ${status}: ${body}`);
|
|
17331
|
+
error.status = status;
|
|
17332
|
+
error.body = body;
|
|
17333
|
+
return error;
|
|
17334
|
+
}
|
|
17335
|
+
mapError(error) {
|
|
17336
|
+
const status = error.status;
|
|
17337
|
+
if (status === 400) {
|
|
17338
|
+
return {
|
|
17339
|
+
code: "VALIDATION_ERROR",
|
|
17340
|
+
message: "Invalid input data",
|
|
17341
|
+
cause: error
|
|
17342
|
+
};
|
|
17343
|
+
}
|
|
17344
|
+
if (status === 401) {
|
|
17345
|
+
return {
|
|
17346
|
+
code: "TOKEN_EXPIRED",
|
|
17347
|
+
message: "Authentication token has expired",
|
|
17348
|
+
cause: error
|
|
17349
|
+
};
|
|
17350
|
+
}
|
|
17351
|
+
if (status === 403) {
|
|
17352
|
+
return {
|
|
17353
|
+
code: "AUTH_ERROR",
|
|
17354
|
+
message: "Insufficient permissions",
|
|
17355
|
+
cause: error
|
|
17356
|
+
};
|
|
17357
|
+
}
|
|
17358
|
+
if (status === 404) {
|
|
17359
|
+
return {
|
|
17360
|
+
code: "NETWORK_ERROR",
|
|
17361
|
+
message: "Customer not found",
|
|
17362
|
+
cause: error
|
|
17363
|
+
};
|
|
17364
|
+
}
|
|
17365
|
+
if (status >= 500) {
|
|
17366
|
+
return {
|
|
17367
|
+
code: "NETWORK_ERROR",
|
|
17368
|
+
message: "Server error occurred",
|
|
17369
|
+
cause: error
|
|
17370
|
+
};
|
|
15666
17371
|
}
|
|
17372
|
+
return {
|
|
17373
|
+
code: "UNKNOWN_ERROR",
|
|
17374
|
+
message: error.message || "Unknown error occurred",
|
|
17375
|
+
cause: error
|
|
17376
|
+
};
|
|
15667
17377
|
}
|
|
15668
|
-
|
|
15669
|
-
|
|
15670
|
-
|
|
15671
|
-
|
|
17378
|
+
};
|
|
17379
|
+
|
|
17380
|
+
// src/components/premium-modals/power-limits/openPowerLimitsSetupModal.ts
|
|
17381
|
+
async function openPowerLimitsSetupModal(params) {
|
|
17382
|
+
if (!params.token) {
|
|
17383
|
+
throw new Error("[PowerLimitsSetupModal] token is required");
|
|
17384
|
+
}
|
|
17385
|
+
if (!params.customerId) {
|
|
17386
|
+
throw new Error("[PowerLimitsSetupModal] customerId is required");
|
|
17387
|
+
}
|
|
17388
|
+
const persister = new PowerLimitsPersister(params.token, params.tbBaseUrl);
|
|
17389
|
+
let currentDeviceType = params.deviceType || "ELEVADOR";
|
|
17390
|
+
let currentTelemetryType = params.telemetryType || "consumption";
|
|
17391
|
+
let existingLimits = params.existingMapPower || null;
|
|
17392
|
+
const view = new PowerLimitsModalView({
|
|
17393
|
+
deviceType: currentDeviceType,
|
|
17394
|
+
telemetryType: currentTelemetryType,
|
|
17395
|
+
styles: params.styles,
|
|
17396
|
+
locale: params.locale,
|
|
17397
|
+
onDeviceTypeChange: async (deviceType) => {
|
|
17398
|
+
currentDeviceType = deviceType;
|
|
17399
|
+
await loadFormData();
|
|
17400
|
+
},
|
|
17401
|
+
onTelemetryTypeChange: async (telemetryType) => {
|
|
17402
|
+
currentTelemetryType = telemetryType;
|
|
17403
|
+
await loadFormData();
|
|
17404
|
+
},
|
|
17405
|
+
onSave: async () => {
|
|
17406
|
+
const formData = view.getFormData();
|
|
17407
|
+
const updatedLimits = persister.mergeFormDataIntoLimits(existingLimits, formData);
|
|
17408
|
+
const result = await persister.saveCustomerPowerLimits(params.customerId, updatedLimits);
|
|
17409
|
+
if (!result.ok) {
|
|
17410
|
+
throw new Error(result.error?.message || "Failed to save configuration");
|
|
17411
|
+
}
|
|
17412
|
+
existingLimits = updatedLimits;
|
|
17413
|
+
if (params.onSave) {
|
|
17414
|
+
params.onSave(updatedLimits);
|
|
17415
|
+
}
|
|
17416
|
+
},
|
|
17417
|
+
onClose: () => {
|
|
17418
|
+
if (params.onClose) {
|
|
17419
|
+
params.onClose();
|
|
17420
|
+
}
|
|
17421
|
+
}
|
|
17422
|
+
});
|
|
17423
|
+
async function loadFormData() {
|
|
17424
|
+
view.showLoading();
|
|
17425
|
+
try {
|
|
17426
|
+
if (!existingLimits) {
|
|
17427
|
+
existingLimits = await persister.loadCustomerPowerLimits(params.customerId);
|
|
17428
|
+
}
|
|
17429
|
+
const formData = persister.extractFormData(existingLimits, currentDeviceType, currentTelemetryType);
|
|
17430
|
+
view.setFormData(formData);
|
|
17431
|
+
} catch (error) {
|
|
17432
|
+
console.error("[PowerLimitsSetupModal] Error loading form data:", error);
|
|
17433
|
+
view.showError(error.message || "Failed to load configuration");
|
|
17434
|
+
} finally {
|
|
17435
|
+
view.hideLoading();
|
|
15672
17436
|
}
|
|
15673
17437
|
}
|
|
15674
|
-
|
|
15675
|
-
|
|
15676
|
-
|
|
17438
|
+
let container;
|
|
17439
|
+
if (params.container) {
|
|
17440
|
+
if (typeof params.container === "string") {
|
|
17441
|
+
container = document.querySelector(params.container);
|
|
17442
|
+
} else {
|
|
17443
|
+
container = params.container;
|
|
17444
|
+
}
|
|
15677
17445
|
}
|
|
17446
|
+
view.render(container);
|
|
17447
|
+
await loadFormData();
|
|
17448
|
+
return {
|
|
17449
|
+
destroy: () => view.destroy(),
|
|
17450
|
+
getFormData: () => view.getFormData(),
|
|
17451
|
+
setFormData: (data) => view.setFormData(data)
|
|
17452
|
+
};
|
|
15678
17453
|
}
|
|
15679
17454
|
|
|
15680
17455
|
// src/components/premium-modals/settings/SettingsModalView.ts
|
|
@@ -20045,220 +21820,6 @@ ${rangeText}`;
|
|
|
20045
21820
|
}
|
|
20046
21821
|
}
|
|
20047
21822
|
|
|
20048
|
-
// src/components/temperature/utils.ts
|
|
20049
|
-
var DAY_PERIODS = [
|
|
20050
|
-
{ id: "madrugada", label: "Madrugada (00h-06h)", startHour: 0, endHour: 6 },
|
|
20051
|
-
{ id: "manha", label: "Manh\xE3 (06h-12h)", startHour: 6, endHour: 12 },
|
|
20052
|
-
{ id: "tarde", label: "Tarde (12h-18h)", startHour: 12, endHour: 18 },
|
|
20053
|
-
{ id: "noite", label: "Noite (18h-24h)", startHour: 18, endHour: 24 }
|
|
20054
|
-
];
|
|
20055
|
-
var DEFAULT_CLAMP_RANGE = { min: 15, max: 40 };
|
|
20056
|
-
function getTodaySoFar() {
|
|
20057
|
-
const now = /* @__PURE__ */ new Date();
|
|
20058
|
-
const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0);
|
|
20059
|
-
return {
|
|
20060
|
-
startTs: startOfDay.getTime(),
|
|
20061
|
-
endTs: now.getTime()
|
|
20062
|
-
};
|
|
20063
|
-
}
|
|
20064
|
-
var CHART_COLORS = [
|
|
20065
|
-
"#1976d2",
|
|
20066
|
-
// Blue
|
|
20067
|
-
"#FF6B6B",
|
|
20068
|
-
// Red
|
|
20069
|
-
"#4CAF50",
|
|
20070
|
-
// Green
|
|
20071
|
-
"#FF9800",
|
|
20072
|
-
// Orange
|
|
20073
|
-
"#9C27B0",
|
|
20074
|
-
// Purple
|
|
20075
|
-
"#00BCD4",
|
|
20076
|
-
// Cyan
|
|
20077
|
-
"#E91E63",
|
|
20078
|
-
// Pink
|
|
20079
|
-
"#795548"
|
|
20080
|
-
// Brown
|
|
20081
|
-
];
|
|
20082
|
-
async function fetchTemperatureData(token, deviceId, startTs, endTs) {
|
|
20083
|
-
const url = `/api/plugins/telemetry/DEVICE/${deviceId}/values/timeseries?keys=temperature&startTs=${encodeURIComponent(startTs)}&endTs=${encodeURIComponent(endTs)}&limit=50000&agg=NONE`;
|
|
20084
|
-
const response = await fetch(url, {
|
|
20085
|
-
headers: {
|
|
20086
|
-
"X-Authorization": `Bearer ${token}`,
|
|
20087
|
-
"Content-Type": "application/json"
|
|
20088
|
-
}
|
|
20089
|
-
});
|
|
20090
|
-
if (!response.ok) {
|
|
20091
|
-
throw new Error(`Failed to fetch temperature data: ${response.status}`);
|
|
20092
|
-
}
|
|
20093
|
-
const data = await response.json();
|
|
20094
|
-
return data?.temperature || [];
|
|
20095
|
-
}
|
|
20096
|
-
function clampTemperature(value, range = DEFAULT_CLAMP_RANGE) {
|
|
20097
|
-
const num = Number(value || 0);
|
|
20098
|
-
if (num < range.min) return range.min;
|
|
20099
|
-
if (num > range.max) return range.max;
|
|
20100
|
-
return num;
|
|
20101
|
-
}
|
|
20102
|
-
function calculateStats(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
20103
|
-
if (data.length === 0) {
|
|
20104
|
-
return { avg: 0, min: 0, max: 0, count: 0 };
|
|
20105
|
-
}
|
|
20106
|
-
const values = data.map((item) => clampTemperature(item.value, clampRange));
|
|
20107
|
-
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
20108
|
-
return {
|
|
20109
|
-
avg: sum / values.length,
|
|
20110
|
-
min: Math.min(...values),
|
|
20111
|
-
max: Math.max(...values),
|
|
20112
|
-
count: values.length
|
|
20113
|
-
};
|
|
20114
|
-
}
|
|
20115
|
-
function interpolateTemperature(data, options) {
|
|
20116
|
-
const { intervalMinutes, startTs, endTs, clampRange = DEFAULT_CLAMP_RANGE } = options;
|
|
20117
|
-
const intervalMs = intervalMinutes * 60 * 1e3;
|
|
20118
|
-
if (data.length === 0) {
|
|
20119
|
-
return [];
|
|
20120
|
-
}
|
|
20121
|
-
const sortedData = [...data].sort((a, b) => a.ts - b.ts);
|
|
20122
|
-
const result = [];
|
|
20123
|
-
let lastKnownValue = clampTemperature(sortedData[0].value, clampRange);
|
|
20124
|
-
let dataIndex = 0;
|
|
20125
|
-
for (let ts = startTs; ts <= endTs; ts += intervalMs) {
|
|
20126
|
-
while (dataIndex < sortedData.length - 1 && sortedData[dataIndex + 1].ts <= ts) {
|
|
20127
|
-
dataIndex++;
|
|
20128
|
-
}
|
|
20129
|
-
const currentData = sortedData[dataIndex];
|
|
20130
|
-
if (currentData && Math.abs(currentData.ts - ts) < intervalMs) {
|
|
20131
|
-
lastKnownValue = clampTemperature(currentData.value, clampRange);
|
|
20132
|
-
}
|
|
20133
|
-
result.push({
|
|
20134
|
-
ts,
|
|
20135
|
-
value: lastKnownValue
|
|
20136
|
-
});
|
|
20137
|
-
}
|
|
20138
|
-
return result;
|
|
20139
|
-
}
|
|
20140
|
-
function aggregateByDay(data, clampRange = DEFAULT_CLAMP_RANGE) {
|
|
20141
|
-
if (data.length === 0) {
|
|
20142
|
-
return [];
|
|
20143
|
-
}
|
|
20144
|
-
const dayMap = /* @__PURE__ */ new Map();
|
|
20145
|
-
data.forEach((item) => {
|
|
20146
|
-
const date = new Date(item.ts);
|
|
20147
|
-
const dateKey = date.toISOString().split("T")[0];
|
|
20148
|
-
if (!dayMap.has(dateKey)) {
|
|
20149
|
-
dayMap.set(dateKey, []);
|
|
20150
|
-
}
|
|
20151
|
-
dayMap.get(dateKey).push(item);
|
|
20152
|
-
});
|
|
20153
|
-
const result = [];
|
|
20154
|
-
dayMap.forEach((dayData, dateKey) => {
|
|
20155
|
-
const values = dayData.map((item) => clampTemperature(item.value, clampRange));
|
|
20156
|
-
const sum = values.reduce((acc, v) => acc + v, 0);
|
|
20157
|
-
result.push({
|
|
20158
|
-
date: dateKey,
|
|
20159
|
-
dateTs: new Date(dateKey).getTime(),
|
|
20160
|
-
avg: sum / values.length,
|
|
20161
|
-
min: Math.min(...values),
|
|
20162
|
-
max: Math.max(...values),
|
|
20163
|
-
count: values.length
|
|
20164
|
-
});
|
|
20165
|
-
});
|
|
20166
|
-
return result.sort((a, b) => a.dateTs - b.dateTs);
|
|
20167
|
-
}
|
|
20168
|
-
function filterByDayPeriods(data, selectedPeriods) {
|
|
20169
|
-
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
20170
|
-
return data;
|
|
20171
|
-
}
|
|
20172
|
-
return data.filter((item) => {
|
|
20173
|
-
const date = new Date(item.ts);
|
|
20174
|
-
const hour = date.getHours();
|
|
20175
|
-
return selectedPeriods.some((periodId) => {
|
|
20176
|
-
const period = DAY_PERIODS.find((p) => p.id === periodId);
|
|
20177
|
-
if (!period) return false;
|
|
20178
|
-
return hour >= period.startHour && hour < period.endHour;
|
|
20179
|
-
});
|
|
20180
|
-
});
|
|
20181
|
-
}
|
|
20182
|
-
function getSelectedPeriodsLabel(selectedPeriods) {
|
|
20183
|
-
if (selectedPeriods.length === 0 || selectedPeriods.length === DAY_PERIODS.length) {
|
|
20184
|
-
return "Todos os per\xEDodos";
|
|
20185
|
-
}
|
|
20186
|
-
if (selectedPeriods.length === 1) {
|
|
20187
|
-
const period = DAY_PERIODS.find((p) => p.id === selectedPeriods[0]);
|
|
20188
|
-
return period?.label || "";
|
|
20189
|
-
}
|
|
20190
|
-
return `${selectedPeriods.length} per\xEDodos selecionados`;
|
|
20191
|
-
}
|
|
20192
|
-
function formatTemperature2(value, decimals = 1) {
|
|
20193
|
-
return `${value.toFixed(decimals)}\xB0C`;
|
|
20194
|
-
}
|
|
20195
|
-
function exportTemperatureCSV(data, deviceLabel, stats, startDate, endDate) {
|
|
20196
|
-
if (data.length === 0) {
|
|
20197
|
-
console.warn("No data to export");
|
|
20198
|
-
return;
|
|
20199
|
-
}
|
|
20200
|
-
const BOM = "\uFEFF";
|
|
20201
|
-
let csvContent = BOM;
|
|
20202
|
-
csvContent += `Relat\xF3rio de Temperatura - ${deviceLabel}
|
|
20203
|
-
`;
|
|
20204
|
-
csvContent += `Per\xEDodo: ${startDate} at\xE9 ${endDate}
|
|
20205
|
-
`;
|
|
20206
|
-
csvContent += `M\xE9dia: ${formatTemperature2(stats.avg)}
|
|
20207
|
-
`;
|
|
20208
|
-
csvContent += `M\xEDnima: ${formatTemperature2(stats.min)}
|
|
20209
|
-
`;
|
|
20210
|
-
csvContent += `M\xE1xima: ${formatTemperature2(stats.max)}
|
|
20211
|
-
`;
|
|
20212
|
-
csvContent += `Total de leituras: ${stats.count}
|
|
20213
|
-
`;
|
|
20214
|
-
csvContent += "\n";
|
|
20215
|
-
csvContent += "Data/Hora,Temperatura (\xB0C)\n";
|
|
20216
|
-
data.forEach((item) => {
|
|
20217
|
-
const date = new Date(item.ts).toLocaleString("pt-BR");
|
|
20218
|
-
const temp = Number(item.value).toFixed(2);
|
|
20219
|
-
csvContent += `"${date}",${temp}
|
|
20220
|
-
`;
|
|
20221
|
-
});
|
|
20222
|
-
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
|
|
20223
|
-
const url = URL.createObjectURL(blob);
|
|
20224
|
-
const link = document.createElement("a");
|
|
20225
|
-
link.href = url;
|
|
20226
|
-
link.download = `temperatura_${deviceLabel.replace(/\s+/g, "_")}_${startDate}_${endDate}.csv`;
|
|
20227
|
-
document.body.appendChild(link);
|
|
20228
|
-
link.click();
|
|
20229
|
-
document.body.removeChild(link);
|
|
20230
|
-
URL.revokeObjectURL(url);
|
|
20231
|
-
}
|
|
20232
|
-
var DARK_THEME = {
|
|
20233
|
-
background: "rgba(0, 0, 0, 0.85)",
|
|
20234
|
-
surface: "#1a1f28",
|
|
20235
|
-
text: "#ffffff",
|
|
20236
|
-
textMuted: "rgba(255, 255, 255, 0.7)",
|
|
20237
|
-
border: "rgba(255, 255, 255, 0.1)",
|
|
20238
|
-
primary: "#1976d2",
|
|
20239
|
-
success: "#4CAF50",
|
|
20240
|
-
warning: "#FF9800",
|
|
20241
|
-
danger: "#f44336",
|
|
20242
|
-
chartLine: "#1976d2",
|
|
20243
|
-
chartGrid: "rgba(255, 255, 255, 0.1)"
|
|
20244
|
-
};
|
|
20245
|
-
var LIGHT_THEME = {
|
|
20246
|
-
background: "rgba(0, 0, 0, 0.6)",
|
|
20247
|
-
surface: "#ffffff",
|
|
20248
|
-
text: "#333333",
|
|
20249
|
-
textMuted: "#666666",
|
|
20250
|
-
border: "#e0e0e0",
|
|
20251
|
-
primary: "#1976d2",
|
|
20252
|
-
success: "#4CAF50",
|
|
20253
|
-
warning: "#FF9800",
|
|
20254
|
-
danger: "#f44336",
|
|
20255
|
-
chartLine: "#1976d2",
|
|
20256
|
-
chartGrid: "#e0e0e0"
|
|
20257
|
-
};
|
|
20258
|
-
function getThemeColors(theme) {
|
|
20259
|
-
return theme === "dark" ? DARK_THEME : LIGHT_THEME;
|
|
20260
|
-
}
|
|
20261
|
-
|
|
20262
21823
|
// src/components/temperature/TemperatureModal.ts
|
|
20263
21824
|
async function openTemperatureModal(params) {
|
|
20264
21825
|
const modalId = `myio-temp-modal-${Date.now()}`;
|
|
@@ -20498,7 +22059,7 @@ ${rangeText}`;
|
|
|
20498
22059
|
">
|
|
20499
22060
|
<span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">Temperatura Atual</span>
|
|
20500
22061
|
<div style="font-weight: 700; font-size: 24px; color: ${statusColor}; margin-top: 4px;">
|
|
20501
|
-
${state.currentTemperature !== null ?
|
|
22062
|
+
${state.currentTemperature !== null ? formatTemperature(state.currentTemperature) : "N/A"}
|
|
20502
22063
|
</div>
|
|
20503
22064
|
<div style="font-size: 11px; color: ${statusColor}; margin-top: 2px;">${statusText}</div>
|
|
20504
22065
|
</div>
|
|
@@ -20509,7 +22070,7 @@ ${rangeText}`;
|
|
|
20509
22070
|
">
|
|
20510
22071
|
<span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">M\xE9dia do Per\xEDodo</span>
|
|
20511
22072
|
<div id="${modalId}-avg" style="font-weight: 600; font-size: 20px; color: ${colors.text}; margin-top: 4px;">
|
|
20512
|
-
${state.stats.count > 0 ?
|
|
22073
|
+
${state.stats.count > 0 ? formatTemperature(state.stats.avg) : "N/A"}
|
|
20513
22074
|
</div>
|
|
20514
22075
|
<div style="font-size: 11px; color: ${colors.textMuted}; margin-top: 2px;">${startDateStr} - ${endDateStr}</div>
|
|
20515
22076
|
</div>
|
|
@@ -20520,7 +22081,7 @@ ${rangeText}`;
|
|
|
20520
22081
|
">
|
|
20521
22082
|
<span style="color: ${colors.textMuted}; font-size: 12px; font-weight: 500;">Min / Max</span>
|
|
20522
22083
|
<div id="${modalId}-minmax" style="font-weight: 600; font-size: 20px; color: ${colors.text}; margin-top: 4px;">
|
|
20523
|
-
${state.stats.count > 0 ? `${
|
|
22084
|
+
${state.stats.count > 0 ? `${formatTemperature(state.stats.min)} / ${formatTemperature(state.stats.max)}` : "N/A"}
|
|
20524
22085
|
</div>
|
|
20525
22086
|
<div style="font-size: 11px; color: ${colors.textMuted}; margin-top: 2px;">${state.stats.count} leituras</div>
|
|
20526
22087
|
</div>
|
|
@@ -20836,7 +22397,7 @@ ${rangeText}`;
|
|
|
20836
22397
|
}
|
|
20837
22398
|
tooltip.innerHTML = `
|
|
20838
22399
|
<div style="font-weight: 600; margin-bottom: 6px; color: ${colors.primary};">
|
|
20839
|
-
${
|
|
22400
|
+
${formatTemperature(point.y)}
|
|
20840
22401
|
</div>
|
|
20841
22402
|
<div style="font-size: 11px; color: ${colors.textMuted};">
|
|
20842
22403
|
\u{1F4C5} ${dateStr}
|
|
@@ -21099,7 +22660,7 @@ ${rangeText}`;
|
|
|
21099
22660
|
<span style="width: 12px; height: 12px; border-radius: 50%; background: ${dd.color};"></span>
|
|
21100
22661
|
<span style="color: ${colors.text}; font-size: 13px;">${dd.device.label}</span>
|
|
21101
22662
|
<span style="color: ${colors.textMuted}; font-size: 11px; margin-left: auto;">
|
|
21102
|
-
${dd.stats.count > 0 ?
|
|
22663
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.avg) : "N/A"}
|
|
21103
22664
|
</span>
|
|
21104
22665
|
</div>
|
|
21105
22666
|
`).join("");
|
|
@@ -21115,15 +22676,15 @@ ${rangeText}`;
|
|
|
21115
22676
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 4px; font-size: 11px;">
|
|
21116
22677
|
<span style="color: ${colors.textMuted};">M\xE9dia:</span>
|
|
21117
22678
|
<span style="color: ${colors.text}; font-weight: 500;">
|
|
21118
|
-
${dd.stats.count > 0 ?
|
|
22679
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.avg) : "N/A"}
|
|
21119
22680
|
</span>
|
|
21120
22681
|
<span style="color: ${colors.textMuted};">Min:</span>
|
|
21121
22682
|
<span style="color: ${colors.text};">
|
|
21122
|
-
${dd.stats.count > 0 ?
|
|
22683
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.min) : "N/A"}
|
|
21123
22684
|
</span>
|
|
21124
22685
|
<span style="color: ${colors.textMuted};">Max:</span>
|
|
21125
22686
|
<span style="color: ${colors.text};">
|
|
21126
|
-
${dd.stats.count > 0 ?
|
|
22687
|
+
${dd.stats.count > 0 ? formatTemperature(dd.stats.max) : "N/A"}
|
|
21127
22688
|
</span>
|
|
21128
22689
|
<span style="color: ${colors.textMuted};">Leituras:</span>
|
|
21129
22690
|
<span style="color: ${colors.text};">${dd.stats.count}</span>
|
|
@@ -21659,7 +23220,7 @@ ${rangeText}`;
|
|
|
21659
23220
|
<span style="font-weight: 600;">${point.deviceLabel}</span>
|
|
21660
23221
|
</div>
|
|
21661
23222
|
<div style="font-weight: 600; font-size: 16px; color: ${point.deviceColor}; margin-bottom: 4px;">
|
|
21662
|
-
${
|
|
23223
|
+
${formatTemperature(point.y)}
|
|
21663
23224
|
</div>
|
|
21664
23225
|
<div style="font-size: 11px; color: ${colors.textMuted};">
|
|
21665
23226
|
\u{1F4C5} ${dateStr}
|
|
@@ -26151,6 +27712,9 @@ ${rangeText}`;
|
|
|
26151
27712
|
exports.MyIODraggableCard = MyIODraggableCard;
|
|
26152
27713
|
exports.MyIOSelectionStoreClass = MyIOSelectionStoreClass;
|
|
26153
27714
|
exports.MyIOToast = MyIOToast;
|
|
27715
|
+
exports.POWER_LIMITS_DEVICE_TYPES = DEVICE_TYPES;
|
|
27716
|
+
exports.POWER_LIMITS_STATUS_CONFIG = STATUS_CONFIG;
|
|
27717
|
+
exports.POWER_LIMITS_TELEMETRY_TYPES = TELEMETRY_TYPES2;
|
|
26154
27718
|
exports.addDetectionContext = addDetectionContext;
|
|
26155
27719
|
exports.addNamespace = addNamespace;
|
|
26156
27720
|
exports.aggregateByDay = aggregateByDay;
|
|
@@ -26205,7 +27769,7 @@ ${rangeText}`;
|
|
|
26205
27769
|
exports.formatNumberReadable = formatNumberReadable;
|
|
26206
27770
|
exports.formatRelativeTime = formatRelativeTime;
|
|
26207
27771
|
exports.formatTankHeadFromCm = formatTankHeadFromCm;
|
|
26208
|
-
exports.formatTemperature =
|
|
27772
|
+
exports.formatTemperature = formatTemperature;
|
|
26209
27773
|
exports.formatWater = formatWater;
|
|
26210
27774
|
exports.formatWaterByGroup = formatWaterByGroup;
|
|
26211
27775
|
exports.formatWaterVolumeM3 = formatWaterVolumeM3;
|
|
@@ -26248,6 +27812,7 @@ ${rangeText}`;
|
|
|
26248
27812
|
exports.openDashboardPopupWaterTank = openDashboardPopupWaterTank;
|
|
26249
27813
|
exports.openDemandModal = openDemandModal;
|
|
26250
27814
|
exports.openGoalsPanel = openGoalsPanel;
|
|
27815
|
+
exports.openPowerLimitsSetupModal = openPowerLimitsSetupModal;
|
|
26251
27816
|
exports.openRealTimeTelemetryModal = openRealTimeTelemetryModal;
|
|
26252
27817
|
exports.openTemperatureComparisonModal = openTemperatureComparisonModal;
|
|
26253
27818
|
exports.openTemperatureModal = openTemperatureModal;
|