myio-js-library 0.1.181 → 0.1.183
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 +925 -319
- package/dist/index.d.cts +151 -1
- package/dist/index.js +923 -319
- package/dist/myio-js-library.umd.js +963 -354
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -583,6 +583,7 @@ __export(index_exports, {
|
|
|
583
583
|
EXPORT_DOMAIN_ICONS: () => EXPORT_DOMAIN_ICONS,
|
|
584
584
|
EXPORT_DOMAIN_LABELS: () => EXPORT_DOMAIN_LABELS,
|
|
585
585
|
EXPORT_DOMAIN_UNITS: () => EXPORT_DOMAIN_UNITS,
|
|
586
|
+
EnergyRangeTooltip: () => EnergyRangeTooltip,
|
|
586
587
|
MyIOChartModal: () => MyIOChartModal,
|
|
587
588
|
MyIODraggableCard: () => MyIODraggableCard,
|
|
588
589
|
MyIOSelectionStore: () => MyIOSelectionStore,
|
|
@@ -591,6 +592,7 @@ __export(index_exports, {
|
|
|
591
592
|
POWER_LIMITS_DEVICE_TYPES: () => DEVICE_TYPES,
|
|
592
593
|
POWER_LIMITS_STATUS_CONFIG: () => STATUS_CONFIG,
|
|
593
594
|
POWER_LIMITS_TELEMETRY_TYPES: () => TELEMETRY_TYPES2,
|
|
595
|
+
TempRangeTooltip: () => TempRangeTooltip,
|
|
594
596
|
addDetectionContext: () => addDetectionContext,
|
|
595
597
|
addNamespace: () => addNamespace,
|
|
596
598
|
aggregateByDay: () => aggregateByDay,
|
|
@@ -1683,11 +1685,11 @@ function buildEntityMapFromDatasource(datasources) {
|
|
|
1683
1685
|
const dsArray = Array.isArray(datasources) ? datasources : [];
|
|
1684
1686
|
const map = /* @__PURE__ */ new Map();
|
|
1685
1687
|
dsArray.forEach((ds) => {
|
|
1686
|
-
const entityId = ds?.entityId;
|
|
1688
|
+
const entityId = ds?.entity?.id?.id || ds?.entity?.id || ds?.entityId || null;
|
|
1687
1689
|
if (!entityId) return;
|
|
1688
1690
|
if (!map.has(entityId)) {
|
|
1689
1691
|
const entity = ds?.entity;
|
|
1690
|
-
const draftLabel = entity?.label || entity?.name || ds?.name || null;
|
|
1692
|
+
const draftLabel = entity?.label || entity?.name || ds?.entityLabel || ds?.name || null;
|
|
1691
1693
|
map.set(entityId, {
|
|
1692
1694
|
id: entityId,
|
|
1693
1695
|
identifier: null,
|
|
@@ -1709,7 +1711,7 @@ function buildEntityMapFromDatasource(datasources) {
|
|
|
1709
1711
|
function hydrateEntityMapWithCtxData(data, map) {
|
|
1710
1712
|
const rows = Array.isArray(data) ? data : [];
|
|
1711
1713
|
rows.forEach((row) => {
|
|
1712
|
-
const entityId = row?.datasource?.entityId || null;
|
|
1714
|
+
const entityId = row?.datasource?.entity?.id?.id || row?.datasource?.entity?.id || row?.datasource?.entityId || null;
|
|
1713
1715
|
if (!entityId || !map.has(entityId)) return;
|
|
1714
1716
|
const rawKey = row?.dataKey?.name || "";
|
|
1715
1717
|
if (!rawKey) return;
|
|
@@ -6064,214 +6066,283 @@ function createLogHelper(debugActive = false) {
|
|
|
6064
6066
|
}
|
|
6065
6067
|
var LogHelper = createLogHelper(false);
|
|
6066
6068
|
|
|
6067
|
-
// src/
|
|
6068
|
-
var
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6074
|
-
|
|
6075
|
-
|
|
6076
|
-
document.head.appendChild(style);
|
|
6077
|
-
}
|
|
6069
|
+
// src/utils/TempRangeTooltip.ts
|
|
6070
|
+
var TOOLTIP_STYLES = `
|
|
6071
|
+
.temp-range-tooltip {
|
|
6072
|
+
position: fixed;
|
|
6073
|
+
z-index: 99999;
|
|
6074
|
+
pointer-events: none;
|
|
6075
|
+
opacity: 0;
|
|
6076
|
+
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
6077
|
+
transform: translateY(5px);
|
|
6078
6078
|
}
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
|
|
6083
|
-
|
|
6084
|
-
const entityObject = params.entityObject;
|
|
6085
|
-
if (!entityObject.entityId) {
|
|
6086
|
-
LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
|
|
6087
|
-
entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
6088
|
-
}
|
|
6089
|
-
if (!params.delayTimeConnectionInMins) {
|
|
6090
|
-
LogHelper2.warn(
|
|
6091
|
-
`[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
|
|
6092
|
-
);
|
|
6093
|
-
}
|
|
6094
|
-
return {
|
|
6095
|
-
entityObject,
|
|
6096
|
-
i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
|
|
6097
|
-
enableSelection: Boolean(params.enableSelection),
|
|
6098
|
-
enableDragDrop: Boolean(params.enableDragDrop),
|
|
6099
|
-
useNewComponents: Boolean(params.useNewComponents),
|
|
6100
|
-
// RFC-0091: Configurable delay time for connection status check (default 15 minutes)
|
|
6101
|
-
delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
|
|
6102
|
-
// Debug options
|
|
6103
|
-
debugActive: params.debugActive ?? false,
|
|
6104
|
-
activeTooltipDebug: params.activeTooltipDebug ?? false,
|
|
6105
|
-
// LogHelper instance for this card
|
|
6106
|
-
LogHelper: LogHelper2,
|
|
6107
|
-
callbacks: {
|
|
6108
|
-
handleActionDashboard: params.handleActionDashboard,
|
|
6109
|
-
handleActionReport: params.handleActionReport,
|
|
6110
|
-
handleActionSettings: params.handleActionSettings,
|
|
6111
|
-
handleSelect: params.handleSelect,
|
|
6112
|
-
handInfo: params.handInfo,
|
|
6113
|
-
handleClickCard: params.handleClickCard
|
|
6114
|
-
}
|
|
6115
|
-
};
|
|
6079
|
+
|
|
6080
|
+
.temp-range-tooltip.visible {
|
|
6081
|
+
opacity: 1;
|
|
6082
|
+
pointer-events: auto;
|
|
6083
|
+
transform: translateY(0);
|
|
6116
6084
|
}
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6085
|
+
|
|
6086
|
+
.temp-range-tooltip__content {
|
|
6087
|
+
background: #ffffff;
|
|
6088
|
+
border: 1px solid #e2e8f0;
|
|
6089
|
+
border-radius: 12px;
|
|
6090
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
|
|
6091
|
+
min-width: 280px;
|
|
6092
|
+
max-width: 320px;
|
|
6093
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
6094
|
+
font-size: 12px;
|
|
6095
|
+
color: #1e293b;
|
|
6096
|
+
overflow: hidden;
|
|
6125
6097
|
}
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
} else {
|
|
6135
|
-
const w = Math.ceil(val);
|
|
6136
|
-
return { num: w.toString(), unit: "W" };
|
|
6137
|
-
}
|
|
6098
|
+
|
|
6099
|
+
.temp-range-tooltip__header {
|
|
6100
|
+
display: flex;
|
|
6101
|
+
align-items: center;
|
|
6102
|
+
gap: 8px;
|
|
6103
|
+
padding: 12px 16px;
|
|
6104
|
+
background: linear-gradient(90deg, #fff7ed 0%, #fed7aa 100%);
|
|
6105
|
+
border-bottom: 1px solid #fdba74;
|
|
6138
6106
|
}
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
}
|
|
6143
|
-
if (domain === "temperature") {
|
|
6144
|
-
return formatTemperature(value, 0);
|
|
6145
|
-
}
|
|
6146
|
-
return formatEnergy(value);
|
|
6107
|
+
|
|
6108
|
+
.temp-range-tooltip__icon {
|
|
6109
|
+
font-size: 18px;
|
|
6147
6110
|
}
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
6154
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
6155
|
-
const year = date.getFullYear();
|
|
6156
|
-
return `${hours}:${minutes} ${day}/${month}/${year}`;
|
|
6111
|
+
|
|
6112
|
+
.temp-range-tooltip__title {
|
|
6113
|
+
font-weight: 700;
|
|
6114
|
+
font-size: 13px;
|
|
6115
|
+
color: #c2410c;
|
|
6157
6116
|
}
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
|
|
6162
|
-
return 0;
|
|
6163
|
-
}
|
|
6164
|
-
const percentage = numericConsumption / numericTarget * 100;
|
|
6165
|
-
return percentage;
|
|
6117
|
+
|
|
6118
|
+
.temp-range-tooltip__body {
|
|
6119
|
+
padding: 16px;
|
|
6166
6120
|
}
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
return { chipClass: "chip--standby", label: "Frio" };
|
|
6174
|
-
case "hot":
|
|
6175
|
-
return { chipClass: "chip--alert", label: "Quente" };
|
|
6176
|
-
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
6177
|
-
case DeviceStatusType.POWER_ON:
|
|
6178
|
-
if (domain === "water") {
|
|
6179
|
-
return { chipClass: "chip--power-on", label: i18n.in_operation_water };
|
|
6180
|
-
}
|
|
6181
|
-
return { chipClass: "chip--power-on", label: i18n.in_operation };
|
|
6182
|
-
case DeviceStatusType.STANDBY:
|
|
6183
|
-
return { chipClass: "chip--standby", label: i18n.standby };
|
|
6184
|
-
case DeviceStatusType.WARNING:
|
|
6185
|
-
return { chipClass: "chip--warning", label: i18n.alert };
|
|
6186
|
-
case DeviceStatusType.MAINTENANCE:
|
|
6187
|
-
return { chipClass: "chip--maintenance", label: i18n.maintenance };
|
|
6188
|
-
case DeviceStatusType.FAILURE:
|
|
6189
|
-
return { chipClass: "chip--failure", label: i18n.failure };
|
|
6190
|
-
case DeviceStatusType.POWER_OFF:
|
|
6191
|
-
return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
|
|
6192
|
-
case DeviceStatusType.OFFLINE:
|
|
6193
|
-
return { chipClass: "chip--offline", label: i18n.offline };
|
|
6194
|
-
case DeviceStatusType.NO_INFO:
|
|
6195
|
-
return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
|
|
6196
|
-
case DeviceStatusType.NOT_INSTALLED:
|
|
6197
|
-
return { chipClass: "chip--not-installed", label: i18n.not_installed };
|
|
6198
|
-
default:
|
|
6199
|
-
return { chipClass: "chip--offline", label: i18n.offline };
|
|
6200
|
-
}
|
|
6121
|
+
|
|
6122
|
+
.temp-range-tooltip__value-row {
|
|
6123
|
+
display: flex;
|
|
6124
|
+
justify-content: space-between;
|
|
6125
|
+
align-items: center;
|
|
6126
|
+
margin-bottom: 16px;
|
|
6201
6127
|
}
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
case DeviceStatusType.STANDBY:
|
|
6208
|
-
return "is-standby";
|
|
6209
|
-
// Green border
|
|
6210
|
-
case DeviceStatusType.WARNING:
|
|
6211
|
-
return "is-warning";
|
|
6212
|
-
// Yellow border
|
|
6213
|
-
case DeviceStatusType.MAINTENANCE:
|
|
6214
|
-
return "is-maintenance";
|
|
6215
|
-
// Yellow border
|
|
6216
|
-
case DeviceStatusType.FAILURE:
|
|
6217
|
-
return "is-failure";
|
|
6218
|
-
// Dark Red border
|
|
6219
|
-
case DeviceStatusType.POWER_OFF:
|
|
6220
|
-
return "is-power-off";
|
|
6221
|
-
// Light Red border
|
|
6222
|
-
case DeviceStatusType.OFFLINE:
|
|
6223
|
-
return "is-offline";
|
|
6224
|
-
// Dark Gray border
|
|
6225
|
-
case DeviceStatusType.NO_INFO:
|
|
6226
|
-
return "is-no-info";
|
|
6227
|
-
// Dark Orange border
|
|
6228
|
-
case DeviceStatusType.NOT_INSTALLED:
|
|
6229
|
-
return "is-not-installed";
|
|
6230
|
-
// Purple border
|
|
6231
|
-
default:
|
|
6232
|
-
return "";
|
|
6233
|
-
}
|
|
6128
|
+
|
|
6129
|
+
.temp-range-tooltip__current {
|
|
6130
|
+
font-size: 28px;
|
|
6131
|
+
font-weight: 700;
|
|
6132
|
+
color: #1e293b;
|
|
6234
6133
|
}
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
|
|
6240
|
-
if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
|
|
6241
|
-
return "";
|
|
6242
|
-
}
|
|
6243
|
-
if (currentTemp > tempMax) return "is-temp-hot";
|
|
6244
|
-
if (currentTemp < tempMin) return "is-temp-cold";
|
|
6245
|
-
return "is-temp-ok";
|
|
6134
|
+
|
|
6135
|
+
.temp-range-tooltip__current sup {
|
|
6136
|
+
font-size: 14px;
|
|
6137
|
+
color: #64748b;
|
|
6246
6138
|
}
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6139
|
+
|
|
6140
|
+
.temp-range-tooltip__deviation {
|
|
6141
|
+
text-align: right;
|
|
6142
|
+
}
|
|
6143
|
+
|
|
6144
|
+
.temp-range-tooltip__deviation-value {
|
|
6145
|
+
font-size: 16px;
|
|
6146
|
+
font-weight: 700;
|
|
6147
|
+
}
|
|
6148
|
+
|
|
6149
|
+
.temp-range-tooltip__deviation-value.cold {
|
|
6150
|
+
color: #2563eb;
|
|
6151
|
+
}
|
|
6152
|
+
|
|
6153
|
+
.temp-range-tooltip__deviation-value.ok {
|
|
6154
|
+
color: #16a34a;
|
|
6155
|
+
}
|
|
6156
|
+
|
|
6157
|
+
.temp-range-tooltip__deviation-value.hot {
|
|
6158
|
+
color: #dc2626;
|
|
6159
|
+
}
|
|
6160
|
+
|
|
6161
|
+
.temp-range-tooltip__deviation-label {
|
|
6162
|
+
font-size: 10px;
|
|
6163
|
+
color: #64748b;
|
|
6164
|
+
text-transform: uppercase;
|
|
6165
|
+
letter-spacing: 0.5px;
|
|
6166
|
+
}
|
|
6167
|
+
|
|
6168
|
+
.temp-range-tooltip__ruler {
|
|
6169
|
+
position: relative;
|
|
6170
|
+
height: 32px;
|
|
6171
|
+
margin: 12px 0;
|
|
6172
|
+
border-radius: 8px;
|
|
6173
|
+
overflow: visible;
|
|
6174
|
+
}
|
|
6175
|
+
|
|
6176
|
+
.temp-range-tooltip__ruler-track {
|
|
6177
|
+
position: absolute;
|
|
6178
|
+
top: 12px;
|
|
6179
|
+
left: 0;
|
|
6180
|
+
right: 0;
|
|
6181
|
+
height: 8px;
|
|
6182
|
+
background: linear-gradient(90deg, #dbeafe 0%, #dcfce7 50%, #fee2e2 100%);
|
|
6183
|
+
border-radius: 4px;
|
|
6184
|
+
border: 1px solid #e2e8f0;
|
|
6185
|
+
}
|
|
6186
|
+
|
|
6187
|
+
.temp-range-tooltip__ruler-range {
|
|
6188
|
+
position: absolute;
|
|
6189
|
+
top: 12px;
|
|
6190
|
+
height: 8px;
|
|
6191
|
+
background: #22c55e;
|
|
6192
|
+
border-radius: 4px;
|
|
6193
|
+
opacity: 0.6;
|
|
6194
|
+
}
|
|
6195
|
+
|
|
6196
|
+
.temp-range-tooltip__ruler-marker {
|
|
6197
|
+
position: absolute;
|
|
6198
|
+
top: 4px;
|
|
6199
|
+
width: 4px;
|
|
6200
|
+
height: 24px;
|
|
6201
|
+
background: #1e293b;
|
|
6202
|
+
border-radius: 2px;
|
|
6203
|
+
transform: translateX(-50%);
|
|
6204
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6205
|
+
}
|
|
6206
|
+
|
|
6207
|
+
.temp-range-tooltip__ruler-marker::after {
|
|
6208
|
+
content: '';
|
|
6209
|
+
position: absolute;
|
|
6210
|
+
top: -4px;
|
|
6211
|
+
left: 50%;
|
|
6212
|
+
transform: translateX(-50%);
|
|
6213
|
+
width: 12px;
|
|
6214
|
+
height: 12px;
|
|
6215
|
+
background: #1e293b;
|
|
6216
|
+
border-radius: 50%;
|
|
6217
|
+
border: 2px solid #fff;
|
|
6218
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6219
|
+
}
|
|
6220
|
+
|
|
6221
|
+
.temp-range-tooltip__ruler-labels {
|
|
6222
|
+
display: flex;
|
|
6223
|
+
justify-content: space-between;
|
|
6224
|
+
margin-top: 8px;
|
|
6225
|
+
font-size: 10px;
|
|
6226
|
+
color: #64748b;
|
|
6227
|
+
}
|
|
6228
|
+
|
|
6229
|
+
.temp-range-tooltip__ruler-min,
|
|
6230
|
+
.temp-range-tooltip__ruler-max {
|
|
6231
|
+
font-weight: 600;
|
|
6232
|
+
}
|
|
6233
|
+
|
|
6234
|
+
.temp-range-tooltip__range-info {
|
|
6235
|
+
display: flex;
|
|
6236
|
+
justify-content: space-between;
|
|
6237
|
+
padding: 10px 12px;
|
|
6238
|
+
background: #f8fafc;
|
|
6239
|
+
border-radius: 8px;
|
|
6240
|
+
margin-top: 12px;
|
|
6241
|
+
}
|
|
6242
|
+
|
|
6243
|
+
.temp-range-tooltip__range-item {
|
|
6244
|
+
text-align: center;
|
|
6245
|
+
}
|
|
6246
|
+
|
|
6247
|
+
.temp-range-tooltip__range-label {
|
|
6248
|
+
font-size: 10px;
|
|
6249
|
+
color: #64748b;
|
|
6250
|
+
text-transform: uppercase;
|
|
6251
|
+
letter-spacing: 0.3px;
|
|
6252
|
+
margin-bottom: 2px;
|
|
6253
|
+
}
|
|
6254
|
+
|
|
6255
|
+
.temp-range-tooltip__range-value {
|
|
6256
|
+
font-size: 14px;
|
|
6257
|
+
font-weight: 600;
|
|
6258
|
+
color: #334155;
|
|
6259
|
+
}
|
|
6260
|
+
|
|
6261
|
+
.temp-range-tooltip__status {
|
|
6262
|
+
display: flex;
|
|
6263
|
+
align-items: center;
|
|
6264
|
+
justify-content: center;
|
|
6265
|
+
gap: 6px;
|
|
6266
|
+
margin-top: 12px;
|
|
6267
|
+
padding: 8px 12px;
|
|
6268
|
+
border-radius: 6px;
|
|
6269
|
+
font-size: 11px;
|
|
6270
|
+
font-weight: 600;
|
|
6271
|
+
}
|
|
6272
|
+
|
|
6273
|
+
.temp-range-tooltip__status.cold {
|
|
6274
|
+
background: #dbeafe;
|
|
6275
|
+
color: #1d4ed8;
|
|
6276
|
+
border: 1px solid #93c5fd;
|
|
6277
|
+
}
|
|
6278
|
+
|
|
6279
|
+
.temp-range-tooltip__status.ok {
|
|
6280
|
+
background: #dcfce7;
|
|
6281
|
+
color: #15803d;
|
|
6282
|
+
border: 1px solid #86efac;
|
|
6283
|
+
}
|
|
6284
|
+
|
|
6285
|
+
.temp-range-tooltip__status.hot {
|
|
6286
|
+
background: #fee2e2;
|
|
6287
|
+
color: #b91c1c;
|
|
6288
|
+
border: 1px solid #fca5a5;
|
|
6289
|
+
}
|
|
6290
|
+
|
|
6291
|
+
.temp-range-tooltip__status.unknown {
|
|
6292
|
+
background: #f3f4f6;
|
|
6293
|
+
color: #6b7280;
|
|
6294
|
+
border: 1px solid #d1d5db;
|
|
6295
|
+
}
|
|
6296
|
+
`;
|
|
6297
|
+
function injectStyles() {
|
|
6298
|
+
if (typeof document === "undefined") return;
|
|
6299
|
+
const styleId = "myio-temp-range-tooltip-styles";
|
|
6300
|
+
if (document.getElementById(styleId)) return;
|
|
6301
|
+
const style = document.createElement("style");
|
|
6302
|
+
style.id = styleId;
|
|
6303
|
+
style.textContent = TOOLTIP_STYLES;
|
|
6304
|
+
document.head.appendChild(style);
|
|
6305
|
+
}
|
|
6306
|
+
function extractTemperature(entityData) {
|
|
6307
|
+
return Number(entityData.val ?? entityData.currentTemperature ?? entityData.temperature) || 0;
|
|
6308
|
+
}
|
|
6309
|
+
function extractRange(entityData) {
|
|
6310
|
+
const tempMin = entityData.temperatureMin ?? entityData.minTemperature ?? null;
|
|
6311
|
+
const tempMax = entityData.temperatureMax ?? entityData.maxTemperature ?? null;
|
|
6312
|
+
return { tempMin, tempMax };
|
|
6313
|
+
}
|
|
6314
|
+
function extractLabel(entityData) {
|
|
6315
|
+
return entityData.labelOrName || entityData.name || entityData.label || "Sensor";
|
|
6316
|
+
}
|
|
6317
|
+
var TempRangeTooltip = {
|
|
6318
|
+
containerId: "myio-temp-range-tooltip",
|
|
6319
|
+
/**
|
|
6320
|
+
* Create or get the tooltip container
|
|
6321
|
+
*/
|
|
6322
|
+
getContainer() {
|
|
6323
|
+
injectStyles();
|
|
6324
|
+
let container = document.getElementById(this.containerId);
|
|
6325
|
+
if (!container) {
|
|
6326
|
+
container = document.createElement("div");
|
|
6327
|
+
container.id = this.containerId;
|
|
6328
|
+
container.className = "temp-range-tooltip";
|
|
6329
|
+
document.body.appendChild(container);
|
|
6330
|
+
}
|
|
6331
|
+
return container;
|
|
6332
|
+
},
|
|
6333
|
+
/**
|
|
6334
|
+
* Calculate temperature status and deviation
|
|
6335
|
+
*/
|
|
6336
|
+
calculateStatus(currentTemp, tempMin, tempMax) {
|
|
6337
|
+
if (tempMin == null || tempMax == null) {
|
|
6338
|
+
return { status: "unknown", deviation: null, deviationPercent: null };
|
|
6339
|
+
}
|
|
6340
|
+
const rangeSize = tempMax - tempMin;
|
|
6341
|
+
const midPoint = (tempMin + tempMax) / 2;
|
|
6342
|
+
if (currentTemp < tempMin) {
|
|
6343
|
+
const deviation = tempMin - currentTemp;
|
|
6344
|
+
const deviationPercent = rangeSize > 0 ? deviation / rangeSize * 100 : 0;
|
|
6345
|
+
return { status: "cold", deviation: -deviation, deviationPercent: -deviationPercent };
|
|
6275
6346
|
} else if (currentTemp > tempMax) {
|
|
6276
6347
|
const deviation = currentTemp - tempMax;
|
|
6277
6348
|
const deviationPercent = rangeSize > 0 ? deviation / rangeSize * 100 : 0;
|
|
@@ -6299,20 +6370,20 @@ var TempRangeTooltip = {
|
|
|
6299
6370
|
},
|
|
6300
6371
|
/**
|
|
6301
6372
|
* Show tooltip for a temperature card
|
|
6302
|
-
* @param
|
|
6303
|
-
* @param
|
|
6304
|
-
* @param
|
|
6373
|
+
* @param triggerElement - The card element
|
|
6374
|
+
* @param entityData - Entity data with temperature info
|
|
6375
|
+
* @param event - Mouse event for cursor position
|
|
6305
6376
|
*/
|
|
6306
|
-
show(triggerElement,
|
|
6377
|
+
show(triggerElement, entityData, event) {
|
|
6307
6378
|
const container = this.getContainer();
|
|
6308
|
-
const currentTemp =
|
|
6309
|
-
const tempMin
|
|
6310
|
-
const
|
|
6379
|
+
const currentTemp = extractTemperature(entityData);
|
|
6380
|
+
const { tempMin, tempMax } = extractRange(entityData);
|
|
6381
|
+
const label = extractLabel(entityData);
|
|
6311
6382
|
const hasRange = tempMin != null && tempMax != null;
|
|
6312
|
-
const { status,
|
|
6383
|
+
const { status, deviationPercent } = this.calculateStatus(currentTemp, tempMin, tempMax);
|
|
6313
6384
|
const markerPos = this.calculateMarkerPosition(currentTemp, tempMin, tempMax);
|
|
6314
6385
|
let rangeLeft = 0, rangeWidth = 100;
|
|
6315
|
-
if (hasRange) {
|
|
6386
|
+
if (hasRange && tempMin != null && tempMax != null) {
|
|
6316
6387
|
const rangeSize = tempMax - tempMin;
|
|
6317
6388
|
const extension = rangeSize * 0.3;
|
|
6318
6389
|
const visibleMin = tempMin - extension;
|
|
@@ -6321,28 +6392,23 @@ var TempRangeTooltip = {
|
|
|
6321
6392
|
rangeLeft = (tempMin - visibleMin) / visibleRange * 100;
|
|
6322
6393
|
rangeWidth = rangeSize / visibleRange * 100;
|
|
6323
6394
|
}
|
|
6324
|
-
let deviationText = "";
|
|
6325
|
-
let deviationClass = status;
|
|
6326
|
-
if (status === "cold") {
|
|
6327
|
-
deviationText = `${Math.abs(deviation).toFixed(1)}\xB0C abaixo`;
|
|
6328
|
-
} else if (status === "hot") {
|
|
6329
|
-
deviationText = `+${deviation.toFixed(1)}\xB0C acima`;
|
|
6330
|
-
} else if (status === "ok") {
|
|
6331
|
-
deviationText = "Na faixa ideal";
|
|
6332
|
-
} else {
|
|
6333
|
-
deviationText = "Faixa n\xE3o configurada";
|
|
6334
|
-
}
|
|
6335
6395
|
const statusLabels = {
|
|
6336
6396
|
cold: "\u2744\uFE0F Abaixo da Faixa Ideal",
|
|
6337
6397
|
ok: "\u2714\uFE0F Dentro da Faixa Ideal",
|
|
6338
6398
|
hot: "\u{1F525} Acima da Faixa Ideal",
|
|
6339
6399
|
unknown: "\u2753 Faixa N\xE3o Configurada"
|
|
6340
6400
|
};
|
|
6401
|
+
const statusColors = {
|
|
6402
|
+
cold: "#2563eb",
|
|
6403
|
+
ok: "#16a34a",
|
|
6404
|
+
hot: "#dc2626",
|
|
6405
|
+
unknown: "#64748b"
|
|
6406
|
+
};
|
|
6341
6407
|
container.innerHTML = `
|
|
6342
6408
|
<div class="temp-range-tooltip__content">
|
|
6343
6409
|
<div class="temp-range-tooltip__header">
|
|
6344
6410
|
<span class="temp-range-tooltip__icon">\u{1F321}\uFE0F</span>
|
|
6345
|
-
<span class="temp-range-tooltip__title">${
|
|
6411
|
+
<span class="temp-range-tooltip__title">${label}</span>
|
|
6346
6412
|
</div>
|
|
6347
6413
|
<div class="temp-range-tooltip__body">
|
|
6348
6414
|
<div class="temp-range-tooltip__value-row">
|
|
@@ -6350,7 +6416,7 @@ var TempRangeTooltip = {
|
|
|
6350
6416
|
${currentTemp.toFixed(1)}<sup>\xB0C</sup>
|
|
6351
6417
|
</div>
|
|
6352
6418
|
<div class="temp-range-tooltip__deviation">
|
|
6353
|
-
<div class="temp-range-tooltip__deviation-value ${
|
|
6419
|
+
<div class="temp-range-tooltip__deviation-value ${status}">
|
|
6354
6420
|
${status === "ok" ? "\u2713" : status === "cold" ? "\u2193" : status === "hot" ? "\u2191" : "?"} ${Math.abs(deviationPercent || 0).toFixed(0)}%
|
|
6355
6421
|
</div>
|
|
6356
6422
|
<div class="temp-range-tooltip__deviation-label">Desvio</div>
|
|
@@ -6377,7 +6443,7 @@ var TempRangeTooltip = {
|
|
|
6377
6443
|
</div>
|
|
6378
6444
|
<div class="temp-range-tooltip__range-item">
|
|
6379
6445
|
<div class="temp-range-tooltip__range-label">Atual</div>
|
|
6380
|
-
<div class="temp-range-tooltip__range-value" style="color: ${status
|
|
6446
|
+
<div class="temp-range-tooltip__range-value" style="color: ${statusColors[status]}">${currentTemp.toFixed(1)}\xB0C</div>
|
|
6381
6447
|
</div>
|
|
6382
6448
|
<div class="temp-range-tooltip__range-item">
|
|
6383
6449
|
<div class="temp-range-tooltip__range-label">M\xE1ximo</div>
|
|
@@ -6422,7 +6488,320 @@ var TempRangeTooltip = {
|
|
|
6422
6488
|
if (container) {
|
|
6423
6489
|
container.classList.remove("visible");
|
|
6424
6490
|
}
|
|
6491
|
+
},
|
|
6492
|
+
/**
|
|
6493
|
+
* Attach tooltip to an element
|
|
6494
|
+
* Returns cleanup function
|
|
6495
|
+
*/
|
|
6496
|
+
attach(element, entityData) {
|
|
6497
|
+
const showHandler = (e) => this.show(element, entityData, e);
|
|
6498
|
+
const hideHandler = () => this.hide();
|
|
6499
|
+
element.style.cursor = "help";
|
|
6500
|
+
element.addEventListener("mouseenter", showHandler);
|
|
6501
|
+
element.addEventListener("mouseleave", hideHandler);
|
|
6502
|
+
return () => {
|
|
6503
|
+
element.removeEventListener("mouseenter", showHandler);
|
|
6504
|
+
element.removeEventListener("mouseleave", hideHandler);
|
|
6505
|
+
element.style.cursor = "";
|
|
6506
|
+
this.hide();
|
|
6507
|
+
};
|
|
6508
|
+
}
|
|
6509
|
+
};
|
|
6510
|
+
|
|
6511
|
+
// src/utils/EnergyRangeTooltip.ts
|
|
6512
|
+
var ENERGY_RANGE_TOOLTIP_CSS = `
|
|
6513
|
+
/* ============================================
|
|
6514
|
+
Energy Range Tooltip (for domain=energy)
|
|
6515
|
+
Shows power ruler with current position and status ranges
|
|
6516
|
+
============================================ */
|
|
6517
|
+
.energy-range-tooltip {
|
|
6518
|
+
position: fixed;
|
|
6519
|
+
z-index: 99999;
|
|
6520
|
+
pointer-events: none;
|
|
6521
|
+
opacity: 0;
|
|
6522
|
+
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
6523
|
+
transform: translateY(5px);
|
|
6524
|
+
}
|
|
6525
|
+
|
|
6526
|
+
.energy-range-tooltip.visible {
|
|
6527
|
+
opacity: 1;
|
|
6528
|
+
pointer-events: auto;
|
|
6529
|
+
transform: translateY(0);
|
|
6530
|
+
}
|
|
6531
|
+
|
|
6532
|
+
.energy-range-tooltip__content {
|
|
6533
|
+
background: #ffffff;
|
|
6534
|
+
border: 1px solid #e2e8f0;
|
|
6535
|
+
border-radius: 12px;
|
|
6536
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
|
|
6537
|
+
min-width: 300px;
|
|
6538
|
+
max-width: 360px;
|
|
6539
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
6540
|
+
font-size: 12px;
|
|
6541
|
+
color: #1e293b;
|
|
6542
|
+
overflow: hidden;
|
|
6543
|
+
}
|
|
6544
|
+
|
|
6545
|
+
.energy-range-tooltip__header {
|
|
6546
|
+
display: flex;
|
|
6547
|
+
align-items: center;
|
|
6548
|
+
gap: 8px;
|
|
6549
|
+
padding: 12px 16px;
|
|
6550
|
+
background: linear-gradient(90deg, #ecfdf5 0%, #d1fae5 100%);
|
|
6551
|
+
border-bottom: 1px solid #6ee7b7;
|
|
6552
|
+
}
|
|
6553
|
+
|
|
6554
|
+
.energy-range-tooltip__icon {
|
|
6555
|
+
font-size: 18px;
|
|
6556
|
+
}
|
|
6557
|
+
|
|
6558
|
+
.energy-range-tooltip__title {
|
|
6559
|
+
font-weight: 700;
|
|
6560
|
+
font-size: 13px;
|
|
6561
|
+
color: #047857;
|
|
6562
|
+
}
|
|
6563
|
+
|
|
6564
|
+
.energy-range-tooltip__body {
|
|
6565
|
+
padding: 16px;
|
|
6566
|
+
}
|
|
6567
|
+
|
|
6568
|
+
/* Power value display */
|
|
6569
|
+
.energy-range-tooltip__value-row {
|
|
6570
|
+
display: flex;
|
|
6571
|
+
justify-content: space-between;
|
|
6572
|
+
align-items: center;
|
|
6573
|
+
margin-bottom: 16px;
|
|
6574
|
+
}
|
|
6575
|
+
|
|
6576
|
+
.energy-range-tooltip__current {
|
|
6577
|
+
font-size: 28px;
|
|
6578
|
+
font-weight: 700;
|
|
6579
|
+
color: #1e293b;
|
|
6580
|
+
}
|
|
6581
|
+
|
|
6582
|
+
.energy-range-tooltip__current sup {
|
|
6583
|
+
font-size: 14px;
|
|
6584
|
+
color: #64748b;
|
|
6585
|
+
}
|
|
6586
|
+
|
|
6587
|
+
.energy-range-tooltip__status-badge {
|
|
6588
|
+
text-align: right;
|
|
6589
|
+
}
|
|
6590
|
+
|
|
6591
|
+
.energy-range-tooltip__status-value {
|
|
6592
|
+
font-size: 14px;
|
|
6593
|
+
font-weight: 700;
|
|
6594
|
+
padding: 4px 10px;
|
|
6595
|
+
border-radius: 6px;
|
|
6596
|
+
}
|
|
6597
|
+
|
|
6598
|
+
.energy-range-tooltip__status-value.standby {
|
|
6599
|
+
background: #dbeafe;
|
|
6600
|
+
color: #1d4ed8;
|
|
6601
|
+
}
|
|
6602
|
+
|
|
6603
|
+
.energy-range-tooltip__status-value.normal {
|
|
6604
|
+
background: #dcfce7;
|
|
6605
|
+
color: #15803d;
|
|
6606
|
+
}
|
|
6607
|
+
|
|
6608
|
+
.energy-range-tooltip__status-value.alert {
|
|
6609
|
+
background: #fef3c7;
|
|
6610
|
+
color: #b45309;
|
|
6611
|
+
}
|
|
6612
|
+
|
|
6613
|
+
.energy-range-tooltip__status-value.failure {
|
|
6614
|
+
background: #fee2e2;
|
|
6615
|
+
color: #b91c1c;
|
|
6616
|
+
}
|
|
6617
|
+
|
|
6618
|
+
.energy-range-tooltip__status-value.offline {
|
|
6619
|
+
background: #f3f4f6;
|
|
6620
|
+
color: #6b7280;
|
|
6621
|
+
}
|
|
6622
|
+
|
|
6623
|
+
/* Power ruler/gauge */
|
|
6624
|
+
.energy-range-tooltip__ruler {
|
|
6625
|
+
position: relative;
|
|
6626
|
+
height: 40px;
|
|
6627
|
+
margin: 12px 0;
|
|
6628
|
+
border-radius: 8px;
|
|
6629
|
+
overflow: visible;
|
|
6630
|
+
}
|
|
6631
|
+
|
|
6632
|
+
.energy-range-tooltip__ruler-track {
|
|
6633
|
+
position: absolute;
|
|
6634
|
+
top: 16px;
|
|
6635
|
+
left: 0;
|
|
6636
|
+
right: 0;
|
|
6637
|
+
height: 8px;
|
|
6638
|
+
display: flex;
|
|
6639
|
+
border-radius: 4px;
|
|
6640
|
+
overflow: hidden;
|
|
6641
|
+
border: 1px solid #e2e8f0;
|
|
6642
|
+
}
|
|
6643
|
+
|
|
6644
|
+
.energy-range-tooltip__ruler-segment {
|
|
6645
|
+
height: 100%;
|
|
6646
|
+
}
|
|
6647
|
+
|
|
6648
|
+
.energy-range-tooltip__ruler-segment.standby {
|
|
6649
|
+
background: #dbeafe;
|
|
6650
|
+
}
|
|
6651
|
+
|
|
6652
|
+
.energy-range-tooltip__ruler-segment.normal {
|
|
6653
|
+
background: #dcfce7;
|
|
6654
|
+
}
|
|
6655
|
+
|
|
6656
|
+
.energy-range-tooltip__ruler-segment.alert {
|
|
6657
|
+
background: #fef3c7;
|
|
6658
|
+
}
|
|
6659
|
+
|
|
6660
|
+
.energy-range-tooltip__ruler-segment.failure {
|
|
6661
|
+
background: #fee2e2;
|
|
6662
|
+
}
|
|
6663
|
+
|
|
6664
|
+
.energy-range-tooltip__ruler-marker {
|
|
6665
|
+
position: absolute;
|
|
6666
|
+
top: 8px;
|
|
6667
|
+
width: 4px;
|
|
6668
|
+
height: 24px;
|
|
6669
|
+
background: #1e293b;
|
|
6670
|
+
border-radius: 2px;
|
|
6671
|
+
transform: translateX(-50%);
|
|
6672
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6673
|
+
}
|
|
6674
|
+
|
|
6675
|
+
.energy-range-tooltip__ruler-marker::after {
|
|
6676
|
+
content: '';
|
|
6677
|
+
position: absolute;
|
|
6678
|
+
top: -4px;
|
|
6679
|
+
left: 50%;
|
|
6680
|
+
transform: translateX(-50%);
|
|
6681
|
+
width: 12px;
|
|
6682
|
+
height: 12px;
|
|
6683
|
+
background: #1e293b;
|
|
6684
|
+
border-radius: 50%;
|
|
6685
|
+
border: 2px solid #fff;
|
|
6686
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6687
|
+
}
|
|
6688
|
+
|
|
6689
|
+
/* Range info grid */
|
|
6690
|
+
.energy-range-tooltip__ranges {
|
|
6691
|
+
display: grid;
|
|
6692
|
+
grid-template-columns: repeat(4, 1fr);
|
|
6693
|
+
gap: 8px;
|
|
6694
|
+
margin-top: 16px;
|
|
6695
|
+
}
|
|
6696
|
+
|
|
6697
|
+
.energy-range-tooltip__range-item {
|
|
6698
|
+
text-align: center;
|
|
6699
|
+
padding: 8px 4px;
|
|
6700
|
+
border-radius: 6px;
|
|
6701
|
+
background: #f8fafc;
|
|
6702
|
+
}
|
|
6703
|
+
|
|
6704
|
+
.energy-range-tooltip__range-item.standby {
|
|
6705
|
+
border-left: 3px solid #3b82f6;
|
|
6706
|
+
}
|
|
6707
|
+
|
|
6708
|
+
.energy-range-tooltip__range-item.normal {
|
|
6709
|
+
border-left: 3px solid #22c55e;
|
|
6710
|
+
}
|
|
6711
|
+
|
|
6712
|
+
.energy-range-tooltip__range-item.alert {
|
|
6713
|
+
border-left: 3px solid #f59e0b;
|
|
6714
|
+
}
|
|
6715
|
+
|
|
6716
|
+
.energy-range-tooltip__range-item.failure {
|
|
6717
|
+
border-left: 3px solid #ef4444;
|
|
6718
|
+
}
|
|
6719
|
+
|
|
6720
|
+
.energy-range-tooltip__range-label {
|
|
6721
|
+
font-size: 9px;
|
|
6722
|
+
color: #64748b;
|
|
6723
|
+
text-transform: uppercase;
|
|
6724
|
+
letter-spacing: 0.3px;
|
|
6725
|
+
margin-bottom: 2px;
|
|
6726
|
+
}
|
|
6727
|
+
|
|
6728
|
+
.energy-range-tooltip__range-value {
|
|
6729
|
+
font-size: 11px;
|
|
6730
|
+
font-weight: 600;
|
|
6731
|
+
color: #334155;
|
|
6732
|
+
}
|
|
6733
|
+
|
|
6734
|
+
/* Status info */
|
|
6735
|
+
.energy-range-tooltip__status-info {
|
|
6736
|
+
display: flex;
|
|
6737
|
+
align-items: center;
|
|
6738
|
+
justify-content: center;
|
|
6739
|
+
gap: 6px;
|
|
6740
|
+
margin-top: 12px;
|
|
6741
|
+
padding: 8px 12px;
|
|
6742
|
+
border-radius: 6px;
|
|
6743
|
+
font-size: 11px;
|
|
6744
|
+
font-weight: 600;
|
|
6745
|
+
}
|
|
6746
|
+
|
|
6747
|
+
.energy-range-tooltip__status-info.standby {
|
|
6748
|
+
background: #dbeafe;
|
|
6749
|
+
color: #1d4ed8;
|
|
6750
|
+
border: 1px solid #93c5fd;
|
|
6751
|
+
}
|
|
6752
|
+
|
|
6753
|
+
.energy-range-tooltip__status-info.normal {
|
|
6754
|
+
background: #dcfce7;
|
|
6755
|
+
color: #15803d;
|
|
6756
|
+
border: 1px solid #86efac;
|
|
6757
|
+
}
|
|
6758
|
+
|
|
6759
|
+
.energy-range-tooltip__status-info.alert {
|
|
6760
|
+
background: #fef3c7;
|
|
6761
|
+
color: #b45309;
|
|
6762
|
+
border: 1px solid #fcd34d;
|
|
6763
|
+
}
|
|
6764
|
+
|
|
6765
|
+
.energy-range-tooltip__status-info.failure {
|
|
6766
|
+
background: #fee2e2;
|
|
6767
|
+
color: #b91c1c;
|
|
6768
|
+
border: 1px solid #fca5a5;
|
|
6769
|
+
}
|
|
6770
|
+
|
|
6771
|
+
.energy-range-tooltip__status-info.offline {
|
|
6772
|
+
background: #f3f4f6;
|
|
6773
|
+
color: #6b7280;
|
|
6774
|
+
border: 1px solid #d1d5db;
|
|
6775
|
+
}
|
|
6776
|
+
`;
|
|
6777
|
+
var cssInjected = false;
|
|
6778
|
+
function injectCSS() {
|
|
6779
|
+
if (cssInjected) return;
|
|
6780
|
+
if (typeof document === "undefined") return;
|
|
6781
|
+
const styleId = "myio-energy-range-tooltip-styles";
|
|
6782
|
+
if (document.getElementById(styleId)) {
|
|
6783
|
+
cssInjected = true;
|
|
6784
|
+
return;
|
|
6425
6785
|
}
|
|
6786
|
+
const style = document.createElement("style");
|
|
6787
|
+
style.id = styleId;
|
|
6788
|
+
style.textContent = ENERGY_RANGE_TOOLTIP_CSS;
|
|
6789
|
+
document.head.appendChild(style);
|
|
6790
|
+
cssInjected = true;
|
|
6791
|
+
}
|
|
6792
|
+
var STATUS_LABELS = {
|
|
6793
|
+
standby: "Standby",
|
|
6794
|
+
normal: "Operacao Normal",
|
|
6795
|
+
alert: "Alerta",
|
|
6796
|
+
failure: "Falha",
|
|
6797
|
+
offline: "Fora da faixa"
|
|
6798
|
+
};
|
|
6799
|
+
var STATUS_INFO_LABELS = {
|
|
6800
|
+
standby: "\u{1F535} Standby",
|
|
6801
|
+
normal: "\u2705 Operacao Normal",
|
|
6802
|
+
alert: "\u26A0\uFE0F Alerta",
|
|
6803
|
+
failure: "\u{1F534} Falha",
|
|
6804
|
+
offline: "\u26AB Offline / Sem dados"
|
|
6426
6805
|
};
|
|
6427
6806
|
var EnergyRangeTooltip = {
|
|
6428
6807
|
containerId: "myio-energy-range-tooltip",
|
|
@@ -6430,6 +6809,7 @@ var EnergyRangeTooltip = {
|
|
|
6430
6809
|
* Create or get the tooltip container
|
|
6431
6810
|
*/
|
|
6432
6811
|
getContainer() {
|
|
6812
|
+
injectCSS();
|
|
6433
6813
|
let container = document.getElementById(this.containerId);
|
|
6434
6814
|
if (!container) {
|
|
6435
6815
|
container = document.createElement("div");
|
|
@@ -6449,18 +6829,18 @@ var EnergyRangeTooltip = {
|
|
|
6449
6829
|
const power = Number(powerValue) || 0;
|
|
6450
6830
|
const { standbyRange, normalRange, alertRange, failureRange } = ranges;
|
|
6451
6831
|
if (standbyRange && power >= standbyRange.down && power <= standbyRange.up) {
|
|
6452
|
-
return { status: "standby", label:
|
|
6832
|
+
return { status: "standby", label: STATUS_LABELS.standby };
|
|
6453
6833
|
}
|
|
6454
6834
|
if (normalRange && power >= normalRange.down && power <= normalRange.up) {
|
|
6455
|
-
return { status: "normal", label:
|
|
6835
|
+
return { status: "normal", label: STATUS_LABELS.normal };
|
|
6456
6836
|
}
|
|
6457
6837
|
if (alertRange && power >= alertRange.down && power <= alertRange.up) {
|
|
6458
|
-
return { status: "alert", label:
|
|
6838
|
+
return { status: "alert", label: STATUS_LABELS.alert };
|
|
6459
6839
|
}
|
|
6460
6840
|
if (failureRange && power >= failureRange.down && power <= failureRange.up) {
|
|
6461
|
-
return { status: "failure", label:
|
|
6841
|
+
return { status: "failure", label: STATUS_LABELS.failure };
|
|
6462
6842
|
}
|
|
6463
|
-
return { status: "offline", label:
|
|
6843
|
+
return { status: "offline", label: STATUS_LABELS.offline };
|
|
6464
6844
|
},
|
|
6465
6845
|
/**
|
|
6466
6846
|
* Calculate marker position on ruler (0-100%)
|
|
@@ -6491,7 +6871,7 @@ var EnergyRangeTooltip = {
|
|
|
6491
6871
|
* Format power value for display
|
|
6492
6872
|
*/
|
|
6493
6873
|
formatPower(value) {
|
|
6494
|
-
if (value == null || isNaN(value)) return "-";
|
|
6874
|
+
if (value == null || isNaN(Number(value))) return "-";
|
|
6495
6875
|
const num = Number(value);
|
|
6496
6876
|
if (num >= 1e3) {
|
|
6497
6877
|
return `${(num / 1e3).toFixed(2)} kW`;
|
|
@@ -6509,13 +6889,40 @@ var EnergyRangeTooltip = {
|
|
|
6509
6889
|
const { status, label } = this.calculateStatus(powerValue, ranges);
|
|
6510
6890
|
const markerPos = this.calculateMarkerPosition(powerValue, ranges);
|
|
6511
6891
|
const segmentWidths = this.calculateSegmentWidths(ranges);
|
|
6512
|
-
const
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6892
|
+
const rangesHtml = hasRanges && ranges ? `
|
|
6893
|
+
<div class="energy-range-tooltip__ruler">
|
|
6894
|
+
<div class="energy-range-tooltip__ruler-track">
|
|
6895
|
+
<div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
|
|
6896
|
+
<div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
|
|
6897
|
+
<div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
|
|
6898
|
+
<div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
|
|
6899
|
+
</div>
|
|
6900
|
+
<div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
|
|
6901
|
+
</div>
|
|
6902
|
+
|
|
6903
|
+
<div class="energy-range-tooltip__ranges">
|
|
6904
|
+
<div class="energy-range-tooltip__range-item standby">
|
|
6905
|
+
<div class="energy-range-tooltip__range-label">Standby</div>
|
|
6906
|
+
<div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
|
|
6907
|
+
</div>
|
|
6908
|
+
<div class="energy-range-tooltip__range-item normal">
|
|
6909
|
+
<div class="energy-range-tooltip__range-label">Normal</div>
|
|
6910
|
+
<div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
|
|
6911
|
+
</div>
|
|
6912
|
+
<div class="energy-range-tooltip__range-item alert">
|
|
6913
|
+
<div class="energy-range-tooltip__range-label">Alerta</div>
|
|
6914
|
+
<div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
|
|
6915
|
+
</div>
|
|
6916
|
+
<div class="energy-range-tooltip__range-item failure">
|
|
6917
|
+
<div class="energy-range-tooltip__range-label">Falha</div>
|
|
6918
|
+
<div class="energy-range-tooltip__range-value">>${ranges.failureRange?.down || 0}W</div>
|
|
6919
|
+
</div>
|
|
6920
|
+
</div>
|
|
6921
|
+
` : `
|
|
6922
|
+
<div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
|
|
6923
|
+
Ranges de potencia nao configurados
|
|
6924
|
+
</div>
|
|
6925
|
+
`;
|
|
6519
6926
|
container.innerHTML = `
|
|
6520
6927
|
<div class="energy-range-tooltip__content">
|
|
6521
6928
|
<div class="energy-range-tooltip__header">
|
|
@@ -6532,51 +6939,18 @@ var EnergyRangeTooltip = {
|
|
|
6532
6939
|
</div>
|
|
6533
6940
|
</div>
|
|
6534
6941
|
|
|
6535
|
-
${
|
|
6536
|
-
<div class="energy-range-tooltip__ruler">
|
|
6537
|
-
<div class="energy-range-tooltip__ruler-track">
|
|
6538
|
-
<div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
|
|
6539
|
-
<div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
|
|
6540
|
-
<div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
|
|
6541
|
-
<div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
|
|
6542
|
-
</div>
|
|
6543
|
-
<div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
|
|
6544
|
-
</div>
|
|
6545
|
-
|
|
6546
|
-
<div class="energy-range-tooltip__ranges">
|
|
6547
|
-
<div class="energy-range-tooltip__range-item standby">
|
|
6548
|
-
<div class="energy-range-tooltip__range-label">Standby</div>
|
|
6549
|
-
<div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
|
|
6550
|
-
</div>
|
|
6551
|
-
<div class="energy-range-tooltip__range-item normal">
|
|
6552
|
-
<div class="energy-range-tooltip__range-label">Normal</div>
|
|
6553
|
-
<div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
|
|
6554
|
-
</div>
|
|
6555
|
-
<div class="energy-range-tooltip__range-item alert">
|
|
6556
|
-
<div class="energy-range-tooltip__range-label">Alerta</div>
|
|
6557
|
-
<div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
|
|
6558
|
-
</div>
|
|
6559
|
-
<div class="energy-range-tooltip__range-item failure">
|
|
6560
|
-
<div class="energy-range-tooltip__range-label">Falha</div>
|
|
6561
|
-
<div class="energy-range-tooltip__range-value">>${ranges.failureRange?.down || 0}W</div>
|
|
6562
|
-
</div>
|
|
6563
|
-
</div>
|
|
6564
|
-
` : `
|
|
6565
|
-
<div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
|
|
6566
|
-
Ranges de pot\xEAncia n\xE3o configurados
|
|
6567
|
-
</div>
|
|
6568
|
-
`}
|
|
6942
|
+
${rangesHtml}
|
|
6569
6943
|
|
|
6570
6944
|
<div class="energy-range-tooltip__status-info ${status}">
|
|
6571
|
-
${
|
|
6945
|
+
${STATUS_INFO_LABELS[status] || STATUS_INFO_LABELS.offline}
|
|
6572
6946
|
</div>
|
|
6573
6947
|
</div>
|
|
6574
6948
|
</div>
|
|
6575
6949
|
`;
|
|
6576
6950
|
let left, top;
|
|
6577
6951
|
if (event && event.clientX && event.clientY) {
|
|
6578
|
-
left = event.clientX +
|
|
6579
|
-
top = event.clientY +
|
|
6952
|
+
left = event.clientX + 8;
|
|
6953
|
+
top = event.clientY + 8;
|
|
6580
6954
|
} else {
|
|
6581
6955
|
const rect = triggerElement.getBoundingClientRect();
|
|
6582
6956
|
left = rect.left + rect.width / 2 - 150;
|
|
@@ -6585,11 +6959,11 @@ var EnergyRangeTooltip = {
|
|
|
6585
6959
|
const tooltipWidth = 320;
|
|
6586
6960
|
const tooltipHeight = 380;
|
|
6587
6961
|
if (left + tooltipWidth > window.innerWidth - 10) {
|
|
6588
|
-
left = (event?.clientX || left) - tooltipWidth -
|
|
6962
|
+
left = (event?.clientX || left) - tooltipWidth - 8;
|
|
6589
6963
|
}
|
|
6590
6964
|
if (left < 10) left = 10;
|
|
6591
6965
|
if (top + tooltipHeight > window.innerHeight - 10) {
|
|
6592
|
-
top = (event?.clientY || top) - tooltipHeight -
|
|
6966
|
+
top = (event?.clientY || top) - tooltipHeight - 8;
|
|
6593
6967
|
}
|
|
6594
6968
|
if (top < 10) top = 10;
|
|
6595
6969
|
container.style.left = left + "px";
|
|
@@ -6604,8 +6978,229 @@ var EnergyRangeTooltip = {
|
|
|
6604
6978
|
if (container) {
|
|
6605
6979
|
container.classList.remove("visible");
|
|
6606
6980
|
}
|
|
6981
|
+
},
|
|
6982
|
+
/**
|
|
6983
|
+
* Attach tooltip to an element with automatic show/hide on hover
|
|
6984
|
+
* Returns cleanup function to remove event listeners
|
|
6985
|
+
*/
|
|
6986
|
+
attach(element, entityData) {
|
|
6987
|
+
const handleMouseEnter = (e) => {
|
|
6988
|
+
this.show(element, entityData, e);
|
|
6989
|
+
};
|
|
6990
|
+
const handleMouseLeave = () => {
|
|
6991
|
+
this.hide();
|
|
6992
|
+
};
|
|
6993
|
+
const handleMouseMove = (e) => {
|
|
6994
|
+
const container = document.getElementById(this.containerId);
|
|
6995
|
+
if (container && container.classList.contains("visible")) {
|
|
6996
|
+
let left = e.clientX + 8;
|
|
6997
|
+
let top = e.clientY + 8;
|
|
6998
|
+
const tooltipWidth = 320;
|
|
6999
|
+
const tooltipHeight = 380;
|
|
7000
|
+
if (left + tooltipWidth > window.innerWidth - 10) {
|
|
7001
|
+
left = e.clientX - tooltipWidth - 8;
|
|
7002
|
+
}
|
|
7003
|
+
if (left < 10) left = 10;
|
|
7004
|
+
if (top + tooltipHeight > window.innerHeight - 10) {
|
|
7005
|
+
top = e.clientY - tooltipHeight - 8;
|
|
7006
|
+
}
|
|
7007
|
+
if (top < 10) top = 10;
|
|
7008
|
+
container.style.left = left + "px";
|
|
7009
|
+
container.style.top = top + "px";
|
|
7010
|
+
}
|
|
7011
|
+
};
|
|
7012
|
+
element.addEventListener("mouseenter", handleMouseEnter);
|
|
7013
|
+
element.addEventListener("mouseleave", handleMouseLeave);
|
|
7014
|
+
element.addEventListener("mousemove", handleMouseMove);
|
|
7015
|
+
return () => {
|
|
7016
|
+
element.removeEventListener("mouseenter", handleMouseEnter);
|
|
7017
|
+
element.removeEventListener("mouseleave", handleMouseLeave);
|
|
7018
|
+
element.removeEventListener("mousemove", handleMouseMove);
|
|
7019
|
+
this.hide();
|
|
7020
|
+
};
|
|
6607
7021
|
}
|
|
6608
7022
|
};
|
|
7023
|
+
|
|
7024
|
+
// src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
|
|
7025
|
+
var LABEL_CHAR_LIMIT = 18;
|
|
7026
|
+
var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
|
|
7027
|
+
var CSS_TAG = "head-office-card-v1";
|
|
7028
|
+
function ensureCss() {
|
|
7029
|
+
if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
|
|
7030
|
+
const style = document.createElement("style");
|
|
7031
|
+
style.setAttribute("data-myio-css", CSS_TAG);
|
|
7032
|
+
style.textContent = CSS_STRING;
|
|
7033
|
+
document.head.appendChild(style);
|
|
7034
|
+
}
|
|
7035
|
+
}
|
|
7036
|
+
function normalizeParams(params) {
|
|
7037
|
+
if (!params || !params.entityObject) {
|
|
7038
|
+
throw new Error("renderCardCompenteHeadOffice: entityObject is required");
|
|
7039
|
+
}
|
|
7040
|
+
const LogHelper2 = createLogHelper(params.debugActive ?? false);
|
|
7041
|
+
const entityObject = params.entityObject;
|
|
7042
|
+
if (!entityObject.entityId) {
|
|
7043
|
+
LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
|
|
7044
|
+
entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
7045
|
+
}
|
|
7046
|
+
if (!params.delayTimeConnectionInMins) {
|
|
7047
|
+
LogHelper2.warn(
|
|
7048
|
+
`[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
|
|
7049
|
+
);
|
|
7050
|
+
}
|
|
7051
|
+
return {
|
|
7052
|
+
entityObject,
|
|
7053
|
+
i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
|
|
7054
|
+
enableSelection: Boolean(params.enableSelection),
|
|
7055
|
+
enableDragDrop: Boolean(params.enableDragDrop),
|
|
7056
|
+
useNewComponents: Boolean(params.useNewComponents),
|
|
7057
|
+
// RFC-0091: Configurable delay time for connection status check (default 15 minutes)
|
|
7058
|
+
delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
|
|
7059
|
+
// Debug options
|
|
7060
|
+
debugActive: params.debugActive ?? false,
|
|
7061
|
+
activeTooltipDebug: params.activeTooltipDebug ?? false,
|
|
7062
|
+
// LogHelper instance for this card
|
|
7063
|
+
LogHelper: LogHelper2,
|
|
7064
|
+
callbacks: {
|
|
7065
|
+
handleActionDashboard: params.handleActionDashboard,
|
|
7066
|
+
handleActionReport: params.handleActionReport,
|
|
7067
|
+
handleActionSettings: params.handleActionSettings,
|
|
7068
|
+
handleSelect: params.handleSelect,
|
|
7069
|
+
handInfo: params.handInfo,
|
|
7070
|
+
handleClickCard: params.handleClickCard
|
|
7071
|
+
}
|
|
7072
|
+
};
|
|
7073
|
+
}
|
|
7074
|
+
function getIconSvg(deviceType, domain) {
|
|
7075
|
+
if (domain === "water") {
|
|
7076
|
+
return Icons.waterDrop;
|
|
7077
|
+
}
|
|
7078
|
+
if (domain === "temperature") {
|
|
7079
|
+
return Icons.thermometer;
|
|
7080
|
+
}
|
|
7081
|
+
return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
|
|
7082
|
+
}
|
|
7083
|
+
function formatPower(valueInWatts) {
|
|
7084
|
+
if (valueInWatts === null || valueInWatts === void 0 || isNaN(valueInWatts)) {
|
|
7085
|
+
return { num: "-", unit: "" };
|
|
7086
|
+
}
|
|
7087
|
+
const val = Number(valueInWatts);
|
|
7088
|
+
if (val >= 1e3) {
|
|
7089
|
+
const kw = Math.ceil(val / 1e3 * 100) / 100;
|
|
7090
|
+
return { num: kw.toFixed(2), unit: "kW" };
|
|
7091
|
+
} else {
|
|
7092
|
+
const w = Math.ceil(val);
|
|
7093
|
+
return { num: w.toString(), unit: "W" };
|
|
7094
|
+
}
|
|
7095
|
+
}
|
|
7096
|
+
function formatValueByDomain(value, domain) {
|
|
7097
|
+
if (domain === "water") {
|
|
7098
|
+
return formatWaterVolumeM3(value);
|
|
7099
|
+
}
|
|
7100
|
+
if (domain === "temperature") {
|
|
7101
|
+
return formatTemperature(value, 0);
|
|
7102
|
+
}
|
|
7103
|
+
return formatEnergy(value);
|
|
7104
|
+
}
|
|
7105
|
+
function formatRelativeTime2(timestamp) {
|
|
7106
|
+
if (!timestamp || isNaN(timestamp)) return "\u2014";
|
|
7107
|
+
const date = new Date(timestamp);
|
|
7108
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
7109
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
7110
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
7111
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
7112
|
+
const year = date.getFullYear();
|
|
7113
|
+
return `${hours}:${minutes} ${day}/${month}/${year}`;
|
|
7114
|
+
}
|
|
7115
|
+
function calculateConsumptionPercentage(target, consumption) {
|
|
7116
|
+
const numericTarget = Number(target);
|
|
7117
|
+
const numericConsumption = Number(consumption);
|
|
7118
|
+
if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
|
|
7119
|
+
return 0;
|
|
7120
|
+
}
|
|
7121
|
+
const percentage = numericConsumption / numericTarget * 100;
|
|
7122
|
+
return percentage;
|
|
7123
|
+
}
|
|
7124
|
+
function getStatusInfo(deviceStatus, i18n, domain) {
|
|
7125
|
+
switch (deviceStatus) {
|
|
7126
|
+
// --- Novos Status de Temperatura ---
|
|
7127
|
+
case "normal":
|
|
7128
|
+
return { chipClass: "chip--ok", label: "Normal" };
|
|
7129
|
+
case "cold":
|
|
7130
|
+
return { chipClass: "chip--standby", label: "Frio" };
|
|
7131
|
+
case "hot":
|
|
7132
|
+
return { chipClass: "chip--alert", label: "Quente" };
|
|
7133
|
+
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
7134
|
+
case DeviceStatusType.POWER_ON:
|
|
7135
|
+
if (domain === "water") {
|
|
7136
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation_water };
|
|
7137
|
+
}
|
|
7138
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation };
|
|
7139
|
+
case DeviceStatusType.STANDBY:
|
|
7140
|
+
return { chipClass: "chip--standby", label: i18n.standby };
|
|
7141
|
+
case DeviceStatusType.WARNING:
|
|
7142
|
+
return { chipClass: "chip--warning", label: i18n.alert };
|
|
7143
|
+
case DeviceStatusType.MAINTENANCE:
|
|
7144
|
+
return { chipClass: "chip--maintenance", label: i18n.maintenance };
|
|
7145
|
+
case DeviceStatusType.FAILURE:
|
|
7146
|
+
return { chipClass: "chip--failure", label: i18n.failure };
|
|
7147
|
+
case DeviceStatusType.POWER_OFF:
|
|
7148
|
+
return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
|
|
7149
|
+
case DeviceStatusType.OFFLINE:
|
|
7150
|
+
return { chipClass: "chip--offline", label: i18n.offline };
|
|
7151
|
+
case DeviceStatusType.NO_INFO:
|
|
7152
|
+
return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
|
|
7153
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
7154
|
+
return { chipClass: "chip--not-installed", label: i18n.not_installed };
|
|
7155
|
+
default:
|
|
7156
|
+
return { chipClass: "chip--offline", label: i18n.offline };
|
|
7157
|
+
}
|
|
7158
|
+
}
|
|
7159
|
+
function getCardStateClass(deviceStatus) {
|
|
7160
|
+
switch (deviceStatus) {
|
|
7161
|
+
case DeviceStatusType.POWER_ON:
|
|
7162
|
+
return "is-power-on";
|
|
7163
|
+
// Blue border
|
|
7164
|
+
case DeviceStatusType.STANDBY:
|
|
7165
|
+
return "is-standby";
|
|
7166
|
+
// Green border
|
|
7167
|
+
case DeviceStatusType.WARNING:
|
|
7168
|
+
return "is-warning";
|
|
7169
|
+
// Yellow border
|
|
7170
|
+
case DeviceStatusType.MAINTENANCE:
|
|
7171
|
+
return "is-maintenance";
|
|
7172
|
+
// Yellow border
|
|
7173
|
+
case DeviceStatusType.FAILURE:
|
|
7174
|
+
return "is-failure";
|
|
7175
|
+
// Dark Red border
|
|
7176
|
+
case DeviceStatusType.POWER_OFF:
|
|
7177
|
+
return "is-power-off";
|
|
7178
|
+
// Light Red border
|
|
7179
|
+
case DeviceStatusType.OFFLINE:
|
|
7180
|
+
return "is-offline";
|
|
7181
|
+
// Dark Gray border
|
|
7182
|
+
case DeviceStatusType.NO_INFO:
|
|
7183
|
+
return "is-no-info";
|
|
7184
|
+
// Dark Orange border
|
|
7185
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
7186
|
+
return "is-not-installed";
|
|
7187
|
+
// Purple border
|
|
7188
|
+
default:
|
|
7189
|
+
return "";
|
|
7190
|
+
}
|
|
7191
|
+
}
|
|
7192
|
+
function getTempRangeClass(entityObject) {
|
|
7193
|
+
if (entityObject.domain !== "temperature") return "";
|
|
7194
|
+
const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
|
|
7195
|
+
const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
|
|
7196
|
+
const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
|
|
7197
|
+
if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
|
|
7198
|
+
return "";
|
|
7199
|
+
}
|
|
7200
|
+
if (currentTemp > tempMax) return "is-temp-hot";
|
|
7201
|
+
if (currentTemp < tempMin) return "is-temp-cold";
|
|
7202
|
+
return "is-temp-ok";
|
|
7203
|
+
}
|
|
6609
7204
|
function getStatusDotClass(deviceStatus) {
|
|
6610
7205
|
switch (deviceStatus) {
|
|
6611
7206
|
// --- Novos Status de Temperatura ---
|
|
@@ -7726,6 +8321,7 @@ function renderCardComponentV5({
|
|
|
7726
8321
|
};
|
|
7727
8322
|
const isTankDevice = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
|
|
7728
8323
|
const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
|
|
8324
|
+
const isEnergyDeviceFlag = isEnergyDevice(deviceType);
|
|
7729
8325
|
const percentageForDisplay = isTankDevice ? (waterPercentage || 0) * 100 : perc;
|
|
7730
8326
|
const calculateTempStatus = () => {
|
|
7731
8327
|
if (temperatureStatus) return temperatureStatus;
|
|
@@ -7742,33 +8338,6 @@ function renderCardComponentV5({
|
|
|
7742
8338
|
tempStatus,
|
|
7743
8339
|
isOffline
|
|
7744
8340
|
});
|
|
7745
|
-
const getTemperatureTooltip = () => {
|
|
7746
|
-
if (!isTermostatoDevice) return "";
|
|
7747
|
-
const currentTemp = Number(val) || 0;
|
|
7748
|
-
const hasRange = temperatureMin !== void 0 && temperatureMax !== void 0 && temperatureMin !== null && temperatureMax !== null;
|
|
7749
|
-
if (isOffline) {
|
|
7750
|
-
return "Dispositivo offline";
|
|
7751
|
-
}
|
|
7752
|
-
if (!hasRange) {
|
|
7753
|
-
return `Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7754
|
-
Faixa n\xE3o configurada`;
|
|
7755
|
-
}
|
|
7756
|
-
const rangeText = `Faixa ideal: ${temperatureMin}\xB0C a ${temperatureMax}\xB0C`;
|
|
7757
|
-
if (tempStatus === "above") {
|
|
7758
|
-
return `ACIMA da faixa ideal
|
|
7759
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7760
|
-
${rangeText}`;
|
|
7761
|
-
} else if (tempStatus === "below") {
|
|
7762
|
-
return `ABAIXO da faixa ideal
|
|
7763
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7764
|
-
${rangeText}`;
|
|
7765
|
-
} else {
|
|
7766
|
-
return `DENTRO da faixa ideal
|
|
7767
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7768
|
-
${rangeText}`;
|
|
7769
|
-
}
|
|
7770
|
-
};
|
|
7771
|
-
const temperatureTooltip = getTemperatureTooltip();
|
|
7772
8341
|
const cardHTML = `
|
|
7773
8342
|
<div class="device-card-centered clickable ${cardEntity.status === "offline" ? "offline" : ""}"
|
|
7774
8343
|
data-entity-id="${entityId}"
|
|
@@ -7794,7 +8363,7 @@ ${rangeText}`;
|
|
|
7794
8363
|
` : ""}
|
|
7795
8364
|
</div>
|
|
7796
8365
|
|
|
7797
|
-
<img class="device-image
|
|
8366
|
+
<img class="device-image ${isTermostatoDevice ? "temp-tooltip-trigger" : ""}${isEnergyDeviceFlag ? " energy-tooltip-trigger" : ""}" src="${deviceImageUrl}" alt="${deviceType}" style="${isTermostatoDevice || isEnergyDeviceFlag ? "cursor: help;" : ""}" />
|
|
7798
8367
|
|
|
7799
8368
|
|
|
7800
8369
|
${customerName && String(customerName).trim() !== "" ? `
|
|
@@ -8358,6 +8927,33 @@ ${rangeText}`;
|
|
|
8358
8927
|
}
|
|
8359
8928
|
});
|
|
8360
8929
|
}
|
|
8930
|
+
const tempTooltipTrigger = enhancedCardElement.querySelector(".temp-tooltip-trigger");
|
|
8931
|
+
let tempTooltipCleanup = null;
|
|
8932
|
+
if (tempTooltipTrigger && isTermostatoDevice) {
|
|
8933
|
+
const tooltipEntityData = {
|
|
8934
|
+
val,
|
|
8935
|
+
temperatureMin,
|
|
8936
|
+
temperatureMax,
|
|
8937
|
+
labelOrName: cardEntity.name,
|
|
8938
|
+
name: cardEntity.name
|
|
8939
|
+
};
|
|
8940
|
+
tempTooltipCleanup = TempRangeTooltip.attach(tempTooltipTrigger, tooltipEntityData);
|
|
8941
|
+
}
|
|
8942
|
+
const energyTooltipTrigger = enhancedCardElement.querySelector(".energy-tooltip-trigger");
|
|
8943
|
+
let energyTooltipCleanup = null;
|
|
8944
|
+
if (energyTooltipTrigger && isEnergyDeviceFlag) {
|
|
8945
|
+
const energyTooltipData = {
|
|
8946
|
+
labelOrName: cardEntity.name,
|
|
8947
|
+
name: cardEntity.name,
|
|
8948
|
+
instantaneousPower: entityObject.instantaneousPower ?? entityObject.consumption_power ?? val,
|
|
8949
|
+
powerRanges: entityObject.powerRanges || entityObject.ranges
|
|
8950
|
+
};
|
|
8951
|
+
energyTooltipCleanup = EnergyRangeTooltip.attach(energyTooltipTrigger, energyTooltipData);
|
|
8952
|
+
}
|
|
8953
|
+
container._cleanup = () => {
|
|
8954
|
+
if (tempTooltipCleanup) tempTooltipCleanup();
|
|
8955
|
+
if (energyTooltipCleanup) energyTooltipCleanup();
|
|
8956
|
+
};
|
|
8361
8957
|
const jQueryLikeObject = {
|
|
8362
8958
|
get: (index) => index === 0 ? container : void 0,
|
|
8363
8959
|
0: container,
|
|
@@ -11342,7 +11938,7 @@ var chartJsLoaded = false;
|
|
|
11342
11938
|
var zoomPluginLoaded = false;
|
|
11343
11939
|
var jsPdfLoaded = false;
|
|
11344
11940
|
var _jspdfPromise = null;
|
|
11345
|
-
var
|
|
11941
|
+
var cssInjected2 = false;
|
|
11346
11942
|
var STRINGS2 = {
|
|
11347
11943
|
"pt-BR": {
|
|
11348
11944
|
title: "Demanda",
|
|
@@ -11518,8 +12114,8 @@ function ensureRoom(doc, nextY, minRoom = 40) {
|
|
|
11518
12114
|
}
|
|
11519
12115
|
return nextY;
|
|
11520
12116
|
}
|
|
11521
|
-
function
|
|
11522
|
-
if (
|
|
12117
|
+
function injectCSS2(styles) {
|
|
12118
|
+
if (cssInjected2) return;
|
|
11523
12119
|
const css = `
|
|
11524
12120
|
.myio-demand-modal-overlay {
|
|
11525
12121
|
position: fixed;
|
|
@@ -11914,7 +12510,7 @@ function injectCSS(styles) {
|
|
|
11914
12510
|
const style = document.createElement("style");
|
|
11915
12511
|
style.textContent = css;
|
|
11916
12512
|
document.head.appendChild(style);
|
|
11917
|
-
|
|
12513
|
+
cssInjected2 = true;
|
|
11918
12514
|
}
|
|
11919
12515
|
function formatDate2(date, locale) {
|
|
11920
12516
|
return date.toLocaleDateString(locale, {
|
|
@@ -12096,7 +12692,7 @@ async function openDemandModal(params) {
|
|
|
12096
12692
|
const locale = params.locale || "pt-BR";
|
|
12097
12693
|
const strings = STRINGS2[locale] || STRINGS2["pt-BR"];
|
|
12098
12694
|
await loadExternalLibraries();
|
|
12099
|
-
|
|
12695
|
+
injectCSS2(styles);
|
|
12100
12696
|
const container = typeof params.container === "string" ? document.querySelector(params.container) : params.container || document.body;
|
|
12101
12697
|
if (!container) {
|
|
12102
12698
|
throw new Error("Container element not found");
|
|
@@ -21745,7 +22341,7 @@ async function createInputDateRangePickerInsideDIV(params) {
|
|
|
21745
22341
|
placeholder = "Clique para selecionar per\xEDodo",
|
|
21746
22342
|
pickerOptions = {},
|
|
21747
22343
|
classNames = {},
|
|
21748
|
-
injectStyles = true,
|
|
22344
|
+
injectStyles: injectStyles2 = true,
|
|
21749
22345
|
showHelper = true
|
|
21750
22346
|
} = params;
|
|
21751
22347
|
validateId(containerId, "containerId");
|
|
@@ -21754,7 +22350,7 @@ async function createInputDateRangePickerInsideDIV(params) {
|
|
|
21754
22350
|
if (!container) {
|
|
21755
22351
|
throw new Error(`[createInputDateRangePickerInsideDIV] Container '#${containerId}' not found`);
|
|
21756
22352
|
}
|
|
21757
|
-
if (
|
|
22353
|
+
if (injectStyles2) {
|
|
21758
22354
|
injectPremiumStyles();
|
|
21759
22355
|
}
|
|
21760
22356
|
let inputEl = document.getElementById(inputId);
|
|
@@ -21949,7 +22545,7 @@ function openGoalsPanel(params) {
|
|
|
21949
22545
|
modal.setAttribute("aria-labelledby", "goals-modal-title");
|
|
21950
22546
|
modal.innerHTML = generateModalHTML();
|
|
21951
22547
|
document.body.appendChild(modal);
|
|
21952
|
-
|
|
22548
|
+
injectStyles2();
|
|
21953
22549
|
attachEventListeners();
|
|
21954
22550
|
trapFocus(modal);
|
|
21955
22551
|
renderTabContent();
|
|
@@ -22702,7 +23298,7 @@ function openGoalsPanel(params) {
|
|
|
22702
23298
|
maximumFractionDigits: 2
|
|
22703
23299
|
}).format(value);
|
|
22704
23300
|
}
|
|
22705
|
-
function
|
|
23301
|
+
function injectStyles2() {
|
|
22706
23302
|
const styleId = "myio-goals-panel-styles";
|
|
22707
23303
|
if (document.getElementById(styleId)) return;
|
|
22708
23304
|
const style = document.createElement("style");
|
|
@@ -24959,7 +25555,7 @@ var LIGHT_THEME2 = {
|
|
|
24959
25555
|
function getColors(theme) {
|
|
24960
25556
|
return theme === "dark" ? DARK_THEME2 : LIGHT_THEME2;
|
|
24961
25557
|
}
|
|
24962
|
-
async function fetchCustomerAttributes(customerId, token) {
|
|
25558
|
+
async function fetchCustomerAttributes(customerId, token, onError) {
|
|
24963
25559
|
const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/values/attributes/SERVER_SCOPE`;
|
|
24964
25560
|
const response = await fetch(url, {
|
|
24965
25561
|
method: "GET",
|
|
@@ -24972,6 +25568,10 @@ async function fetchCustomerAttributes(customerId, token) {
|
|
|
24972
25568
|
if (response.status === 404 || response.status === 400) {
|
|
24973
25569
|
return { minTemperature: null, maxTemperature: null };
|
|
24974
25570
|
}
|
|
25571
|
+
if (onError) {
|
|
25572
|
+
onError({ status: response.status, message: `Failed to fetch attributes: ${response.status}` });
|
|
25573
|
+
return { minTemperature: null, maxTemperature: null };
|
|
25574
|
+
}
|
|
24975
25575
|
throw new Error(`Failed to fetch attributes: ${response.status}`);
|
|
24976
25576
|
}
|
|
24977
25577
|
const attributes = await response.json();
|
|
@@ -24988,7 +25588,7 @@ async function fetchCustomerAttributes(customerId, token) {
|
|
|
24988
25588
|
}
|
|
24989
25589
|
return { minTemperature, maxTemperature };
|
|
24990
25590
|
}
|
|
24991
|
-
async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature) {
|
|
25591
|
+
async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature, onError) {
|
|
24992
25592
|
const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/SERVER_SCOPE`;
|
|
24993
25593
|
const attributes = {
|
|
24994
25594
|
minTemperature,
|
|
@@ -25003,6 +25603,10 @@ async function saveCustomerAttributes(customerId, token, minTemperature, maxTemp
|
|
|
25003
25603
|
body: JSON.stringify(attributes)
|
|
25004
25604
|
});
|
|
25005
25605
|
if (!response.ok) {
|
|
25606
|
+
if (onError) {
|
|
25607
|
+
onError({ status: response.status, message: `Failed to save attributes: ${response.status}` });
|
|
25608
|
+
return;
|
|
25609
|
+
}
|
|
25006
25610
|
throw new Error(`Failed to save attributes: ${response.status}`);
|
|
25007
25611
|
}
|
|
25008
25612
|
}
|
|
@@ -25419,7 +26023,7 @@ function openTemperatureSettingsModal(params) {
|
|
|
25419
26023
|
state.successMessage = null;
|
|
25420
26024
|
renderModal3(container, state, modalId, destroy, handleSave);
|
|
25421
26025
|
try {
|
|
25422
|
-
await saveCustomerAttributes(state.customerId, state.token, min, max);
|
|
26026
|
+
await saveCustomerAttributes(state.customerId, state.token, min, max, params.onError);
|
|
25423
26027
|
state.minTemperature = min;
|
|
25424
26028
|
state.maxTemperature = max;
|
|
25425
26029
|
state.isSaving = false;
|
|
@@ -25436,7 +26040,7 @@ function openTemperatureSettingsModal(params) {
|
|
|
25436
26040
|
}
|
|
25437
26041
|
};
|
|
25438
26042
|
renderModal3(container, state, modalId, destroy, handleSave);
|
|
25439
|
-
fetchCustomerAttributes(state.customerId, state.token).then(({ minTemperature, maxTemperature }) => {
|
|
26043
|
+
fetchCustomerAttributes(state.customerId, state.token, params.onError).then(({ minTemperature, maxTemperature }) => {
|
|
25440
26044
|
state.minTemperature = minTemperature;
|
|
25441
26045
|
state.maxTemperature = maxTemperature;
|
|
25442
26046
|
state.isLoading = false;
|
|
@@ -27597,7 +28201,7 @@ function createConsumptionChartWidget(config) {
|
|
|
27597
28201
|
</div>
|
|
27598
28202
|
`;
|
|
27599
28203
|
}
|
|
27600
|
-
function
|
|
28204
|
+
function injectStyles2() {
|
|
27601
28205
|
if (styleElement) return;
|
|
27602
28206
|
styleElement = document.createElement("style");
|
|
27603
28207
|
styleElement.id = `${widgetId}-styles`;
|
|
@@ -28079,7 +28683,7 @@ function createConsumptionChartWidget(config) {
|
|
|
28079
28683
|
console.error(`[ConsumptionWidget] Container #${config.containerId} not found`);
|
|
28080
28684
|
return;
|
|
28081
28685
|
}
|
|
28082
|
-
|
|
28686
|
+
injectStyles2();
|
|
28083
28687
|
containerElement.innerHTML = renderHTML();
|
|
28084
28688
|
setupListeners();
|
|
28085
28689
|
setLoading(true);
|
|
@@ -29219,6 +29823,7 @@ function createDistributionChartWidget(config) {
|
|
|
29219
29823
|
EXPORT_DOMAIN_ICONS,
|
|
29220
29824
|
EXPORT_DOMAIN_LABELS,
|
|
29221
29825
|
EXPORT_DOMAIN_UNITS,
|
|
29826
|
+
EnergyRangeTooltip,
|
|
29222
29827
|
MyIOChartModal,
|
|
29223
29828
|
MyIODraggableCard,
|
|
29224
29829
|
MyIOSelectionStore,
|
|
@@ -29227,6 +29832,7 @@ function createDistributionChartWidget(config) {
|
|
|
29227
29832
|
POWER_LIMITS_DEVICE_TYPES,
|
|
29228
29833
|
POWER_LIMITS_STATUS_CONFIG,
|
|
29229
29834
|
POWER_LIMITS_TELEMETRY_TYPES,
|
|
29835
|
+
TempRangeTooltip,
|
|
29230
29836
|
addDetectionContext,
|
|
29231
29837
|
addNamespace,
|
|
29232
29838
|
aggregateByDay,
|