myio-js-library 0.1.412 → 0.1.413

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
@@ -1122,7 +1122,7 @@ module.exports = __toCommonJS(index_exports);
1122
1122
  // package.json
1123
1123
  var package_default = {
1124
1124
  name: "myio-js-library",
1125
- version: "0.1.412",
1125
+ version: "0.1.413",
1126
1126
  description: "A clean, standalone JS SDK for MYIO projects",
1127
1127
  license: "MIT",
1128
1128
  repository: "github:gh-myio/myio-js-library",
@@ -30972,7 +30972,7 @@ var AllReportModal = class {
30972
30972
  this.debugLog("[AllReportModal] Empty/invalid API response:", apiResponse);
30973
30973
  return [];
30974
30974
  }
30975
- if (!this.params.itemsList || this.params.itemsList.length === 0) {
30975
+ if (!this.params.itemsList) {
30976
30976
  this.debugLog("\u{1F4CB} No itemsList provided \u2014 mapping directly from API array");
30977
30977
  return apiArray.map((item) => ({
30978
30978
  identifier: item.assetName || this.resolveStoreIdentifierFromApi(item) || item.id || "",
@@ -30980,124 +30980,34 @@ var AllReportModal = class {
30980
30980
  consumption: this.pickConsumption(item)
30981
30981
  }));
30982
30982
  }
30983
- const sumByApiId = /* @__PURE__ */ new Map();
30984
- let apiItemsWithoutId = 0;
30985
- let totalApiConsumption = 0;
30986
- this.debugLog("\u{1F528} Building ID index from API data...");
30987
- for (const [index, item] of apiArray.entries()) {
30988
- const consumption = this.pickConsumption(item);
30989
- totalApiConsumption += consumption;
30990
- if (index < 3) {
30991
- this.debugLog(`[AllReportModal] NEW MAPPING - API item ${index}:`, {
30992
- id: item?.id,
30993
- name: item?.name,
30994
- assetName: item?.assetName,
30995
- total_value: item?.total_value,
30996
- extractedConsumption: consumption
30997
- });
30998
- }
30999
- this.debugLog(`\u{1F4CA} Processing API item ${index}`, {
31000
- item,
31001
- extractedConsumption: consumption,
31002
- hasId: !!item?.id
31003
- });
31004
- if (item?.id) {
31005
- const id = String(item.id);
31006
- const previousSum = sumByApiId.get(id) || 0;
31007
- sumByApiId.set(id, previousSum + consumption);
31008
- this.debugLog(
31009
- `\u2705 Added to ID index: ${id} = ${previousSum} + ${consumption} = ${previousSum + consumption}`
31010
- );
31011
- } else {
31012
- apiItemsWithoutId++;
31013
- this.debugLog(`\u274C API item without ID:`, item);
31014
- }
31015
- }
31016
- this.debugLog("[AllReportModal] NEW MAPPING - Total API consumption:", totalApiConsumption);
31017
- this.debugLog("[AllReportModal] NEW MAPPING - Unique API IDs:", sumByApiId.size);
31018
- this.debugLog("\u{1F4CA} ID index built", {
31019
- sumByApiIdSize: sumByApiId.size,
31020
- sumByApiIdEntries: Array.from(sumByApiId.entries()),
31021
- apiItemsWithoutId
31022
- });
31023
- let matchedById = 0, matchedBySubstring = 0;
30983
+ const orchIdSet = new Set(this.params.itemsList.map((item) => String(item.id)));
30984
+ const orchMeta = new Map(this.params.itemsList.map((item) => [String(item.id), item]));
30985
+ this.debugLog("[AllReportModal] API-driven filter \u2014 orchestrator devices:", orchIdSet.size);
30986
+ this.debugLog("[AllReportModal] API-driven filter \u2014 API total devices:", apiArray.length);
30987
+ const rows = [];
31024
30988
  let totalMappedConsumption = 0;
31025
- this.debugLog("\u{1F3AF} Starting itemsList mapping...");
31026
- const rows = this.params.itemsList.map((listItem, index) => {
31027
- this.debugLog(`\u{1F50D} Processing listItem ${index}`, listItem);
31028
- let consumption = sumByApiId.get(listItem.id) ?? 0;
31029
- this.debugLog(`\u{1F3AF} Primary ID match for ${listItem.id}: ${consumption}`);
31030
- if (index < 3) {
31031
- this.debugLog(`[AllReportModal] NEW MAPPING - ItemsList item ${index}:`, {
31032
- id: listItem.id,
31033
- identifier: listItem.identifier,
31034
- label: listItem.label,
31035
- idMatchConsumption: consumption
31036
- });
31037
- }
31038
- if (consumption > 0) {
31039
- matchedById++;
31040
- this.debugLog(`\u2705 Matched by ID: ${listItem.id} -> ${consumption}`);
31041
- } else {
31042
- this.debugLog(`\u{1F504} No ID match, trying substring fallback for identifier: ${listItem.identifier}`);
31043
- for (const [apiIndex, apiItem] of apiArray.entries()) {
31044
- const assetName = apiItem?.assetName || "";
31045
- const name = apiItem?.name || "";
31046
- const assetNameMatch = assetName.includes(listItem.identifier);
31047
- const nameMatch = name.includes(listItem.identifier);
31048
- if (assetNameMatch || nameMatch) {
31049
- const itemConsumption = this.pickConsumption(apiItem);
31050
- consumption += itemConsumption;
31051
- if (index < 3) {
31052
- this.debugLog(`[AllReportModal] NEW MAPPING - Substring match for ${listItem.identifier}:`, {
31053
- apiItemName: name,
31054
- apiItemAssetName: assetName,
31055
- itemConsumption,
31056
- totalConsumption: consumption
31057
- });
31058
- }
31059
- this.debugLog(`\u2705 Substring match found in API item ${apiIndex}`, {
31060
- listItemIdentifier: listItem.identifier,
31061
- apiItemAssetName: assetName,
31062
- apiItemName: name,
31063
- assetNameMatch,
31064
- nameMatch,
31065
- itemConsumption,
31066
- totalConsumption: consumption
31067
- });
31068
- }
31069
- }
31070
- if (consumption > 0) {
31071
- matchedBySubstring++;
31072
- this.debugLog(`\u2705 Matched by substring: ${listItem.identifier} -> ${consumption}`);
31073
- } else {
31074
- this.debugLog(`\u274C No match found for: ${listItem.identifier}`);
31075
- }
31076
- }
30989
+ for (const apiItem of apiArray) {
30990
+ const apiId = String(apiItem?.id || "");
30991
+ if (!apiId || !orchIdSet.has(apiId)) continue;
30992
+ const meta = orchMeta.get(apiId);
30993
+ const consumption = Math.round(this.pickConsumption(apiItem) * 100) / 100;
31077
30994
  const result = {
31078
- identifier: listItem.identifier,
31079
- name: listItem.label,
31080
- consumption: Math.round(consumption * 100) / 100,
31081
- ...listItem.groupLabel ? { groupLabel: listItem.groupLabel } : {}
30995
+ identifier: meta?.identifier || apiItem.name || apiId,
30996
+ name: meta?.label || apiItem.name || apiId,
30997
+ consumption,
30998
+ ...meta?.groupLabel ? { groupLabel: meta.groupLabel } : {}
31082
30999
  };
31083
- totalMappedConsumption += result.consumption;
31084
- this.debugLog(`\u{1F4DD} Final row for ${listItem.identifier}:`, result);
31085
- return result;
31086
- });
31087
- const stats = {
31088
- apiItems: apiArray.length,
31089
- uniqueApiIds: sumByApiId.size,
31090
- itemsInList: this.params.itemsList.length,
31091
- matchedById,
31092
- matchedBySubstring,
31093
- unmatched: this.params.itemsList.length - matchedById - matchedBySubstring,
31094
- apiItemsWithoutId,
31095
- totalApiConsumption,
31000
+ totalMappedConsumption += consumption;
31001
+ rows.push(result);
31002
+ }
31003
+ this.debugLog(
31004
+ "[AllReportModal] API-driven filter \u2014 matched:",
31005
+ rows.length,
31006
+ "| discarded:",
31007
+ apiArray.length - rows.length,
31008
+ "| total consumption:",
31096
31009
  totalMappedConsumption
31097
- };
31098
- this.debugLog("[AllReportModal] NEW MAPPING - Final stats:", stats);
31099
- this.debugLog("\u{1F4CA} Final mapping stats:", stats);
31100
- this.debugLog("[AllReportModal] Mapping stats:", stats);
31010
+ );
31101
31011
  return rows;
31102
31012
  }
31103
31013
  parseConsumptionValue(item) {
@@ -50196,14 +50106,22 @@ function createAlarmCardElement(alarm, params) {
50196
50106
  if (snoozeBtn) {
50197
50107
  snoozeBtn.addEventListener("click", (e) => {
50198
50108
  e.stopPropagation();
50199
- card.dispatchEvent(new CustomEvent("alarm-snooze", { bubbles: true, detail: { alarmId: alarm.id } }));
50109
+ if (params?.onSnooze) {
50110
+ params.onSnooze(alarm.id);
50111
+ } else {
50112
+ card.dispatchEvent(new CustomEvent("alarm-snooze", { bubbles: true, detail: { alarmId: alarm.id } }));
50113
+ }
50200
50114
  });
50201
50115
  }
50202
50116
  const escalateBtn = card.querySelector('[data-action="escalate"]');
50203
50117
  if (escalateBtn) {
50204
50118
  escalateBtn.addEventListener("click", (e) => {
50205
50119
  e.stopPropagation();
50206
- card.dispatchEvent(new CustomEvent("alarm-escalate", { bubbles: true, detail: { alarmId: alarm.id } }));
50120
+ if (params?.onEscalate) {
50121
+ params.onEscalate(alarm.id);
50122
+ } else {
50123
+ card.dispatchEvent(new CustomEvent("alarm-escalate", { bubbles: true, detail: { alarmId: alarm.id } }));
50124
+ }
50207
50125
  });
50208
50126
  }
50209
50127
  const typeList = card.querySelector(".alarm-card-type-list");
@@ -54414,8 +54332,10 @@ var AlarmsTab = class {
54414
54332
  try {
54415
54333
  const gcdrBaseUrl = this.config.gcdrApiBaseUrl || GCDR_DEFAULT_BASE_URL;
54416
54334
  const alarmsBaseUrl = this.config.alarmsApiBaseUrl || ALARMS_DEFAULT_BASE_URL;
54335
+ const aso = window.AlarmServiceOrchestrator;
54336
+ const fromOrch = this.config.gcdrDeviceId ? aso?.getAlarmsForDevice(this.config.gcdrDeviceId) ?? null : null;
54417
54337
  const prefetched = this.config.prefetchedAlarms;
54418
- const alarmsPromise = prefetched != null ? Promise.resolve(
54338
+ const alarmsPromise = fromOrch != null && fromOrch.length > 0 ? Promise.resolve(fromOrch) : prefetched != null ? Promise.resolve(
54419
54339
  prefetched.filter(
54420
54340
  (a) => a.deviceId === this.config.gcdrDeviceId
54421
54341
  )
@@ -54590,6 +54510,8 @@ var AlarmsTab = class {
54590
54510
  if (!grid) return;
54591
54511
  grid.innerHTML = "";
54592
54512
  const alarmsBaseUrl = this.config.alarmsApiBaseUrl || ALARMS_DEFAULT_BASE_URL;
54513
+ const AlarmService2 = window.MyIOLibrary?.AlarmService;
54514
+ const userEmail = window.MyIOUtils?.currentUserEmail || "";
54593
54515
  for (const group of this.alarmGroups) {
54594
54516
  const alarm = this.mapGroupToAlarm(group);
54595
54517
  const params = {
@@ -54597,31 +54519,56 @@ var AlarmsTab = class {
54597
54519
  showDeviceBadge: false,
54598
54520
  alarmTypes: alarm._alarmTypes,
54599
54521
  onAcknowledge: async () => {
54600
- await Promise.all(
54601
- group.alarmIds.map((id) => this.postAlarmAction(alarmsBaseUrl, id, "acknowledge"))
54602
- );
54522
+ if (AlarmService2?.batchAcknowledge) {
54523
+ await AlarmService2.batchAcknowledge(group.alarmIds, userEmail);
54524
+ } else {
54525
+ await Promise.all(
54526
+ group.alarmIds.map((id) => this.postAlarmAction(alarmsBaseUrl, id, "acknowledge"))
54527
+ );
54528
+ }
54529
+ await this.refreshAlarmsGrid(alarmsBaseUrl);
54530
+ },
54531
+ onSnooze: async () => {
54532
+ if (AlarmService2?.batchSilence) {
54533
+ await AlarmService2.batchSilence(group.alarmIds, userEmail, "4h");
54534
+ } else {
54535
+ await Promise.all(
54536
+ group.alarmIds.map((id) => this.postAlarmAction(alarmsBaseUrl, id, "snooze"))
54537
+ );
54538
+ }
54539
+ await this.refreshAlarmsGrid(alarmsBaseUrl);
54540
+ },
54541
+ onEscalate: async () => {
54542
+ if (AlarmService2?.batchEscalate) {
54543
+ await AlarmService2.batchEscalate(group.alarmIds, userEmail);
54544
+ } else {
54545
+ await Promise.all(
54546
+ group.alarmIds.map((id) => this.postAlarmAction(alarmsBaseUrl, id, "escalate"))
54547
+ );
54548
+ }
54603
54549
  await this.refreshAlarmsGrid(alarmsBaseUrl);
54550
+ },
54551
+ onDetails: () => {
54552
+ console.info("[AlarmsTab] Alarm group details:", {
54553
+ ruleId: group.ruleId,
54554
+ title: group.title,
54555
+ alarmIds: group.alarmIds,
54556
+ stateCounts: group.stateCounts
54557
+ });
54604
54558
  }
54605
54559
  };
54606
54560
  const el = createAlarmCardElement(alarm, params);
54607
- el.addEventListener("alarm-snooze", async () => {
54608
- await Promise.all(
54609
- group.alarmIds.map((id) => this.postAlarmAction(alarmsBaseUrl, id, "snooze"))
54610
- );
54611
- await this.refreshAlarmsGrid(alarmsBaseUrl);
54612
- });
54613
- el.addEventListener("alarm-escalate", async () => {
54614
- await Promise.all(
54615
- group.alarmIds.map((id) => this.postAlarmAction(alarmsBaseUrl, id, "escalate"))
54616
- );
54617
- await this.refreshAlarmsGrid(alarmsBaseUrl);
54618
- });
54619
54561
  grid.appendChild(el);
54620
54562
  }
54621
54563
  }
54622
54564
  async refreshAlarmsGrid(alarmsBaseUrl) {
54623
54565
  this.activeAlarms = await this.fetchActiveAlarms(alarmsBaseUrl);
54624
54566
  this.alarmGroups = this.groupAlarms(this.activeAlarms);
54567
+ const aso = window.AlarmServiceOrchestrator;
54568
+ if (aso) {
54569
+ await aso.refresh().catch(() => {
54570
+ });
54571
+ }
54625
54572
  const badge = this.config.container.querySelector("#at-alarms-count");
54626
54573
  if (badge) {
54627
54574
  badge.textContent = String(this.alarmGroups.length);
@@ -94235,6 +94182,7 @@ var TELEMETRY_GRID_SHOPPING_STYLES = `
94235
94182
  justify-content: center;
94236
94183
  box-sizing: border-box;
94237
94184
  overflow: visible;
94185
+ position: relative;
94238
94186
  }
94239
94187
 
94240
94188
  /* ============ Loading Overlay ============ */
@@ -94925,6 +94873,7 @@ var TelemetryGridShoppingView = class {
94925
94873
  // Card instances for cleanup
94926
94874
  cardInstances = /* @__PURE__ */ new Map();
94927
94875
  isMaximized = false;
94876
+ _alarmBadgeStylesInjected = false;
94928
94877
  originalParent = null;
94929
94878
  originalNextSibling = null;
94930
94879
  constructor(params, controller) {
@@ -95296,6 +95245,13 @@ var TelemetryGridShoppingView = class {
95296
95245
  if (cardElement) {
95297
95246
  wrapper.appendChild(cardElement);
95298
95247
  this.cardInstances.set(device.entityId, $card);
95248
+ const aso = window.AlarmServiceOrchestrator;
95249
+ if (aso && device.gcdrDeviceId) {
95250
+ const count = aso.getAlarmCountForDevice(device.gcdrDeviceId);
95251
+ if (count > 0) {
95252
+ wrapper.appendChild(this._createAlarmBadge(count));
95253
+ }
95254
+ }
95299
95255
  } else {
95300
95256
  this.log("Card element not found for:", device.labelOrName);
95301
95257
  wrapper.innerHTML = this.buildFallbackCard(device);
@@ -95390,6 +95346,49 @@ var TelemetryGridShoppingView = class {
95390
95346
  }
95391
95347
  }
95392
95348
  }
95349
+ // =========================================================================
95350
+ // RFC-0183: Alarm Badge
95351
+ // =========================================================================
95352
+ _createAlarmBadge(count) {
95353
+ this._injectAlarmBadgeStyles();
95354
+ const badge = document.createElement("div");
95355
+ badge.className = "myio-alarm-badge";
95356
+ badge.title = `${count} alarme${count !== 1 ? "s" : ""} ativo${count !== 1 ? "s" : ""}`;
95357
+ badge.innerHTML = `
95358
+ <svg viewBox="0 0 24 24" width="10" height="10" fill="currentColor" aria-hidden="true">
95359
+ <path d="M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2zm6-6V11c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2z"/>
95360
+ </svg>
95361
+ <span>${count > 99 ? "99+" : count}</span>
95362
+ `;
95363
+ return badge;
95364
+ }
95365
+ _injectAlarmBadgeStyles() {
95366
+ if (this._alarmBadgeStylesInjected) return;
95367
+ this._alarmBadgeStylesInjected = true;
95368
+ if (document.getElementById("myio-alarm-badge-styles")) return;
95369
+ const s = document.createElement("style");
95370
+ s.id = "myio-alarm-badge-styles";
95371
+ s.textContent = `
95372
+ .myio-alarm-badge {
95373
+ position: absolute;
95374
+ top: 6px;
95375
+ left: 6px;
95376
+ background: #dc2626;
95377
+ color: #fff;
95378
+ border-radius: 10px;
95379
+ padding: 2px 5px;
95380
+ font-size: 10px;
95381
+ font-weight: 700;
95382
+ display: flex;
95383
+ align-items: center;
95384
+ gap: 2px;
95385
+ z-index: 10;
95386
+ pointer-events: none;
95387
+ line-height: 1.3;
95388
+ }
95389
+ `;
95390
+ document.head.appendChild(s);
95391
+ }
95393
95392
  destroy() {
95394
95393
  this.log("destroy");
95395
95394
  this.destroyCards();
package/dist/index.d.cts CHANGED
@@ -13007,6 +13007,7 @@ interface TelemetryDevice {
13007
13007
  identifier?: string;
13008
13008
  domain?: TelemetryDomain$1;
13009
13009
  log_annotations?: Record<string, unknown>;
13010
+ alarmCount?: number;
13010
13011
  }
13011
13012
  interface FilterState {
13012
13013
  searchTerm: string;
@@ -14521,6 +14522,10 @@ interface AlarmCardParams {
14521
14522
  onCardClick?: (alarm: Alarm) => void;
14522
14523
  /** Callback when acknowledge button is clicked */
14523
14524
  onAcknowledge?: (alarmId: string) => void;
14525
+ /** Callback when snooze (adiar) button is clicked */
14526
+ onSnooze?: (alarmId: string) => void;
14527
+ /** Callback when escalate button is clicked */
14528
+ onEscalate?: (alarmId: string) => void;
14524
14529
  /** Callback when details button is clicked */
14525
14530
  onDetails?: (alarmId: string) => void;
14526
14531
  /** Callback when more button is clicked */