myio-js-library 0.1.494 → 0.1.496

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
@@ -1162,7 +1162,7 @@ module.exports = __toCommonJS(index_exports);
1162
1162
  // package.json
1163
1163
  var package_default = {
1164
1164
  name: "myio-js-library",
1165
- version: "0.1.494",
1165
+ version: "0.1.496",
1166
1166
  description: "A clean, standalone JS SDK for MYIO projects",
1167
1167
  license: "MIT",
1168
1168
  repository: "github:gh-myio/myio-js-library",
@@ -23680,13 +23680,13 @@ function createDateRangePicker($2, input, opts) {
23680
23680
  const now = moment();
23681
23681
  ranges = {
23682
23682
  "\xDAltima hora": [moment().subtract(1, "hours"), now.clone()],
23683
- "\xDAltimas 6 horas": [moment().subtract(6, "hours"), now.clone()],
23684
23683
  "\xDAltimas 12 horas": [moment().subtract(12, "hours"), now.clone()],
23685
23684
  "\xDAltimas 24 horas": [moment().subtract(24, "hours"), now.clone()],
23686
23685
  "Hoje": [moment().startOf("day"), now.clone()],
23687
23686
  "Ontem": [moment().subtract(1, "day").startOf("day"), moment().subtract(1, "day").endOf("day")],
23688
23687
  "\xDAltimos 7 dias": [moment().subtract(6, "days").startOf("day"), now.clone()],
23689
- "Este m\xEAs": [moment().startOf("month"), now.clone()]
23688
+ "Este m\xEAs": [moment().startOf("month"), now.clone()],
23689
+ "M\xEAs Anterior": [moment().subtract(1, "month").startOf("month"), moment().subtract(1, "month").endOf("month")]
23690
23690
  };
23691
23691
  } else {
23692
23692
  ranges = {
@@ -23821,9 +23821,9 @@ var TELEMETRY_CONFIG = {
23821
23821
  reactivePower: { label: "Pot\xEAncia Reativa", unit: "kVAr", icon: "\u{1F504}", decimals: 2 },
23822
23822
  apparentPower: { label: "Pot\xEAncia Aparente", unit: "kVA", icon: "\u{1F4C8}", decimals: 2 },
23823
23823
  // Power factor phases + total (dimensionless 0–1, pseudo-unit 'fp')
23824
- fp_a: { label: "Fat. Pot\xEAncia Fase A", unit: "fp", icon: "\u{1F4D0}", decimals: 3 },
23825
- fp_b: { label: "Fat. Pot\xEAncia Fase B", unit: "fp", icon: "\u{1F4D0}", decimals: 3 },
23826
- fp_c: { label: "Fat. Pot\xEAncia Fase C", unit: "fp", icon: "\u{1F4D0}", decimals: 3 },
23824
+ fp_a: { label: "Fat. Pot. A", unit: "fp", icon: "\u{1F4D0}", decimals: 3 },
23825
+ fp_b: { label: "Fat. Pot. B", unit: "fp", icon: "\u{1F4D0}", decimals: 3 },
23826
+ fp_c: { label: "Fat. Pot. C", unit: "fp", icon: "\u{1F4D0}", decimals: 3 },
23827
23827
  powerFactor: { label: "Fator de Pot\xEAncia", unit: "fp", icon: "\u{1F4D0}", decimals: 3 },
23828
23828
  // Temperature
23829
23829
  temperature: { label: "Temperatura", unit: "\xB0C", icon: "\u{1F321}\uFE0F", decimals: 1 }
@@ -23853,22 +23853,22 @@ var PHASE_SHORT_LABEL = {
23853
23853
  apparentPower: "Total"
23854
23854
  };
23855
23855
  var UNIT_GROUP_META = {
23856
- "W": { label: "Pot\xEAncia", icon: "\u2699\uFE0F" },
23857
- "A": { label: "Corrente", icon: "\u{1F50C}" },
23858
- "V": { label: "Tens\xE3o", icon: "\u26A1" },
23859
- "fp": { label: "Fator de Pot\xEAncia", icon: "\u{1F4D0}" },
23856
+ W: { label: "Pot\xEAncia", icon: "\u2699\uFE0F" },
23857
+ A: { label: "Corrente", icon: "\u{1F50C}" },
23858
+ V: { label: "Tens\xE3o", icon: "\u26A1" },
23859
+ fp: { label: "Fator de Pot\xEAncia", icon: "\u{1F4D0}" },
23860
23860
  "\xB0C": { label: "Temperatura", icon: "\u{1F321}\uFE0F" },
23861
- "kWh": { label: "Energia", icon: "\u{1F4CA}" },
23862
- "kW": { label: "Pot\xEAncia Ativa", icon: "\u2699\uFE0F" },
23863
- "kVAr": { label: "Pot. Reativa", icon: "\u{1F504}" },
23864
- "kVA": { label: "Pot. Aparente", icon: "\u{1F4C8}" }
23861
+ kWh: { label: "Energia", icon: "\u{1F4CA}" },
23862
+ kW: { label: "Pot\xEAncia Ativa", icon: "\u2699\uFE0F" },
23863
+ kVAr: { label: "Pot. Reativa", icon: "\u{1F504}" },
23864
+ kVA: { label: "Pot. Aparente", icon: "\u{1F4C8}" }
23865
23865
  };
23866
23866
  var STRINGS = {
23867
23867
  "pt-BR": {
23868
23868
  title: "Telemetrias Instant\xE2neas",
23869
23869
  close: "Fechar",
23870
23870
  pause: "Pausar",
23871
- resume: "Retomar",
23871
+ resume: "Reiniciar",
23872
23872
  export: "Exportar CSV",
23873
23873
  autoUpdate: "Atualiza\xE7\xE3o autom\xE1tica",
23874
23874
  lastUpdate: "\xDAltima atualiza\xE7\xE3o",
@@ -23932,11 +23932,14 @@ async function openRealTimeTelemetryModal(params) {
23932
23932
  const isMyioUser = !!userEmail?.toLowerCase().includes("@myio.com.br");
23933
23933
  let checkDeviceIntervalMs = 3e4;
23934
23934
  let checkDeviceWaitMs = 15e3;
23935
+ const SESSION_LIMIT_MS = 5 * 60 * 1e3;
23935
23936
  let refreshIntervalId = null;
23936
23937
  let countdownTimerId = null;
23937
23938
  let nextTickAt = 0;
23938
23939
  let isFirstTick = true;
23939
23940
  let isPaused = false;
23941
+ let sessionCountdownTimerId = null;
23942
+ let sessionExpiresAt = 0;
23940
23943
  let cardTooltipEl = null;
23941
23944
  let cardTooltipKey = null;
23942
23945
  let cardTooltipPinned = false;
@@ -23953,7 +23956,9 @@ async function openRealTimeTelemetryModal(params) {
23953
23956
  let realtimeHistorySnapshot = null;
23954
23957
  let realtimeLastKnownSnapshot = null;
23955
23958
  let chart = null;
23956
- let selectedChartKeys = [telemetryKeys.includes("consumption") ? "consumption" : telemetryKeys[0] ?? "consumption"];
23959
+ let selectedChartKeys = [
23960
+ telemetryKeys.includes("consumption") ? "consumption" : telemetryKeys[0] ?? "consumption"
23961
+ ];
23957
23962
  let selectedAgg = "NONE";
23958
23963
  let selectedLimit = 500;
23959
23964
  let selectedIntervalMs = 0;
@@ -24006,7 +24011,7 @@ async function openRealTimeTelemetryModal(params) {
24006
24011
  }
24007
24012
 
24008
24013
  .myio-realtime-telemetry-header {
24009
- padding: 4px 12px;
24014
+ padding: 8px 12px;
24010
24015
  border-bottom: none;
24011
24016
  display: flex;
24012
24017
  justify-content: space-between;
@@ -24014,18 +24019,18 @@ async function openRealTimeTelemetryModal(params) {
24014
24019
  background: #3e1a7d;
24015
24020
  color: white;
24016
24021
  border-radius: 12px 12px 0 0;
24017
- min-height: 20px;
24022
+ min-height: 32px;
24018
24023
  }
24019
24024
 
24020
24025
  .myio-realtime-telemetry-title {
24021
- font-size: 18px;
24026
+ font-size: 16px;
24022
24027
  font-weight: 600;
24023
- margin: 6px;
24028
+ margin: 0;
24024
24029
  display: flex;
24025
24030
  align-items: center;
24026
24031
  gap: 8px;
24027
24032
  color: white;
24028
- line-height: 2;
24033
+ line-height: 1.4;
24029
24034
  }
24030
24035
 
24031
24036
  .myio-rtt-device-label {
@@ -24818,12 +24823,12 @@ async function openRealTimeTelemetryModal(params) {
24818
24823
 
24819
24824
  <div class="myio-realtime-telemetry-container">
24820
24825
  <div class="myio-realtime-telemetry-header">
24821
- <h2 class="myio-realtime-telemetry-title">
24826
+ <div class="myio-realtime-telemetry-title">
24822
24827
  \u26A1 ${strings.title}${deviceLabel ? `<span class="myio-rtt-device-label">${deviceLabel}${deviceCheckName && deviceCheckName !== deviceLabel ? `<span class="myio-rtt-device-name">(${deviceCheckName})</span>` : ""}</span>` : ""}${customerName ? `<span class="myio-rtt-customer-badge">${customerName}</span>` : ""}${(() => {
24823
24828
  const v = window.MyIOLibrary?.version;
24824
24829
  return v ? `<span class="myio-rtt-version-badge">v${v}</span>` : "";
24825
24830
  })()}
24826
- </h2>
24831
+ </div>
24827
24832
  <div class="myio-rtt-header-actions">
24828
24833
  <button class="myio-rtt-header-btn" id="rtt-gear-btn" title="Configura\xE7\xF5es de polling" style="display:none;">
24829
24834
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:16px;height:16px;">
@@ -24889,7 +24894,7 @@ async function openRealTimeTelemetryModal(params) {
24889
24894
  <div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:16px;">
24890
24895
  <div class="myio-rtt-mode-tabs" id="rtt-mode-tabs">
24891
24896
  <button class="myio-rtt-tab active" data-mode="realtime">Realtime</button>
24892
- <button class="myio-rtt-tab" data-mode="period">Per\xEDodo</button>
24897
+ <button class="myio-rtt-tab" data-mode="period">Pro Per\xEDodo</button>
24893
24898
  </div>
24894
24899
  <div class="myio-rtt-period-input" id="rtt-period-row">
24895
24900
  <div class="myio-rtt-period-controls">
@@ -24955,6 +24960,7 @@ async function openRealTimeTelemetryModal(params) {
24955
24960
  </div>
24956
24961
 
24957
24962
  <div class="myio-telemetry-actions">
24963
+ <span id="rtt-session-countdown" style="display:none;align-items:center;font-size:12px;font-weight:600;color:#667eea;background:rgba(102,126,234,0.1);padding:0 10px;height:32px;line-height:32px;border-radius:10px;white-space:nowrap;"></span>
24958
24964
  <button class="myio-telemetry-btn myio-telemetry-btn-secondary" id="pause-btn">
24959
24965
  <span id="pause-btn-icon">\u23F8\uFE0F</span>
24960
24966
  <span id="pause-btn-text">${strings.pause}</span>
@@ -24979,6 +24985,7 @@ async function openRealTimeTelemetryModal(params) {
24979
24985
  const pauseBtn = overlay.querySelector("#pause-btn");
24980
24986
  const pauseBtnIcon = overlay.querySelector("#pause-btn-icon");
24981
24987
  const pauseBtnText = overlay.querySelector("#pause-btn-text");
24988
+ const sessionCountdownEl = overlay.querySelector("#rtt-session-countdown");
24982
24989
  const exportBtn = overlay.querySelector("#export-btn");
24983
24990
  const loadingState = overlay.querySelector("#loading-state");
24984
24991
  const telemetryContent = overlay.querySelector("#telemetry-content");
@@ -25000,6 +25007,26 @@ async function openRealTimeTelemetryModal(params) {
25000
25007
  const countdownText = overlay.querySelector("#rtt-countdown-text");
25001
25008
  const centralBadge = overlay.querySelector("#rtt-central-badge");
25002
25009
  const deviceBadge = overlay.querySelector("#rtt-device-badge");
25010
+ const chartTitleEl = overlay.querySelector("#chart-title");
25011
+ function updateChartTitle() {
25012
+ if (!chartTitleEl) return;
25013
+ if (currentMode === "period") {
25014
+ chartTitleEl.innerHTML = "Hist\xF3rico de Telemetria";
25015
+ return;
25016
+ }
25017
+ const deviceOk = lastTelemetryUpdateMs > 0 && Date.now() - lastTelemetryUpdateMs <= DEVICE_OK_DELTA_MS;
25018
+ let iconHtml = "";
25019
+ if (centralStatus === "unknown") {
25020
+ iconHtml = "";
25021
+ } else if (centralStatus === "ok" && deviceOk) {
25022
+ iconHtml = `<span title="Central online e dispositivo online" style="margin-left:8px;cursor:default;font-size:16px;vertical-align:middle;">\u2705</span>`;
25023
+ } else if (centralStatus === "ok" && !deviceOk) {
25024
+ iconHtml = `<span title="Central online e dispositivo offline / conex\xE3o fraca" style="margin-left:8px;cursor:default;font-size:16px;vertical-align:middle;">\u26A0\uFE0F</span>`;
25025
+ } else {
25026
+ iconHtml = `<span title="Central offline" style="margin-left:8px;cursor:default;font-size:16px;vertical-align:middle;">\u{1F534}</span>`;
25027
+ }
25028
+ chartTitleEl.innerHTML = `Telemetria em Tempo Real${iconHtml}`;
25029
+ }
25003
25030
  function updateStatusBadges() {
25004
25031
  if (!centralBadge || !deviceBadge) return;
25005
25032
  if (centralStatus === "unknown") {
@@ -25024,7 +25051,9 @@ async function openRealTimeTelemetryModal(params) {
25024
25051
  deviceBadge.textContent = "Device OFFLINE";
25025
25052
  deviceBadge.style.cssText = "display:inline-block;font-size:11px;font-weight:700;padding:2px 8px;border-radius:10px;letter-spacing:0.3px;color:#fff;background:#e74c3c;";
25026
25053
  }
25054
+ updateChartTitle();
25027
25055
  }
25056
+ updateChartTitle();
25028
25057
  function startCountdown(targetMs, label = "pr\xF3xima em") {
25029
25058
  nextTickAt = Date.now() + targetMs;
25030
25059
  if (countdownTimerId !== null) {
@@ -25045,6 +25074,36 @@ async function openRealTimeTelemetryModal(params) {
25045
25074
  }
25046
25075
  if (countdownText) countdownText.textContent = "";
25047
25076
  }
25077
+ function startSession() {
25078
+ stopSession();
25079
+ sessionExpiresAt = Date.now() + SESSION_LIMIT_MS;
25080
+ sessionCountdownTimerId = window.setInterval(() => {
25081
+ const remaining = Math.max(0, Math.ceil((sessionExpiresAt - Date.now()) / 1e3));
25082
+ if (sessionCountdownEl) {
25083
+ if (remaining > 0) {
25084
+ const mins = Math.floor(remaining / 60);
25085
+ const secs = remaining % 60;
25086
+ sessionCountdownEl.textContent = `\u23F1 ${mins}:${secs.toString().padStart(2, "0")}`;
25087
+ sessionCountdownEl.style.display = "inline-flex";
25088
+ }
25089
+ }
25090
+ if (remaining <= 0) {
25091
+ stopSession();
25092
+ if (!isPaused) {
25093
+ togglePause();
25094
+ clearCountdown();
25095
+ showRTTToast("Sess\xE3o de 5 min encerrada. Clique em Reiniciar para um novo ciclo.", "warn");
25096
+ }
25097
+ }
25098
+ }, 1e3);
25099
+ }
25100
+ function stopSession() {
25101
+ if (sessionCountdownTimerId !== null) {
25102
+ clearInterval(sessionCountdownTimerId);
25103
+ sessionCountdownTimerId = null;
25104
+ }
25105
+ if (sessionCountdownEl) sessionCountdownEl.style.display = "none";
25106
+ }
25048
25107
  function showRTTToast(message, type = "info") {
25049
25108
  const bg = { warn: "#e67e22", error: "#e74c3c", info: "#3498db" }[type];
25050
25109
  overlay.querySelector(".myio-rtt-toast")?.remove();
@@ -25197,12 +25256,15 @@ async function openRealTimeTelemetryModal(params) {
25197
25256
  function buildTooltipHistoryRows(key, color) {
25198
25257
  const history = telemetryHistory.get(key) || [];
25199
25258
  const recent = [...history].reverse().slice(0, 30);
25200
- if (recent.length === 0) return '<div class="rtt-tt-row"><span class="rtt-tt-row-ts">Sem dados ainda</span></div>';
25201
- return recent.map((p) => `
25259
+ if (recent.length === 0)
25260
+ return '<div class="rtt-tt-row"><span class="rtt-tt-row-ts">Sem dados ainda</span></div>';
25261
+ return recent.map(
25262
+ (p) => `
25202
25263
  <div class="rtt-tt-row">
25203
25264
  <span class="rtt-tt-row-ts">${new Date(p.x).toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit", second: "2-digit" })}</span>
25204
25265
  <span class="rtt-tt-row-val" style="color:${color};">${getFormattedValue(key, p.y)}</span>
25205
- </div>`).join("");
25266
+ </div>`
25267
+ ).join("");
25206
25268
  }
25207
25269
  function openCardTooltip(key, anchorEl) {
25208
25270
  closeCardTooltip();
@@ -25212,7 +25274,13 @@ async function openRealTimeTelemetryModal(params) {
25212
25274
  const history = telemetryHistory.get(key) || [];
25213
25275
  const latestPoint = history[history.length - 1];
25214
25276
  const latestVal = latestPoint ? getFormattedValue(key, latestPoint.y) : "--";
25215
- const latestTime = latestPoint ? new Date(latestPoint.x).toLocaleString(locale, { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" }) : "--";
25277
+ const latestTime = latestPoint ? new Date(latestPoint.x).toLocaleString(locale, {
25278
+ day: "2-digit",
25279
+ month: "2-digit",
25280
+ hour: "2-digit",
25281
+ minute: "2-digit",
25282
+ second: "2-digit"
25283
+ }) : "--";
25216
25284
  const tooltip = document.createElement("div");
25217
25285
  tooltip.id = "rtt-card-tooltip";
25218
25286
  if (currentTheme === "dark") tooltip.dataset["theme"] = "dark";
@@ -25271,7 +25339,8 @@ async function openRealTimeTelemetryModal(params) {
25271
25339
  const tsEl = cardTooltipEl.querySelector("#rtt-tt-ts");
25272
25340
  const listEl = cardTooltipEl.querySelector("#rtt-tt-list");
25273
25341
  if (valEl) valEl.textContent = getFormattedValue(key, latest.y);
25274
- if (tsEl) tsEl.textContent = `Recebido: ${new Date(latest.x).toLocaleString(locale, { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" })}`;
25342
+ if (tsEl)
25343
+ tsEl.textContent = `Recebido: ${new Date(latest.x).toLocaleString(locale, { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" })}`;
25275
25344
  if (listEl) listEl.innerHTML = buildTooltipHistoryRows(key, color);
25276
25345
  }
25277
25346
  function closeCardTooltip() {
@@ -25302,7 +25371,13 @@ async function openRealTimeTelemetryModal(params) {
25302
25371
  const headerColor = isOk ? "#27ae60" : "#e74c3c";
25303
25372
  const headerLabel = centralStatus === "unknown" ? "Central \u2014 aguardando..." : isOk ? "Central OK" : "Central OFFLINE";
25304
25373
  const recentRows = [...checkDeviceHistory].reverse().slice(0, 10).map((r) => {
25305
- const dt = new Date(r.ts).toLocaleString(locale, { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" });
25374
+ const dt = new Date(r.ts).toLocaleString(locale, {
25375
+ day: "2-digit",
25376
+ month: "2-digit",
25377
+ hour: "2-digit",
25378
+ minute: "2-digit",
25379
+ second: "2-digit"
25380
+ });
25306
25381
  const icon = r.status === "ok" ? "\u2705" : "\u274C";
25307
25382
  return `<div class="rtt-tt-history-row">${icon} ${dt}</div>`;
25308
25383
  }).join("");
@@ -25369,7 +25444,13 @@ async function openRealTimeTelemetryModal(params) {
25369
25444
  const deviceOk = lastTelemetryUpdateMs > 0 && Date.now() - lastTelemetryUpdateMs <= DEVICE_OK_DELTA_MS;
25370
25445
  const headerColor = deviceOk ? "#27ae60" : "#e74c3c";
25371
25446
  const headerLabel = deviceOk ? "Device OK" : "Device OFFLINE";
25372
- const lastUpdateStr = lastTelemetryUpdateMs > 0 ? new Date(lastTelemetryUpdateMs).toLocaleString(locale, { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit" }) : "--";
25447
+ const lastUpdateStr = lastTelemetryUpdateMs > 0 ? new Date(lastTelemetryUpdateMs).toLocaleString(locale, {
25448
+ day: "2-digit",
25449
+ month: "2-digit",
25450
+ hour: "2-digit",
25451
+ minute: "2-digit",
25452
+ second: "2-digit"
25453
+ }) : "--";
25373
25454
  function row(icon, label, value) {
25374
25455
  return `<div style="display:flex;flex-direction:column;gap:1px;padding:5px 0;border-bottom:1px solid #f3f4f6;">
25375
25456
  <span style="font-size:10px;color:#9ca3af;font-weight:500;">${icon} ${label}</span>
@@ -25450,6 +25531,7 @@ async function openRealTimeTelemetryModal(params) {
25450
25531
  refreshIntervalId = null;
25451
25532
  }
25452
25533
  clearCountdown();
25534
+ stopSession();
25453
25535
  if (chart) {
25454
25536
  chart.destroy();
25455
25537
  chart = null;
@@ -25546,10 +25628,9 @@ async function openRealTimeTelemetryModal(params) {
25546
25628
  if (!isPaused && currentMode !== "period") {
25547
25629
  if (useCheckDevice) {
25548
25630
  try {
25549
- await fetch(
25550
- `https://${centralId}.y.myio.com.br/api/check_device/${deviceCheckName}`,
25551
- { signal: AbortSignal.timeout(1e4) }
25552
- );
25631
+ await fetch(`https://${centralId}.y.myio.com.br/api/check_device/${deviceCheckName}`, {
25632
+ signal: AbortSignal.timeout(1e4)
25633
+ });
25553
25634
  centralStatus = "ok";
25554
25635
  checkDeviceHistory.push({ ts: Date.now(), status: "ok" });
25555
25636
  } catch (e) {
@@ -25582,9 +25663,9 @@ async function openRealTimeTelemetryModal(params) {
25582
25663
  backdrop.innerHTML = `
25583
25664
  <div class="myio-realtime-telemetry-container" style="width:min(420px,94vw);max-height:90vh;overflow-y:auto;position:relative;">
25584
25665
  <div class="myio-realtime-telemetry-header" style="cursor:default;">
25585
- <h2 class="myio-realtime-telemetry-title" style="font-size:15px;">
25666
+ <div class="myio-realtime-telemetry-title" style="font-size:15px;">
25586
25667
  \u2699\uFE0F Configura\xE7\xF5es de Polling
25587
- </h2>
25668
+ </div>
25588
25669
  <div class="myio-rtt-header-actions">
25589
25670
  <button id="rtt-poll-close-x" class="myio-rtt-header-btn" title="Fechar" style="font-size:20px;line-height:1;">\xD7</button>
25590
25671
  </div>
@@ -25713,6 +25794,7 @@ async function openRealTimeTelemetryModal(params) {
25713
25794
  const points = series.map((pt) => {
25714
25795
  let y = pt.value ?? 0;
25715
25796
  if (key === "total_current" || key === "current") y = y / 1e3;
25797
+ if (key === "fp_a" || key === "fp_b" || key === "fp_c" || key === "powerFactor") y = y / 255;
25716
25798
  return { x: pt.ts, y };
25717
25799
  });
25718
25800
  telemetryHistory.set(key, points);
@@ -25749,6 +25831,7 @@ async function openRealTimeTelemetryModal(params) {
25749
25831
  const points = series.map((pt) => {
25750
25832
  let y = pt.value ?? 0;
25751
25833
  if (key === "total_current" || key === "current") y = y / 1e3;
25834
+ if (key === "fp_a" || key === "fp_b" || key === "fp_c" || key === "powerFactor") y = y / 255;
25752
25835
  return { x: pt.ts, y };
25753
25836
  });
25754
25837
  telemetryHistory.set(key, points);
@@ -25795,6 +25878,9 @@ async function openRealTimeTelemetryModal(params) {
25795
25878
  if (key === "total_current" || key === "current" || key === "current_a" || key === "current_b" || key === "current_c") {
25796
25879
  numValue = numValue / 1e3;
25797
25880
  }
25881
+ if (key === "fp_a" || key === "fp_b" || key === "fp_c" || key === "powerFactor") {
25882
+ numValue = numValue / 255;
25883
+ }
25798
25884
  const formattedNum = numValue.toFixed(config.decimals);
25799
25885
  const displayUnit = config.unit === "fp" ? "" : config.unit;
25800
25886
  const formatted = displayUnit ? `${formattedNum} ${displayUnit}` : formattedNum;
@@ -25823,14 +25909,14 @@ async function openRealTimeTelemetryModal(params) {
25823
25909
  return "stable";
25824
25910
  }
25825
25911
  const GROUP_KEY_ORDER = {
25826
- "W": ["consumption", "power", "activePower", "a", "b", "c"],
25827
- "A": ["total_current", "current", "current_a", "current_b", "current_c"],
25828
- "V": ["voltage_a", "voltage_b", "voltage_c"],
25829
- "fp": ["powerFactor", "fp_a", "fp_b", "fp_c"],
25830
- "kW": ["activePower"],
25831
- "kVAr": ["reactivePower"],
25832
- "kVA": ["apparentPower"],
25833
- "kWh": ["energy"],
25912
+ W: ["consumption", "power", "activePower", "a", "b", "c"],
25913
+ A: ["total_current", "current", "current_a", "current_b", "current_c"],
25914
+ V: ["voltage_a", "voltage_b", "voltage_c"],
25915
+ fp: ["powerFactor", "fp_a", "fp_b", "fp_c"],
25916
+ kW: ["activePower"],
25917
+ kVAr: ["reactivePower"],
25918
+ kVA: ["apparentPower"],
25919
+ kWh: ["energy"],
25834
25920
  "\xB0C": ["temperature"]
25835
25921
  };
25836
25922
  function updateTelemetryCards(values) {
@@ -26003,8 +26089,10 @@ async function openRealTimeTelemetryModal(params) {
26003
26089
  chartContainer.style.display = "block";
26004
26090
  const multi = selectedChartKeys.length > 1;
26005
26091
  const primaryKey = selectedChartKeys[0] || "consumption";
26006
- const UNIT_PRIORITY = { "W": 0, "kW": 0, "A": 1, "V": 2 };
26007
- const distinctUnits = [...new Set(selectedChartKeys.map((k) => (TELEMETRY_CONFIG[k] || { unit: "" }).unit))].sort((a, b) => (UNIT_PRIORITY[a] ?? 99) - (UNIT_PRIORITY[b] ?? 99));
26092
+ const UNIT_PRIORITY = { W: 0, kW: 0, A: 1, V: 2 };
26093
+ const distinctUnits = [
26094
+ ...new Set(selectedChartKeys.map((k) => (TELEMETRY_CONFIG[k] || { unit: "" }).unit))
26095
+ ].sort((a, b) => (UNIT_PRIORITY[a] ?? 99) - (UNIT_PRIORITY[b] ?? 99));
26008
26096
  const dualAxis = distinctUnits.length === 2;
26009
26097
  const leftUnit = distinctUnits[0] ?? "";
26010
26098
  const rightUnit = dualAxis ? distinctUnits[1] : "";
@@ -26045,7 +26133,11 @@ async function openRealTimeTelemetryModal(params) {
26045
26133
  const xTickCallback = isDailyBucket ? function(value) {
26046
26134
  return new Date(value).toLocaleDateString(locale, { day: "2-digit", month: "2-digit" });
26047
26135
  } : function(value) {
26048
- return new Date(value).toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
26136
+ return new Date(value).toLocaleTimeString(locale, {
26137
+ hour: "2-digit",
26138
+ minute: "2-digit",
26139
+ second: "2-digit"
26140
+ });
26049
26141
  };
26050
26142
  const scales = {
26051
26143
  x: {
@@ -26061,9 +26153,9 @@ async function openRealTimeTelemetryModal(params) {
26061
26153
  // For daily buckets: force ticks at exact data-point positions (TB anchors at bucket midpoint)
26062
26154
  ...isDailyBucket ? {
26063
26155
  afterBuildTicks: (scale) => {
26064
- const xVals = [...new Set(
26065
- datasets.flatMap((d) => d.data.map((p) => p.x))
26066
- )].sort((a, b) => a - b);
26156
+ const xVals = [
26157
+ ...new Set(datasets.flatMap((d) => d.data.map((p) => p.x)))
26158
+ ].sort((a, b) => a - b);
26067
26159
  scale.ticks = xVals.map((v) => ({ value: v }));
26068
26160
  }
26069
26161
  } : {}
@@ -26164,14 +26256,21 @@ async function openRealTimeTelemetryModal(params) {
26164
26256
  clearTimeout(refreshIntervalId);
26165
26257
  refreshIntervalId = null;
26166
26258
  }
26259
+ stopSession();
26260
+ clearCountdown();
26167
26261
  pauseBtnIcon.textContent = "\u25B6\uFE0F";
26168
26262
  pauseBtnText.textContent = strings.resume;
26263
+ pauseBtn.classList.remove("myio-telemetry-btn-secondary");
26264
+ pauseBtn.classList.add("myio-telemetry-btn-primary");
26169
26265
  statusIndicator.classList.add("paused");
26170
26266
  statusText.textContent = `${strings.autoUpdate}: OFF`;
26171
26267
  } else {
26172
26268
  scheduleCheckDeviceTick();
26269
+ startSession();
26173
26270
  pauseBtnIcon.textContent = "\u23F8\uFE0F";
26174
26271
  pauseBtnText.textContent = strings.pause;
26272
+ pauseBtn.classList.remove("myio-telemetry-btn-primary");
26273
+ pauseBtn.classList.add("myio-telemetry-btn-secondary");
26175
26274
  statusIndicator.classList.remove("paused");
26176
26275
  statusText.textContent = `${strings.autoUpdate}: ON`;
26177
26276
  }
@@ -26228,23 +26327,26 @@ async function openRealTimeTelemetryModal(params) {
26228
26327
  expandIcon.innerHTML = isExpanded ? '<polyline points="4 14 10 14 10 20"></polyline><polyline points="20 10 14 10 14 4"></polyline><line x1="10" y1="14" x2="3" y2="21"></line><line x1="21" y1="3" x2="14" y2="10"></line>' : '<polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" y1="3" x2="14" y2="10"></line><line x1="3" y1="21" x2="10" y2="14"></line>';
26229
26328
  }
26230
26329
  if (chart) {
26231
- requestAnimationFrame(() => requestAnimationFrame(() => {
26232
- if (isExpanded) {
26233
- chart.options.responsive = false;
26234
- const w = chartContainer.clientWidth - 40;
26235
- const h = chartContainer.clientHeight - 60;
26236
- chart.resize(Math.max(w, 200), Math.max(h, 120));
26237
- } else {
26238
- chart.options.responsive = true;
26239
- chartCanvas.style.height = "";
26240
- chart.resize();
26241
- }
26242
- }));
26330
+ requestAnimationFrame(
26331
+ () => requestAnimationFrame(() => {
26332
+ if (isExpanded) {
26333
+ chart.options.responsive = false;
26334
+ const w = chartContainer.clientWidth - 40;
26335
+ const h = chartContainer.clientHeight - 60;
26336
+ chart.resize(Math.max(w, 200), Math.max(h, 120));
26337
+ } else {
26338
+ chart.options.responsive = true;
26339
+ chartCanvas.style.height = "";
26340
+ chart.resize();
26341
+ }
26342
+ })
26343
+ );
26243
26344
  }
26244
26345
  }
26245
26346
  async function switchMode(mode) {
26246
26347
  if (mode === currentMode) return;
26247
26348
  currentMode = mode;
26349
+ updateChartTitle();
26248
26350
  modeTabs.forEach((btn) => {
26249
26351
  btn.classList.toggle("active", btn.dataset["mode"] === mode);
26250
26352
  });
@@ -26275,7 +26377,9 @@ async function openRealTimeTelemetryModal(params) {
26275
26377
  } else {
26276
26378
  periodRow.classList.remove("visible");
26277
26379
  if (realtimeHistorySnapshot) {
26278
- telemetryHistory = new Map(Array.from(realtimeHistorySnapshot.entries()).map(([k, v]) => [k, [...v]]));
26380
+ telemetryHistory = new Map(
26381
+ Array.from(realtimeHistorySnapshot.entries()).map(([k, v]) => [k, [...v]])
26382
+ );
26279
26383
  lastKnownValues = realtimeLastKnownSnapshot ? new Map(realtimeLastKnownSnapshot) : /* @__PURE__ */ new Map();
26280
26384
  realtimeHistorySnapshot = null;
26281
26385
  realtimeLastKnownSnapshot = null;
@@ -26285,6 +26389,7 @@ async function openRealTimeTelemetryModal(params) {
26285
26389
  isFirstTick = true;
26286
26390
  await refreshData();
26287
26391
  scheduleCheckDeviceTick();
26392
+ startSession();
26288
26393
  }
26289
26394
  }
26290
26395
  }
@@ -26372,10 +26477,9 @@ async function openRealTimeTelemetryModal(params) {
26372
26477
  if (useCheckDeviceOnOpen) {
26373
26478
  startCountdown(checkDeviceWaitMs);
26374
26479
  try {
26375
- await fetch(
26376
- `https://${centralId}.y.myio.com.br/api/check_device/${deviceCheckName}`,
26377
- { signal: AbortSignal.timeout(1e4) }
26378
- );
26480
+ await fetch(`https://${centralId}.y.myio.com.br/api/check_device/${deviceCheckName}`, {
26481
+ signal: AbortSignal.timeout(1e4)
26482
+ });
26379
26483
  centralStatus = "ok";
26380
26484
  checkDeviceHistory.push({ ts: Date.now(), status: "ok" });
26381
26485
  } catch (e) {
@@ -26391,6 +26495,7 @@ async function openRealTimeTelemetryModal(params) {
26391
26495
  await refreshData();
26392
26496
  isFirstTick = false;
26393
26497
  scheduleCheckDeviceTick();
26498
+ startSession();
26394
26499
  return {
26395
26500
  destroy: closeModal2
26396
26501
  };
@@ -29230,7 +29335,7 @@ var EnergyModalView = class {
29230
29335
  currentEnergyData = null;
29231
29336
  dateRangePicker = null;
29232
29337
  isLoading = false;
29233
- currentTheme = "dark";
29338
+ currentTheme = "light";
29234
29339
  currentBarMode = "stacked";
29235
29340
  // RFC-0097: Granularity selector state (only 1h and 1d supported)
29236
29341
  currentGranularity = "1d";
@@ -29256,7 +29361,7 @@ var EnergyModalView = class {
29256
29361
  } else if (configTheme === "dark" || configTheme === "light") {
29257
29362
  this.currentTheme = configTheme;
29258
29363
  } else {
29259
- this.currentTheme = "dark";
29364
+ this.currentTheme = "light";
29260
29365
  }
29261
29366
  }
29262
29367
  /**
@@ -29278,7 +29383,7 @@ var EnergyModalView = class {
29278
29383
  /**
29279
29384
  * RFC-0097: Sets granularity and re-renders chart
29280
29385
  */
29281
- setGranularity(granularity) {
29386
+ async setGranularity(granularity) {
29282
29387
  if (this.currentGranularity === granularity) return;
29283
29388
  this.currentGranularity = granularity;
29284
29389
  const buttons = document.querySelectorAll(".myio-btn-granularity");
@@ -29291,6 +29396,14 @@ var EnergyModalView = class {
29291
29396
  }
29292
29397
  });
29293
29398
  localStorage.setItem("myio-modal-granularity", granularity);
29399
+ const dateRangeInput = document.getElementById("date-range");
29400
+ if (dateRangeInput) {
29401
+ try {
29402
+ await this.rebuildDateRangePicker(dateRangeInput);
29403
+ } catch (err) {
29404
+ console.warn("[EnergyModalView] Failed to rebuild DateRangePicker after granularity change:", err);
29405
+ }
29406
+ }
29294
29407
  this.reRenderChart();
29295
29408
  console.log("[EnergyModalView] [RFC-0097] Granularity changed to:", granularity);
29296
29409
  }
@@ -29617,14 +29730,12 @@ var EnergyModalView = class {
29617
29730
  </svg>
29618
29731
  </button>
29619
29732
  ` : ""}
29620
- ${this.config.params.mode === "comparison" ? `
29621
29733
  <!-- RFC-0097: Granularity Selector (only 1h and 1d supported) -->
29622
29734
  <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;">
29623
29735
  <span class="myio-label-secondary" style="font-size: 11px; margin-right: 4px; white-space: nowrap;">Granularidade:</span>
29624
29736
  <button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1h" ? "active" : ""}" data-granularity="1h" title="Hora">1h</button>
29625
29737
  <button class="myio-btn myio-btn-granularity ${this.currentGranularity === "1d" ? "active" : ""}" data-granularity="1d" title="Dia">1d</button>
29626
29738
  </div>
29627
- ` : ""}
29628
29739
  <button id="close-btn" class="myio-btn myio-btn-secondary">
29629
29740
  Fechar
29630
29741
  </button>
@@ -29940,7 +30051,7 @@ var EnergyModalView = class {
29940
30051
  endISO = this.normalizeToSaoPauloISO(this.config.params.endDate, true);
29941
30052
  }
29942
30053
  const tzIdentifier = this.config.params.timezone || "America/Sao_Paulo";
29943
- const granularity = this.config.params.granularity || "1d";
30054
+ const granularity = this.currentGranularity;
29944
30055
  const ingestionId = this.config.context.resolved.ingestionId;
29945
30056
  console.log(`[EnergyModalView] Initializing v2 chart with: deviceId=${ingestionId}, startDate=${startISO}, endDate=${endISO}, granularity=${granularity}, theme=${this.currentTheme}, timezone=${tzIdentifier}`);
29946
30057
  const chartConfig = {
@@ -30008,13 +30119,11 @@ var EnergyModalView = class {
30008
30119
  let startDateStr, endDateStr;
30009
30120
  if (this.dateRangePicker) {
30010
30121
  const dates = this.dateRangePicker.getDates();
30011
- startDateStr = dates.startISO.split("T")[0];
30012
- endDateStr = dates.endISO.split("T")[0];
30122
+ startDateStr = dates.startISO;
30123
+ endDateStr = dates.endISO;
30013
30124
  } else {
30014
- const startDate = new Date(this.config.params.startDate);
30015
- const endDate = new Date(this.config.params.endDate);
30016
- startDateStr = startDate.toISOString().split("T")[0];
30017
- endDateStr = endDate.toISOString().split("T")[0];
30125
+ startDateStr = this.normalizeToSaoPauloISO(this.config.params.startDate, false);
30126
+ endDateStr = this.normalizeToSaoPauloISO(this.config.params.endDate, true);
30018
30127
  }
30019
30128
  const tzIdentifier = this.config.params.timezone || "America/Sao_Paulo";
30020
30129
  const chartConfig = {
@@ -30025,9 +30134,9 @@ var EnergyModalView = class {
30025
30134
  // Already validated in constructor
30026
30135
  readingType: this.config.params.readingType || "energy",
30027
30136
  startDate: startDateStr,
30028
- // NO TIME (YYYY-MM-DD)
30137
+ // Full ISO with -03:00 offset
30029
30138
  endDate: endDateStr,
30030
- // NO TIME (YYYY-MM-DD)
30139
+ // Full ISO with -03:00 offset
30031
30140
  granularity: this.currentGranularity,
30032
30141
  // RFC-0097: Use current granularity from selector
30033
30142
  theme: this.currentTheme,
@@ -30084,13 +30193,11 @@ var EnergyModalView = class {
30084
30193
  let startDateStr, endDateStr;
30085
30194
  if (this.dateRangePicker) {
30086
30195
  const dates = this.dateRangePicker.getDates();
30087
- startDateStr = dates.startISO.split("T")[0];
30088
- endDateStr = dates.endISO.split("T")[0];
30196
+ startDateStr = dates.startISO;
30197
+ endDateStr = dates.endISO;
30089
30198
  } else {
30090
- const startDate = new Date(this.config.params.startDate);
30091
- const endDate = new Date(this.config.params.endDate);
30092
- startDateStr = startDate.toISOString().split("T")[0];
30093
- endDateStr = endDate.toISOString().split("T")[0];
30199
+ startDateStr = this.normalizeToSaoPauloISO(this.config.params.startDate, false);
30200
+ endDateStr = this.normalizeToSaoPauloISO(this.config.params.endDate, true);
30094
30201
  }
30095
30202
  const tzIdentifier = this.config.params.timezone || "America/Sao_Paulo";
30096
30203
  const chartConfig = {
@@ -30396,7 +30503,7 @@ var EnergyModalView = class {
30396
30503
  token: jwtToken,
30397
30504
  deviceId: this.config.params.deviceId,
30398
30505
  tbBaseUrl: this.config.params.tbBaseUrl || "",
30399
- deviceLabel: this.config.params.deviceLabel || "Dispositivo",
30506
+ deviceLabel: this.config.context.device.label || this.config.params.deviceLabel || "Dispositivo",
30400
30507
  deviceName: this.config.context.device.name,
30401
30508
  customerName: this.config.params.customerName,
30402
30509
  centralId: this.config.context.resolved.centralId,
@@ -30460,13 +30567,38 @@ var EnergyModalView = class {
30460
30567
  });
30461
30568
  console.log("[EnergyModalView] [RFC-0097] Granularity selector initialized with:", this.currentGranularity);
30462
30569
  }
30570
+ await this.rebuildDateRangePicker(dateRangeInput);
30571
+ }
30572
+ /**
30573
+ * (Re)builds the DateRangePicker. Time picker only shown when granularity = '1h'.
30574
+ * Preserves the currently selected range when rebuilding after a granularity change.
30575
+ */
30576
+ async rebuildDateRangePicker(input) {
30577
+ let presetStart;
30578
+ let presetEnd;
30579
+ if (this.dateRangePicker) {
30580
+ try {
30581
+ const current = this.dateRangePicker.getDates();
30582
+ presetStart = current.startISO;
30583
+ presetEnd = current.endISO;
30584
+ } catch {
30585
+ }
30586
+ this.dateRangePicker.destroy();
30587
+ this.dateRangePicker = null;
30588
+ }
30589
+ if (!presetStart) {
30590
+ presetStart = this.config.params.startDate instanceof Date ? this.config.params.startDate.toISOString().split("T")[0] : this.config.params.startDate;
30591
+ }
30592
+ if (!presetEnd) {
30593
+ presetEnd = this.config.params.endDate instanceof Date ? this.config.params.endDate.toISOString().split("T")[0] : this.config.params.endDate;
30594
+ }
30463
30595
  try {
30464
- this.dateRangePicker = await attach(dateRangeInput, {
30465
- presetStart: this.config.params.startDate instanceof Date ? this.config.params.startDate.toISOString().split("T")[0] : this.config.params.startDate,
30466
- presetEnd: this.config.params.endDate instanceof Date ? this.config.params.endDate.toISOString().split("T")[0] : this.config.params.endDate,
30596
+ this.dateRangePicker = await attach(input, {
30597
+ presetStart,
30598
+ presetEnd,
30467
30599
  maxRangeDays: 90,
30468
- includeTime: true,
30469
- timePrecision: "hour",
30600
+ includeTime: this.currentGranularity === "1h",
30601
+ timePrecision: "minute",
30470
30602
  parentEl: this.modal.element,
30471
30603
  onApply: ({ startISO, endISO }) => {
30472
30604
  this.hideError();
@@ -30866,7 +30998,7 @@ var EnergyModal = class {
30866
30998
  * Normalizes and validates parameters
30867
30999
  */
30868
31000
  normalizeParams(params) {
30869
- if (!validateJwtToken(params.tbJwtToken)) {
31001
+ if (!validateJwtToken(params.tbJwtToken || "")) {
30870
31002
  throw new Error("Invalid JWT token format");
30871
31003
  }
30872
31004
  return {
@@ -30898,10 +31030,10 @@ var EnergyModal = class {
30898
31030
  attributes: {}
30899
31031
  },
30900
31032
  resolved: {
30901
- ingestionId: null,
30902
- centralId: null,
30903
- slaveId: null,
30904
- customerId: null
31033
+ ingestionId: void 0,
31034
+ centralId: void 0,
31035
+ slaveId: void 0,
31036
+ customerId: void 0
30905
31037
  }
30906
31038
  };
30907
31039
  }
@@ -31037,10 +31169,10 @@ var EnergyModal = class {
31037
31169
  };
31038
31170
  const mainTitle = domainTitles[readingType] ?? "\u26A1 Gr\xE1fico de Energia";
31039
31171
  const label = this.context?.device.label || "";
31040
- const identifier = this.context?.device?.attributes?.identifier || "";
31172
+ const deviceName = this.context?.device.name || this.context?.device?.attributes?.identifier || "";
31041
31173
  const customer = this.params.customerName || "";
31042
31174
  const version2 = window.MyIOLibrary?.version;
31043
- const deviceBadge = label ? `<span class="myio-modal-header-device-label">${label}${identifier && identifier !== label ? `<span class="myio-modal-header-device-name">(${identifier})</span>` : ""}</span>` : "";
31175
+ const deviceBadge = label ? `<span class="myio-modal-header-device-label">${label}${deviceName && deviceName !== label ? `<span class="myio-modal-header-device-name">(${deviceName})</span>` : ""}</span>` : "";
31044
31176
  const customerBadge = customer ? `<span class="myio-modal-header-customer-badge">${customer}</span>` : "";
31045
31177
  const versionBadge = version2 ? `<span class="myio-modal-header-version-badge">v${version2}</span>` : "";
31046
31178
  return `${mainTitle}${deviceBadge}${customerBadge}${versionBadge}`;
@@ -31169,10 +31301,15 @@ var EnergyModal = class {
31169
31301
  title: "Dispositivo n\xE3o encontrado",
31170
31302
  detail: "Este dispositivo ainda n\xE3o possui dados de telemetria cadastrados. Verifique a integra\xE7\xE3o ou contate o suporte."
31171
31303
  };
31304
+ if (msg.includes("token_expired") || msg.includes("token has expired") || msg.includes("authentication token") || msg.includes("token expirou"))
31305
+ return {
31306
+ title: "Sess\xE3o expirada",
31307
+ detail: "Seu token de acesso expirou. Recarregue a p\xE1gina para continuar."
31308
+ };
31172
31309
  if (msg.includes("insufficient permissions") || msg.includes("401") || msg.includes("403") || msg.includes("unauthorized") || msg.includes("forbidden"))
31173
31310
  return {
31174
31311
  title: "Sem permiss\xE3o de acesso",
31175
- detail: "Sua sess\xE3o pode ter expirado ou voc\xEA n\xE3o tem permiss\xE3o para visualizar estes dados. Tente reabrir o modal."
31312
+ detail: "Voc\xEA n\xE3o tem permiss\xE3o para visualizar estes dados. Tente reabrir o modal ou contate o suporte."
31176
31313
  };
31177
31314
  if (msg.includes("failed to fetch") || msg.includes("networkerror") || msg.includes("network error") || msg.includes("err_network"))
31178
31315
  return {
@@ -92924,7 +93061,7 @@ var MyIOAuthContext = class _MyIOAuthContext {
92924
93061
  const q = encodeURIComponent(config.currentUserEmail);
92925
93062
  const cid = config.customerId ? `&customerId=${encodeURIComponent(config.customerId)}` : "";
92926
93063
  const res = await fetch(
92927
- `${config.gcdrApiBaseUrl}/api/v1/users?search=${q}${cid}&limit=10`,
93064
+ `${config.gcdrApiBaseUrl}/users?search=${q}${cid}&limit=10`,
92928
93065
  { headers: gcdrHeaders }
92929
93066
  );
92930
93067
  if (res.ok) {