myio-js-library 0.1.180 → 0.1.182
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 +939 -328
- package/dist/index.d.cts +151 -1
- package/dist/index.js +937 -328
- package/dist/myio-js-library.umd.js +977 -363
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -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 ---
|
|
@@ -6986,29 +7579,34 @@ function bindEvents(root, state, callbacks) {
|
|
|
6986
7579
|
MyIOSelectionStore2.on("selection:change", onSelectionChange);
|
|
6987
7580
|
root._selectionListener = onSelectionChange;
|
|
6988
7581
|
}
|
|
6989
|
-
|
|
7582
|
+
const valueElement = root.querySelector(".myio-ho-card__value");
|
|
7583
|
+
if (entityObject.domain === "temperature" && valueElement) {
|
|
6990
7584
|
const showTooltip = (e) => {
|
|
6991
7585
|
TempRangeTooltip.show(root, state.entityObject, e);
|
|
6992
7586
|
};
|
|
6993
7587
|
const hideTooltip = () => {
|
|
6994
7588
|
TempRangeTooltip.hide();
|
|
6995
7589
|
};
|
|
6996
|
-
|
|
6997
|
-
|
|
7590
|
+
valueElement.style.cursor = "help";
|
|
7591
|
+
valueElement.addEventListener("mouseenter", showTooltip);
|
|
7592
|
+
valueElement.addEventListener("mouseleave", hideTooltip);
|
|
6998
7593
|
root._tempTooltipShowFn = showTooltip;
|
|
6999
7594
|
root._tempTooltipHideFn = hideTooltip;
|
|
7595
|
+
root._tooltipElement = valueElement;
|
|
7000
7596
|
}
|
|
7001
|
-
if (entityObject.domain === "energy") {
|
|
7597
|
+
if (entityObject.domain === "energy" && valueElement) {
|
|
7002
7598
|
const showEnergyTooltip = (e) => {
|
|
7003
7599
|
EnergyRangeTooltip.show(root, state.entityObject, e);
|
|
7004
7600
|
};
|
|
7005
7601
|
const hideEnergyTooltip = () => {
|
|
7006
7602
|
EnergyRangeTooltip.hide();
|
|
7007
7603
|
};
|
|
7008
|
-
|
|
7009
|
-
|
|
7604
|
+
valueElement.style.cursor = "help";
|
|
7605
|
+
valueElement.addEventListener("mouseenter", showEnergyTooltip);
|
|
7606
|
+
valueElement.addEventListener("mouseleave", hideEnergyTooltip);
|
|
7010
7607
|
root._energyTooltipShowFn = showEnergyTooltip;
|
|
7011
7608
|
root._energyTooltipHideFn = hideEnergyTooltip;
|
|
7609
|
+
root._tooltipElement = valueElement;
|
|
7012
7610
|
}
|
|
7013
7611
|
root._cleanup = () => {
|
|
7014
7612
|
document.removeEventListener("click", closeMenu);
|
|
@@ -7016,14 +7614,14 @@ function bindEvents(root, state, callbacks) {
|
|
|
7016
7614
|
if (MyIOSelectionStore2 && root._selectionListener) {
|
|
7017
7615
|
MyIOSelectionStore2.off("selection:change", root._selectionListener);
|
|
7018
7616
|
}
|
|
7019
|
-
if (root._tempTooltipShowFn) {
|
|
7020
|
-
root.removeEventListener("mouseenter", root._tempTooltipShowFn);
|
|
7021
|
-
root.removeEventListener("mouseleave", root._tempTooltipHideFn);
|
|
7617
|
+
if (root._tempTooltipShowFn && root._tooltipElement) {
|
|
7618
|
+
root._tooltipElement.removeEventListener("mouseenter", root._tempTooltipShowFn);
|
|
7619
|
+
root._tooltipElement.removeEventListener("mouseleave", root._tempTooltipHideFn);
|
|
7022
7620
|
TempRangeTooltip.hide();
|
|
7023
7621
|
}
|
|
7024
|
-
if (root._energyTooltipShowFn) {
|
|
7025
|
-
root.removeEventListener("mouseenter", root._energyTooltipShowFn);
|
|
7026
|
-
root.removeEventListener("mouseleave", root._energyTooltipHideFn);
|
|
7622
|
+
if (root._energyTooltipShowFn && root._tooltipElement) {
|
|
7623
|
+
root._tooltipElement.removeEventListener("mouseenter", root._energyTooltipShowFn);
|
|
7624
|
+
root._tooltipElement.removeEventListener("mouseleave", root._energyTooltipHideFn);
|
|
7027
7625
|
EnergyRangeTooltip.hide();
|
|
7028
7626
|
}
|
|
7029
7627
|
};
|
|
@@ -7576,6 +8174,7 @@ function renderCardComponentV5({
|
|
|
7576
8174
|
};
|
|
7577
8175
|
const isTankDevice = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
|
|
7578
8176
|
const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
|
|
8177
|
+
const isEnergyDeviceFlag = isEnergyDevice(deviceType);
|
|
7579
8178
|
const percentageForDisplay = isTankDevice ? (waterPercentage || 0) * 100 : perc;
|
|
7580
8179
|
const calculateTempStatus = () => {
|
|
7581
8180
|
if (temperatureStatus) return temperatureStatus;
|
|
@@ -7592,33 +8191,6 @@ function renderCardComponentV5({
|
|
|
7592
8191
|
tempStatus,
|
|
7593
8192
|
isOffline
|
|
7594
8193
|
});
|
|
7595
|
-
const getTemperatureTooltip = () => {
|
|
7596
|
-
if (!isTermostatoDevice) return "";
|
|
7597
|
-
const currentTemp = Number(val) || 0;
|
|
7598
|
-
const hasRange = temperatureMin !== void 0 && temperatureMax !== void 0 && temperatureMin !== null && temperatureMax !== null;
|
|
7599
|
-
if (isOffline) {
|
|
7600
|
-
return "Dispositivo offline";
|
|
7601
|
-
}
|
|
7602
|
-
if (!hasRange) {
|
|
7603
|
-
return `Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7604
|
-
Faixa n\xE3o configurada`;
|
|
7605
|
-
}
|
|
7606
|
-
const rangeText = `Faixa ideal: ${temperatureMin}\xB0C a ${temperatureMax}\xB0C`;
|
|
7607
|
-
if (tempStatus === "above") {
|
|
7608
|
-
return `ACIMA da faixa ideal
|
|
7609
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7610
|
-
${rangeText}`;
|
|
7611
|
-
} else if (tempStatus === "below") {
|
|
7612
|
-
return `ABAIXO da faixa ideal
|
|
7613
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7614
|
-
${rangeText}`;
|
|
7615
|
-
} else {
|
|
7616
|
-
return `DENTRO da faixa ideal
|
|
7617
|
-
Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
|
|
7618
|
-
${rangeText}`;
|
|
7619
|
-
}
|
|
7620
|
-
};
|
|
7621
|
-
const temperatureTooltip = getTemperatureTooltip();
|
|
7622
8194
|
const cardHTML = `
|
|
7623
8195
|
<div class="device-card-centered clickable ${cardEntity.status === "offline" ? "offline" : ""}"
|
|
7624
8196
|
data-entity-id="${entityId}"
|
|
@@ -7644,7 +8216,7 @@ ${rangeText}`;
|
|
|
7644
8216
|
` : ""}
|
|
7645
8217
|
</div>
|
|
7646
8218
|
|
|
7647
|
-
<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;" : ""}" />
|
|
7648
8220
|
|
|
7649
8221
|
|
|
7650
8222
|
${customerName && String(customerName).trim() !== "" ? `
|
|
@@ -8208,6 +8780,33 @@ ${rangeText}`;
|
|
|
8208
8780
|
}
|
|
8209
8781
|
});
|
|
8210
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
|
+
};
|
|
8211
8810
|
const jQueryLikeObject = {
|
|
8212
8811
|
get: (index) => index === 0 ? container : void 0,
|
|
8213
8812
|
0: container,
|
|
@@ -11192,7 +11791,7 @@ var chartJsLoaded = false;
|
|
|
11192
11791
|
var zoomPluginLoaded = false;
|
|
11193
11792
|
var jsPdfLoaded = false;
|
|
11194
11793
|
var _jspdfPromise = null;
|
|
11195
|
-
var
|
|
11794
|
+
var cssInjected2 = false;
|
|
11196
11795
|
var STRINGS2 = {
|
|
11197
11796
|
"pt-BR": {
|
|
11198
11797
|
title: "Demanda",
|
|
@@ -11368,8 +11967,8 @@ function ensureRoom(doc, nextY, minRoom = 40) {
|
|
|
11368
11967
|
}
|
|
11369
11968
|
return nextY;
|
|
11370
11969
|
}
|
|
11371
|
-
function
|
|
11372
|
-
if (
|
|
11970
|
+
function injectCSS2(styles) {
|
|
11971
|
+
if (cssInjected2) return;
|
|
11373
11972
|
const css = `
|
|
11374
11973
|
.myio-demand-modal-overlay {
|
|
11375
11974
|
position: fixed;
|
|
@@ -11764,7 +12363,7 @@ function injectCSS(styles) {
|
|
|
11764
12363
|
const style = document.createElement("style");
|
|
11765
12364
|
style.textContent = css;
|
|
11766
12365
|
document.head.appendChild(style);
|
|
11767
|
-
|
|
12366
|
+
cssInjected2 = true;
|
|
11768
12367
|
}
|
|
11769
12368
|
function formatDate2(date, locale) {
|
|
11770
12369
|
return date.toLocaleDateString(locale, {
|
|
@@ -11946,7 +12545,7 @@ async function openDemandModal(params) {
|
|
|
11946
12545
|
const locale = params.locale || "pt-BR";
|
|
11947
12546
|
const strings = STRINGS2[locale] || STRINGS2["pt-BR"];
|
|
11948
12547
|
await loadExternalLibraries();
|
|
11949
|
-
|
|
12548
|
+
injectCSS2(styles);
|
|
11950
12549
|
const container = typeof params.container === "string" ? document.querySelector(params.container) : params.container || document.body;
|
|
11951
12550
|
if (!container) {
|
|
11952
12551
|
throw new Error("Container element not found");
|
|
@@ -21595,7 +22194,7 @@ async function createInputDateRangePickerInsideDIV(params) {
|
|
|
21595
22194
|
placeholder = "Clique para selecionar per\xEDodo",
|
|
21596
22195
|
pickerOptions = {},
|
|
21597
22196
|
classNames = {},
|
|
21598
|
-
injectStyles = true,
|
|
22197
|
+
injectStyles: injectStyles2 = true,
|
|
21599
22198
|
showHelper = true
|
|
21600
22199
|
} = params;
|
|
21601
22200
|
validateId(containerId, "containerId");
|
|
@@ -21604,7 +22203,7 @@ async function createInputDateRangePickerInsideDIV(params) {
|
|
|
21604
22203
|
if (!container) {
|
|
21605
22204
|
throw new Error(`[createInputDateRangePickerInsideDIV] Container '#${containerId}' not found`);
|
|
21606
22205
|
}
|
|
21607
|
-
if (
|
|
22206
|
+
if (injectStyles2) {
|
|
21608
22207
|
injectPremiumStyles();
|
|
21609
22208
|
}
|
|
21610
22209
|
let inputEl = document.getElementById(inputId);
|
|
@@ -21799,7 +22398,7 @@ function openGoalsPanel(params) {
|
|
|
21799
22398
|
modal.setAttribute("aria-labelledby", "goals-modal-title");
|
|
21800
22399
|
modal.innerHTML = generateModalHTML();
|
|
21801
22400
|
document.body.appendChild(modal);
|
|
21802
|
-
|
|
22401
|
+
injectStyles2();
|
|
21803
22402
|
attachEventListeners();
|
|
21804
22403
|
trapFocus(modal);
|
|
21805
22404
|
renderTabContent();
|
|
@@ -22552,7 +23151,7 @@ function openGoalsPanel(params) {
|
|
|
22552
23151
|
maximumFractionDigits: 2
|
|
22553
23152
|
}).format(value);
|
|
22554
23153
|
}
|
|
22555
|
-
function
|
|
23154
|
+
function injectStyles2() {
|
|
22556
23155
|
const styleId = "myio-goals-panel-styles";
|
|
22557
23156
|
if (document.getElementById(styleId)) return;
|
|
22558
23157
|
const style = document.createElement("style");
|
|
@@ -24809,7 +25408,7 @@ var LIGHT_THEME2 = {
|
|
|
24809
25408
|
function getColors(theme) {
|
|
24810
25409
|
return theme === "dark" ? DARK_THEME2 : LIGHT_THEME2;
|
|
24811
25410
|
}
|
|
24812
|
-
async function fetchCustomerAttributes(customerId, token) {
|
|
25411
|
+
async function fetchCustomerAttributes(customerId, token, onError) {
|
|
24813
25412
|
const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/values/attributes/SERVER_SCOPE`;
|
|
24814
25413
|
const response = await fetch(url, {
|
|
24815
25414
|
method: "GET",
|
|
@@ -24822,6 +25421,10 @@ async function fetchCustomerAttributes(customerId, token) {
|
|
|
24822
25421
|
if (response.status === 404 || response.status === 400) {
|
|
24823
25422
|
return { minTemperature: null, maxTemperature: null };
|
|
24824
25423
|
}
|
|
25424
|
+
if (onError) {
|
|
25425
|
+
onError({ status: response.status, message: `Failed to fetch attributes: ${response.status}` });
|
|
25426
|
+
return { minTemperature: null, maxTemperature: null };
|
|
25427
|
+
}
|
|
24825
25428
|
throw new Error(`Failed to fetch attributes: ${response.status}`);
|
|
24826
25429
|
}
|
|
24827
25430
|
const attributes = await response.json();
|
|
@@ -24838,7 +25441,7 @@ async function fetchCustomerAttributes(customerId, token) {
|
|
|
24838
25441
|
}
|
|
24839
25442
|
return { minTemperature, maxTemperature };
|
|
24840
25443
|
}
|
|
24841
|
-
async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature) {
|
|
25444
|
+
async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature, onError) {
|
|
24842
25445
|
const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/SERVER_SCOPE`;
|
|
24843
25446
|
const attributes = {
|
|
24844
25447
|
minTemperature,
|
|
@@ -24853,6 +25456,10 @@ async function saveCustomerAttributes(customerId, token, minTemperature, maxTemp
|
|
|
24853
25456
|
body: JSON.stringify(attributes)
|
|
24854
25457
|
});
|
|
24855
25458
|
if (!response.ok) {
|
|
25459
|
+
if (onError) {
|
|
25460
|
+
onError({ status: response.status, message: `Failed to save attributes: ${response.status}` });
|
|
25461
|
+
return;
|
|
25462
|
+
}
|
|
24856
25463
|
throw new Error(`Failed to save attributes: ${response.status}`);
|
|
24857
25464
|
}
|
|
24858
25465
|
}
|
|
@@ -25269,7 +25876,7 @@ function openTemperatureSettingsModal(params) {
|
|
|
25269
25876
|
state.successMessage = null;
|
|
25270
25877
|
renderModal3(container, state, modalId, destroy, handleSave);
|
|
25271
25878
|
try {
|
|
25272
|
-
await saveCustomerAttributes(state.customerId, state.token, min, max);
|
|
25879
|
+
await saveCustomerAttributes(state.customerId, state.token, min, max, params.onError);
|
|
25273
25880
|
state.minTemperature = min;
|
|
25274
25881
|
state.maxTemperature = max;
|
|
25275
25882
|
state.isSaving = false;
|
|
@@ -25286,7 +25893,7 @@ function openTemperatureSettingsModal(params) {
|
|
|
25286
25893
|
}
|
|
25287
25894
|
};
|
|
25288
25895
|
renderModal3(container, state, modalId, destroy, handleSave);
|
|
25289
|
-
fetchCustomerAttributes(state.customerId, state.token).then(({ minTemperature, maxTemperature }) => {
|
|
25896
|
+
fetchCustomerAttributes(state.customerId, state.token, params.onError).then(({ minTemperature, maxTemperature }) => {
|
|
25290
25897
|
state.minTemperature = minTemperature;
|
|
25291
25898
|
state.maxTemperature = maxTemperature;
|
|
25292
25899
|
state.isLoading = false;
|
|
@@ -27447,7 +28054,7 @@ function createConsumptionChartWidget(config) {
|
|
|
27447
28054
|
</div>
|
|
27448
28055
|
`;
|
|
27449
28056
|
}
|
|
27450
|
-
function
|
|
28057
|
+
function injectStyles2() {
|
|
27451
28058
|
if (styleElement) return;
|
|
27452
28059
|
styleElement = document.createElement("style");
|
|
27453
28060
|
styleElement.id = `${widgetId}-styles`;
|
|
@@ -27929,7 +28536,7 @@ function createConsumptionChartWidget(config) {
|
|
|
27929
28536
|
console.error(`[ConsumptionWidget] Container #${config.containerId} not found`);
|
|
27930
28537
|
return;
|
|
27931
28538
|
}
|
|
27932
|
-
|
|
28539
|
+
injectStyles2();
|
|
27933
28540
|
containerElement.innerHTML = renderHTML();
|
|
27934
28541
|
setupListeners();
|
|
27935
28542
|
setLoading(true);
|
|
@@ -29068,6 +29675,7 @@ export {
|
|
|
29068
29675
|
EXPORT_DOMAIN_ICONS,
|
|
29069
29676
|
EXPORT_DOMAIN_LABELS,
|
|
29070
29677
|
EXPORT_DOMAIN_UNITS,
|
|
29678
|
+
EnergyRangeTooltip,
|
|
29071
29679
|
MyIOChartModal,
|
|
29072
29680
|
MyIODraggableCard,
|
|
29073
29681
|
MyIOSelectionStore,
|
|
@@ -29076,6 +29684,7 @@ export {
|
|
|
29076
29684
|
DEVICE_TYPES as POWER_LIMITS_DEVICE_TYPES,
|
|
29077
29685
|
STATUS_CONFIG as POWER_LIMITS_STATUS_CONFIG,
|
|
29078
29686
|
TELEMETRY_TYPES2 as POWER_LIMITS_TELEMETRY_TYPES,
|
|
29687
|
+
TempRangeTooltip,
|
|
29079
29688
|
addDetectionContext,
|
|
29080
29689
|
addNamespace,
|
|
29081
29690
|
aggregateByDay,
|