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 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 (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
5138
- entityObject.deviceStatus = DeviceStatusType.NO_INFO;
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.config.params.granularity,
11463
- // REQUIRED
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.config.params.granularity,
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("ingestionId not found in device attributes. Please configure the device properly.");
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 (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
5030
- entityObject.deviceStatus = DeviceStatusType.NO_INFO;
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.config.params.granularity,
11355
- // REQUIRED
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.config.params.granularity,
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("ingestionId not found in device attributes. Please configure the device properly.");
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 (verifyOfflineStatus(entityObject, delayTimeConnectionInMins) === false) {
5022
- entityObject.deviceStatus = DeviceStatusType.NO_INFO;
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.config.params.granularity,
11214
- // REQUIRED
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.config.params.granularity,
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("ingestionId not found in device attributes. Please configure the device properly.");
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
  }