myio-js-library 0.1.157 → 0.1.158
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 +124 -6
- package/dist/index.js +124 -6
- package/dist/myio-js-library.umd.js +124 -6
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5134,8 +5134,14 @@ function verifyOfflineStatus(entityObject, delayTimeInMins = 15) {
|
|
|
5134
5134
|
}
|
|
5135
5135
|
function paint(root, state) {
|
|
5136
5136
|
const { entityObject, i18n, delayTimeConnectionInMins } = state;
|
|
5137
|
-
if (
|
|
5138
|
-
entityObject.
|
|
5137
|
+
if (entityObject.connectionStatus) {
|
|
5138
|
+
if (entityObject.connectionStatus === "offline") {
|
|
5139
|
+
entityObject.deviceStatus = DeviceStatusType.NO_INFO;
|
|
5140
|
+
}
|
|
5141
|
+
} else {
|
|
5142
|
+
if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
|
|
5143
|
+
entityObject.deviceStatus = DeviceStatusType.NO_INFO;
|
|
5144
|
+
}
|
|
5139
5145
|
}
|
|
5140
5146
|
const stateClass = getCardStateClass(entityObject.deviceStatus);
|
|
5141
5147
|
root.className = `myio-ho-card ${stateClass}`;
|
|
@@ -10945,11 +10951,14 @@ var EnergyModalView = class {
|
|
|
10945
10951
|
isLoading = false;
|
|
10946
10952
|
currentTheme = "dark";
|
|
10947
10953
|
currentBarMode = "stacked";
|
|
10954
|
+
// RFC-0097: Granularity selector state (only 1h and 1d supported)
|
|
10955
|
+
currentGranularity = "1d";
|
|
10948
10956
|
constructor(modal, config) {
|
|
10949
10957
|
this.modal = modal;
|
|
10950
10958
|
this.config = config;
|
|
10951
10959
|
this.initializeTheme();
|
|
10952
10960
|
this.initializeBarMode();
|
|
10961
|
+
this.initializeGranularity();
|
|
10953
10962
|
this.validateConfiguration();
|
|
10954
10963
|
this.render();
|
|
10955
10964
|
}
|
|
@@ -10967,6 +10976,59 @@ var EnergyModalView = class {
|
|
|
10967
10976
|
const savedBarMode = localStorage.getItem("myio-modal-bar-mode");
|
|
10968
10977
|
this.currentBarMode = savedBarMode || "stacked";
|
|
10969
10978
|
}
|
|
10979
|
+
/**
|
|
10980
|
+
* RFC-0097: Initializes granularity from config or localStorage
|
|
10981
|
+
*/
|
|
10982
|
+
initializeGranularity() {
|
|
10983
|
+
const savedGranularity = localStorage.getItem("myio-modal-granularity");
|
|
10984
|
+
const configGranularity = this.config.params.granularity;
|
|
10985
|
+
const candidate = savedGranularity || configGranularity || "1d";
|
|
10986
|
+
this.currentGranularity = candidate === "1h" || candidate === "1d" ? candidate : "1d";
|
|
10987
|
+
}
|
|
10988
|
+
/**
|
|
10989
|
+
* RFC-0097: Sets granularity and re-renders chart
|
|
10990
|
+
*/
|
|
10991
|
+
setGranularity(granularity) {
|
|
10992
|
+
if (this.currentGranularity === granularity) return;
|
|
10993
|
+
this.currentGranularity = granularity;
|
|
10994
|
+
const buttons = document.querySelectorAll(".myio-btn-granularity");
|
|
10995
|
+
buttons.forEach((btn) => {
|
|
10996
|
+
const btnEl = btn;
|
|
10997
|
+
if (btnEl.dataset.granularity === granularity) {
|
|
10998
|
+
btnEl.classList.add("active");
|
|
10999
|
+
} else {
|
|
11000
|
+
btnEl.classList.remove("active");
|
|
11001
|
+
}
|
|
11002
|
+
});
|
|
11003
|
+
localStorage.setItem("myio-modal-granularity", granularity);
|
|
11004
|
+
this.reRenderChart();
|
|
11005
|
+
console.log("[EnergyModalView] [RFC-0097] Granularity changed to:", granularity);
|
|
11006
|
+
}
|
|
11007
|
+
/**
|
|
11008
|
+
* RFC-0097: Calculates suggested granularity based on date range
|
|
11009
|
+
* Only supports '1h' (hour) and '1d' (day)
|
|
11010
|
+
*/
|
|
11011
|
+
calculateSuggestedGranularity(startDate, endDate) {
|
|
11012
|
+
const start = new Date(startDate);
|
|
11013
|
+
const end = new Date(endDate);
|
|
11014
|
+
const diffDays = Math.ceil((end.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
|
|
11015
|
+
if (diffDays <= 1) return "1h";
|
|
11016
|
+
return "1d";
|
|
11017
|
+
}
|
|
11018
|
+
/**
|
|
11019
|
+
* RFC-0097: Applies granularity UI state (highlights correct button)
|
|
11020
|
+
*/
|
|
11021
|
+
applyGranularityUI() {
|
|
11022
|
+
const buttons = document.querySelectorAll(".myio-btn-granularity");
|
|
11023
|
+
buttons.forEach((btn) => {
|
|
11024
|
+
const btnEl = btn;
|
|
11025
|
+
if (btnEl.dataset.granularity === this.currentGranularity) {
|
|
11026
|
+
btnEl.classList.add("active");
|
|
11027
|
+
} else {
|
|
11028
|
+
btnEl.classList.remove("active");
|
|
11029
|
+
}
|
|
11030
|
+
});
|
|
11031
|
+
}
|
|
10970
11032
|
/**
|
|
10971
11033
|
* Toggles between dark and light theme
|
|
10972
11034
|
*/
|
|
@@ -11237,6 +11299,14 @@ var EnergyModalView = class {
|
|
|
11237
11299
|
</svg>
|
|
11238
11300
|
</button>
|
|
11239
11301
|
` : ""}
|
|
11302
|
+
${this.config.params.mode === "comparison" ? `
|
|
11303
|
+
<!-- RFC-0097: Granularity Selector (only 1h and 1d supported) -->
|
|
11304
|
+
<div class="myio-granularity-selector" style="display: flex; align-items: center; gap: 4px; margin-left: 8px; padding: 4px 8px; background: rgba(0,0,0,0.05); border-radius: 8px;">
|
|
11305
|
+
<span style="font-size: 11px; color: #666; margin-right: 4px; white-space: nowrap;">Granularidade:</span>
|
|
11306
|
+
<button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1h" ? "active" : ""}" data-granularity="1h" title="Hora">1h</button>
|
|
11307
|
+
<button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1d" ? "active" : ""}" data-granularity="1d" title="Dia">1d</button>
|
|
11308
|
+
</div>
|
|
11309
|
+
` : ""}
|
|
11240
11310
|
<button id="close-btn" class="myio-btn myio-btn-secondary">
|
|
11241
11311
|
Fechar
|
|
11242
11312
|
</button>
|
|
@@ -11459,8 +11529,8 @@ var EnergyModalView = class {
|
|
|
11459
11529
|
// ← NO TIME (YYYY-MM-DD)
|
|
11460
11530
|
endDate: endDateStr,
|
|
11461
11531
|
// ← NO TIME (YYYY-MM-DD)
|
|
11462
|
-
granularity: this.
|
|
11463
|
-
//
|
|
11532
|
+
granularity: this.currentGranularity,
|
|
11533
|
+
// RFC-0097: Use current granularity from selector
|
|
11464
11534
|
theme: this.currentTheme,
|
|
11465
11535
|
// ← Use current theme (dynamic)
|
|
11466
11536
|
bar_mode: this.currentBarMode,
|
|
@@ -11532,7 +11602,8 @@ var EnergyModalView = class {
|
|
|
11532
11602
|
readingType: "temperature",
|
|
11533
11603
|
startDate: startDateStr,
|
|
11534
11604
|
endDate: endDateStr,
|
|
11535
|
-
granularity: this.
|
|
11605
|
+
granularity: this.currentGranularity,
|
|
11606
|
+
// RFC-0097: Use current granularity from selector
|
|
11536
11607
|
theme: this.currentTheme,
|
|
11537
11608
|
timezone: tzIdentifier,
|
|
11538
11609
|
iframeBaseUrl: this.config.params.chartsBaseUrl || "https://graphs.apps.myio-bas.com",
|
|
@@ -11855,6 +11926,20 @@ var EnergyModalView = class {
|
|
|
11855
11926
|
this.toggleBarMode();
|
|
11856
11927
|
});
|
|
11857
11928
|
}
|
|
11929
|
+
const granularityButtons = document.querySelectorAll(".myio-btn-granularity");
|
|
11930
|
+
if (granularityButtons.length > 0) {
|
|
11931
|
+
this.applyGranularityUI();
|
|
11932
|
+
granularityButtons.forEach((btn) => {
|
|
11933
|
+
btn.addEventListener("click", (e) => {
|
|
11934
|
+
const target = e.currentTarget;
|
|
11935
|
+
const newGranularity = target.dataset.granularity;
|
|
11936
|
+
if (newGranularity) {
|
|
11937
|
+
this.setGranularity(newGranularity);
|
|
11938
|
+
}
|
|
11939
|
+
});
|
|
11940
|
+
});
|
|
11941
|
+
console.log("[EnergyModalView] [RFC-0097] Granularity selector initialized with:", this.currentGranularity);
|
|
11942
|
+
}
|
|
11858
11943
|
try {
|
|
11859
11944
|
this.dateRangePicker = await attach(dateRangeInput, {
|
|
11860
11945
|
presetStart: this.config.params.startDate instanceof Date ? this.config.params.startDate.toISOString().split("T")[0] : this.config.params.startDate,
|
|
@@ -11957,6 +12042,37 @@ var EnergyModalView = class {
|
|
|
11957
12042
|
background: #e5e7eb;
|
|
11958
12043
|
}
|
|
11959
12044
|
|
|
12045
|
+
/* RFC-0097: Granularity selector buttons */
|
|
12046
|
+
.myio-btn-granularity {
|
|
12047
|
+
padding: 4px 10px;
|
|
12048
|
+
font-size: 12px;
|
|
12049
|
+
font-weight: 600;
|
|
12050
|
+
border-radius: 6px;
|
|
12051
|
+
border: 1px solid var(--myio-energy-border);
|
|
12052
|
+
background: var(--myio-energy-bg);
|
|
12053
|
+
color: var(--myio-energy-text);
|
|
12054
|
+
cursor: pointer;
|
|
12055
|
+
transition: all 0.2s ease;
|
|
12056
|
+
min-width: 36px;
|
|
12057
|
+
}
|
|
12058
|
+
|
|
12059
|
+
.myio-btn-granularity:hover:not(.active) {
|
|
12060
|
+
background: #f3f4f6;
|
|
12061
|
+
border-color: var(--myio-energy-primary);
|
|
12062
|
+
color: var(--myio-energy-primary);
|
|
12063
|
+
}
|
|
12064
|
+
|
|
12065
|
+
.myio-btn-granularity.active {
|
|
12066
|
+
background: var(--myio-energy-primary);
|
|
12067
|
+
color: white;
|
|
12068
|
+
border-color: var(--myio-energy-primary);
|
|
12069
|
+
box-shadow: 0 2px 4px rgba(74, 20, 140, 0.25);
|
|
12070
|
+
}
|
|
12071
|
+
|
|
12072
|
+
.myio-granularity-selector {
|
|
12073
|
+
border: 1px solid var(--myio-energy-border);
|
|
12074
|
+
}
|
|
12075
|
+
|
|
11960
12076
|
.myio-modal-scope {
|
|
11961
12077
|
height: 100% !important;
|
|
11962
12078
|
display: flex !important;
|
|
@@ -12337,7 +12453,9 @@ var EnergyModal = class {
|
|
|
12337
12453
|
return;
|
|
12338
12454
|
}
|
|
12339
12455
|
if (!this.context?.resolved.ingestionId) {
|
|
12340
|
-
const error = new Error(
|
|
12456
|
+
const error = new Error(
|
|
12457
|
+
"ingestionId not found in device attributes. Please configure the device properly."
|
|
12458
|
+
);
|
|
12341
12459
|
this.handleError(error);
|
|
12342
12460
|
return;
|
|
12343
12461
|
}
|
package/dist/index.js
CHANGED
|
@@ -5026,8 +5026,14 @@ function verifyOfflineStatus(entityObject, delayTimeInMins = 15) {
|
|
|
5026
5026
|
}
|
|
5027
5027
|
function paint(root, state) {
|
|
5028
5028
|
const { entityObject, i18n, delayTimeConnectionInMins } = state;
|
|
5029
|
-
if (
|
|
5030
|
-
entityObject.
|
|
5029
|
+
if (entityObject.connectionStatus) {
|
|
5030
|
+
if (entityObject.connectionStatus === "offline") {
|
|
5031
|
+
entityObject.deviceStatus = DeviceStatusType.NO_INFO;
|
|
5032
|
+
}
|
|
5033
|
+
} else {
|
|
5034
|
+
if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
|
|
5035
|
+
entityObject.deviceStatus = DeviceStatusType.NO_INFO;
|
|
5036
|
+
}
|
|
5031
5037
|
}
|
|
5032
5038
|
const stateClass = getCardStateClass(entityObject.deviceStatus);
|
|
5033
5039
|
root.className = `myio-ho-card ${stateClass}`;
|
|
@@ -10837,11 +10843,14 @@ var EnergyModalView = class {
|
|
|
10837
10843
|
isLoading = false;
|
|
10838
10844
|
currentTheme = "dark";
|
|
10839
10845
|
currentBarMode = "stacked";
|
|
10846
|
+
// RFC-0097: Granularity selector state (only 1h and 1d supported)
|
|
10847
|
+
currentGranularity = "1d";
|
|
10840
10848
|
constructor(modal, config) {
|
|
10841
10849
|
this.modal = modal;
|
|
10842
10850
|
this.config = config;
|
|
10843
10851
|
this.initializeTheme();
|
|
10844
10852
|
this.initializeBarMode();
|
|
10853
|
+
this.initializeGranularity();
|
|
10845
10854
|
this.validateConfiguration();
|
|
10846
10855
|
this.render();
|
|
10847
10856
|
}
|
|
@@ -10859,6 +10868,59 @@ var EnergyModalView = class {
|
|
|
10859
10868
|
const savedBarMode = localStorage.getItem("myio-modal-bar-mode");
|
|
10860
10869
|
this.currentBarMode = savedBarMode || "stacked";
|
|
10861
10870
|
}
|
|
10871
|
+
/**
|
|
10872
|
+
* RFC-0097: Initializes granularity from config or localStorage
|
|
10873
|
+
*/
|
|
10874
|
+
initializeGranularity() {
|
|
10875
|
+
const savedGranularity = localStorage.getItem("myio-modal-granularity");
|
|
10876
|
+
const configGranularity = this.config.params.granularity;
|
|
10877
|
+
const candidate = savedGranularity || configGranularity || "1d";
|
|
10878
|
+
this.currentGranularity = candidate === "1h" || candidate === "1d" ? candidate : "1d";
|
|
10879
|
+
}
|
|
10880
|
+
/**
|
|
10881
|
+
* RFC-0097: Sets granularity and re-renders chart
|
|
10882
|
+
*/
|
|
10883
|
+
setGranularity(granularity) {
|
|
10884
|
+
if (this.currentGranularity === granularity) return;
|
|
10885
|
+
this.currentGranularity = granularity;
|
|
10886
|
+
const buttons = document.querySelectorAll(".myio-btn-granularity");
|
|
10887
|
+
buttons.forEach((btn) => {
|
|
10888
|
+
const btnEl = btn;
|
|
10889
|
+
if (btnEl.dataset.granularity === granularity) {
|
|
10890
|
+
btnEl.classList.add("active");
|
|
10891
|
+
} else {
|
|
10892
|
+
btnEl.classList.remove("active");
|
|
10893
|
+
}
|
|
10894
|
+
});
|
|
10895
|
+
localStorage.setItem("myio-modal-granularity", granularity);
|
|
10896
|
+
this.reRenderChart();
|
|
10897
|
+
console.log("[EnergyModalView] [RFC-0097] Granularity changed to:", granularity);
|
|
10898
|
+
}
|
|
10899
|
+
/**
|
|
10900
|
+
* RFC-0097: Calculates suggested granularity based on date range
|
|
10901
|
+
* Only supports '1h' (hour) and '1d' (day)
|
|
10902
|
+
*/
|
|
10903
|
+
calculateSuggestedGranularity(startDate, endDate) {
|
|
10904
|
+
const start = new Date(startDate);
|
|
10905
|
+
const end = new Date(endDate);
|
|
10906
|
+
const diffDays = Math.ceil((end.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
|
|
10907
|
+
if (diffDays <= 1) return "1h";
|
|
10908
|
+
return "1d";
|
|
10909
|
+
}
|
|
10910
|
+
/**
|
|
10911
|
+
* RFC-0097: Applies granularity UI state (highlights correct button)
|
|
10912
|
+
*/
|
|
10913
|
+
applyGranularityUI() {
|
|
10914
|
+
const buttons = document.querySelectorAll(".myio-btn-granularity");
|
|
10915
|
+
buttons.forEach((btn) => {
|
|
10916
|
+
const btnEl = btn;
|
|
10917
|
+
if (btnEl.dataset.granularity === this.currentGranularity) {
|
|
10918
|
+
btnEl.classList.add("active");
|
|
10919
|
+
} else {
|
|
10920
|
+
btnEl.classList.remove("active");
|
|
10921
|
+
}
|
|
10922
|
+
});
|
|
10923
|
+
}
|
|
10862
10924
|
/**
|
|
10863
10925
|
* Toggles between dark and light theme
|
|
10864
10926
|
*/
|
|
@@ -11129,6 +11191,14 @@ var EnergyModalView = class {
|
|
|
11129
11191
|
</svg>
|
|
11130
11192
|
</button>
|
|
11131
11193
|
` : ""}
|
|
11194
|
+
${this.config.params.mode === "comparison" ? `
|
|
11195
|
+
<!-- RFC-0097: Granularity Selector (only 1h and 1d supported) -->
|
|
11196
|
+
<div class="myio-granularity-selector" style="display: flex; align-items: center; gap: 4px; margin-left: 8px; padding: 4px 8px; background: rgba(0,0,0,0.05); border-radius: 8px;">
|
|
11197
|
+
<span style="font-size: 11px; color: #666; margin-right: 4px; white-space: nowrap;">Granularidade:</span>
|
|
11198
|
+
<button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1h" ? "active" : ""}" data-granularity="1h" title="Hora">1h</button>
|
|
11199
|
+
<button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1d" ? "active" : ""}" data-granularity="1d" title="Dia">1d</button>
|
|
11200
|
+
</div>
|
|
11201
|
+
` : ""}
|
|
11132
11202
|
<button id="close-btn" class="myio-btn myio-btn-secondary">
|
|
11133
11203
|
Fechar
|
|
11134
11204
|
</button>
|
|
@@ -11351,8 +11421,8 @@ var EnergyModalView = class {
|
|
|
11351
11421
|
// ← NO TIME (YYYY-MM-DD)
|
|
11352
11422
|
endDate: endDateStr,
|
|
11353
11423
|
// ← NO TIME (YYYY-MM-DD)
|
|
11354
|
-
granularity: this.
|
|
11355
|
-
//
|
|
11424
|
+
granularity: this.currentGranularity,
|
|
11425
|
+
// RFC-0097: Use current granularity from selector
|
|
11356
11426
|
theme: this.currentTheme,
|
|
11357
11427
|
// ← Use current theme (dynamic)
|
|
11358
11428
|
bar_mode: this.currentBarMode,
|
|
@@ -11424,7 +11494,8 @@ var EnergyModalView = class {
|
|
|
11424
11494
|
readingType: "temperature",
|
|
11425
11495
|
startDate: startDateStr,
|
|
11426
11496
|
endDate: endDateStr,
|
|
11427
|
-
granularity: this.
|
|
11497
|
+
granularity: this.currentGranularity,
|
|
11498
|
+
// RFC-0097: Use current granularity from selector
|
|
11428
11499
|
theme: this.currentTheme,
|
|
11429
11500
|
timezone: tzIdentifier,
|
|
11430
11501
|
iframeBaseUrl: this.config.params.chartsBaseUrl || "https://graphs.apps.myio-bas.com",
|
|
@@ -11747,6 +11818,20 @@ var EnergyModalView = class {
|
|
|
11747
11818
|
this.toggleBarMode();
|
|
11748
11819
|
});
|
|
11749
11820
|
}
|
|
11821
|
+
const granularityButtons = document.querySelectorAll(".myio-btn-granularity");
|
|
11822
|
+
if (granularityButtons.length > 0) {
|
|
11823
|
+
this.applyGranularityUI();
|
|
11824
|
+
granularityButtons.forEach((btn) => {
|
|
11825
|
+
btn.addEventListener("click", (e) => {
|
|
11826
|
+
const target = e.currentTarget;
|
|
11827
|
+
const newGranularity = target.dataset.granularity;
|
|
11828
|
+
if (newGranularity) {
|
|
11829
|
+
this.setGranularity(newGranularity);
|
|
11830
|
+
}
|
|
11831
|
+
});
|
|
11832
|
+
});
|
|
11833
|
+
console.log("[EnergyModalView] [RFC-0097] Granularity selector initialized with:", this.currentGranularity);
|
|
11834
|
+
}
|
|
11750
11835
|
try {
|
|
11751
11836
|
this.dateRangePicker = await attach(dateRangeInput, {
|
|
11752
11837
|
presetStart: this.config.params.startDate instanceof Date ? this.config.params.startDate.toISOString().split("T")[0] : this.config.params.startDate,
|
|
@@ -11849,6 +11934,37 @@ var EnergyModalView = class {
|
|
|
11849
11934
|
background: #e5e7eb;
|
|
11850
11935
|
}
|
|
11851
11936
|
|
|
11937
|
+
/* RFC-0097: Granularity selector buttons */
|
|
11938
|
+
.myio-btn-granularity {
|
|
11939
|
+
padding: 4px 10px;
|
|
11940
|
+
font-size: 12px;
|
|
11941
|
+
font-weight: 600;
|
|
11942
|
+
border-radius: 6px;
|
|
11943
|
+
border: 1px solid var(--myio-energy-border);
|
|
11944
|
+
background: var(--myio-energy-bg);
|
|
11945
|
+
color: var(--myio-energy-text);
|
|
11946
|
+
cursor: pointer;
|
|
11947
|
+
transition: all 0.2s ease;
|
|
11948
|
+
min-width: 36px;
|
|
11949
|
+
}
|
|
11950
|
+
|
|
11951
|
+
.myio-btn-granularity:hover:not(.active) {
|
|
11952
|
+
background: #f3f4f6;
|
|
11953
|
+
border-color: var(--myio-energy-primary);
|
|
11954
|
+
color: var(--myio-energy-primary);
|
|
11955
|
+
}
|
|
11956
|
+
|
|
11957
|
+
.myio-btn-granularity.active {
|
|
11958
|
+
background: var(--myio-energy-primary);
|
|
11959
|
+
color: white;
|
|
11960
|
+
border-color: var(--myio-energy-primary);
|
|
11961
|
+
box-shadow: 0 2px 4px rgba(74, 20, 140, 0.25);
|
|
11962
|
+
}
|
|
11963
|
+
|
|
11964
|
+
.myio-granularity-selector {
|
|
11965
|
+
border: 1px solid var(--myio-energy-border);
|
|
11966
|
+
}
|
|
11967
|
+
|
|
11852
11968
|
.myio-modal-scope {
|
|
11853
11969
|
height: 100% !important;
|
|
11854
11970
|
display: flex !important;
|
|
@@ -12229,7 +12345,9 @@ var EnergyModal = class {
|
|
|
12229
12345
|
return;
|
|
12230
12346
|
}
|
|
12231
12347
|
if (!this.context?.resolved.ingestionId) {
|
|
12232
|
-
const error = new Error(
|
|
12348
|
+
const error = new Error(
|
|
12349
|
+
"ingestionId not found in device attributes. Please configure the device properly."
|
|
12350
|
+
);
|
|
12233
12351
|
this.handleError(error);
|
|
12234
12352
|
return;
|
|
12235
12353
|
}
|
|
@@ -5018,8 +5018,14 @@
|
|
|
5018
5018
|
}
|
|
5019
5019
|
function paint(root, state) {
|
|
5020
5020
|
const { entityObject, i18n, delayTimeConnectionInMins } = state;
|
|
5021
|
-
if (
|
|
5022
|
-
entityObject.
|
|
5021
|
+
if (entityObject.connectionStatus) {
|
|
5022
|
+
if (entityObject.connectionStatus === "offline") {
|
|
5023
|
+
entityObject.deviceStatus = DeviceStatusType.NO_INFO;
|
|
5024
|
+
}
|
|
5025
|
+
} else {
|
|
5026
|
+
if (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
|
|
5027
|
+
entityObject.deviceStatus = DeviceStatusType.NO_INFO;
|
|
5028
|
+
}
|
|
5023
5029
|
}
|
|
5024
5030
|
const stateClass = getCardStateClass(entityObject.deviceStatus);
|
|
5025
5031
|
root.className = `myio-ho-card ${stateClass}`;
|
|
@@ -10696,11 +10702,14 @@ ${rangeText}`;
|
|
|
10696
10702
|
isLoading = false;
|
|
10697
10703
|
currentTheme = "dark";
|
|
10698
10704
|
currentBarMode = "stacked";
|
|
10705
|
+
// RFC-0097: Granularity selector state (only 1h and 1d supported)
|
|
10706
|
+
currentGranularity = "1d";
|
|
10699
10707
|
constructor(modal, config) {
|
|
10700
10708
|
this.modal = modal;
|
|
10701
10709
|
this.config = config;
|
|
10702
10710
|
this.initializeTheme();
|
|
10703
10711
|
this.initializeBarMode();
|
|
10712
|
+
this.initializeGranularity();
|
|
10704
10713
|
this.validateConfiguration();
|
|
10705
10714
|
this.render();
|
|
10706
10715
|
}
|
|
@@ -10718,6 +10727,59 @@ ${rangeText}`;
|
|
|
10718
10727
|
const savedBarMode = localStorage.getItem("myio-modal-bar-mode");
|
|
10719
10728
|
this.currentBarMode = savedBarMode || "stacked";
|
|
10720
10729
|
}
|
|
10730
|
+
/**
|
|
10731
|
+
* RFC-0097: Initializes granularity from config or localStorage
|
|
10732
|
+
*/
|
|
10733
|
+
initializeGranularity() {
|
|
10734
|
+
const savedGranularity = localStorage.getItem("myio-modal-granularity");
|
|
10735
|
+
const configGranularity = this.config.params.granularity;
|
|
10736
|
+
const candidate = savedGranularity || configGranularity || "1d";
|
|
10737
|
+
this.currentGranularity = candidate === "1h" || candidate === "1d" ? candidate : "1d";
|
|
10738
|
+
}
|
|
10739
|
+
/**
|
|
10740
|
+
* RFC-0097: Sets granularity and re-renders chart
|
|
10741
|
+
*/
|
|
10742
|
+
setGranularity(granularity) {
|
|
10743
|
+
if (this.currentGranularity === granularity) return;
|
|
10744
|
+
this.currentGranularity = granularity;
|
|
10745
|
+
const buttons = document.querySelectorAll(".myio-btn-granularity");
|
|
10746
|
+
buttons.forEach((btn) => {
|
|
10747
|
+
const btnEl = btn;
|
|
10748
|
+
if (btnEl.dataset.granularity === granularity) {
|
|
10749
|
+
btnEl.classList.add("active");
|
|
10750
|
+
} else {
|
|
10751
|
+
btnEl.classList.remove("active");
|
|
10752
|
+
}
|
|
10753
|
+
});
|
|
10754
|
+
localStorage.setItem("myio-modal-granularity", granularity);
|
|
10755
|
+
this.reRenderChart();
|
|
10756
|
+
console.log("[EnergyModalView] [RFC-0097] Granularity changed to:", granularity);
|
|
10757
|
+
}
|
|
10758
|
+
/**
|
|
10759
|
+
* RFC-0097: Calculates suggested granularity based on date range
|
|
10760
|
+
* Only supports '1h' (hour) and '1d' (day)
|
|
10761
|
+
*/
|
|
10762
|
+
calculateSuggestedGranularity(startDate, endDate) {
|
|
10763
|
+
const start = new Date(startDate);
|
|
10764
|
+
const end = new Date(endDate);
|
|
10765
|
+
const diffDays = Math.ceil((end.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24));
|
|
10766
|
+
if (diffDays <= 1) return "1h";
|
|
10767
|
+
return "1d";
|
|
10768
|
+
}
|
|
10769
|
+
/**
|
|
10770
|
+
* RFC-0097: Applies granularity UI state (highlights correct button)
|
|
10771
|
+
*/
|
|
10772
|
+
applyGranularityUI() {
|
|
10773
|
+
const buttons = document.querySelectorAll(".myio-btn-granularity");
|
|
10774
|
+
buttons.forEach((btn) => {
|
|
10775
|
+
const btnEl = btn;
|
|
10776
|
+
if (btnEl.dataset.granularity === this.currentGranularity) {
|
|
10777
|
+
btnEl.classList.add("active");
|
|
10778
|
+
} else {
|
|
10779
|
+
btnEl.classList.remove("active");
|
|
10780
|
+
}
|
|
10781
|
+
});
|
|
10782
|
+
}
|
|
10721
10783
|
/**
|
|
10722
10784
|
* Toggles between dark and light theme
|
|
10723
10785
|
*/
|
|
@@ -10988,6 +11050,14 @@ ${rangeText}`;
|
|
|
10988
11050
|
</svg>
|
|
10989
11051
|
</button>
|
|
10990
11052
|
` : ""}
|
|
11053
|
+
${this.config.params.mode === "comparison" ? `
|
|
11054
|
+
<!-- RFC-0097: Granularity Selector (only 1h and 1d supported) -->
|
|
11055
|
+
<div class="myio-granularity-selector" style="display: flex; align-items: center; gap: 4px; margin-left: 8px; padding: 4px 8px; background: rgba(0,0,0,0.05); border-radius: 8px;">
|
|
11056
|
+
<span style="font-size: 11px; color: #666; margin-right: 4px; white-space: nowrap;">Granularidade:</span>
|
|
11057
|
+
<button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1h" ? "active" : ""}" data-granularity="1h" title="Hora">1h</button>
|
|
11058
|
+
<button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1d" ? "active" : ""}" data-granularity="1d" title="Dia">1d</button>
|
|
11059
|
+
</div>
|
|
11060
|
+
` : ""}
|
|
10991
11061
|
<button id="close-btn" class="myio-btn myio-btn-secondary">
|
|
10992
11062
|
Fechar
|
|
10993
11063
|
</button>
|
|
@@ -11210,8 +11280,8 @@ ${rangeText}`;
|
|
|
11210
11280
|
// ← NO TIME (YYYY-MM-DD)
|
|
11211
11281
|
endDate: endDateStr,
|
|
11212
11282
|
// ← NO TIME (YYYY-MM-DD)
|
|
11213
|
-
granularity: this.
|
|
11214
|
-
//
|
|
11283
|
+
granularity: this.currentGranularity,
|
|
11284
|
+
// RFC-0097: Use current granularity from selector
|
|
11215
11285
|
theme: this.currentTheme,
|
|
11216
11286
|
// ← Use current theme (dynamic)
|
|
11217
11287
|
bar_mode: this.currentBarMode,
|
|
@@ -11283,7 +11353,8 @@ ${rangeText}`;
|
|
|
11283
11353
|
readingType: "temperature",
|
|
11284
11354
|
startDate: startDateStr,
|
|
11285
11355
|
endDate: endDateStr,
|
|
11286
|
-
granularity: this.
|
|
11356
|
+
granularity: this.currentGranularity,
|
|
11357
|
+
// RFC-0097: Use current granularity from selector
|
|
11287
11358
|
theme: this.currentTheme,
|
|
11288
11359
|
timezone: tzIdentifier,
|
|
11289
11360
|
iframeBaseUrl: this.config.params.chartsBaseUrl || "https://graphs.apps.myio-bas.com",
|
|
@@ -11606,6 +11677,20 @@ ${rangeText}`;
|
|
|
11606
11677
|
this.toggleBarMode();
|
|
11607
11678
|
});
|
|
11608
11679
|
}
|
|
11680
|
+
const granularityButtons = document.querySelectorAll(".myio-btn-granularity");
|
|
11681
|
+
if (granularityButtons.length > 0) {
|
|
11682
|
+
this.applyGranularityUI();
|
|
11683
|
+
granularityButtons.forEach((btn) => {
|
|
11684
|
+
btn.addEventListener("click", (e) => {
|
|
11685
|
+
const target = e.currentTarget;
|
|
11686
|
+
const newGranularity = target.dataset.granularity;
|
|
11687
|
+
if (newGranularity) {
|
|
11688
|
+
this.setGranularity(newGranularity);
|
|
11689
|
+
}
|
|
11690
|
+
});
|
|
11691
|
+
});
|
|
11692
|
+
console.log("[EnergyModalView] [RFC-0097] Granularity selector initialized with:", this.currentGranularity);
|
|
11693
|
+
}
|
|
11609
11694
|
try {
|
|
11610
11695
|
this.dateRangePicker = await attach(dateRangeInput, {
|
|
11611
11696
|
presetStart: this.config.params.startDate instanceof Date ? this.config.params.startDate.toISOString().split("T")[0] : this.config.params.startDate,
|
|
@@ -11708,6 +11793,37 @@ ${rangeText}`;
|
|
|
11708
11793
|
background: #e5e7eb;
|
|
11709
11794
|
}
|
|
11710
11795
|
|
|
11796
|
+
/* RFC-0097: Granularity selector buttons */
|
|
11797
|
+
.myio-btn-granularity {
|
|
11798
|
+
padding: 4px 10px;
|
|
11799
|
+
font-size: 12px;
|
|
11800
|
+
font-weight: 600;
|
|
11801
|
+
border-radius: 6px;
|
|
11802
|
+
border: 1px solid var(--myio-energy-border);
|
|
11803
|
+
background: var(--myio-energy-bg);
|
|
11804
|
+
color: var(--myio-energy-text);
|
|
11805
|
+
cursor: pointer;
|
|
11806
|
+
transition: all 0.2s ease;
|
|
11807
|
+
min-width: 36px;
|
|
11808
|
+
}
|
|
11809
|
+
|
|
11810
|
+
.myio-btn-granularity:hover:not(.active) {
|
|
11811
|
+
background: #f3f4f6;
|
|
11812
|
+
border-color: var(--myio-energy-primary);
|
|
11813
|
+
color: var(--myio-energy-primary);
|
|
11814
|
+
}
|
|
11815
|
+
|
|
11816
|
+
.myio-btn-granularity.active {
|
|
11817
|
+
background: var(--myio-energy-primary);
|
|
11818
|
+
color: white;
|
|
11819
|
+
border-color: var(--myio-energy-primary);
|
|
11820
|
+
box-shadow: 0 2px 4px rgba(74, 20, 140, 0.25);
|
|
11821
|
+
}
|
|
11822
|
+
|
|
11823
|
+
.myio-granularity-selector {
|
|
11824
|
+
border: 1px solid var(--myio-energy-border);
|
|
11825
|
+
}
|
|
11826
|
+
|
|
11711
11827
|
.myio-modal-scope {
|
|
11712
11828
|
height: 100% !important;
|
|
11713
11829
|
display: flex !important;
|
|
@@ -12088,7 +12204,9 @@ ${rangeText}`;
|
|
|
12088
12204
|
return;
|
|
12089
12205
|
}
|
|
12090
12206
|
if (!this.context?.resolved.ingestionId) {
|
|
12091
|
-
const error = new Error(
|
|
12207
|
+
const error = new Error(
|
|
12208
|
+
"ingestionId not found in device attributes. Please configure the device properly."
|
|
12209
|
+
);
|
|
12092
12210
|
this.handleError(error);
|
|
12093
12211
|
return;
|
|
12094
12212
|
}
|