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.js
CHANGED
|
@@ -1538,11 +1538,11 @@ function buildEntityMapFromDatasource(datasources) {
|
|
|
1538
1538
|
const dsArray = Array.isArray(datasources) ? datasources : [];
|
|
1539
1539
|
const map = /* @__PURE__ */ new Map();
|
|
1540
1540
|
dsArray.forEach((ds) => {
|
|
1541
|
-
const entityId = ds?.entityId;
|
|
1541
|
+
const entityId = ds?.entity?.id?.id || ds?.entity?.id || ds?.entityId || null;
|
|
1542
1542
|
if (!entityId) return;
|
|
1543
1543
|
if (!map.has(entityId)) {
|
|
1544
1544
|
const entity = ds?.entity;
|
|
1545
|
-
const draftLabel = entity?.label || entity?.name || ds?.name || null;
|
|
1545
|
+
const draftLabel = entity?.label || entity?.name || ds?.entityLabel || ds?.name || null;
|
|
1546
1546
|
map.set(entityId, {
|
|
1547
1547
|
id: entityId,
|
|
1548
1548
|
identifier: null,
|
|
@@ -1564,7 +1564,7 @@ function buildEntityMapFromDatasource(datasources) {
|
|
|
1564
1564
|
function hydrateEntityMapWithCtxData(data, map) {
|
|
1565
1565
|
const rows = Array.isArray(data) ? data : [];
|
|
1566
1566
|
rows.forEach((row) => {
|
|
1567
|
-
const entityId = row?.datasource?.entityId || null;
|
|
1567
|
+
const entityId = row?.datasource?.entity?.id?.id || row?.datasource?.entity?.id || row?.datasource?.entityId || null;
|
|
1568
1568
|
if (!entityId || !map.has(entityId)) return;
|
|
1569
1569
|
const rawKey = row?.dataKey?.name || "";
|
|
1570
1570
|
if (!rawKey) return;
|
|
@@ -5919,214 +5919,283 @@ function createLogHelper(debugActive = false) {
|
|
|
5919
5919
|
}
|
|
5920
5920
|
var LogHelper = createLogHelper(false);
|
|
5921
5921
|
|
|
5922
|
-
// src/
|
|
5923
|
-
var
|
|
5924
|
-
|
|
5925
|
-
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
|
|
5929
|
-
|
|
5930
|
-
|
|
5931
|
-
document.head.appendChild(style);
|
|
5932
|
-
}
|
|
5922
|
+
// src/utils/TempRangeTooltip.ts
|
|
5923
|
+
var TOOLTIP_STYLES = `
|
|
5924
|
+
.temp-range-tooltip {
|
|
5925
|
+
position: fixed;
|
|
5926
|
+
z-index: 99999;
|
|
5927
|
+
pointer-events: none;
|
|
5928
|
+
opacity: 0;
|
|
5929
|
+
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
5930
|
+
transform: translateY(5px);
|
|
5933
5931
|
}
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
5937
|
-
|
|
5938
|
-
|
|
5939
|
-
const entityObject = params.entityObject;
|
|
5940
|
-
if (!entityObject.entityId) {
|
|
5941
|
-
LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
|
|
5942
|
-
entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
5943
|
-
}
|
|
5944
|
-
if (!params.delayTimeConnectionInMins) {
|
|
5945
|
-
LogHelper2.warn(
|
|
5946
|
-
`[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
|
|
5947
|
-
);
|
|
5948
|
-
}
|
|
5949
|
-
return {
|
|
5950
|
-
entityObject,
|
|
5951
|
-
i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
|
|
5952
|
-
enableSelection: Boolean(params.enableSelection),
|
|
5953
|
-
enableDragDrop: Boolean(params.enableDragDrop),
|
|
5954
|
-
useNewComponents: Boolean(params.useNewComponents),
|
|
5955
|
-
// RFC-0091: Configurable delay time for connection status check (default 15 minutes)
|
|
5956
|
-
delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
|
|
5957
|
-
// Debug options
|
|
5958
|
-
debugActive: params.debugActive ?? false,
|
|
5959
|
-
activeTooltipDebug: params.activeTooltipDebug ?? false,
|
|
5960
|
-
// LogHelper instance for this card
|
|
5961
|
-
LogHelper: LogHelper2,
|
|
5962
|
-
callbacks: {
|
|
5963
|
-
handleActionDashboard: params.handleActionDashboard,
|
|
5964
|
-
handleActionReport: params.handleActionReport,
|
|
5965
|
-
handleActionSettings: params.handleActionSettings,
|
|
5966
|
-
handleSelect: params.handleSelect,
|
|
5967
|
-
handInfo: params.handInfo,
|
|
5968
|
-
handleClickCard: params.handleClickCard
|
|
5969
|
-
}
|
|
5970
|
-
};
|
|
5932
|
+
|
|
5933
|
+
.temp-range-tooltip.visible {
|
|
5934
|
+
opacity: 1;
|
|
5935
|
+
pointer-events: auto;
|
|
5936
|
+
transform: translateY(0);
|
|
5971
5937
|
}
|
|
5972
|
-
|
|
5973
|
-
|
|
5974
|
-
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5938
|
+
|
|
5939
|
+
.temp-range-tooltip__content {
|
|
5940
|
+
background: #ffffff;
|
|
5941
|
+
border: 1px solid #e2e8f0;
|
|
5942
|
+
border-radius: 12px;
|
|
5943
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
|
|
5944
|
+
min-width: 280px;
|
|
5945
|
+
max-width: 320px;
|
|
5946
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
5947
|
+
font-size: 12px;
|
|
5948
|
+
color: #1e293b;
|
|
5949
|
+
overflow: hidden;
|
|
5980
5950
|
}
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
} else {
|
|
5990
|
-
const w = Math.ceil(val);
|
|
5991
|
-
return { num: w.toString(), unit: "W" };
|
|
5992
|
-
}
|
|
5951
|
+
|
|
5952
|
+
.temp-range-tooltip__header {
|
|
5953
|
+
display: flex;
|
|
5954
|
+
align-items: center;
|
|
5955
|
+
gap: 8px;
|
|
5956
|
+
padding: 12px 16px;
|
|
5957
|
+
background: linear-gradient(90deg, #fff7ed 0%, #fed7aa 100%);
|
|
5958
|
+
border-bottom: 1px solid #fdba74;
|
|
5993
5959
|
}
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
}
|
|
5998
|
-
if (domain === "temperature") {
|
|
5999
|
-
return formatTemperature(value, 0);
|
|
6000
|
-
}
|
|
6001
|
-
return formatEnergy(value);
|
|
5960
|
+
|
|
5961
|
+
.temp-range-tooltip__icon {
|
|
5962
|
+
font-size: 18px;
|
|
6002
5963
|
}
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
6009
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
6010
|
-
const year = date.getFullYear();
|
|
6011
|
-
return `${hours}:${minutes} ${day}/${month}/${year}`;
|
|
5964
|
+
|
|
5965
|
+
.temp-range-tooltip__title {
|
|
5966
|
+
font-weight: 700;
|
|
5967
|
+
font-size: 13px;
|
|
5968
|
+
color: #c2410c;
|
|
6012
5969
|
}
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
|
|
6017
|
-
return 0;
|
|
6018
|
-
}
|
|
6019
|
-
const percentage = numericConsumption / numericTarget * 100;
|
|
6020
|
-
return percentage;
|
|
5970
|
+
|
|
5971
|
+
.temp-range-tooltip__body {
|
|
5972
|
+
padding: 16px;
|
|
6021
5973
|
}
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6025
|
-
|
|
6026
|
-
|
|
6027
|
-
|
|
6028
|
-
return { chipClass: "chip--standby", label: "Frio" };
|
|
6029
|
-
case "hot":
|
|
6030
|
-
return { chipClass: "chip--alert", label: "Quente" };
|
|
6031
|
-
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
6032
|
-
case DeviceStatusType.POWER_ON:
|
|
6033
|
-
if (domain === "water") {
|
|
6034
|
-
return { chipClass: "chip--power-on", label: i18n.in_operation_water };
|
|
6035
|
-
}
|
|
6036
|
-
return { chipClass: "chip--power-on", label: i18n.in_operation };
|
|
6037
|
-
case DeviceStatusType.STANDBY:
|
|
6038
|
-
return { chipClass: "chip--standby", label: i18n.standby };
|
|
6039
|
-
case DeviceStatusType.WARNING:
|
|
6040
|
-
return { chipClass: "chip--warning", label: i18n.alert };
|
|
6041
|
-
case DeviceStatusType.MAINTENANCE:
|
|
6042
|
-
return { chipClass: "chip--maintenance", label: i18n.maintenance };
|
|
6043
|
-
case DeviceStatusType.FAILURE:
|
|
6044
|
-
return { chipClass: "chip--failure", label: i18n.failure };
|
|
6045
|
-
case DeviceStatusType.POWER_OFF:
|
|
6046
|
-
return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
|
|
6047
|
-
case DeviceStatusType.OFFLINE:
|
|
6048
|
-
return { chipClass: "chip--offline", label: i18n.offline };
|
|
6049
|
-
case DeviceStatusType.NO_INFO:
|
|
6050
|
-
return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
|
|
6051
|
-
case DeviceStatusType.NOT_INSTALLED:
|
|
6052
|
-
return { chipClass: "chip--not-installed", label: i18n.not_installed };
|
|
6053
|
-
default:
|
|
6054
|
-
return { chipClass: "chip--offline", label: i18n.offline };
|
|
6055
|
-
}
|
|
5974
|
+
|
|
5975
|
+
.temp-range-tooltip__value-row {
|
|
5976
|
+
display: flex;
|
|
5977
|
+
justify-content: space-between;
|
|
5978
|
+
align-items: center;
|
|
5979
|
+
margin-bottom: 16px;
|
|
6056
5980
|
}
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
case DeviceStatusType.STANDBY:
|
|
6063
|
-
return "is-standby";
|
|
6064
|
-
// Green border
|
|
6065
|
-
case DeviceStatusType.WARNING:
|
|
6066
|
-
return "is-warning";
|
|
6067
|
-
// Yellow border
|
|
6068
|
-
case DeviceStatusType.MAINTENANCE:
|
|
6069
|
-
return "is-maintenance";
|
|
6070
|
-
// Yellow border
|
|
6071
|
-
case DeviceStatusType.FAILURE:
|
|
6072
|
-
return "is-failure";
|
|
6073
|
-
// Dark Red border
|
|
6074
|
-
case DeviceStatusType.POWER_OFF:
|
|
6075
|
-
return "is-power-off";
|
|
6076
|
-
// Light Red border
|
|
6077
|
-
case DeviceStatusType.OFFLINE:
|
|
6078
|
-
return "is-offline";
|
|
6079
|
-
// Dark Gray border
|
|
6080
|
-
case DeviceStatusType.NO_INFO:
|
|
6081
|
-
return "is-no-info";
|
|
6082
|
-
// Dark Orange border
|
|
6083
|
-
case DeviceStatusType.NOT_INSTALLED:
|
|
6084
|
-
return "is-not-installed";
|
|
6085
|
-
// Purple border
|
|
6086
|
-
default:
|
|
6087
|
-
return "";
|
|
6088
|
-
}
|
|
5981
|
+
|
|
5982
|
+
.temp-range-tooltip__current {
|
|
5983
|
+
font-size: 28px;
|
|
5984
|
+
font-weight: 700;
|
|
5985
|
+
color: #1e293b;
|
|
6089
5986
|
}
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
|
|
6095
|
-
if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
|
|
6096
|
-
return "";
|
|
6097
|
-
}
|
|
6098
|
-
if (currentTemp > tempMax) return "is-temp-hot";
|
|
6099
|
-
if (currentTemp < tempMin) return "is-temp-cold";
|
|
6100
|
-
return "is-temp-ok";
|
|
5987
|
+
|
|
5988
|
+
.temp-range-tooltip__current sup {
|
|
5989
|
+
font-size: 14px;
|
|
5990
|
+
color: #64748b;
|
|
6101
5991
|
}
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6106
|
-
|
|
6107
|
-
|
|
6108
|
-
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
5992
|
+
|
|
5993
|
+
.temp-range-tooltip__deviation {
|
|
5994
|
+
text-align: right;
|
|
5995
|
+
}
|
|
5996
|
+
|
|
5997
|
+
.temp-range-tooltip__deviation-value {
|
|
5998
|
+
font-size: 16px;
|
|
5999
|
+
font-weight: 700;
|
|
6000
|
+
}
|
|
6001
|
+
|
|
6002
|
+
.temp-range-tooltip__deviation-value.cold {
|
|
6003
|
+
color: #2563eb;
|
|
6004
|
+
}
|
|
6005
|
+
|
|
6006
|
+
.temp-range-tooltip__deviation-value.ok {
|
|
6007
|
+
color: #16a34a;
|
|
6008
|
+
}
|
|
6009
|
+
|
|
6010
|
+
.temp-range-tooltip__deviation-value.hot {
|
|
6011
|
+
color: #dc2626;
|
|
6012
|
+
}
|
|
6013
|
+
|
|
6014
|
+
.temp-range-tooltip__deviation-label {
|
|
6015
|
+
font-size: 10px;
|
|
6016
|
+
color: #64748b;
|
|
6017
|
+
text-transform: uppercase;
|
|
6018
|
+
letter-spacing: 0.5px;
|
|
6019
|
+
}
|
|
6020
|
+
|
|
6021
|
+
.temp-range-tooltip__ruler {
|
|
6022
|
+
position: relative;
|
|
6023
|
+
height: 32px;
|
|
6024
|
+
margin: 12px 0;
|
|
6025
|
+
border-radius: 8px;
|
|
6026
|
+
overflow: visible;
|
|
6027
|
+
}
|
|
6028
|
+
|
|
6029
|
+
.temp-range-tooltip__ruler-track {
|
|
6030
|
+
position: absolute;
|
|
6031
|
+
top: 12px;
|
|
6032
|
+
left: 0;
|
|
6033
|
+
right: 0;
|
|
6034
|
+
height: 8px;
|
|
6035
|
+
background: linear-gradient(90deg, #dbeafe 0%, #dcfce7 50%, #fee2e2 100%);
|
|
6036
|
+
border-radius: 4px;
|
|
6037
|
+
border: 1px solid #e2e8f0;
|
|
6038
|
+
}
|
|
6039
|
+
|
|
6040
|
+
.temp-range-tooltip__ruler-range {
|
|
6041
|
+
position: absolute;
|
|
6042
|
+
top: 12px;
|
|
6043
|
+
height: 8px;
|
|
6044
|
+
background: #22c55e;
|
|
6045
|
+
border-radius: 4px;
|
|
6046
|
+
opacity: 0.6;
|
|
6047
|
+
}
|
|
6048
|
+
|
|
6049
|
+
.temp-range-tooltip__ruler-marker {
|
|
6050
|
+
position: absolute;
|
|
6051
|
+
top: 4px;
|
|
6052
|
+
width: 4px;
|
|
6053
|
+
height: 24px;
|
|
6054
|
+
background: #1e293b;
|
|
6055
|
+
border-radius: 2px;
|
|
6056
|
+
transform: translateX(-50%);
|
|
6057
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6058
|
+
}
|
|
6059
|
+
|
|
6060
|
+
.temp-range-tooltip__ruler-marker::after {
|
|
6061
|
+
content: '';
|
|
6062
|
+
position: absolute;
|
|
6063
|
+
top: -4px;
|
|
6064
|
+
left: 50%;
|
|
6065
|
+
transform: translateX(-50%);
|
|
6066
|
+
width: 12px;
|
|
6067
|
+
height: 12px;
|
|
6068
|
+
background: #1e293b;
|
|
6069
|
+
border-radius: 50%;
|
|
6070
|
+
border: 2px solid #fff;
|
|
6071
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6072
|
+
}
|
|
6073
|
+
|
|
6074
|
+
.temp-range-tooltip__ruler-labels {
|
|
6075
|
+
display: flex;
|
|
6076
|
+
justify-content: space-between;
|
|
6077
|
+
margin-top: 8px;
|
|
6078
|
+
font-size: 10px;
|
|
6079
|
+
color: #64748b;
|
|
6080
|
+
}
|
|
6081
|
+
|
|
6082
|
+
.temp-range-tooltip__ruler-min,
|
|
6083
|
+
.temp-range-tooltip__ruler-max {
|
|
6084
|
+
font-weight: 600;
|
|
6085
|
+
}
|
|
6086
|
+
|
|
6087
|
+
.temp-range-tooltip__range-info {
|
|
6088
|
+
display: flex;
|
|
6089
|
+
justify-content: space-between;
|
|
6090
|
+
padding: 10px 12px;
|
|
6091
|
+
background: #f8fafc;
|
|
6092
|
+
border-radius: 8px;
|
|
6093
|
+
margin-top: 12px;
|
|
6094
|
+
}
|
|
6095
|
+
|
|
6096
|
+
.temp-range-tooltip__range-item {
|
|
6097
|
+
text-align: center;
|
|
6098
|
+
}
|
|
6099
|
+
|
|
6100
|
+
.temp-range-tooltip__range-label {
|
|
6101
|
+
font-size: 10px;
|
|
6102
|
+
color: #64748b;
|
|
6103
|
+
text-transform: uppercase;
|
|
6104
|
+
letter-spacing: 0.3px;
|
|
6105
|
+
margin-bottom: 2px;
|
|
6106
|
+
}
|
|
6107
|
+
|
|
6108
|
+
.temp-range-tooltip__range-value {
|
|
6109
|
+
font-size: 14px;
|
|
6110
|
+
font-weight: 600;
|
|
6111
|
+
color: #334155;
|
|
6112
|
+
}
|
|
6113
|
+
|
|
6114
|
+
.temp-range-tooltip__status {
|
|
6115
|
+
display: flex;
|
|
6116
|
+
align-items: center;
|
|
6117
|
+
justify-content: center;
|
|
6118
|
+
gap: 6px;
|
|
6119
|
+
margin-top: 12px;
|
|
6120
|
+
padding: 8px 12px;
|
|
6121
|
+
border-radius: 6px;
|
|
6122
|
+
font-size: 11px;
|
|
6123
|
+
font-weight: 600;
|
|
6124
|
+
}
|
|
6125
|
+
|
|
6126
|
+
.temp-range-tooltip__status.cold {
|
|
6127
|
+
background: #dbeafe;
|
|
6128
|
+
color: #1d4ed8;
|
|
6129
|
+
border: 1px solid #93c5fd;
|
|
6130
|
+
}
|
|
6131
|
+
|
|
6132
|
+
.temp-range-tooltip__status.ok {
|
|
6133
|
+
background: #dcfce7;
|
|
6134
|
+
color: #15803d;
|
|
6135
|
+
border: 1px solid #86efac;
|
|
6136
|
+
}
|
|
6137
|
+
|
|
6138
|
+
.temp-range-tooltip__status.hot {
|
|
6139
|
+
background: #fee2e2;
|
|
6140
|
+
color: #b91c1c;
|
|
6141
|
+
border: 1px solid #fca5a5;
|
|
6142
|
+
}
|
|
6143
|
+
|
|
6144
|
+
.temp-range-tooltip__status.unknown {
|
|
6145
|
+
background: #f3f4f6;
|
|
6146
|
+
color: #6b7280;
|
|
6147
|
+
border: 1px solid #d1d5db;
|
|
6148
|
+
}
|
|
6149
|
+
`;
|
|
6150
|
+
function injectStyles() {
|
|
6151
|
+
if (typeof document === "undefined") return;
|
|
6152
|
+
const styleId = "myio-temp-range-tooltip-styles";
|
|
6153
|
+
if (document.getElementById(styleId)) return;
|
|
6154
|
+
const style = document.createElement("style");
|
|
6155
|
+
style.id = styleId;
|
|
6156
|
+
style.textContent = TOOLTIP_STYLES;
|
|
6157
|
+
document.head.appendChild(style);
|
|
6158
|
+
}
|
|
6159
|
+
function extractTemperature(entityData) {
|
|
6160
|
+
return Number(entityData.val ?? entityData.currentTemperature ?? entityData.temperature) || 0;
|
|
6161
|
+
}
|
|
6162
|
+
function extractRange(entityData) {
|
|
6163
|
+
const tempMin = entityData.temperatureMin ?? entityData.minTemperature ?? null;
|
|
6164
|
+
const tempMax = entityData.temperatureMax ?? entityData.maxTemperature ?? null;
|
|
6165
|
+
return { tempMin, tempMax };
|
|
6166
|
+
}
|
|
6167
|
+
function extractLabel(entityData) {
|
|
6168
|
+
return entityData.labelOrName || entityData.name || entityData.label || "Sensor";
|
|
6169
|
+
}
|
|
6170
|
+
var TempRangeTooltip = {
|
|
6171
|
+
containerId: "myio-temp-range-tooltip",
|
|
6172
|
+
/**
|
|
6173
|
+
* Create or get the tooltip container
|
|
6174
|
+
*/
|
|
6175
|
+
getContainer() {
|
|
6176
|
+
injectStyles();
|
|
6177
|
+
let container = document.getElementById(this.containerId);
|
|
6178
|
+
if (!container) {
|
|
6179
|
+
container = document.createElement("div");
|
|
6180
|
+
container.id = this.containerId;
|
|
6181
|
+
container.className = "temp-range-tooltip";
|
|
6182
|
+
document.body.appendChild(container);
|
|
6183
|
+
}
|
|
6184
|
+
return container;
|
|
6185
|
+
},
|
|
6186
|
+
/**
|
|
6187
|
+
* Calculate temperature status and deviation
|
|
6188
|
+
*/
|
|
6189
|
+
calculateStatus(currentTemp, tempMin, tempMax) {
|
|
6190
|
+
if (tempMin == null || tempMax == null) {
|
|
6191
|
+
return { status: "unknown", deviation: null, deviationPercent: null };
|
|
6192
|
+
}
|
|
6193
|
+
const rangeSize = tempMax - tempMin;
|
|
6194
|
+
const midPoint = (tempMin + tempMax) / 2;
|
|
6195
|
+
if (currentTemp < tempMin) {
|
|
6196
|
+
const deviation = tempMin - currentTemp;
|
|
6197
|
+
const deviationPercent = rangeSize > 0 ? deviation / rangeSize * 100 : 0;
|
|
6198
|
+
return { status: "cold", deviation: -deviation, deviationPercent: -deviationPercent };
|
|
6130
6199
|
} else if (currentTemp > tempMax) {
|
|
6131
6200
|
const deviation = currentTemp - tempMax;
|
|
6132
6201
|
const deviationPercent = rangeSize > 0 ? deviation / rangeSize * 100 : 0;
|
|
@@ -6154,20 +6223,20 @@ var TempRangeTooltip = {
|
|
|
6154
6223
|
},
|
|
6155
6224
|
/**
|
|
6156
6225
|
* Show tooltip for a temperature card
|
|
6157
|
-
* @param
|
|
6158
|
-
* @param
|
|
6159
|
-
* @param
|
|
6226
|
+
* @param triggerElement - The card element
|
|
6227
|
+
* @param entityData - Entity data with temperature info
|
|
6228
|
+
* @param event - Mouse event for cursor position
|
|
6160
6229
|
*/
|
|
6161
|
-
show(triggerElement,
|
|
6230
|
+
show(triggerElement, entityData, event) {
|
|
6162
6231
|
const container = this.getContainer();
|
|
6163
|
-
const currentTemp =
|
|
6164
|
-
const tempMin
|
|
6165
|
-
const
|
|
6232
|
+
const currentTemp = extractTemperature(entityData);
|
|
6233
|
+
const { tempMin, tempMax } = extractRange(entityData);
|
|
6234
|
+
const label = extractLabel(entityData);
|
|
6166
6235
|
const hasRange = tempMin != null && tempMax != null;
|
|
6167
|
-
const { status,
|
|
6236
|
+
const { status, deviationPercent } = this.calculateStatus(currentTemp, tempMin, tempMax);
|
|
6168
6237
|
const markerPos = this.calculateMarkerPosition(currentTemp, tempMin, tempMax);
|
|
6169
6238
|
let rangeLeft = 0, rangeWidth = 100;
|
|
6170
|
-
if (hasRange) {
|
|
6239
|
+
if (hasRange && tempMin != null && tempMax != null) {
|
|
6171
6240
|
const rangeSize = tempMax - tempMin;
|
|
6172
6241
|
const extension = rangeSize * 0.3;
|
|
6173
6242
|
const visibleMin = tempMin - extension;
|
|
@@ -6176,28 +6245,23 @@ var TempRangeTooltip = {
|
|
|
6176
6245
|
rangeLeft = (tempMin - visibleMin) / visibleRange * 100;
|
|
6177
6246
|
rangeWidth = rangeSize / visibleRange * 100;
|
|
6178
6247
|
}
|
|
6179
|
-
let deviationText = "";
|
|
6180
|
-
let deviationClass = status;
|
|
6181
|
-
if (status === "cold") {
|
|
6182
|
-
deviationText = `${Math.abs(deviation).toFixed(1)}\xB0C abaixo`;
|
|
6183
|
-
} else if (status === "hot") {
|
|
6184
|
-
deviationText = `+${deviation.toFixed(1)}\xB0C acima`;
|
|
6185
|
-
} else if (status === "ok") {
|
|
6186
|
-
deviationText = "Na faixa ideal";
|
|
6187
|
-
} else {
|
|
6188
|
-
deviationText = "Faixa n\xE3o configurada";
|
|
6189
|
-
}
|
|
6190
6248
|
const statusLabels = {
|
|
6191
6249
|
cold: "\u2744\uFE0F Abaixo da Faixa Ideal",
|
|
6192
6250
|
ok: "\u2714\uFE0F Dentro da Faixa Ideal",
|
|
6193
6251
|
hot: "\u{1F525} Acima da Faixa Ideal",
|
|
6194
6252
|
unknown: "\u2753 Faixa N\xE3o Configurada"
|
|
6195
6253
|
};
|
|
6254
|
+
const statusColors = {
|
|
6255
|
+
cold: "#2563eb",
|
|
6256
|
+
ok: "#16a34a",
|
|
6257
|
+
hot: "#dc2626",
|
|
6258
|
+
unknown: "#64748b"
|
|
6259
|
+
};
|
|
6196
6260
|
container.innerHTML = `
|
|
6197
6261
|
<div class="temp-range-tooltip__content">
|
|
6198
6262
|
<div class="temp-range-tooltip__header">
|
|
6199
6263
|
<span class="temp-range-tooltip__icon">\u{1F321}\uFE0F</span>
|
|
6200
|
-
<span class="temp-range-tooltip__title">${
|
|
6264
|
+
<span class="temp-range-tooltip__title">${label}</span>
|
|
6201
6265
|
</div>
|
|
6202
6266
|
<div class="temp-range-tooltip__body">
|
|
6203
6267
|
<div class="temp-range-tooltip__value-row">
|
|
@@ -6205,7 +6269,7 @@ var TempRangeTooltip = {
|
|
|
6205
6269
|
${currentTemp.toFixed(1)}<sup>\xB0C</sup>
|
|
6206
6270
|
</div>
|
|
6207
6271
|
<div class="temp-range-tooltip__deviation">
|
|
6208
|
-
<div class="temp-range-tooltip__deviation-value ${
|
|
6272
|
+
<div class="temp-range-tooltip__deviation-value ${status}">
|
|
6209
6273
|
${status === "ok" ? "\u2713" : status === "cold" ? "\u2193" : status === "hot" ? "\u2191" : "?"} ${Math.abs(deviationPercent || 0).toFixed(0)}%
|
|
6210
6274
|
</div>
|
|
6211
6275
|
<div class="temp-range-tooltip__deviation-label">Desvio</div>
|
|
@@ -6232,7 +6296,7 @@ var TempRangeTooltip = {
|
|
|
6232
6296
|
</div>
|
|
6233
6297
|
<div class="temp-range-tooltip__range-item">
|
|
6234
6298
|
<div class="temp-range-tooltip__range-label">Atual</div>
|
|
6235
|
-
<div class="temp-range-tooltip__range-value" style="color: ${status
|
|
6299
|
+
<div class="temp-range-tooltip__range-value" style="color: ${statusColors[status]}">${currentTemp.toFixed(1)}\xB0C</div>
|
|
6236
6300
|
</div>
|
|
6237
6301
|
<div class="temp-range-tooltip__range-item">
|
|
6238
6302
|
<div class="temp-range-tooltip__range-label">M\xE1ximo</div>
|
|
@@ -6277,7 +6341,320 @@ var TempRangeTooltip = {
|
|
|
6277
6341
|
if (container) {
|
|
6278
6342
|
container.classList.remove("visible");
|
|
6279
6343
|
}
|
|
6344
|
+
},
|
|
6345
|
+
/**
|
|
6346
|
+
* Attach tooltip to an element
|
|
6347
|
+
* Returns cleanup function
|
|
6348
|
+
*/
|
|
6349
|
+
attach(element, entityData) {
|
|
6350
|
+
const showHandler = (e) => this.show(element, entityData, e);
|
|
6351
|
+
const hideHandler = () => this.hide();
|
|
6352
|
+
element.style.cursor = "help";
|
|
6353
|
+
element.addEventListener("mouseenter", showHandler);
|
|
6354
|
+
element.addEventListener("mouseleave", hideHandler);
|
|
6355
|
+
return () => {
|
|
6356
|
+
element.removeEventListener("mouseenter", showHandler);
|
|
6357
|
+
element.removeEventListener("mouseleave", hideHandler);
|
|
6358
|
+
element.style.cursor = "";
|
|
6359
|
+
this.hide();
|
|
6360
|
+
};
|
|
6361
|
+
}
|
|
6362
|
+
};
|
|
6363
|
+
|
|
6364
|
+
// src/utils/EnergyRangeTooltip.ts
|
|
6365
|
+
var ENERGY_RANGE_TOOLTIP_CSS = `
|
|
6366
|
+
/* ============================================
|
|
6367
|
+
Energy Range Tooltip (for domain=energy)
|
|
6368
|
+
Shows power ruler with current position and status ranges
|
|
6369
|
+
============================================ */
|
|
6370
|
+
.energy-range-tooltip {
|
|
6371
|
+
position: fixed;
|
|
6372
|
+
z-index: 99999;
|
|
6373
|
+
pointer-events: none;
|
|
6374
|
+
opacity: 0;
|
|
6375
|
+
transition: opacity 0.2s ease, transform 0.2s ease;
|
|
6376
|
+
transform: translateY(5px);
|
|
6377
|
+
}
|
|
6378
|
+
|
|
6379
|
+
.energy-range-tooltip.visible {
|
|
6380
|
+
opacity: 1;
|
|
6381
|
+
pointer-events: auto;
|
|
6382
|
+
transform: translateY(0);
|
|
6383
|
+
}
|
|
6384
|
+
|
|
6385
|
+
.energy-range-tooltip__content {
|
|
6386
|
+
background: #ffffff;
|
|
6387
|
+
border: 1px solid #e2e8f0;
|
|
6388
|
+
border-radius: 12px;
|
|
6389
|
+
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
|
|
6390
|
+
min-width: 300px;
|
|
6391
|
+
max-width: 360px;
|
|
6392
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
6393
|
+
font-size: 12px;
|
|
6394
|
+
color: #1e293b;
|
|
6395
|
+
overflow: hidden;
|
|
6396
|
+
}
|
|
6397
|
+
|
|
6398
|
+
.energy-range-tooltip__header {
|
|
6399
|
+
display: flex;
|
|
6400
|
+
align-items: center;
|
|
6401
|
+
gap: 8px;
|
|
6402
|
+
padding: 12px 16px;
|
|
6403
|
+
background: linear-gradient(90deg, #ecfdf5 0%, #d1fae5 100%);
|
|
6404
|
+
border-bottom: 1px solid #6ee7b7;
|
|
6405
|
+
}
|
|
6406
|
+
|
|
6407
|
+
.energy-range-tooltip__icon {
|
|
6408
|
+
font-size: 18px;
|
|
6409
|
+
}
|
|
6410
|
+
|
|
6411
|
+
.energy-range-tooltip__title {
|
|
6412
|
+
font-weight: 700;
|
|
6413
|
+
font-size: 13px;
|
|
6414
|
+
color: #047857;
|
|
6415
|
+
}
|
|
6416
|
+
|
|
6417
|
+
.energy-range-tooltip__body {
|
|
6418
|
+
padding: 16px;
|
|
6419
|
+
}
|
|
6420
|
+
|
|
6421
|
+
/* Power value display */
|
|
6422
|
+
.energy-range-tooltip__value-row {
|
|
6423
|
+
display: flex;
|
|
6424
|
+
justify-content: space-between;
|
|
6425
|
+
align-items: center;
|
|
6426
|
+
margin-bottom: 16px;
|
|
6427
|
+
}
|
|
6428
|
+
|
|
6429
|
+
.energy-range-tooltip__current {
|
|
6430
|
+
font-size: 28px;
|
|
6431
|
+
font-weight: 700;
|
|
6432
|
+
color: #1e293b;
|
|
6433
|
+
}
|
|
6434
|
+
|
|
6435
|
+
.energy-range-tooltip__current sup {
|
|
6436
|
+
font-size: 14px;
|
|
6437
|
+
color: #64748b;
|
|
6438
|
+
}
|
|
6439
|
+
|
|
6440
|
+
.energy-range-tooltip__status-badge {
|
|
6441
|
+
text-align: right;
|
|
6442
|
+
}
|
|
6443
|
+
|
|
6444
|
+
.energy-range-tooltip__status-value {
|
|
6445
|
+
font-size: 14px;
|
|
6446
|
+
font-weight: 700;
|
|
6447
|
+
padding: 4px 10px;
|
|
6448
|
+
border-radius: 6px;
|
|
6449
|
+
}
|
|
6450
|
+
|
|
6451
|
+
.energy-range-tooltip__status-value.standby {
|
|
6452
|
+
background: #dbeafe;
|
|
6453
|
+
color: #1d4ed8;
|
|
6454
|
+
}
|
|
6455
|
+
|
|
6456
|
+
.energy-range-tooltip__status-value.normal {
|
|
6457
|
+
background: #dcfce7;
|
|
6458
|
+
color: #15803d;
|
|
6459
|
+
}
|
|
6460
|
+
|
|
6461
|
+
.energy-range-tooltip__status-value.alert {
|
|
6462
|
+
background: #fef3c7;
|
|
6463
|
+
color: #b45309;
|
|
6464
|
+
}
|
|
6465
|
+
|
|
6466
|
+
.energy-range-tooltip__status-value.failure {
|
|
6467
|
+
background: #fee2e2;
|
|
6468
|
+
color: #b91c1c;
|
|
6469
|
+
}
|
|
6470
|
+
|
|
6471
|
+
.energy-range-tooltip__status-value.offline {
|
|
6472
|
+
background: #f3f4f6;
|
|
6473
|
+
color: #6b7280;
|
|
6474
|
+
}
|
|
6475
|
+
|
|
6476
|
+
/* Power ruler/gauge */
|
|
6477
|
+
.energy-range-tooltip__ruler {
|
|
6478
|
+
position: relative;
|
|
6479
|
+
height: 40px;
|
|
6480
|
+
margin: 12px 0;
|
|
6481
|
+
border-radius: 8px;
|
|
6482
|
+
overflow: visible;
|
|
6483
|
+
}
|
|
6484
|
+
|
|
6485
|
+
.energy-range-tooltip__ruler-track {
|
|
6486
|
+
position: absolute;
|
|
6487
|
+
top: 16px;
|
|
6488
|
+
left: 0;
|
|
6489
|
+
right: 0;
|
|
6490
|
+
height: 8px;
|
|
6491
|
+
display: flex;
|
|
6492
|
+
border-radius: 4px;
|
|
6493
|
+
overflow: hidden;
|
|
6494
|
+
border: 1px solid #e2e8f0;
|
|
6495
|
+
}
|
|
6496
|
+
|
|
6497
|
+
.energy-range-tooltip__ruler-segment {
|
|
6498
|
+
height: 100%;
|
|
6499
|
+
}
|
|
6500
|
+
|
|
6501
|
+
.energy-range-tooltip__ruler-segment.standby {
|
|
6502
|
+
background: #dbeafe;
|
|
6503
|
+
}
|
|
6504
|
+
|
|
6505
|
+
.energy-range-tooltip__ruler-segment.normal {
|
|
6506
|
+
background: #dcfce7;
|
|
6507
|
+
}
|
|
6508
|
+
|
|
6509
|
+
.energy-range-tooltip__ruler-segment.alert {
|
|
6510
|
+
background: #fef3c7;
|
|
6511
|
+
}
|
|
6512
|
+
|
|
6513
|
+
.energy-range-tooltip__ruler-segment.failure {
|
|
6514
|
+
background: #fee2e2;
|
|
6515
|
+
}
|
|
6516
|
+
|
|
6517
|
+
.energy-range-tooltip__ruler-marker {
|
|
6518
|
+
position: absolute;
|
|
6519
|
+
top: 8px;
|
|
6520
|
+
width: 4px;
|
|
6521
|
+
height: 24px;
|
|
6522
|
+
background: #1e293b;
|
|
6523
|
+
border-radius: 2px;
|
|
6524
|
+
transform: translateX(-50%);
|
|
6525
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6526
|
+
}
|
|
6527
|
+
|
|
6528
|
+
.energy-range-tooltip__ruler-marker::after {
|
|
6529
|
+
content: '';
|
|
6530
|
+
position: absolute;
|
|
6531
|
+
top: -4px;
|
|
6532
|
+
left: 50%;
|
|
6533
|
+
transform: translateX(-50%);
|
|
6534
|
+
width: 12px;
|
|
6535
|
+
height: 12px;
|
|
6536
|
+
background: #1e293b;
|
|
6537
|
+
border-radius: 50%;
|
|
6538
|
+
border: 2px solid #fff;
|
|
6539
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
6540
|
+
}
|
|
6541
|
+
|
|
6542
|
+
/* Range info grid */
|
|
6543
|
+
.energy-range-tooltip__ranges {
|
|
6544
|
+
display: grid;
|
|
6545
|
+
grid-template-columns: repeat(4, 1fr);
|
|
6546
|
+
gap: 8px;
|
|
6547
|
+
margin-top: 16px;
|
|
6548
|
+
}
|
|
6549
|
+
|
|
6550
|
+
.energy-range-tooltip__range-item {
|
|
6551
|
+
text-align: center;
|
|
6552
|
+
padding: 8px 4px;
|
|
6553
|
+
border-radius: 6px;
|
|
6554
|
+
background: #f8fafc;
|
|
6555
|
+
}
|
|
6556
|
+
|
|
6557
|
+
.energy-range-tooltip__range-item.standby {
|
|
6558
|
+
border-left: 3px solid #3b82f6;
|
|
6559
|
+
}
|
|
6560
|
+
|
|
6561
|
+
.energy-range-tooltip__range-item.normal {
|
|
6562
|
+
border-left: 3px solid #22c55e;
|
|
6563
|
+
}
|
|
6564
|
+
|
|
6565
|
+
.energy-range-tooltip__range-item.alert {
|
|
6566
|
+
border-left: 3px solid #f59e0b;
|
|
6567
|
+
}
|
|
6568
|
+
|
|
6569
|
+
.energy-range-tooltip__range-item.failure {
|
|
6570
|
+
border-left: 3px solid #ef4444;
|
|
6571
|
+
}
|
|
6572
|
+
|
|
6573
|
+
.energy-range-tooltip__range-label {
|
|
6574
|
+
font-size: 9px;
|
|
6575
|
+
color: #64748b;
|
|
6576
|
+
text-transform: uppercase;
|
|
6577
|
+
letter-spacing: 0.3px;
|
|
6578
|
+
margin-bottom: 2px;
|
|
6579
|
+
}
|
|
6580
|
+
|
|
6581
|
+
.energy-range-tooltip__range-value {
|
|
6582
|
+
font-size: 11px;
|
|
6583
|
+
font-weight: 600;
|
|
6584
|
+
color: #334155;
|
|
6585
|
+
}
|
|
6586
|
+
|
|
6587
|
+
/* Status info */
|
|
6588
|
+
.energy-range-tooltip__status-info {
|
|
6589
|
+
display: flex;
|
|
6590
|
+
align-items: center;
|
|
6591
|
+
justify-content: center;
|
|
6592
|
+
gap: 6px;
|
|
6593
|
+
margin-top: 12px;
|
|
6594
|
+
padding: 8px 12px;
|
|
6595
|
+
border-radius: 6px;
|
|
6596
|
+
font-size: 11px;
|
|
6597
|
+
font-weight: 600;
|
|
6598
|
+
}
|
|
6599
|
+
|
|
6600
|
+
.energy-range-tooltip__status-info.standby {
|
|
6601
|
+
background: #dbeafe;
|
|
6602
|
+
color: #1d4ed8;
|
|
6603
|
+
border: 1px solid #93c5fd;
|
|
6604
|
+
}
|
|
6605
|
+
|
|
6606
|
+
.energy-range-tooltip__status-info.normal {
|
|
6607
|
+
background: #dcfce7;
|
|
6608
|
+
color: #15803d;
|
|
6609
|
+
border: 1px solid #86efac;
|
|
6610
|
+
}
|
|
6611
|
+
|
|
6612
|
+
.energy-range-tooltip__status-info.alert {
|
|
6613
|
+
background: #fef3c7;
|
|
6614
|
+
color: #b45309;
|
|
6615
|
+
border: 1px solid #fcd34d;
|
|
6616
|
+
}
|
|
6617
|
+
|
|
6618
|
+
.energy-range-tooltip__status-info.failure {
|
|
6619
|
+
background: #fee2e2;
|
|
6620
|
+
color: #b91c1c;
|
|
6621
|
+
border: 1px solid #fca5a5;
|
|
6622
|
+
}
|
|
6623
|
+
|
|
6624
|
+
.energy-range-tooltip__status-info.offline {
|
|
6625
|
+
background: #f3f4f6;
|
|
6626
|
+
color: #6b7280;
|
|
6627
|
+
border: 1px solid #d1d5db;
|
|
6628
|
+
}
|
|
6629
|
+
`;
|
|
6630
|
+
var cssInjected = false;
|
|
6631
|
+
function injectCSS() {
|
|
6632
|
+
if (cssInjected) return;
|
|
6633
|
+
if (typeof document === "undefined") return;
|
|
6634
|
+
const styleId = "myio-energy-range-tooltip-styles";
|
|
6635
|
+
if (document.getElementById(styleId)) {
|
|
6636
|
+
cssInjected = true;
|
|
6637
|
+
return;
|
|
6280
6638
|
}
|
|
6639
|
+
const style = document.createElement("style");
|
|
6640
|
+
style.id = styleId;
|
|
6641
|
+
style.textContent = ENERGY_RANGE_TOOLTIP_CSS;
|
|
6642
|
+
document.head.appendChild(style);
|
|
6643
|
+
cssInjected = true;
|
|
6644
|
+
}
|
|
6645
|
+
var STATUS_LABELS = {
|
|
6646
|
+
standby: "Standby",
|
|
6647
|
+
normal: "Operacao Normal",
|
|
6648
|
+
alert: "Alerta",
|
|
6649
|
+
failure: "Falha",
|
|
6650
|
+
offline: "Fora da faixa"
|
|
6651
|
+
};
|
|
6652
|
+
var STATUS_INFO_LABELS = {
|
|
6653
|
+
standby: "\u{1F535} Standby",
|
|
6654
|
+
normal: "\u2705 Operacao Normal",
|
|
6655
|
+
alert: "\u26A0\uFE0F Alerta",
|
|
6656
|
+
failure: "\u{1F534} Falha",
|
|
6657
|
+
offline: "\u26AB Offline / Sem dados"
|
|
6281
6658
|
};
|
|
6282
6659
|
var EnergyRangeTooltip = {
|
|
6283
6660
|
containerId: "myio-energy-range-tooltip",
|
|
@@ -6285,6 +6662,7 @@ var EnergyRangeTooltip = {
|
|
|
6285
6662
|
* Create or get the tooltip container
|
|
6286
6663
|
*/
|
|
6287
6664
|
getContainer() {
|
|
6665
|
+
injectCSS();
|
|
6288
6666
|
let container = document.getElementById(this.containerId);
|
|
6289
6667
|
if (!container) {
|
|
6290
6668
|
container = document.createElement("div");
|
|
@@ -6304,18 +6682,18 @@ var EnergyRangeTooltip = {
|
|
|
6304
6682
|
const power = Number(powerValue) || 0;
|
|
6305
6683
|
const { standbyRange, normalRange, alertRange, failureRange } = ranges;
|
|
6306
6684
|
if (standbyRange && power >= standbyRange.down && power <= standbyRange.up) {
|
|
6307
|
-
return { status: "standby", label:
|
|
6685
|
+
return { status: "standby", label: STATUS_LABELS.standby };
|
|
6308
6686
|
}
|
|
6309
6687
|
if (normalRange && power >= normalRange.down && power <= normalRange.up) {
|
|
6310
|
-
return { status: "normal", label:
|
|
6688
|
+
return { status: "normal", label: STATUS_LABELS.normal };
|
|
6311
6689
|
}
|
|
6312
6690
|
if (alertRange && power >= alertRange.down && power <= alertRange.up) {
|
|
6313
|
-
return { status: "alert", label:
|
|
6691
|
+
return { status: "alert", label: STATUS_LABELS.alert };
|
|
6314
6692
|
}
|
|
6315
6693
|
if (failureRange && power >= failureRange.down && power <= failureRange.up) {
|
|
6316
|
-
return { status: "failure", label:
|
|
6694
|
+
return { status: "failure", label: STATUS_LABELS.failure };
|
|
6317
6695
|
}
|
|
6318
|
-
return { status: "offline", label:
|
|
6696
|
+
return { status: "offline", label: STATUS_LABELS.offline };
|
|
6319
6697
|
},
|
|
6320
6698
|
/**
|
|
6321
6699
|
* Calculate marker position on ruler (0-100%)
|
|
@@ -6346,7 +6724,7 @@ var EnergyRangeTooltip = {
|
|
|
6346
6724
|
* Format power value for display
|
|
6347
6725
|
*/
|
|
6348
6726
|
formatPower(value) {
|
|
6349
|
-
if (value == null || isNaN(value)) return "-";
|
|
6727
|
+
if (value == null || isNaN(Number(value))) return "-";
|
|
6350
6728
|
const num = Number(value);
|
|
6351
6729
|
if (num >= 1e3) {
|
|
6352
6730
|
return `${(num / 1e3).toFixed(2)} kW`;
|
|
@@ -6364,13 +6742,40 @@ var EnergyRangeTooltip = {
|
|
|
6364
6742
|
const { status, label } = this.calculateStatus(powerValue, ranges);
|
|
6365
6743
|
const markerPos = this.calculateMarkerPosition(powerValue, ranges);
|
|
6366
6744
|
const segmentWidths = this.calculateSegmentWidths(ranges);
|
|
6367
|
-
const
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6745
|
+
const rangesHtml = hasRanges && ranges ? `
|
|
6746
|
+
<div class="energy-range-tooltip__ruler">
|
|
6747
|
+
<div class="energy-range-tooltip__ruler-track">
|
|
6748
|
+
<div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
|
|
6749
|
+
<div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
|
|
6750
|
+
<div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
|
|
6751
|
+
<div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
|
|
6752
|
+
</div>
|
|
6753
|
+
<div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
|
|
6754
|
+
</div>
|
|
6755
|
+
|
|
6756
|
+
<div class="energy-range-tooltip__ranges">
|
|
6757
|
+
<div class="energy-range-tooltip__range-item standby">
|
|
6758
|
+
<div class="energy-range-tooltip__range-label">Standby</div>
|
|
6759
|
+
<div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
|
|
6760
|
+
</div>
|
|
6761
|
+
<div class="energy-range-tooltip__range-item normal">
|
|
6762
|
+
<div class="energy-range-tooltip__range-label">Normal</div>
|
|
6763
|
+
<div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
|
|
6764
|
+
</div>
|
|
6765
|
+
<div class="energy-range-tooltip__range-item alert">
|
|
6766
|
+
<div class="energy-range-tooltip__range-label">Alerta</div>
|
|
6767
|
+
<div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
|
|
6768
|
+
</div>
|
|
6769
|
+
<div class="energy-range-tooltip__range-item failure">
|
|
6770
|
+
<div class="energy-range-tooltip__range-label">Falha</div>
|
|
6771
|
+
<div class="energy-range-tooltip__range-value">>${ranges.failureRange?.down || 0}W</div>
|
|
6772
|
+
</div>
|
|
6773
|
+
</div>
|
|
6774
|
+
` : `
|
|
6775
|
+
<div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
|
|
6776
|
+
Ranges de potencia nao configurados
|
|
6777
|
+
</div>
|
|
6778
|
+
`;
|
|
6374
6779
|
container.innerHTML = `
|
|
6375
6780
|
<div class="energy-range-tooltip__content">
|
|
6376
6781
|
<div class="energy-range-tooltip__header">
|
|
@@ -6387,51 +6792,18 @@ var EnergyRangeTooltip = {
|
|
|
6387
6792
|
</div>
|
|
6388
6793
|
</div>
|
|
6389
6794
|
|
|
6390
|
-
${
|
|
6391
|
-
<div class="energy-range-tooltip__ruler">
|
|
6392
|
-
<div class="energy-range-tooltip__ruler-track">
|
|
6393
|
-
<div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
|
|
6394
|
-
<div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
|
|
6395
|
-
<div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
|
|
6396
|
-
<div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
|
|
6397
|
-
</div>
|
|
6398
|
-
<div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
|
|
6399
|
-
</div>
|
|
6400
|
-
|
|
6401
|
-
<div class="energy-range-tooltip__ranges">
|
|
6402
|
-
<div class="energy-range-tooltip__range-item standby">
|
|
6403
|
-
<div class="energy-range-tooltip__range-label">Standby</div>
|
|
6404
|
-
<div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
|
|
6405
|
-
</div>
|
|
6406
|
-
<div class="energy-range-tooltip__range-item normal">
|
|
6407
|
-
<div class="energy-range-tooltip__range-label">Normal</div>
|
|
6408
|
-
<div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
|
|
6409
|
-
</div>
|
|
6410
|
-
<div class="energy-range-tooltip__range-item alert">
|
|
6411
|
-
<div class="energy-range-tooltip__range-label">Alerta</div>
|
|
6412
|
-
<div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
|
|
6413
|
-
</div>
|
|
6414
|
-
<div class="energy-range-tooltip__range-item failure">
|
|
6415
|
-
<div class="energy-range-tooltip__range-label">Falha</div>
|
|
6416
|
-
<div class="energy-range-tooltip__range-value">>${ranges.failureRange?.down || 0}W</div>
|
|
6417
|
-
</div>
|
|
6418
|
-
</div>
|
|
6419
|
-
` : `
|
|
6420
|
-
<div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
|
|
6421
|
-
Ranges de pot\xEAncia n\xE3o configurados
|
|
6422
|
-
</div>
|
|
6423
|
-
`}
|
|
6795
|
+
${rangesHtml}
|
|
6424
6796
|
|
|
6425
6797
|
<div class="energy-range-tooltip__status-info ${status}">
|
|
6426
|
-
${
|
|
6798
|
+
${STATUS_INFO_LABELS[status] || STATUS_INFO_LABELS.offline}
|
|
6427
6799
|
</div>
|
|
6428
6800
|
</div>
|
|
6429
6801
|
</div>
|
|
6430
6802
|
`;
|
|
6431
6803
|
let left, top;
|
|
6432
6804
|
if (event && event.clientX && event.clientY) {
|
|
6433
|
-
left = event.clientX +
|
|
6434
|
-
top = event.clientY +
|
|
6805
|
+
left = event.clientX + 8;
|
|
6806
|
+
top = event.clientY + 8;
|
|
6435
6807
|
} else {
|
|
6436
6808
|
const rect = triggerElement.getBoundingClientRect();
|
|
6437
6809
|
left = rect.left + rect.width / 2 - 150;
|
|
@@ -6440,11 +6812,11 @@ var EnergyRangeTooltip = {
|
|
|
6440
6812
|
const tooltipWidth = 320;
|
|
6441
6813
|
const tooltipHeight = 380;
|
|
6442
6814
|
if (left + tooltipWidth > window.innerWidth - 10) {
|
|
6443
|
-
left = (event?.clientX || left) - tooltipWidth -
|
|
6815
|
+
left = (event?.clientX || left) - tooltipWidth - 8;
|
|
6444
6816
|
}
|
|
6445
6817
|
if (left < 10) left = 10;
|
|
6446
6818
|
if (top + tooltipHeight > window.innerHeight - 10) {
|
|
6447
|
-
top = (event?.clientY || top) - tooltipHeight -
|
|
6819
|
+
top = (event?.clientY || top) - tooltipHeight - 8;
|
|
6448
6820
|
}
|
|
6449
6821
|
if (top < 10) top = 10;
|
|
6450
6822
|
container.style.left = left + "px";
|
|
@@ -6459,8 +6831,229 @@ var EnergyRangeTooltip = {
|
|
|
6459
6831
|
if (container) {
|
|
6460
6832
|
container.classList.remove("visible");
|
|
6461
6833
|
}
|
|
6834
|
+
},
|
|
6835
|
+
/**
|
|
6836
|
+
* Attach tooltip to an element with automatic show/hide on hover
|
|
6837
|
+
* Returns cleanup function to remove event listeners
|
|
6838
|
+
*/
|
|
6839
|
+
attach(element, entityData) {
|
|
6840
|
+
const handleMouseEnter = (e) => {
|
|
6841
|
+
this.show(element, entityData, e);
|
|
6842
|
+
};
|
|
6843
|
+
const handleMouseLeave = () => {
|
|
6844
|
+
this.hide();
|
|
6845
|
+
};
|
|
6846
|
+
const handleMouseMove = (e) => {
|
|
6847
|
+
const container = document.getElementById(this.containerId);
|
|
6848
|
+
if (container && container.classList.contains("visible")) {
|
|
6849
|
+
let left = e.clientX + 8;
|
|
6850
|
+
let top = e.clientY + 8;
|
|
6851
|
+
const tooltipWidth = 320;
|
|
6852
|
+
const tooltipHeight = 380;
|
|
6853
|
+
if (left + tooltipWidth > window.innerWidth - 10) {
|
|
6854
|
+
left = e.clientX - tooltipWidth - 8;
|
|
6855
|
+
}
|
|
6856
|
+
if (left < 10) left = 10;
|
|
6857
|
+
if (top + tooltipHeight > window.innerHeight - 10) {
|
|
6858
|
+
top = e.clientY - tooltipHeight - 8;
|
|
6859
|
+
}
|
|
6860
|
+
if (top < 10) top = 10;
|
|
6861
|
+
container.style.left = left + "px";
|
|
6862
|
+
container.style.top = top + "px";
|
|
6863
|
+
}
|
|
6864
|
+
};
|
|
6865
|
+
element.addEventListener("mouseenter", handleMouseEnter);
|
|
6866
|
+
element.addEventListener("mouseleave", handleMouseLeave);
|
|
6867
|
+
element.addEventListener("mousemove", handleMouseMove);
|
|
6868
|
+
return () => {
|
|
6869
|
+
element.removeEventListener("mouseenter", handleMouseEnter);
|
|
6870
|
+
element.removeEventListener("mouseleave", handleMouseLeave);
|
|
6871
|
+
element.removeEventListener("mousemove", handleMouseMove);
|
|
6872
|
+
this.hide();
|
|
6873
|
+
};
|
|
6462
6874
|
}
|
|
6463
6875
|
};
|
|
6876
|
+
|
|
6877
|
+
// src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
|
|
6878
|
+
var LABEL_CHAR_LIMIT = 18;
|
|
6879
|
+
var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
|
|
6880
|
+
var CSS_TAG = "head-office-card-v1";
|
|
6881
|
+
function ensureCss() {
|
|
6882
|
+
if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
|
|
6883
|
+
const style = document.createElement("style");
|
|
6884
|
+
style.setAttribute("data-myio-css", CSS_TAG);
|
|
6885
|
+
style.textContent = CSS_STRING;
|
|
6886
|
+
document.head.appendChild(style);
|
|
6887
|
+
}
|
|
6888
|
+
}
|
|
6889
|
+
function normalizeParams(params) {
|
|
6890
|
+
if (!params || !params.entityObject) {
|
|
6891
|
+
throw new Error("renderCardCompenteHeadOffice: entityObject is required");
|
|
6892
|
+
}
|
|
6893
|
+
const LogHelper2 = createLogHelper(params.debugActive ?? false);
|
|
6894
|
+
const entityObject = params.entityObject;
|
|
6895
|
+
if (!entityObject.entityId) {
|
|
6896
|
+
LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
|
|
6897
|
+
entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
6898
|
+
}
|
|
6899
|
+
if (!params.delayTimeConnectionInMins) {
|
|
6900
|
+
LogHelper2.warn(
|
|
6901
|
+
`[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
|
|
6902
|
+
);
|
|
6903
|
+
}
|
|
6904
|
+
return {
|
|
6905
|
+
entityObject,
|
|
6906
|
+
i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
|
|
6907
|
+
enableSelection: Boolean(params.enableSelection),
|
|
6908
|
+
enableDragDrop: Boolean(params.enableDragDrop),
|
|
6909
|
+
useNewComponents: Boolean(params.useNewComponents),
|
|
6910
|
+
// RFC-0091: Configurable delay time for connection status check (default 15 minutes)
|
|
6911
|
+
delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
|
|
6912
|
+
// Debug options
|
|
6913
|
+
debugActive: params.debugActive ?? false,
|
|
6914
|
+
activeTooltipDebug: params.activeTooltipDebug ?? false,
|
|
6915
|
+
// LogHelper instance for this card
|
|
6916
|
+
LogHelper: LogHelper2,
|
|
6917
|
+
callbacks: {
|
|
6918
|
+
handleActionDashboard: params.handleActionDashboard,
|
|
6919
|
+
handleActionReport: params.handleActionReport,
|
|
6920
|
+
handleActionSettings: params.handleActionSettings,
|
|
6921
|
+
handleSelect: params.handleSelect,
|
|
6922
|
+
handInfo: params.handInfo,
|
|
6923
|
+
handleClickCard: params.handleClickCard
|
|
6924
|
+
}
|
|
6925
|
+
};
|
|
6926
|
+
}
|
|
6927
|
+
function getIconSvg(deviceType, domain) {
|
|
6928
|
+
if (domain === "water") {
|
|
6929
|
+
return Icons.waterDrop;
|
|
6930
|
+
}
|
|
6931
|
+
if (domain === "temperature") {
|
|
6932
|
+
return Icons.thermometer;
|
|
6933
|
+
}
|
|
6934
|
+
return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
|
|
6935
|
+
}
|
|
6936
|
+
function formatPower(valueInWatts) {
|
|
6937
|
+
if (valueInWatts === null || valueInWatts === void 0 || isNaN(valueInWatts)) {
|
|
6938
|
+
return { num: "-", unit: "" };
|
|
6939
|
+
}
|
|
6940
|
+
const val = Number(valueInWatts);
|
|
6941
|
+
if (val >= 1e3) {
|
|
6942
|
+
const kw = Math.ceil(val / 1e3 * 100) / 100;
|
|
6943
|
+
return { num: kw.toFixed(2), unit: "kW" };
|
|
6944
|
+
} else {
|
|
6945
|
+
const w = Math.ceil(val);
|
|
6946
|
+
return { num: w.toString(), unit: "W" };
|
|
6947
|
+
}
|
|
6948
|
+
}
|
|
6949
|
+
function formatValueByDomain(value, domain) {
|
|
6950
|
+
if (domain === "water") {
|
|
6951
|
+
return formatWaterVolumeM3(value);
|
|
6952
|
+
}
|
|
6953
|
+
if (domain === "temperature") {
|
|
6954
|
+
return formatTemperature(value, 0);
|
|
6955
|
+
}
|
|
6956
|
+
return formatEnergy(value);
|
|
6957
|
+
}
|
|
6958
|
+
function formatRelativeTime2(timestamp) {
|
|
6959
|
+
if (!timestamp || isNaN(timestamp)) return "\u2014";
|
|
6960
|
+
const date = new Date(timestamp);
|
|
6961
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
6962
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
6963
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
6964
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
6965
|
+
const year = date.getFullYear();
|
|
6966
|
+
return `${hours}:${minutes} ${day}/${month}/${year}`;
|
|
6967
|
+
}
|
|
6968
|
+
function calculateConsumptionPercentage(target, consumption) {
|
|
6969
|
+
const numericTarget = Number(target);
|
|
6970
|
+
const numericConsumption = Number(consumption);
|
|
6971
|
+
if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
|
|
6972
|
+
return 0;
|
|
6973
|
+
}
|
|
6974
|
+
const percentage = numericConsumption / numericTarget * 100;
|
|
6975
|
+
return percentage;
|
|
6976
|
+
}
|
|
6977
|
+
function getStatusInfo(deviceStatus, i18n, domain) {
|
|
6978
|
+
switch (deviceStatus) {
|
|
6979
|
+
// --- Novos Status de Temperatura ---
|
|
6980
|
+
case "normal":
|
|
6981
|
+
return { chipClass: "chip--ok", label: "Normal" };
|
|
6982
|
+
case "cold":
|
|
6983
|
+
return { chipClass: "chip--standby", label: "Frio" };
|
|
6984
|
+
case "hot":
|
|
6985
|
+
return { chipClass: "chip--alert", label: "Quente" };
|
|
6986
|
+
// --- Status Existentes (aligned with getCardStateClass) ---
|
|
6987
|
+
case DeviceStatusType.POWER_ON:
|
|
6988
|
+
if (domain === "water") {
|
|
6989
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation_water };
|
|
6990
|
+
}
|
|
6991
|
+
return { chipClass: "chip--power-on", label: i18n.in_operation };
|
|
6992
|
+
case DeviceStatusType.STANDBY:
|
|
6993
|
+
return { chipClass: "chip--standby", label: i18n.standby };
|
|
6994
|
+
case DeviceStatusType.WARNING:
|
|
6995
|
+
return { chipClass: "chip--warning", label: i18n.alert };
|
|
6996
|
+
case DeviceStatusType.MAINTENANCE:
|
|
6997
|
+
return { chipClass: "chip--maintenance", label: i18n.maintenance };
|
|
6998
|
+
case DeviceStatusType.FAILURE:
|
|
6999
|
+
return { chipClass: "chip--failure", label: i18n.failure };
|
|
7000
|
+
case DeviceStatusType.POWER_OFF:
|
|
7001
|
+
return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
|
|
7002
|
+
case DeviceStatusType.OFFLINE:
|
|
7003
|
+
return { chipClass: "chip--offline", label: i18n.offline };
|
|
7004
|
+
case DeviceStatusType.NO_INFO:
|
|
7005
|
+
return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
|
|
7006
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
7007
|
+
return { chipClass: "chip--not-installed", label: i18n.not_installed };
|
|
7008
|
+
default:
|
|
7009
|
+
return { chipClass: "chip--offline", label: i18n.offline };
|
|
7010
|
+
}
|
|
7011
|
+
}
|
|
7012
|
+
function getCardStateClass(deviceStatus) {
|
|
7013
|
+
switch (deviceStatus) {
|
|
7014
|
+
case DeviceStatusType.POWER_ON:
|
|
7015
|
+
return "is-power-on";
|
|
7016
|
+
// Blue border
|
|
7017
|
+
case DeviceStatusType.STANDBY:
|
|
7018
|
+
return "is-standby";
|
|
7019
|
+
// Green border
|
|
7020
|
+
case DeviceStatusType.WARNING:
|
|
7021
|
+
return "is-warning";
|
|
7022
|
+
// Yellow border
|
|
7023
|
+
case DeviceStatusType.MAINTENANCE:
|
|
7024
|
+
return "is-maintenance";
|
|
7025
|
+
// Yellow border
|
|
7026
|
+
case DeviceStatusType.FAILURE:
|
|
7027
|
+
return "is-failure";
|
|
7028
|
+
// Dark Red border
|
|
7029
|
+
case DeviceStatusType.POWER_OFF:
|
|
7030
|
+
return "is-power-off";
|
|
7031
|
+
// Light Red border
|
|
7032
|
+
case DeviceStatusType.OFFLINE:
|
|
7033
|
+
return "is-offline";
|
|
7034
|
+
// Dark Gray border
|
|
7035
|
+
case DeviceStatusType.NO_INFO:
|
|
7036
|
+
return "is-no-info";
|
|
7037
|
+
// Dark Orange border
|
|
7038
|
+
case DeviceStatusType.NOT_INSTALLED:
|
|
7039
|
+
return "is-not-installed";
|
|
7040
|
+
// Purple border
|
|
7041
|
+
default:
|
|
7042
|
+
return "";
|
|
7043
|
+
}
|
|
7044
|
+
}
|
|
7045
|
+
function getTempRangeClass(entityObject) {
|
|
7046
|
+
if (entityObject.domain !== "temperature") return "";
|
|
7047
|
+
const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
|
|
7048
|
+
const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
|
|
7049
|
+
const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
|
|
7050
|
+
if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
|
|
7051
|
+
return "";
|
|
7052
|
+
}
|
|
7053
|
+
if (currentTemp > tempMax) return "is-temp-hot";
|
|
7054
|
+
if (currentTemp < tempMin) return "is-temp-cold";
|
|
7055
|
+
return "is-temp-ok";
|
|
7056
|
+
}
|
|
6464
7057
|
function getStatusDotClass(deviceStatus) {
|
|
6465
7058
|
switch (deviceStatus) {
|
|
6466
7059
|
// --- Novos Status de Temperatura ---
|
|
@@ -7581,6 +8174,7 @@ function renderCardComponentV5({
|
|
|
7581
8174
|
};
|
|
7582
8175
|
const isTankDevice = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
|
|
7583
8176
|
const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
|
|
8177
|
+
const isEnergyDeviceFlag = isEnergyDevice(deviceType);
|
|
7584
8178
|
const percentageForDisplay = isTankDevice ? (waterPercentage || 0) * 100 : perc;
|
|
7585
8179
|
const calculateTempStatus = () => {
|
|
7586
8180
|
if (temperatureStatus) return temperatureStatus;
|
|
@@ -7597,33 +8191,6 @@ function renderCardComponentV5({
|
|
|
7597
8191
|
tempStatus,
|
|
7598
8192
|
isOffline
|
|
7599
8193
|
});
|
|
7600
|
-
const getTemperatureTooltip = () => {
|
|
7601
|
-
if (!isTermostatoDevice) return "";
|
|
7602
|
-
const currentTemp = Number(val) || 0;
|
|
7603
|
-
const hasRange = temperatureMin !== void 0 && temperatureMax !== void 0 && temperatureMin !== null && temperatureMax !== null;
|
|
7604
|
-
if (isOffline) {
|
|
7605
|
-
return "Dispositivo offline";
|
|
7606
|
-
}
|
|
7607
|
-
if (!hasRange) {
|
|
7608
|
-
return `Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7609
|
-
Faixa n\xE3o configurada`;
|
|
7610
|
-
}
|
|
7611
|
-
const rangeText = `Faixa ideal: ${temperatureMin}\xB0C a ${temperatureMax}\xB0C`;
|
|
7612
|
-
if (tempStatus === "above") {
|
|
7613
|
-
return `ACIMA da faixa ideal
|
|
7614
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7615
|
-
${rangeText}`;
|
|
7616
|
-
} else if (tempStatus === "below") {
|
|
7617
|
-
return `ABAIXO da faixa ideal
|
|
7618
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7619
|
-
${rangeText}`;
|
|
7620
|
-
} else {
|
|
7621
|
-
return `DENTRO da faixa ideal
|
|
7622
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7623
|
-
${rangeText}`;
|
|
7624
|
-
}
|
|
7625
|
-
};
|
|
7626
|
-
const temperatureTooltip = getTemperatureTooltip();
|
|
7627
8194
|
const cardHTML = `
|
|
7628
8195
|
<div class="device-card-centered clickable ${cardEntity.status === "offline" ? "offline" : ""}"
|
|
7629
8196
|
data-entity-id="${entityId}"
|
|
@@ -7649,7 +8216,7 @@ ${rangeText}`;
|
|
|
7649
8216
|
` : ""}
|
|
7650
8217
|
</div>
|
|
7651
8218
|
|
|
7652
|
-
<img class="device-image
|
|
8219
|
+
<img class="device-image ${isTermostatoDevice ? "temp-tooltip-trigger" : ""}${isEnergyDeviceFlag ? " energy-tooltip-trigger" : ""}" src="${deviceImageUrl}" alt="${deviceType}" style="${isTermostatoDevice || isEnergyDeviceFlag ? "cursor: help;" : ""}" />
|
|
7653
8220
|
|
|
7654
8221
|
|
|
7655
8222
|
${customerName && String(customerName).trim() !== "" ? `
|
|
@@ -8213,6 +8780,33 @@ ${rangeText}`;
|
|
|
8213
8780
|
}
|
|
8214
8781
|
});
|
|
8215
8782
|
}
|
|
8783
|
+
const tempTooltipTrigger = enhancedCardElement.querySelector(".temp-tooltip-trigger");
|
|
8784
|
+
let tempTooltipCleanup = null;
|
|
8785
|
+
if (tempTooltipTrigger && isTermostatoDevice) {
|
|
8786
|
+
const tooltipEntityData = {
|
|
8787
|
+
val,
|
|
8788
|
+
temperatureMin,
|
|
8789
|
+
temperatureMax,
|
|
8790
|
+
labelOrName: cardEntity.name,
|
|
8791
|
+
name: cardEntity.name
|
|
8792
|
+
};
|
|
8793
|
+
tempTooltipCleanup = TempRangeTooltip.attach(tempTooltipTrigger, tooltipEntityData);
|
|
8794
|
+
}
|
|
8795
|
+
const energyTooltipTrigger = enhancedCardElement.querySelector(".energy-tooltip-trigger");
|
|
8796
|
+
let energyTooltipCleanup = null;
|
|
8797
|
+
if (energyTooltipTrigger && isEnergyDeviceFlag) {
|
|
8798
|
+
const energyTooltipData = {
|
|
8799
|
+
labelOrName: cardEntity.name,
|
|
8800
|
+
name: cardEntity.name,
|
|
8801
|
+
instantaneousPower: entityObject.instantaneousPower ?? entityObject.consumption_power ?? val,
|
|
8802
|
+
powerRanges: entityObject.powerRanges || entityObject.ranges
|
|
8803
|
+
};
|
|
8804
|
+
energyTooltipCleanup = EnergyRangeTooltip.attach(energyTooltipTrigger, energyTooltipData);
|
|
8805
|
+
}
|
|
8806
|
+
container._cleanup = () => {
|
|
8807
|
+
if (tempTooltipCleanup) tempTooltipCleanup();
|
|
8808
|
+
if (energyTooltipCleanup) energyTooltipCleanup();
|
|
8809
|
+
};
|
|
8216
8810
|
const jQueryLikeObject = {
|
|
8217
8811
|
get: (index) => index === 0 ? container : void 0,
|
|
8218
8812
|
0: container,
|
|
@@ -11197,7 +11791,7 @@ var chartJsLoaded = false;
|
|
|
11197
11791
|
var zoomPluginLoaded = false;
|
|
11198
11792
|
var jsPdfLoaded = false;
|
|
11199
11793
|
var _jspdfPromise = null;
|
|
11200
|
-
var
|
|
11794
|
+
var cssInjected2 = false;
|
|
11201
11795
|
var STRINGS2 = {
|
|
11202
11796
|
"pt-BR": {
|
|
11203
11797
|
title: "Demanda",
|
|
@@ -11373,8 +11967,8 @@ function ensureRoom(doc, nextY, minRoom = 40) {
|
|
|
11373
11967
|
}
|
|
11374
11968
|
return nextY;
|
|
11375
11969
|
}
|
|
11376
|
-
function
|
|
11377
|
-
if (
|
|
11970
|
+
function injectCSS2(styles) {
|
|
11971
|
+
if (cssInjected2) return;
|
|
11378
11972
|
const css = `
|
|
11379
11973
|
.myio-demand-modal-overlay {
|
|
11380
11974
|
position: fixed;
|
|
@@ -11769,7 +12363,7 @@ function injectCSS(styles) {
|
|
|
11769
12363
|
const style = document.createElement("style");
|
|
11770
12364
|
style.textContent = css;
|
|
11771
12365
|
document.head.appendChild(style);
|
|
11772
|
-
|
|
12366
|
+
cssInjected2 = true;
|
|
11773
12367
|
}
|
|
11774
12368
|
function formatDate2(date, locale) {
|
|
11775
12369
|
return date.toLocaleDateString(locale, {
|
|
@@ -11951,7 +12545,7 @@ async function openDemandModal(params) {
|
|
|
11951
12545
|
const locale = params.locale || "pt-BR";
|
|
11952
12546
|
const strings = STRINGS2[locale] || STRINGS2["pt-BR"];
|
|
11953
12547
|
await loadExternalLibraries();
|
|
11954
|
-
|
|
12548
|
+
injectCSS2(styles);
|
|
11955
12549
|
const container = typeof params.container === "string" ? document.querySelector(params.container) : params.container || document.body;
|
|
11956
12550
|
if (!container) {
|
|
11957
12551
|
throw new Error("Container element not found");
|
|
@@ -21600,7 +22194,7 @@ async function createInputDateRangePickerInsideDIV(params) {
|
|
|
21600
22194
|
placeholder = "Clique para selecionar per\xEDodo",
|
|
21601
22195
|
pickerOptions = {},
|
|
21602
22196
|
classNames = {},
|
|
21603
|
-
injectStyles = true,
|
|
22197
|
+
injectStyles: injectStyles2 = true,
|
|
21604
22198
|
showHelper = true
|
|
21605
22199
|
} = params;
|
|
21606
22200
|
validateId(containerId, "containerId");
|
|
@@ -21609,7 +22203,7 @@ async function createInputDateRangePickerInsideDIV(params) {
|
|
|
21609
22203
|
if (!container) {
|
|
21610
22204
|
throw new Error(`[createInputDateRangePickerInsideDIV] Container '#${containerId}' not found`);
|
|
21611
22205
|
}
|
|
21612
|
-
if (
|
|
22206
|
+
if (injectStyles2) {
|
|
21613
22207
|
injectPremiumStyles();
|
|
21614
22208
|
}
|
|
21615
22209
|
let inputEl = document.getElementById(inputId);
|
|
@@ -21804,7 +22398,7 @@ function openGoalsPanel(params) {
|
|
|
21804
22398
|
modal.setAttribute("aria-labelledby", "goals-modal-title");
|
|
21805
22399
|
modal.innerHTML = generateModalHTML();
|
|
21806
22400
|
document.body.appendChild(modal);
|
|
21807
|
-
|
|
22401
|
+
injectStyles2();
|
|
21808
22402
|
attachEventListeners();
|
|
21809
22403
|
trapFocus(modal);
|
|
21810
22404
|
renderTabContent();
|
|
@@ -22557,7 +23151,7 @@ function openGoalsPanel(params) {
|
|
|
22557
23151
|
maximumFractionDigits: 2
|
|
22558
23152
|
}).format(value);
|
|
22559
23153
|
}
|
|
22560
|
-
function
|
|
23154
|
+
function injectStyles2() {
|
|
22561
23155
|
const styleId = "myio-goals-panel-styles";
|
|
22562
23156
|
if (document.getElementById(styleId)) return;
|
|
22563
23157
|
const style = document.createElement("style");
|
|
@@ -24814,7 +25408,7 @@ var LIGHT_THEME2 = {
|
|
|
24814
25408
|
function getColors(theme) {
|
|
24815
25409
|
return theme === "dark" ? DARK_THEME2 : LIGHT_THEME2;
|
|
24816
25410
|
}
|
|
24817
|
-
async function fetchCustomerAttributes(customerId, token) {
|
|
25411
|
+
async function fetchCustomerAttributes(customerId, token, onError) {
|
|
24818
25412
|
const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/values/attributes/SERVER_SCOPE`;
|
|
24819
25413
|
const response = await fetch(url, {
|
|
24820
25414
|
method: "GET",
|
|
@@ -24827,6 +25421,10 @@ async function fetchCustomerAttributes(customerId, token) {
|
|
|
24827
25421
|
if (response.status === 404 || response.status === 400) {
|
|
24828
25422
|
return { minTemperature: null, maxTemperature: null };
|
|
24829
25423
|
}
|
|
25424
|
+
if (onError) {
|
|
25425
|
+
onError({ status: response.status, message: `Failed to fetch attributes: ${response.status}` });
|
|
25426
|
+
return { minTemperature: null, maxTemperature: null };
|
|
25427
|
+
}
|
|
24830
25428
|
throw new Error(`Failed to fetch attributes: ${response.status}`);
|
|
24831
25429
|
}
|
|
24832
25430
|
const attributes = await response.json();
|
|
@@ -24843,7 +25441,7 @@ async function fetchCustomerAttributes(customerId, token) {
|
|
|
24843
25441
|
}
|
|
24844
25442
|
return { minTemperature, maxTemperature };
|
|
24845
25443
|
}
|
|
24846
|
-
async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature) {
|
|
25444
|
+
async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature, onError) {
|
|
24847
25445
|
const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/SERVER_SCOPE`;
|
|
24848
25446
|
const attributes = {
|
|
24849
25447
|
minTemperature,
|
|
@@ -24858,6 +25456,10 @@ async function saveCustomerAttributes(customerId, token, minTemperature, maxTemp
|
|
|
24858
25456
|
body: JSON.stringify(attributes)
|
|
24859
25457
|
});
|
|
24860
25458
|
if (!response.ok) {
|
|
25459
|
+
if (onError) {
|
|
25460
|
+
onError({ status: response.status, message: `Failed to save attributes: ${response.status}` });
|
|
25461
|
+
return;
|
|
25462
|
+
}
|
|
24861
25463
|
throw new Error(`Failed to save attributes: ${response.status}`);
|
|
24862
25464
|
}
|
|
24863
25465
|
}
|
|
@@ -25274,7 +25876,7 @@ function openTemperatureSettingsModal(params) {
|
|
|
25274
25876
|
state.successMessage = null;
|
|
25275
25877
|
renderModal3(container, state, modalId, destroy, handleSave);
|
|
25276
25878
|
try {
|
|
25277
|
-
await saveCustomerAttributes(state.customerId, state.token, min, max);
|
|
25879
|
+
await saveCustomerAttributes(state.customerId, state.token, min, max, params.onError);
|
|
25278
25880
|
state.minTemperature = min;
|
|
25279
25881
|
state.maxTemperature = max;
|
|
25280
25882
|
state.isSaving = false;
|
|
@@ -25291,7 +25893,7 @@ function openTemperatureSettingsModal(params) {
|
|
|
25291
25893
|
}
|
|
25292
25894
|
};
|
|
25293
25895
|
renderModal3(container, state, modalId, destroy, handleSave);
|
|
25294
|
-
fetchCustomerAttributes(state.customerId, state.token).then(({ minTemperature, maxTemperature }) => {
|
|
25896
|
+
fetchCustomerAttributes(state.customerId, state.token, params.onError).then(({ minTemperature, maxTemperature }) => {
|
|
25295
25897
|
state.minTemperature = minTemperature;
|
|
25296
25898
|
state.maxTemperature = maxTemperature;
|
|
25297
25899
|
state.isLoading = false;
|
|
@@ -27452,7 +28054,7 @@ function createConsumptionChartWidget(config) {
|
|
|
27452
28054
|
</div>
|
|
27453
28055
|
`;
|
|
27454
28056
|
}
|
|
27455
|
-
function
|
|
28057
|
+
function injectStyles2() {
|
|
27456
28058
|
if (styleElement) return;
|
|
27457
28059
|
styleElement = document.createElement("style");
|
|
27458
28060
|
styleElement.id = `${widgetId}-styles`;
|
|
@@ -27934,7 +28536,7 @@ function createConsumptionChartWidget(config) {
|
|
|
27934
28536
|
console.error(`[ConsumptionWidget] Container #${config.containerId} not found`);
|
|
27935
28537
|
return;
|
|
27936
28538
|
}
|
|
27937
|
-
|
|
28539
|
+
injectStyles2();
|
|
27938
28540
|
containerElement.innerHTML = renderHTML();
|
|
27939
28541
|
setupListeners();
|
|
27940
28542
|
setLoading(true);
|
|
@@ -29073,6 +29675,7 @@ export {
|
|
|
29073
29675
|
EXPORT_DOMAIN_ICONS,
|
|
29074
29676
|
EXPORT_DOMAIN_LABELS,
|
|
29075
29677
|
EXPORT_DOMAIN_UNITS,
|
|
29678
|
+
EnergyRangeTooltip,
|
|
29076
29679
|
MyIOChartModal,
|
|
29077
29680
|
MyIODraggableCard,
|
|
29078
29681
|
MyIOSelectionStore,
|
|
@@ -29081,6 +29684,7 @@ export {
|
|
|
29081
29684
|
DEVICE_TYPES as POWER_LIMITS_DEVICE_TYPES,
|
|
29082
29685
|
STATUS_CONFIG as POWER_LIMITS_STATUS_CONFIG,
|
|
29083
29686
|
TELEMETRY_TYPES2 as POWER_LIMITS_TELEMETRY_TYPES,
|
|
29687
|
+
TempRangeTooltip,
|
|
29084
29688
|
addDetectionContext,
|
|
29085
29689
|
addNamespace,
|
|
29086
29690
|
aggregateByDay,
|