myio-js-library 0.1.546 → 0.1.548
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 +2437 -331
- package/dist/index.d.cts +316 -1
- package/dist/index.d.ts +316 -1
- package/dist/index.js +2430 -329
- package/dist/myio-js-library.umd.js +2427 -329
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -470,6 +470,9 @@ __export(src_exports, {
|
|
|
470
470
|
createModalHeader: () => createModalHeader,
|
|
471
471
|
createMoneyVarianceColumn: () => createMoneyVarianceColumn,
|
|
472
472
|
createMyIOTheme: () => createMyIOTheme,
|
|
473
|
+
createMyioGcdrLoginSubmit: () => createMyioGcdrLoginSubmit,
|
|
474
|
+
createMyioGcdrLoginView: () => createMyioGcdrLoginView,
|
|
475
|
+
createMyioGcdrShell: () => createMyioGcdrShell,
|
|
473
476
|
createNewTicketWizard: () => createNewTicketWizard,
|
|
474
477
|
createOnOffDeviceModal: () => createOnOffDeviceModal,
|
|
475
478
|
createOnOffTimelineChart: () => createOnOffTimelineChart,
|
|
@@ -710,6 +713,7 @@ __export(src_exports, {
|
|
|
710
713
|
isInRange: () => isInRange,
|
|
711
714
|
isLeapYear: () => isLeapYear,
|
|
712
715
|
isMoneyColumnConfident: () => isMoneyColumnConfident,
|
|
716
|
+
isMyioGcdrLoginModalOpen: () => isMyioGcdrLoginModalOpen,
|
|
713
717
|
isOnOffDeviceProfile: () => isOnOffDeviceProfile,
|
|
714
718
|
isSolenoidDevice: () => isSolenoidDevice,
|
|
715
719
|
isStoreDevice: () => isStoreDevice,
|
|
@@ -771,6 +775,7 @@ __export(src_exports, {
|
|
|
771
775
|
openMeasurementSetupModal: () => openMeasurementSetupModal,
|
|
772
776
|
openMessageDialog: () => openMessageDialog,
|
|
773
777
|
openMetasGuide: () => openMetasGuide,
|
|
778
|
+
openMyioGcdrLoginModal: () => openMyioGcdrLoginModal,
|
|
774
779
|
openOnOffDeviceModal: () => openOnOffDeviceModal,
|
|
775
780
|
openOnboardModal: () => openOnboardModal,
|
|
776
781
|
openOperationalComparisonModal: () => openOperationalComparisonModal,
|
|
@@ -894,7 +899,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
894
899
|
// package.json
|
|
895
900
|
var package_default = {
|
|
896
901
|
name: "myio-js-library",
|
|
897
|
-
version: "0.1.
|
|
902
|
+
version: "0.1.548",
|
|
898
903
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
899
904
|
license: "MIT",
|
|
900
905
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -5423,22 +5428,22 @@ function generateExportHTML(modalId, exportFormats) {
|
|
|
5423
5428
|
if (exportFormats.length === 0) return "";
|
|
5424
5429
|
if (exportFormats.length === 1) {
|
|
5425
5430
|
const format = exportFormats[0];
|
|
5426
|
-
const
|
|
5431
|
+
const icon2 = EXPORT_FORMAT_ICONS[format] || "\u{1F4E5}";
|
|
5427
5432
|
return `<button
|
|
5428
5433
|
id="${modalId}-export"
|
|
5429
5434
|
class="myio-modal-header__btn"
|
|
5430
5435
|
title="Exportar ${EXPORT_FORMAT_LABELS[format]}"
|
|
5431
|
-
>${
|
|
5436
|
+
>${icon2}</button>`;
|
|
5432
5437
|
}
|
|
5433
5438
|
const dropdownOptions = exportFormats.map((format) => {
|
|
5434
|
-
const
|
|
5439
|
+
const icon2 = EXPORT_FORMAT_ICONS[format] || "\u{1F4C4}";
|
|
5435
5440
|
const label = EXPORT_FORMAT_LABELS[format] || format.toUpperCase();
|
|
5436
5441
|
return `<button
|
|
5437
5442
|
id="${modalId}-export-${format}"
|
|
5438
5443
|
class="myio-export-option"
|
|
5439
5444
|
data-format="${format}"
|
|
5440
5445
|
title="Exportar ${label}"
|
|
5441
|
-
>${
|
|
5446
|
+
>${icon2} ${label}</button>`;
|
|
5442
5447
|
}).join("");
|
|
5443
5448
|
return `
|
|
5444
5449
|
<div style="position: relative; display: inline-block;">
|
|
@@ -5493,7 +5498,7 @@ var ModalHeader = {
|
|
|
5493
5498
|
generateHTML(options) {
|
|
5494
5499
|
injectCSS();
|
|
5495
5500
|
const {
|
|
5496
|
-
icon,
|
|
5501
|
+
icon: icon2,
|
|
5497
5502
|
title,
|
|
5498
5503
|
modalId,
|
|
5499
5504
|
theme = "dark",
|
|
@@ -5535,7 +5540,7 @@ var ModalHeader = {
|
|
|
5535
5540
|
data-drag-handle
|
|
5536
5541
|
>
|
|
5537
5542
|
<div class="myio-modal-header__left">
|
|
5538
|
-
<span class="myio-modal-header__icon">${
|
|
5543
|
+
<span class="myio-modal-header__icon">${icon2}</span>
|
|
5539
5544
|
<h2 class="myio-modal-header__title">${title}</h2>
|
|
5540
5545
|
</div>
|
|
5541
5546
|
<div class="myio-modal-header__actions">
|
|
@@ -5553,7 +5558,7 @@ var ModalHeader = {
|
|
|
5553
5558
|
*/
|
|
5554
5559
|
generateInlineHTML(options) {
|
|
5555
5560
|
const {
|
|
5556
|
-
icon,
|
|
5561
|
+
icon: icon2,
|
|
5557
5562
|
title,
|
|
5558
5563
|
modalId,
|
|
5559
5564
|
theme = "dark",
|
|
@@ -5598,7 +5603,7 @@ var ModalHeader = {
|
|
|
5598
5603
|
return `
|
|
5599
5604
|
<div id="${modalId}-header" style="${headerStyle}" data-drag-handle>
|
|
5600
5605
|
<div style="display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0;">
|
|
5601
|
-
<span style="font-size: 18px;">${
|
|
5606
|
+
<span style="font-size: 18px;">${icon2}</span>
|
|
5602
5607
|
<h2 style="margin: 0; font-size: 16px; font-weight: 600; color: ${textColor}; line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
|
|
5603
5608
|
${title}
|
|
5604
5609
|
</h2>
|
|
@@ -6370,10 +6375,10 @@ var state = {
|
|
|
6370
6375
|
pinnedCounter: 0,
|
|
6371
6376
|
isPinned: false
|
|
6372
6377
|
};
|
|
6373
|
-
function generateHeaderHTML(
|
|
6378
|
+
function generateHeaderHTML(icon2, title) {
|
|
6374
6379
|
return `
|
|
6375
6380
|
<div class="myio-info-tooltip__header" data-drag-handle>
|
|
6376
|
-
<span class="myio-info-tooltip__icon">${
|
|
6381
|
+
<span class="myio-info-tooltip__icon">${icon2}</span>
|
|
6377
6382
|
<span class="myio-info-tooltip__title">${title}</span>
|
|
6378
6383
|
<div class="myio-info-tooltip__header-actions">
|
|
6379
6384
|
<button class="myio-info-tooltip__header-btn" data-action="pin" title="Fixar na tela">
|
|
@@ -7002,7 +7007,7 @@ function openDeviceProfileModal(params) {
|
|
|
7002
7007
|
});
|
|
7003
7008
|
const body = handle.element;
|
|
7004
7009
|
handle.on("close", () => {
|
|
7005
|
-
cardHandles.forEach((
|
|
7010
|
+
cardHandles.forEach((h3) => h3.destroy());
|
|
7006
7011
|
cardHandles = [];
|
|
7007
7012
|
onClose?.();
|
|
7008
7013
|
});
|
|
@@ -7044,7 +7049,7 @@ function openDeviceProfileModal(params) {
|
|
|
7044
7049
|
</div>`;
|
|
7045
7050
|
}
|
|
7046
7051
|
function mountCards() {
|
|
7047
|
-
cardHandles.forEach((
|
|
7052
|
+
cardHandles.forEach((h3) => h3.destroy());
|
|
7048
7053
|
cardHandles = [];
|
|
7049
7054
|
cardIds = [];
|
|
7050
7055
|
const d = dom();
|
|
@@ -7074,10 +7079,10 @@ function openDeviceProfileModal(params) {
|
|
|
7074
7079
|
cardIds.push(id);
|
|
7075
7080
|
};
|
|
7076
7081
|
const sep = (text2) => {
|
|
7077
|
-
const
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
editor.appendChild(
|
|
7082
|
+
const h3 = document.createElement("h3");
|
|
7083
|
+
h3.className = "mdp-sep-title";
|
|
7084
|
+
h3.textContent = text2;
|
|
7085
|
+
editor.appendChild(h3);
|
|
7081
7086
|
};
|
|
7082
7087
|
sep("Colunas (grupos)");
|
|
7083
7088
|
addCard(
|
|
@@ -7466,7 +7471,7 @@ function openDeviceProfileModal(params) {
|
|
|
7466
7471
|
function setAllCollapsed(collapsed) {
|
|
7467
7472
|
if (collapsed) cardIds.forEach((id) => collapsedIds.add(id));
|
|
7468
7473
|
else collapsedIds.clear();
|
|
7469
|
-
cardHandles.forEach((
|
|
7474
|
+
cardHandles.forEach((h3) => h3.setCollapsed(collapsed));
|
|
7470
7475
|
}
|
|
7471
7476
|
function refreshPreview() {
|
|
7472
7477
|
const hasCats = !!dom()?.categories;
|
|
@@ -16110,13 +16115,13 @@ var MyIODraggableCard = class {
|
|
|
16110
16115
|
this.container.appendChild(card);
|
|
16111
16116
|
}
|
|
16112
16117
|
_generateCardHTML() {
|
|
16113
|
-
const { id, name, icon, group, lastValue, unit, status } = this.entity;
|
|
16118
|
+
const { id, name, icon: icon2, group, lastValue, unit, status } = this.entity;
|
|
16114
16119
|
const checkboxHtml = this.options.showCheckbox ? `<input type="checkbox" class="card-checkbox" aria-label="Select ${name}">` : "";
|
|
16115
16120
|
return `
|
|
16116
16121
|
<div class="card-header">
|
|
16117
16122
|
${checkboxHtml}
|
|
16118
|
-
<div class="card-icon card-icon-${
|
|
16119
|
-
${this._getIconSvg(
|
|
16123
|
+
<div class="card-icon card-icon-${icon2}">
|
|
16124
|
+
${this._getIconSvg(icon2)}
|
|
16120
16125
|
</div>
|
|
16121
16126
|
<div class="card-status card-status-${status}"></div>
|
|
16122
16127
|
</div>
|
|
@@ -18644,6 +18649,12 @@ function renderCardComponentV5({
|
|
|
18644
18649
|
temperatureMax,
|
|
18645
18650
|
temperatureStatus,
|
|
18646
18651
|
// 'ok' | 'above' | 'below' | undefined
|
|
18652
|
+
// Temperatura atual vinda do Ingestion = média das últimas 2 h; true = nenhuma leitura na janela
|
|
18653
|
+
temperatureNoRecentReading = false,
|
|
18654
|
+
temperatureSource,
|
|
18655
|
+
// 'ingestion-avg-2h' | 'thingsboard' | undefined
|
|
18656
|
+
temperatureFetchedAt,
|
|
18657
|
+
// ms da consulta (rótulo "Atualizado às HH:MM")
|
|
18647
18658
|
// Per-device exclude_groups_totals attribute (SERVER_SCOPE) — drives the orange marker
|
|
18648
18659
|
excludeGroupsTotals
|
|
18649
18660
|
} = entityObject;
|
|
@@ -18740,7 +18751,7 @@ function renderCardComponentV5({
|
|
|
18740
18751
|
const connectionStatus = mapDeviceToConnectionStatus(deviceStatus);
|
|
18741
18752
|
const isOffline = isDeviceOffline(deviceStatus);
|
|
18742
18753
|
const shouldFlashIcon2 = shouldFlashIcon(deviceStatus);
|
|
18743
|
-
const
|
|
18754
|
+
const icon2 = getDeviceStatusIcon(deviceStatus, deviceType);
|
|
18744
18755
|
const connectionIcon = getConnectionStatusIcon(connectionStatus);
|
|
18745
18756
|
const debugDeviceName = "3F SCMAL3L4304ABC";
|
|
18746
18757
|
const labelStr = String(labelOrName || "");
|
|
@@ -18803,7 +18814,14 @@ function renderCardComponentV5({
|
|
|
18803
18814
|
const percentageForDisplay = isTankDevice2 ? (waterPercentage || 0) * 100 : perc;
|
|
18804
18815
|
const tankLevelCm = isTankDevice2 ? Number(waterLevel ?? val) : null;
|
|
18805
18816
|
const _pctDecimals = resolvePercentDecimals(percentDecimals);
|
|
18817
|
+
const showNoTempReading = !!temperatureNoRecentReading && isTemperatureDevice2(deviceType);
|
|
18818
|
+
const tempValueTitle = (() => {
|
|
18819
|
+
if (!isTemperatureDevice2(deviceType) || temperatureSource !== "ingestion-avg-2h") return "";
|
|
18820
|
+
const at = temperatureFetchedAt ? ` \xB7 Atualizado \xE0s ${new Date(temperatureFetchedAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })}` : "";
|
|
18821
|
+
return showNoTempReading ? `Nenhuma leitura nas \xFAltimas 2 h${at}` : `Temperatura (m\xE9dia das \xFAltimas 2 h)${at}`;
|
|
18822
|
+
})();
|
|
18806
18823
|
const formatCardValue = (value, deviceType2) => {
|
|
18824
|
+
if (showNoTempReading) return "Sem leitura recente";
|
|
18807
18825
|
if (isTankDevice2) {
|
|
18808
18826
|
return `${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%`;
|
|
18809
18827
|
}
|
|
@@ -19106,7 +19124,7 @@ function renderCardComponentV5({
|
|
|
19106
19124
|
}
|
|
19107
19125
|
return "ok";
|
|
19108
19126
|
};
|
|
19109
|
-
const tempStatus = isTermostatoDevice ? calculateTempStatus2() : null;
|
|
19127
|
+
const tempStatus = isTermostatoDevice && !showNoTempReading ? calculateTempStatus2() : null;
|
|
19110
19128
|
const deviceImageUrl = getDeviceImageUrl(deviceType, percentageForDisplay, {
|
|
19111
19129
|
tempStatus,
|
|
19112
19130
|
isOffline
|
|
@@ -19126,7 +19144,7 @@ function renderCardComponentV5({
|
|
|
19126
19144
|
}
|
|
19127
19145
|
return null;
|
|
19128
19146
|
};
|
|
19129
|
-
const tempDeviationPercent = isTermostatoDevice ? calculateTempDeviationPercent() : null;
|
|
19147
|
+
const tempDeviationPercent = isTermostatoDevice && !showNoTempReading ? calculateTempDeviationPercent() : null;
|
|
19130
19148
|
const cardHTML = `
|
|
19131
19149
|
<div class="device-card-centered clickable ${cardEntity.status === "offline" ? "offline" : ""}"
|
|
19132
19150
|
data-entity-id="${entityId}"
|
|
@@ -19169,9 +19187,9 @@ function renderCardComponentV5({
|
|
|
19169
19187
|
<div class="device-data-row">
|
|
19170
19188
|
<div class="consumption-main">
|
|
19171
19189
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
19172
|
-
${
|
|
19190
|
+
${icon2}
|
|
19173
19191
|
</span>
|
|
19174
|
-
<span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType)}</span>
|
|
19192
|
+
<span class="consumption-value"${showNoTempReading ? ' style="color:#9ca3af;font-weight:500;font-size:0.85em;"' : ""}${tempValueTitle ? ` title="${tempValueTitle}"` : ""}>${formatCardValue(cardEntity.lastValue, deviceType)}</span>
|
|
19175
19193
|
</div>
|
|
19176
19194
|
</div>
|
|
19177
19195
|
${isTankDevice2 ? `<span class="device-percentage-badge device-tank-level-badge" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important;">${formatTankHeadFromCm(tankLevelCm)}</span>` : !isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
|
|
@@ -20579,7 +20597,7 @@ function renderCardComponentV6({
|
|
|
20579
20597
|
const connectionStatus = mapDeviceToConnectionStatus(deviceStatus);
|
|
20580
20598
|
const isOffline = isDeviceOffline(deviceStatus);
|
|
20581
20599
|
const shouldFlashIcon2 = shouldFlashIcon(deviceStatus);
|
|
20582
|
-
const
|
|
20600
|
+
const icon2 = getDeviceStatusIcon(deviceStatus, effectiveDeviceType);
|
|
20583
20601
|
const connectionIcon = getConnectionStatusIcon(connectionStatus);
|
|
20584
20602
|
const mapDeviceTypeToIcon = (deviceType2) => {
|
|
20585
20603
|
const category = getDeviceCategory(deviceType2);
|
|
@@ -20961,7 +20979,7 @@ function renderCardComponentV6({
|
|
|
20961
20979
|
<div class="device-data-row">
|
|
20962
20980
|
<div class="consumption-main">
|
|
20963
20981
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
20964
|
-
${
|
|
20982
|
+
${icon2}
|
|
20965
20983
|
</span>
|
|
20966
20984
|
<span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType, deviceProfile)}</span>
|
|
20967
20985
|
</div>
|
|
@@ -22510,12 +22528,12 @@ function renderCardAmbienteV6({
|
|
|
22510
22528
|
statusText = isOn2 ? "ON" : "OFF";
|
|
22511
22529
|
stateClass = isOn2 ? "on" : "off";
|
|
22512
22530
|
}
|
|
22513
|
-
const
|
|
22531
|
+
const icon2 = isLamp ? "\u{1F4A1}" : "\u{1F518}";
|
|
22514
22532
|
const deviceEl = document.createElement("div");
|
|
22515
22533
|
deviceEl.className = `myio-ambiente-card__switch-device ${stateClass} ${isLamp ? "lamp" : "remote"}`;
|
|
22516
22534
|
deviceEl.title = device.label || device.name || (isLamp ? "L\xE2mpada" : "Controle");
|
|
22517
22535
|
deviceEl.innerHTML = `
|
|
22518
|
-
<span class="myio-ambiente-card__switch-device-icon">${
|
|
22536
|
+
<span class="myio-ambiente-card__switch-device-icon">${icon2}</span>
|
|
22519
22537
|
<span class="myio-ambiente-card__switch-device-value">${statusText}</span>
|
|
22520
22538
|
`;
|
|
22521
22539
|
scrollContainer.appendChild(deviceEl);
|
|
@@ -22936,10 +22954,10 @@ var HeaderPanelComponent = class {
|
|
|
22936
22954
|
el2.style.display = quantity >= 0 ? "" : "none";
|
|
22937
22955
|
}
|
|
22938
22956
|
}
|
|
22939
|
-
setIcon(
|
|
22940
|
-
this.options.icon =
|
|
22957
|
+
setIcon(icon2) {
|
|
22958
|
+
this.options.icon = icon2;
|
|
22941
22959
|
const el2 = this.root.querySelector(".myio-hp__icon");
|
|
22942
|
-
if (el2) el2.innerHTML =
|
|
22960
|
+
if (el2) el2.innerHTML = icon2;
|
|
22943
22961
|
}
|
|
22944
22962
|
setSubtitle(subtitle) {
|
|
22945
22963
|
this.options.subtitle = subtitle;
|
|
@@ -22998,7 +23016,7 @@ var HeaderPanelComponent = class {
|
|
|
22998
23016
|
render() {
|
|
22999
23017
|
const {
|
|
23000
23018
|
title,
|
|
23001
|
-
icon,
|
|
23019
|
+
icon: icon2,
|
|
23002
23020
|
quantity,
|
|
23003
23021
|
style,
|
|
23004
23022
|
showSearch,
|
|
@@ -23015,10 +23033,10 @@ var HeaderPanelComponent = class {
|
|
|
23015
23033
|
}
|
|
23016
23034
|
const left = document.createElement("div");
|
|
23017
23035
|
left.className = "myio-hp__left";
|
|
23018
|
-
if (
|
|
23036
|
+
if (icon2) {
|
|
23019
23037
|
const iconEl = document.createElement("span");
|
|
23020
23038
|
iconEl.className = "myio-hp__icon";
|
|
23021
|
-
iconEl.innerHTML =
|
|
23039
|
+
iconEl.innerHTML = icon2;
|
|
23022
23040
|
if (style?.iconColor) iconEl.style.color = style.iconColor;
|
|
23023
23041
|
left.appendChild(iconEl);
|
|
23024
23042
|
}
|
|
@@ -23497,10 +23515,10 @@ var EntityListPanel = class {
|
|
|
23497
23515
|
}
|
|
23498
23516
|
}
|
|
23499
23517
|
/** Update icon */
|
|
23500
|
-
setIcon(
|
|
23501
|
-
this.options.icon =
|
|
23518
|
+
setIcon(icon2) {
|
|
23519
|
+
this.options.icon = icon2;
|
|
23502
23520
|
if (this.headerComponent) {
|
|
23503
|
-
this.headerComponent.setIcon(
|
|
23521
|
+
this.headerComponent.setIcon(icon2);
|
|
23504
23522
|
}
|
|
23505
23523
|
}
|
|
23506
23524
|
/** Update background watermark image */
|
|
@@ -23550,7 +23568,7 @@ var EntityListPanel = class {
|
|
|
23550
23568
|
const {
|
|
23551
23569
|
title,
|
|
23552
23570
|
subtitle,
|
|
23553
|
-
icon,
|
|
23571
|
+
icon: icon2,
|
|
23554
23572
|
quantity,
|
|
23555
23573
|
backgroundImage,
|
|
23556
23574
|
searchPlaceholder,
|
|
@@ -23569,7 +23587,7 @@ var EntityListPanel = class {
|
|
|
23569
23587
|
this.headerComponent = new HeaderPanelComponent({
|
|
23570
23588
|
title,
|
|
23571
23589
|
subtitle,
|
|
23572
|
-
icon,
|
|
23590
|
+
icon: icon2,
|
|
23573
23591
|
quantity,
|
|
23574
23592
|
style: titleStyle,
|
|
23575
23593
|
showBottomBorder: false,
|
|
@@ -24050,10 +24068,10 @@ var CardGridPanel = class {
|
|
|
24050
24068
|
}
|
|
24051
24069
|
}
|
|
24052
24070
|
/** Update icon */
|
|
24053
|
-
setIcon(
|
|
24054
|
-
this.options.icon =
|
|
24071
|
+
setIcon(icon2) {
|
|
24072
|
+
this.options.icon = icon2;
|
|
24055
24073
|
if (this.headerComponent) {
|
|
24056
|
-
this.headerComponent.setIcon(
|
|
24074
|
+
this.headerComponent.setIcon(icon2);
|
|
24057
24075
|
}
|
|
24058
24076
|
}
|
|
24059
24077
|
/** Set maximize state without triggering callback (for external reset) */
|
|
@@ -24109,7 +24127,7 @@ var CardGridPanel = class {
|
|
|
24109
24127
|
render() {
|
|
24110
24128
|
const {
|
|
24111
24129
|
title,
|
|
24112
|
-
icon,
|
|
24130
|
+
icon: icon2,
|
|
24113
24131
|
quantity,
|
|
24114
24132
|
gridMinCardWidth,
|
|
24115
24133
|
titleStyle,
|
|
@@ -24124,7 +24142,7 @@ var CardGridPanel = class {
|
|
|
24124
24142
|
this.root.innerHTML = "";
|
|
24125
24143
|
this.headerComponent = new HeaderPanelComponent({
|
|
24126
24144
|
title,
|
|
24127
|
-
icon,
|
|
24145
|
+
icon: icon2,
|
|
24128
24146
|
quantity,
|
|
24129
24147
|
style: titleStyle,
|
|
24130
24148
|
showBottomBorder: true,
|
|
@@ -28263,20 +28281,20 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28263
28281
|
}
|
|
28264
28282
|
const todayStr = (/* @__PURE__ */ new Date()).toLocaleDateString(locale, { day: "2-digit", month: "2-digit", year: "numeric" });
|
|
28265
28283
|
const dateHtml = `<span style="margin-left:8px;font-size:13px;font-weight:400;opacity:0.55;">(${todayStr})</span>`;
|
|
28266
|
-
const
|
|
28284
|
+
const icon2 = (glyph, title) => `<span title="${title}" style="margin-left:8px;cursor:default;font-size:16px;vertical-align:middle;">${glyph}</span>`;
|
|
28267
28285
|
let iconHtml;
|
|
28268
28286
|
if (!hasTelemetryToday()) {
|
|
28269
|
-
iconHtml =
|
|
28287
|
+
iconHtml = icon2("\u274C", "Sem telemetrias de hoje para este dispositivo");
|
|
28270
28288
|
} else if (centralStatus === "offline") {
|
|
28271
|
-
iconHtml =
|
|
28289
|
+
iconHtml = icon2("\u{1F534}", `Central offline (${STATUS_MAX_RETRIES} falhas seguidas)`);
|
|
28272
28290
|
} else if (deviceStatus === "offline") {
|
|
28273
|
-
iconHtml =
|
|
28291
|
+
iconHtml = icon2("\u{1F534}", `Dispositivo offline (${STATUS_MAX_RETRIES} verifica\xE7\xF5es seguidas sem telemetria recente)`);
|
|
28274
28292
|
} else if (centralStatus === "warning") {
|
|
28275
|
-
iconHtml =
|
|
28293
|
+
iconHtml = icon2("\u26A0\uFE0F", `Aten\xE7\xE3o: central sem resposta (tentativa ${centralFailStreak}/${STATUS_MAX_RETRIES})`);
|
|
28276
28294
|
} else if (deviceStatus === "warning") {
|
|
28277
|
-
iconHtml =
|
|
28295
|
+
iconHtml = icon2("\u26A0\uFE0F", `Aten\xE7\xE3o: ${deviceStaleLabel()} (verifica\xE7\xE3o ${deviceStaleStreak}/${STATUS_MAX_RETRIES})`);
|
|
28278
28296
|
} else {
|
|
28279
|
-
iconHtml =
|
|
28297
|
+
iconHtml = icon2("\u2705", "H\xE1 telemetrias de hoje e o dispositivo est\xE1 respondendo");
|
|
28280
28298
|
}
|
|
28281
28299
|
chartTitleEl.innerHTML = `Telemetria em Tempo Real de hoje${dateHtml}${iconHtml}`;
|
|
28282
28300
|
}
|
|
@@ -28647,7 +28665,7 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28647
28665
|
}
|
|
28648
28666
|
injectCardTooltipStyles();
|
|
28649
28667
|
const ok = checkDeviceHistory.filter((r) => r.status === "ok").length;
|
|
28650
|
-
const
|
|
28668
|
+
const fail2 = checkDeviceHistory.filter((r) => r.status === "offline").length;
|
|
28651
28669
|
const total = checkDeviceHistory.length;
|
|
28652
28670
|
const firstTs = checkDeviceHistory[0]?.ts;
|
|
28653
28671
|
const uptimeLabel = firstTs ? (() => {
|
|
@@ -28666,10 +28684,10 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28666
28684
|
minute: "2-digit",
|
|
28667
28685
|
second: "2-digit"
|
|
28668
28686
|
});
|
|
28669
|
-
const
|
|
28670
|
-
return `<div class="rtt-tt-history-row">${
|
|
28687
|
+
const icon2 = r.status === "ok" ? "\u2705" : "\u274C";
|
|
28688
|
+
return `<div class="rtt-tt-history-row">${icon2} ${dt}</div>`;
|
|
28671
28689
|
}).join("");
|
|
28672
|
-
const failBlock =
|
|
28690
|
+
const failBlock = fail2 > 0 ? `<div style="margin-top:8px;padding:6px 8px;background:#fff5f5;border-radius:6px;font-size:11px;color:#e74c3c;">\u26A0\uFE0F ${fail2} falha${fail2 > 1 ? "s" : ""} registrada${fail2 > 1 ? "s" : ""}</div>` : "";
|
|
28673
28691
|
const tooltip = document.createElement("div");
|
|
28674
28692
|
tooltip.id = "rtt-status-tooltip";
|
|
28675
28693
|
if (currentTheme === "dark") tooltip.dataset["theme"] = "dark";
|
|
@@ -28689,7 +28707,7 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28689
28707
|
${centralId ? `<div style="font-family:ui-monospace,monospace;background:#f1f5f9;border-radius:5px;padding:3px 8px;font-size:11px;color:#475569;">\u{1F511} Central ID: <b>${centralId}</b></div>` : ""}
|
|
28690
28708
|
<div style="font-size:12px;">\u{1F4E1} <b>${ok}</b> chamadas com sucesso${total > 0 ? ` de ${total}` : ""}</div>
|
|
28691
28709
|
<div style="font-size:12px;">\u23F1\uFE0F Monitorando h\xE1: <b>${uptimeLabel}</b></div>
|
|
28692
|
-
${
|
|
28710
|
+
${fail2 > 0 ? `<div style="font-size:12px;color:#e74c3c;">\u274C <b>${fail2}</b> falha${fail2 > 1 ? "s" : ""}</div>` : ""}
|
|
28693
28711
|
</div>
|
|
28694
28712
|
${failBlock}
|
|
28695
28713
|
</div>
|
|
@@ -28739,9 +28757,9 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28739
28757
|
minute: "2-digit",
|
|
28740
28758
|
second: "2-digit"
|
|
28741
28759
|
}) : "--";
|
|
28742
|
-
function row(
|
|
28760
|
+
function row(icon2, label, value) {
|
|
28743
28761
|
return `<div style="display:flex;flex-direction:column;gap:1px;padding:5px 0;border-bottom:1px solid #f3f4f6;">
|
|
28744
|
-
<span style="font-size:10px;color:#9ca3af;font-weight:500;">${
|
|
28762
|
+
<span style="font-size:10px;color:#9ca3af;font-weight:500;">${icon2} ${label}</span>
|
|
28745
28763
|
<span style="font-family:monospace;font-size:12px;color:#1f2937;font-weight:600;word-break:break-all;">${value || "\u2014"}</span>
|
|
28746
28764
|
</div>`;
|
|
28747
28765
|
}
|
|
@@ -29189,11 +29207,11 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29189
29207
|
function showCoverageNotice(text2, resume) {
|
|
29190
29208
|
if (!coverageNoticeEl) return;
|
|
29191
29209
|
coverageNoticeEl.textContent = "";
|
|
29192
|
-
const
|
|
29193
|
-
|
|
29210
|
+
const icon2 = document.createElement("span");
|
|
29211
|
+
icon2.textContent = "\u26A0\uFE0F ";
|
|
29194
29212
|
const msg = document.createElement("span");
|
|
29195
29213
|
msg.textContent = text2;
|
|
29196
|
-
coverageNoticeEl.append(
|
|
29214
|
+
coverageNoticeEl.append(icon2, msg);
|
|
29197
29215
|
coverageResume = resume ? { startISO: resume.startISO, endISO: resume.endISO } : null;
|
|
29198
29216
|
if (resume) {
|
|
29199
29217
|
const link = document.createElement("a");
|
|
@@ -29738,8 +29756,8 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29738
29756
|
if (!chart) return;
|
|
29739
29757
|
chart.options.responsive = false;
|
|
29740
29758
|
const w = chartContainer.clientWidth - 40;
|
|
29741
|
-
const
|
|
29742
|
-
chart.resize(Math.max(w, 200), Math.max(
|
|
29759
|
+
const h3 = chartContainer.clientHeight - 60;
|
|
29760
|
+
chart.resize(Math.max(w, 200), Math.max(h3, 120));
|
|
29743
29761
|
})
|
|
29744
29762
|
);
|
|
29745
29763
|
}
|
|
@@ -29885,8 +29903,8 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29885
29903
|
URL.revokeObjectURL(url);
|
|
29886
29904
|
}
|
|
29887
29905
|
function ensureRoom2(doc, nextY, minRoom = 12) {
|
|
29888
|
-
const
|
|
29889
|
-
if (nextY + minRoom >
|
|
29906
|
+
const h3 = doc.internal.pageSize.getHeight();
|
|
29907
|
+
if (nextY + minRoom > h3 - 15) {
|
|
29890
29908
|
doc.addPage();
|
|
29891
29909
|
return 20;
|
|
29892
29910
|
}
|
|
@@ -29985,8 +30003,8 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29985
30003
|
if (isExpanded) {
|
|
29986
30004
|
chart.options.responsive = false;
|
|
29987
30005
|
const w = chartContainer.clientWidth - 40;
|
|
29988
|
-
const
|
|
29989
|
-
chart.resize(Math.max(w, 200), Math.max(
|
|
30006
|
+
const h3 = chartContainer.clientHeight - 60;
|
|
30007
|
+
chart.resize(Math.max(w, 200), Math.max(h3, 120));
|
|
29990
30008
|
} else {
|
|
29991
30009
|
chart.options.responsive = true;
|
|
29992
30010
|
chartCanvas.style.height = "";
|
|
@@ -30774,10 +30792,10 @@ var BASControlPanel = class {
|
|
|
30774
30792
|
}
|
|
30775
30793
|
return items.join("");
|
|
30776
30794
|
}
|
|
30777
|
-
renderTelemetryItem(label, value, unit,
|
|
30795
|
+
renderTelemetryItem(label, value, unit, icon2) {
|
|
30778
30796
|
return `
|
|
30779
30797
|
<div class="myio-bas-telemetry-item">
|
|
30780
|
-
<span class="myio-bas-telemetry-icon">${
|
|
30798
|
+
<span class="myio-bas-telemetry-icon">${icon2}</span>
|
|
30781
30799
|
<div class="myio-bas-telemetry-content">
|
|
30782
30800
|
<span class="myio-bas-telemetry-label">${label}</span>
|
|
30783
30801
|
<span class="myio-bas-telemetry-value">${value} <span class="myio-bas-telemetry-unit">${unit}</span></span>
|
|
@@ -34143,20 +34161,20 @@ function mixHex(a, b, ratio) {
|
|
|
34143
34161
|
};
|
|
34144
34162
|
return `#${mix(0)}${mix(2)}${mix(4)}`;
|
|
34145
34163
|
}
|
|
34146
|
-
function hslToHex(
|
|
34164
|
+
function hslToHex(h3, s, l) {
|
|
34147
34165
|
const sat = s / 100;
|
|
34148
34166
|
const lig = l / 100;
|
|
34149
|
-
const k = (n) => (n +
|
|
34167
|
+
const k = (n) => (n + h3 / 30) % 12;
|
|
34150
34168
|
const a = sat * Math.min(lig, 1 - lig);
|
|
34151
34169
|
const f = (n) => lig - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
34152
34170
|
const to = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
|
|
34153
34171
|
return `#${to(f(0))}${to(f(8))}${to(f(4))}`;
|
|
34154
34172
|
}
|
|
34155
34173
|
function hashColor(label, dark) {
|
|
34156
|
-
let
|
|
34157
|
-
for (let i = 0; i < label.length; i++)
|
|
34158
|
-
const hue = Math.abs(
|
|
34159
|
-
const sat = 55 + Math.abs(
|
|
34174
|
+
let h3 = 5381;
|
|
34175
|
+
for (let i = 0; i < label.length; i++) h3 = (h3 << 5) + h3 + label.charCodeAt(i) | 0;
|
|
34176
|
+
const hue = Math.abs(h3) % 360;
|
|
34177
|
+
const sat = 55 + Math.abs(h3 >> 8) % 25;
|
|
34160
34178
|
return hslToHex(hue, sat, dark ? 58 : 44);
|
|
34161
34179
|
}
|
|
34162
34180
|
function paletteColor(base, index, dark) {
|
|
@@ -34365,11 +34383,11 @@ function createParticipationChart(container, params) {
|
|
|
34365
34383
|
].join(" ");
|
|
34366
34384
|
}
|
|
34367
34385
|
function buildPieSvg2(entries, total) {
|
|
34368
|
-
const
|
|
34386
|
+
const svg2 = document.createElementNS(SVG_NS, "svg");
|
|
34369
34387
|
const SIZE = 300;
|
|
34370
|
-
|
|
34371
|
-
|
|
34372
|
-
|
|
34388
|
+
svg2.setAttribute("viewBox", `0 0 ${SIZE} ${SIZE}`);
|
|
34389
|
+
svg2.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
34390
|
+
svg2.setAttribute("role", "img");
|
|
34373
34391
|
const cx = SIZE / 2;
|
|
34374
34392
|
const cy = SIZE / 2;
|
|
34375
34393
|
const ro = 128;
|
|
@@ -34401,7 +34419,7 @@ function createParticipationChart(container, params) {
|
|
|
34401
34419
|
path.addEventListener("mouseleave", () => {
|
|
34402
34420
|
path.style.transform = "";
|
|
34403
34421
|
});
|
|
34404
|
-
|
|
34422
|
+
svg2.appendChild(path);
|
|
34405
34423
|
attachItemTooltip(path, item, pct);
|
|
34406
34424
|
if (pct >= 8) {
|
|
34407
34425
|
const rl = (ro + ri) / 2;
|
|
@@ -34418,10 +34436,10 @@ function createParticipationChart(container, params) {
|
|
|
34418
34436
|
text2.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
|
|
34419
34437
|
text2.setAttribute("pointer-events", "none");
|
|
34420
34438
|
text2.textContent = fmtPct(pct);
|
|
34421
|
-
|
|
34439
|
+
svg2.appendChild(text2);
|
|
34422
34440
|
}
|
|
34423
34441
|
});
|
|
34424
|
-
return
|
|
34442
|
+
return svg2;
|
|
34425
34443
|
}
|
|
34426
34444
|
function buildBarsSvg(entries, total) {
|
|
34427
34445
|
const sorted = [...entries].sort((a, b) => b.item.value - a.item.value);
|
|
@@ -34433,10 +34451,10 @@ function createParticipationChart(container, params) {
|
|
|
34433
34451
|
const maxValue = sorted.reduce((m, e) => Math.max(m, e.item.value), 0);
|
|
34434
34452
|
const textColor = resolvedText();
|
|
34435
34453
|
const mutedColor = resolvedMuted();
|
|
34436
|
-
const
|
|
34437
|
-
|
|
34438
|
-
|
|
34439
|
-
|
|
34454
|
+
const svg2 = document.createElementNS(SVG_NS, "svg");
|
|
34455
|
+
svg2.setAttribute("viewBox", `0 0 ${W} ${H}`);
|
|
34456
|
+
svg2.setAttribute("preserveAspectRatio", "xMidYMin meet");
|
|
34457
|
+
svg2.setAttribute("role", "img");
|
|
34440
34458
|
sorted.forEach(({ item, color }, row) => {
|
|
34441
34459
|
const pct = total > 0 ? item.value / total * 100 : 0;
|
|
34442
34460
|
const y = row * ROW_H + 4;
|
|
@@ -34450,7 +34468,7 @@ function createParticipationChart(container, params) {
|
|
|
34450
34468
|
label.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
|
|
34451
34469
|
const raw = item.label || "";
|
|
34452
34470
|
label.textContent = raw.length > 18 ? `${raw.slice(0, 17)}\u2026` : raw;
|
|
34453
|
-
|
|
34471
|
+
svg2.appendChild(label);
|
|
34454
34472
|
const rect = document.createElementNS(SVG_NS, "rect");
|
|
34455
34473
|
rect.setAttribute("x", String(LABEL_W));
|
|
34456
34474
|
rect.setAttribute("y", String(y + 3));
|
|
@@ -34460,7 +34478,7 @@ function createParticipationChart(container, params) {
|
|
|
34460
34478
|
rect.setAttribute("fill", color);
|
|
34461
34479
|
rect.setAttribute("class", `${PARTICIPATION_CHART_CSS_PREFIX}__bar-rect`);
|
|
34462
34480
|
rect.setAttribute("data-key", keyOf(item));
|
|
34463
|
-
|
|
34481
|
+
svg2.appendChild(rect);
|
|
34464
34482
|
attachItemTooltip(rect, item, pct);
|
|
34465
34483
|
const value = document.createElementNS(SVG_NS, "text");
|
|
34466
34484
|
value.setAttribute("x", String(LABEL_W + barW + 6));
|
|
@@ -34470,9 +34488,9 @@ function createParticipationChart(container, params) {
|
|
|
34470
34488
|
value.setAttribute("font-size", "10.5");
|
|
34471
34489
|
value.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
|
|
34472
34490
|
value.textContent = `${settings.formatValue(item.value)}${settings.unit ? ` ${settings.unit}` : ""} \xB7 ${fmtPct(pct)}`;
|
|
34473
|
-
|
|
34491
|
+
svg2.appendChild(value);
|
|
34474
34492
|
});
|
|
34475
|
-
return
|
|
34493
|
+
return svg2;
|
|
34476
34494
|
}
|
|
34477
34495
|
function buildLegend2(total) {
|
|
34478
34496
|
const legend = document.createElement("div");
|
|
@@ -34538,15 +34556,15 @@ function createParticipationChart(container, params) {
|
|
|
34538
34556
|
root.appendChild(body);
|
|
34539
34557
|
}
|
|
34540
34558
|
async function svgToPng(scale = 2) {
|
|
34541
|
-
const
|
|
34542
|
-
if (!
|
|
34559
|
+
const svg2 = root.querySelector("svg");
|
|
34560
|
+
if (!svg2) {
|
|
34543
34561
|
console.warn("[ParticipationChart] Nada para exportar \u2014 gr\xE1fico vazio.");
|
|
34544
34562
|
return null;
|
|
34545
34563
|
}
|
|
34546
|
-
const vb =
|
|
34564
|
+
const vb = svg2.viewBox.baseVal;
|
|
34547
34565
|
const width = vb && vb.width ? vb.width : 300;
|
|
34548
34566
|
const height = vb && vb.height ? vb.height : 300;
|
|
34549
|
-
const clone =
|
|
34567
|
+
const clone = svg2.cloneNode(true);
|
|
34550
34568
|
clone.setAttribute("xmlns", SVG_NS);
|
|
34551
34569
|
clone.setAttribute("width", String(width));
|
|
34552
34570
|
clone.setAttribute("height", String(height));
|
|
@@ -34882,14 +34900,14 @@ function createExportButton(kind, container, params = {}) {
|
|
|
34882
34900
|
const label = settings.label ?? defaultLabel;
|
|
34883
34901
|
const locked = !!settings.locked;
|
|
34884
34902
|
const disabled = locked || !!settings.disabled;
|
|
34885
|
-
const
|
|
34903
|
+
const icon2 = locked ? LOCK_ICON : settings.icon ?? defaultIcon;
|
|
34886
34904
|
btn.className = `${EXPORT_BUTTON_CSS_PREFIX}${locked ? ` ${EXPORT_BUTTON_CSS_PREFIX}--locked` : ""}`;
|
|
34887
34905
|
btn.disabled = disabled;
|
|
34888
34906
|
btn.style.borderColor = colors2.border;
|
|
34889
34907
|
btn.style.color = colors2.text;
|
|
34890
34908
|
btn.style.background = colors2.bg;
|
|
34891
34909
|
btn.setAttribute("aria-label", label);
|
|
34892
|
-
btn.innerHTML = `${
|
|
34910
|
+
btn.innerHTML = `${icon2 ? `<span class="${EXPORT_BUTTON_CSS_PREFIX}__icon">${icon2}</span>` : ""}${label}`;
|
|
34893
34911
|
tooltipCleanup?.();
|
|
34894
34912
|
tooltipCleanup = null;
|
|
34895
34913
|
const tt = settings.tooltip;
|
|
@@ -40813,11 +40831,11 @@ var PowerLimitsModalView = class {
|
|
|
40813
40831
|
const statusKey = status === "standby" ? "standBy" : status;
|
|
40814
40832
|
const config2 = STATUS_CONFIG[statusKey];
|
|
40815
40833
|
const formValues = this.formData[status];
|
|
40816
|
-
const
|
|
40834
|
+
const icon2 = domainIcons[statusKey];
|
|
40817
40835
|
return `
|
|
40818
40836
|
<div class="myio-power-limits-card-item myio-status-${status}" style="--status-color: ${config2.color}; --status-bg: ${config2.bgColor};">
|
|
40819
40837
|
<div class="myio-card-header">
|
|
40820
|
-
<span class="myio-status-icon">${
|
|
40838
|
+
<span class="myio-status-icon">${icon2}</span>
|
|
40821
40839
|
<span class="myio-status-indicator"></span>
|
|
40822
40840
|
<span class="myio-status-label">${config2.label}</span>
|
|
40823
40841
|
</div>
|
|
@@ -48317,7 +48335,7 @@ var AnnotationsTab = class {
|
|
|
48317
48335
|
const isReject = type === "rejected";
|
|
48318
48336
|
const isComment = type === "comment";
|
|
48319
48337
|
let title;
|
|
48320
|
-
let
|
|
48338
|
+
let icon2;
|
|
48321
48339
|
let headerClass;
|
|
48322
48340
|
let btnClass;
|
|
48323
48341
|
let labelText;
|
|
@@ -48327,7 +48345,7 @@ var AnnotationsTab = class {
|
|
|
48327
48345
|
let isRequired;
|
|
48328
48346
|
if (isApprove) {
|
|
48329
48347
|
title = "Aprovar Anota\xE7\xE3o";
|
|
48330
|
-
|
|
48348
|
+
icon2 = "\u2713";
|
|
48331
48349
|
headerClass = "response-modal__header--approve";
|
|
48332
48350
|
btnClass = "response-modal__btn--approve";
|
|
48333
48351
|
labelText = "Observa\xE7\xE3o (opcional)";
|
|
@@ -48337,7 +48355,7 @@ var AnnotationsTab = class {
|
|
|
48337
48355
|
isRequired = false;
|
|
48338
48356
|
} else if (isReject) {
|
|
48339
48357
|
title = "Rejeitar Anota\xE7\xE3o";
|
|
48340
|
-
|
|
48358
|
+
icon2 = "\u2717";
|
|
48341
48359
|
headerClass = "response-modal__header--reject";
|
|
48342
48360
|
btnClass = "response-modal__btn--reject";
|
|
48343
48361
|
labelText = "Justificativa";
|
|
@@ -48347,7 +48365,7 @@ var AnnotationsTab = class {
|
|
|
48347
48365
|
isRequired = true;
|
|
48348
48366
|
} else if (isComment) {
|
|
48349
48367
|
title = "Adicionar Coment\xE1rio";
|
|
48350
|
-
|
|
48368
|
+
icon2 = "\u{1F4AC}";
|
|
48351
48369
|
headerClass = "response-modal__header--comment";
|
|
48352
48370
|
btnClass = "response-modal__btn--comment";
|
|
48353
48371
|
labelText = "Coment\xE1rio";
|
|
@@ -48357,7 +48375,7 @@ var AnnotationsTab = class {
|
|
|
48357
48375
|
isRequired = true;
|
|
48358
48376
|
} else {
|
|
48359
48377
|
title = "Arquivar Anota\xE7\xE3o";
|
|
48360
|
-
|
|
48378
|
+
icon2 = "\u2B07\uFE0F";
|
|
48361
48379
|
headerClass = "response-modal__header--archive";
|
|
48362
48380
|
btnClass = "response-modal__btn--archive-modal";
|
|
48363
48381
|
labelText = "Justificativa";
|
|
@@ -48371,7 +48389,7 @@ var AnnotationsTab = class {
|
|
|
48371
48389
|
overlay.innerHTML = `
|
|
48372
48390
|
<div class="response-modal">
|
|
48373
48391
|
<div class="response-modal__header ${headerClass}">
|
|
48374
|
-
<span class="response-modal__icon">${
|
|
48392
|
+
<span class="response-modal__icon">${icon2}</span>
|
|
48375
48393
|
<span class="response-modal__title">${title}</span>
|
|
48376
48394
|
</div>
|
|
48377
48395
|
<div class="response-modal__body">
|
|
@@ -50627,9 +50645,9 @@ var AnnotationsTab = class {
|
|
|
50627
50645
|
` : ""}
|
|
50628
50646
|
<div class="annotation-detail__history">
|
|
50629
50647
|
<div class="annotation-detail__history-title">Hist\xF3rico (${annotation.history.length + (annotation.responses?.length || 0)} eventos)</div>
|
|
50630
|
-
${annotation.history.map((
|
|
50648
|
+
${annotation.history.map((h3) => `
|
|
50631
50649
|
<div class="annotation-detail__history-item">
|
|
50632
|
-
<strong>${
|
|
50650
|
+
<strong>${h3.action}</strong> por ${h3.userName} em ${this.formatDate(h3.timestamp)}
|
|
50633
50651
|
</div>
|
|
50634
50652
|
`).join("")}
|
|
50635
50653
|
${(annotation.responses || []).map((r) => `
|
|
@@ -51850,9 +51868,9 @@ function seededRand(seed) {
|
|
|
51850
51868
|
};
|
|
51851
51869
|
}
|
|
51852
51870
|
function hashStr(s) {
|
|
51853
|
-
let
|
|
51854
|
-
for (let i = 0; i < s.length; i++)
|
|
51855
|
-
return Math.abs(
|
|
51871
|
+
let h3 = 0;
|
|
51872
|
+
for (let i = 0; i < s.length; i++) h3 = Math.imul(31, h3) + s.charCodeAt(i) | 0;
|
|
51873
|
+
return Math.abs(h3);
|
|
51856
51874
|
}
|
|
51857
51875
|
function generateBuckets(alarm, devices, period = "mes") {
|
|
51858
51876
|
const count = alarm.occurrenceCount || 1;
|
|
@@ -51937,11 +51955,11 @@ function generateDowDistribution(alarm) {
|
|
|
51937
51955
|
function generateHodDistribution(alarm) {
|
|
51938
51956
|
const count = alarm.occurrenceCount || 1;
|
|
51939
51957
|
const rand = seededRand(hashStr(alarm.id + "hod"));
|
|
51940
|
-
const weights = Array.from({ length: 24 }, (_,
|
|
51941
|
-
if (
|
|
51942
|
-
if (
|
|
51943
|
-
if (
|
|
51944
|
-
if (
|
|
51958
|
+
const weights = Array.from({ length: 24 }, (_, h3) => {
|
|
51959
|
+
if (h3 < 6) return 0.05 + rand() * 0.05;
|
|
51960
|
+
if (h3 < 10) return 0.3 + rand() * 0.3;
|
|
51961
|
+
if (h3 <= 19) return 0.7 + rand() * 0.6;
|
|
51962
|
+
if (h3 <= 22) return 0.3 + rand() * 0.3;
|
|
51945
51963
|
return 0.05 + rand() * 0.05;
|
|
51946
51964
|
});
|
|
51947
51965
|
const wSum = weights.reduce((a, b) => a + b, 0);
|
|
@@ -52074,7 +52092,7 @@ function createHodChart(canvas, vals) {
|
|
|
52074
52092
|
return new Chart2(canvas, {
|
|
52075
52093
|
type: "bar",
|
|
52076
52094
|
data: {
|
|
52077
|
-
labels: Array.from({ length: 24 }, (_,
|
|
52095
|
+
labels: Array.from({ length: 24 }, (_, h3) => `${h3}h`),
|
|
52078
52096
|
datasets: [{
|
|
52079
52097
|
label: "Ocorr\xEAncias",
|
|
52080
52098
|
data: vals,
|
|
@@ -60562,12 +60580,12 @@ var TicketsTab = class {
|
|
|
60562
60580
|
const container = this.config.container;
|
|
60563
60581
|
const toggle = container.querySelector("#ct-new-ticket-toggle");
|
|
60564
60582
|
const body = container.querySelector("#ct-new-ticket-body");
|
|
60565
|
-
const
|
|
60583
|
+
const icon2 = container.querySelector("#ct-collapse-icon");
|
|
60566
60584
|
if (toggle && body) {
|
|
60567
60585
|
toggle.addEventListener("click", () => {
|
|
60568
60586
|
const isOpen = body.style.display !== "none";
|
|
60569
60587
|
body.style.display = isOpen ? "none" : "block";
|
|
60570
|
-
if (
|
|
60588
|
+
if (icon2) icon2.textContent = isOpen ? "\u25BC" : "\u25B2";
|
|
60571
60589
|
});
|
|
60572
60590
|
}
|
|
60573
60591
|
if (this.config.requesterEmail) {
|
|
@@ -60779,13 +60797,13 @@ ${description}` : description;
|
|
|
60779
60797
|
return;
|
|
60780
60798
|
}
|
|
60781
60799
|
area.innerHTML = this._selectedFiles.map((f, i) => {
|
|
60782
|
-
const
|
|
60800
|
+
const icon2 = this._getFileIcon(f);
|
|
60783
60801
|
const isImage = f.type.startsWith("image/");
|
|
60784
60802
|
const tooltip = `${f.name}
|
|
60785
60803
|
${this._formatFileSize(f.size)} \xB7 ${f.type || "arquivo"}`;
|
|
60786
60804
|
return `
|
|
60787
60805
|
<div class="ct-file-chip" data-index="${i}" title="${this.esc(tooltip)}">
|
|
60788
|
-
${isImage ? `<img class="ct-file-thumb" src="${URL.createObjectURL(f)}" alt="${this.esc(f.name)}">` : `<span class="ct-file-icon">${
|
|
60806
|
+
${isImage ? `<img class="ct-file-thumb" src="${URL.createObjectURL(f)}" alt="${this.esc(f.name)}">` : `<span class="ct-file-icon">${icon2}</span>`}
|
|
60789
60807
|
<span class="ct-file-name">${this.esc(f.name.length > 18 ? f.name.slice(0, 16) + "\u2026" : f.name)}</span>
|
|
60790
60808
|
<span class="ct-file-size">${this._formatFileSize(f.size)}</span>
|
|
60791
60809
|
<button type="button" class="ct-file-remove" data-index="${i}" title="Remover">\u2715</button>
|
|
@@ -62448,11 +62466,11 @@ var SettingsModalView = class _SettingsModalView {
|
|
|
62448
62466
|
formatUptime(seconds) {
|
|
62449
62467
|
if (seconds == null || Number.isNaN(seconds)) return "\u2014";
|
|
62450
62468
|
const d = Math.floor(seconds / 86400);
|
|
62451
|
-
const
|
|
62469
|
+
const h3 = Math.floor(seconds % 86400 / 3600);
|
|
62452
62470
|
const m = Math.floor(seconds % 3600 / 60);
|
|
62453
62471
|
const parts = [];
|
|
62454
62472
|
if (d > 0) parts.push(`${d}d`);
|
|
62455
|
-
if (
|
|
62473
|
+
if (h3 > 0 || d > 0) parts.push(`${h3}h`);
|
|
62456
62474
|
parts.push(`${m}min`);
|
|
62457
62475
|
return parts.join(" ");
|
|
62458
62476
|
}
|
|
@@ -65551,11 +65569,11 @@ function formatIsoRelativeSimple(iso) {
|
|
|
65551
65569
|
function formatUptime(seconds) {
|
|
65552
65570
|
if (seconds == null || Number.isNaN(seconds)) return "\u2014";
|
|
65553
65571
|
const d = Math.floor(seconds / 86400);
|
|
65554
|
-
const
|
|
65572
|
+
const h3 = Math.floor(seconds % 86400 / 3600);
|
|
65555
65573
|
const m = Math.floor(seconds % 3600 / 60);
|
|
65556
65574
|
const parts = [];
|
|
65557
65575
|
if (d > 0) parts.push(`${d}d`);
|
|
65558
|
-
if (
|
|
65576
|
+
if (h3 > 0 || d > 0) parts.push(`${h3}h`);
|
|
65559
65577
|
parts.push(`${m}min`);
|
|
65560
65578
|
return parts.join(" ");
|
|
65561
65579
|
}
|
|
@@ -68610,7 +68628,7 @@ var WelcomeModalView = class _WelcomeModalView {
|
|
|
68610
68628
|
const meta = card.metaCounts || {};
|
|
68611
68629
|
const details = card.metaDetails || {};
|
|
68612
68630
|
const loadingBody = '<div style="opacity:.7;padding:6px 0">Carregando\u2026</div>';
|
|
68613
|
-
const header = (
|
|
68631
|
+
const header = (icon2, label, count) => `<div style="font-weight:800;font-size:13px;margin-bottom:8px">${icon2} ${label}${count === null || count === void 0 ? "" : ` (${count})`} \u2014 ${esc8(card.title)}</div>`;
|
|
68614
68632
|
const row = (titleHtml, subHtml) => `<div style="padding:6px 0;border-top:1px solid #334155">
|
|
68615
68633
|
<div style="font-weight:600">${titleHtml}</div>
|
|
68616
68634
|
${subHtml ? `<div style="opacity:.7">${subHtml}</div>` : ""}
|
|
@@ -69295,15 +69313,15 @@ var WelcomeModalView = class _WelcomeModalView {
|
|
|
69295
69313
|
if (svgIcon) {
|
|
69296
69314
|
ctaBtn.appendChild(svgIcon);
|
|
69297
69315
|
} else {
|
|
69298
|
-
const
|
|
69299
|
-
|
|
69300
|
-
|
|
69301
|
-
|
|
69302
|
-
|
|
69303
|
-
|
|
69304
|
-
|
|
69305
|
-
|
|
69306
|
-
ctaBtn.appendChild(
|
|
69316
|
+
const svg2 = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
69317
|
+
svg2.setAttribute("viewBox", "0 0 24 24");
|
|
69318
|
+
svg2.setAttribute("fill", "none");
|
|
69319
|
+
svg2.setAttribute("stroke", "currentColor");
|
|
69320
|
+
svg2.setAttribute("stroke-width", "2");
|
|
69321
|
+
svg2.setAttribute("stroke-linecap", "round");
|
|
69322
|
+
svg2.setAttribute("stroke-linejoin", "round");
|
|
69323
|
+
svg2.innerHTML = '<line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />';
|
|
69324
|
+
ctaBtn.appendChild(svg2);
|
|
69307
69325
|
}
|
|
69308
69326
|
}
|
|
69309
69327
|
}
|
|
@@ -71164,10 +71182,10 @@ function createHeaderComponent(params) {
|
|
|
71164
71182
|
const categoriesHtml = categories.map((c) => {
|
|
71165
71183
|
const name = String(c?.name ?? c?.label ?? "Categoria");
|
|
71166
71184
|
const deviceCount = Number(c?.deviceCount ?? c?.count ?? 0);
|
|
71167
|
-
const
|
|
71185
|
+
const icon2 = String(c?.icon ?? "");
|
|
71168
71186
|
return `
|
|
71169
71187
|
<div class="myio-info-tooltip__row" style="padding: 6px 0; gap: 8px;">
|
|
71170
|
-
<span class="myio-info-tooltip__label">${
|
|
71188
|
+
<span class="myio-info-tooltip__label">${icon2 ? `${icon2} ` : ""}${name}</span>
|
|
71171
71189
|
<span class="myio-info-tooltip__value myio-info-tooltip__value--highlight">${deviceCount}</span>
|
|
71172
71190
|
</div>
|
|
71173
71191
|
`;
|
|
@@ -72465,11 +72483,11 @@ function createOverlay() {
|
|
|
72465
72483
|
overlay.style.setProperty("--fc-primary-hover", colors.primaryHover);
|
|
72466
72484
|
return overlay;
|
|
72467
72485
|
}
|
|
72468
|
-
function createAlertBox(
|
|
72486
|
+
function createAlertBox(icon2, title, message, buttonLabel) {
|
|
72469
72487
|
const box = document.createElement("div");
|
|
72470
72488
|
box.className = "myio-footer-alert-box";
|
|
72471
72489
|
box.innerHTML = `
|
|
72472
|
-
<div class="myio-footer-alert-icon">${
|
|
72490
|
+
<div class="myio-footer-alert-icon">${icon2}</div>
|
|
72473
72491
|
<h2 class="myio-footer-alert-title">${title}</h2>
|
|
72474
72492
|
<p class="myio-footer-alert-message">${message}</p>
|
|
72475
72493
|
<button class="myio-footer-alert-button" type="button">${buttonLabel}</button>
|
|
@@ -75889,8 +75907,8 @@ function addCanvasToPdf(doc, canvas, x = 10, y = 20, maxWmm = 190) {
|
|
|
75889
75907
|
return y + mmH;
|
|
75890
75908
|
}
|
|
75891
75909
|
function ensureRoom(doc, nextY, minRoom = 40) {
|
|
75892
|
-
const
|
|
75893
|
-
if (nextY + minRoom >
|
|
75910
|
+
const h3 = doc.internal.pageSize.getHeight();
|
|
75911
|
+
if (nextY + minRoom > h3) {
|
|
75894
75912
|
doc.addPage();
|
|
75895
75913
|
return 20;
|
|
75896
75914
|
}
|
|
@@ -77647,9 +77665,9 @@ function openGoalsPanel(params) {
|
|
|
77647
77665
|
};
|
|
77648
77666
|
const onWriteFailure = (res) => {
|
|
77649
77667
|
state6.saving = false;
|
|
77650
|
-
const
|
|
77651
|
-
if (
|
|
77652
|
-
state6.conflictVersion =
|
|
77668
|
+
const conflict2 = readVersionConflict(res);
|
|
77669
|
+
if (conflict2 !== null) {
|
|
77670
|
+
state6.conflictVersion = conflict2;
|
|
77653
77671
|
state6.conflict = true;
|
|
77654
77672
|
state6.pendingReapply = dirtySnapshot;
|
|
77655
77673
|
reload();
|
|
@@ -77715,9 +77733,9 @@ function openGoalsPanel(params) {
|
|
|
77715
77733
|
reload();
|
|
77716
77734
|
return;
|
|
77717
77735
|
}
|
|
77718
|
-
const
|
|
77719
|
-
if (
|
|
77720
|
-
state6.conflictVersion =
|
|
77736
|
+
const conflict2 = readVersionConflict(res);
|
|
77737
|
+
if (conflict2 !== null) {
|
|
77738
|
+
state6.conflictVersion = conflict2;
|
|
77721
77739
|
state6.conflict = true;
|
|
77722
77740
|
reload();
|
|
77723
77741
|
} else {
|
|
@@ -77739,9 +77757,9 @@ function openGoalsPanel(params) {
|
|
|
77739
77757
|
reload();
|
|
77740
77758
|
return;
|
|
77741
77759
|
}
|
|
77742
|
-
const
|
|
77743
|
-
if (
|
|
77744
|
-
state6.conflictVersion =
|
|
77760
|
+
const conflict2 = readVersionConflict(res);
|
|
77761
|
+
if (conflict2 !== null) {
|
|
77762
|
+
state6.conflictVersion = conflict2;
|
|
77745
77763
|
state6.conflict = true;
|
|
77746
77764
|
reload();
|
|
77747
77765
|
} else {
|
|
@@ -77767,7 +77785,7 @@ function openGoalsPanel(params) {
|
|
|
77767
77785
|
const value = sampleHourValue();
|
|
77768
77786
|
const day = `${state6.year}-03-15`;
|
|
77769
77787
|
const lines = ["bucket,value"];
|
|
77770
|
-
for (let
|
|
77788
|
+
for (let h3 = 0; h3 < 24; h3++) lines.push(`${day}T${pad2(h3)},${value}`);
|
|
77771
77789
|
return lines.join("\n");
|
|
77772
77790
|
}
|
|
77773
77791
|
function downloadCsv(csv, suffix) {
|
|
@@ -77821,8 +77839,8 @@ function openGoalsPanel(params) {
|
|
|
77821
77839
|
state6.importApplied = res.data;
|
|
77822
77840
|
reload();
|
|
77823
77841
|
} else {
|
|
77824
|
-
const
|
|
77825
|
-
if (
|
|
77842
|
+
const conflict2 = readVersionConflict(res);
|
|
77843
|
+
if (conflict2 !== null) state6.conflictVersion = conflict2;
|
|
77826
77844
|
else state6.saveError = res.error && res.error.message || "Failed to apply import";
|
|
77827
77845
|
}
|
|
77828
77846
|
renderImportBody();
|
|
@@ -78034,19 +78052,19 @@ function openGoalsPanel(params) {
|
|
|
78034
78052
|
if (!yearOptions.includes(state6.year)) yearOptions.unshift(state6.year);
|
|
78035
78053
|
const actions = state6.editing ? `
|
|
78036
78054
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="open-import" ${state6.loading || state6.error ? "disabled" : ""}>
|
|
78037
|
-
${
|
|
78055
|
+
${icon2("upload")} ${i18n2.importBtn}
|
|
78038
78056
|
</button>
|
|
78039
78057
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="view-summary" ${state6.loading ? "disabled" : ""}>
|
|
78040
|
-
${
|
|
78058
|
+
${icon2("eye")} ${i18n2.viewSummary}
|
|
78041
78059
|
</button>
|
|
78042
78060
|
<button class="myio-goals-btn myio-goals-btn-primary" data-action="save" ${state6.loading || state6.error || state6.saving ? "disabled" : ""}>
|
|
78043
|
-
${
|
|
78061
|
+
${icon2("save")} ${state6.saving ? i18n2.saving : i18n2.save}
|
|
78044
78062
|
</button>` : `
|
|
78045
78063
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="download-hourly" ${state6.loading ? "disabled" : ""}>
|
|
78046
|
-
${
|
|
78064
|
+
${icon2("download")} ${i18n2.downloadHourlyExample}
|
|
78047
78065
|
</button>
|
|
78048
78066
|
<button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit" ${state6.loading || state6.error ? "disabled" : ""}>
|
|
78049
|
-
${
|
|
78067
|
+
${icon2("pencil")} ${i18n2.enableEditing}
|
|
78050
78068
|
</button>`;
|
|
78051
78069
|
return `
|
|
78052
78070
|
<div class="myio-goals-toolbar">
|
|
@@ -78064,9 +78082,9 @@ function openGoalsPanel(params) {
|
|
|
78064
78082
|
</select>
|
|
78065
78083
|
</label>
|
|
78066
78084
|
<div class="myio-goals-chips">
|
|
78067
|
-
<span class="myio-goals-chip myio-goals-chip-accent">${
|
|
78085
|
+
<span class="myio-goals-chip myio-goals-chip-accent">${icon2("target")} ${i18n2.domains[state6.domain]} \xB7 ${i18n2.aggregation[cfg.aggregationMethod]}</span>
|
|
78068
78086
|
<span class="myio-goals-chip myio-goals-chip-mono">${unitLabel2()}</span>
|
|
78069
|
-
<span class="myio-goals-chip myio-goals-chip-violet">${
|
|
78087
|
+
<span class="myio-goals-chip myio-goals-chip-violet">${icon2("history")} ${i18n2.currentVersion.replace("{n}", version2)}</span>
|
|
78070
78088
|
${renderMarginChip()}
|
|
78071
78089
|
${renderDeviceGranularityChip()}
|
|
78072
78090
|
${renderCoverageChip()}
|
|
@@ -78133,7 +78151,7 @@ function openGoalsPanel(params) {
|
|
|
78133
78151
|
${state6.saving ? "disabled" : ""} />
|
|
78134
78152
|
<span class="myio-goals-margin-pct">%</span>
|
|
78135
78153
|
<button class="myio-goals-btn myio-goals-btn-outline myio-goals-btn-sm" data-action="save-margin" ${state6.saving ? "disabled" : ""}>
|
|
78136
|
-
${
|
|
78154
|
+
${icon2("save")} ${i18n2.margin.save}
|
|
78137
78155
|
</button>
|
|
78138
78156
|
${pct != null ? `<button class="myio-goals-btn myio-goals-btn-outline myio-goals-btn-sm" data-action="clear-margin" ${state6.saving ? "disabled" : ""}>${i18n2.margin.clear}</button>` : ""}
|
|
78139
78157
|
<span class="myio-goals-margin-hint">${i18n2.margin.hint}</span>
|
|
@@ -78142,24 +78160,24 @@ function openGoalsPanel(params) {
|
|
|
78142
78160
|
function renderMessages() {
|
|
78143
78161
|
let html = "";
|
|
78144
78162
|
if (state6.conflict) {
|
|
78145
|
-
html += `<div class="myio-goals-alert myio-goals-alert-amber">${
|
|
78163
|
+
html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon2("alert")} ${i18n2.versionConflict}</div>`;
|
|
78146
78164
|
}
|
|
78147
78165
|
if (state6.saveError && !state6.conflict) {
|
|
78148
|
-
html += `<div class="myio-goals-alert myio-goals-alert-red">${
|
|
78166
|
+
html += `<div class="myio-goals-alert myio-goals-alert-red">${icon2("alert")} ${esc4(state6.saveError)}</div>`;
|
|
78149
78167
|
}
|
|
78150
78168
|
if (state6.saved && !state6.saveError) {
|
|
78151
|
-
html += `<div class="myio-goals-alert myio-goals-alert-green">${
|
|
78169
|
+
html += `<div class="myio-goals-alert myio-goals-alert-green">${icon2("check")} ${i18n2.saveSuccess}</div>`;
|
|
78152
78170
|
}
|
|
78153
78171
|
return html;
|
|
78154
78172
|
}
|
|
78155
78173
|
function renderMain() {
|
|
78156
78174
|
if (state6.loading) {
|
|
78157
|
-
return `<div class="myio-goals-center">${
|
|
78175
|
+
return `<div class="myio-goals-center">${icon2("spinner")} <span>${i18n2.loading}</span></div>`;
|
|
78158
78176
|
}
|
|
78159
78177
|
if (state6.error) {
|
|
78160
78178
|
return `
|
|
78161
78179
|
<div class="myio-goals-center myio-goals-center-col">
|
|
78162
|
-
${
|
|
78180
|
+
${icon2("alert-lg")}
|
|
78163
78181
|
<p>${esc4(state6.error)}</p>
|
|
78164
78182
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="retry">${i18n2.retry}</button>
|
|
78165
78183
|
</div>`;
|
|
@@ -78172,20 +78190,20 @@ function openGoalsPanel(params) {
|
|
|
78172
78190
|
if (!s.hasData) {
|
|
78173
78191
|
return `
|
|
78174
78192
|
<div class="myio-goals-center myio-goals-center-col">
|
|
78175
|
-
${
|
|
78193
|
+
${icon2("target-lg")}
|
|
78176
78194
|
<p>${i18n2.noData.replace("{year}", state6.year)}</p>
|
|
78177
|
-
<button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit">${
|
|
78195
|
+
<button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit">${icon2("pencil")} ${i18n2.enableEditing}</button>
|
|
78178
78196
|
</div>`;
|
|
78179
78197
|
}
|
|
78180
78198
|
const avg = isAverage();
|
|
78181
|
-
const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` :
|
|
78199
|
+
const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon2("sigma");
|
|
78182
78200
|
const kpis = [
|
|
78183
|
-
{ ic:
|
|
78201
|
+
{ ic: icon2("calendar"), label: i18n2.summary.year, value: String(state6.year) },
|
|
78184
78202
|
{ ic: glyph, label: avg ? i18n2.summary.yearAverage : i18n2.summary.yearTotal, value: fmt2(s.yearValue) },
|
|
78185
|
-
{ ic:
|
|
78186
|
-
{ ic:
|
|
78187
|
-
{ ic:
|
|
78188
|
-
{ ic:
|
|
78203
|
+
{ ic: icon2("calendar-range"), label: i18n2.summary.monthsWithGoal, value: `${s.monthsWithGoal} / 12` },
|
|
78204
|
+
{ ic: icon2("calendar-days"), label: i18n2.summary.daysWithGoal, value: String(s.daysWithGoal) },
|
|
78205
|
+
{ ic: icon2("trend"), label: i18n2.summary.avgPerMonth, value: fmt2(s.avgPerMonth) },
|
|
78206
|
+
{ ic: icon2("trend"), label: i18n2.summary.avgPerDay, value: fmt2(s.avgPerDay) }
|
|
78189
78207
|
];
|
|
78190
78208
|
const marginPct = currentMarginPct();
|
|
78191
78209
|
const adjAnnual = state6.goals && state6.goals.tree && state6.goals.tree.annual ? state6.goals.tree.annual.adjustedValue : null;
|
|
@@ -78198,7 +78216,7 @@ function openGoalsPanel(params) {
|
|
|
78198
78216
|
}
|
|
78199
78217
|
const topCol = (title, items, labeler) => `
|
|
78200
78218
|
<div class="myio-goals-topcard">
|
|
78201
|
-
<h4>${
|
|
78219
|
+
<h4>${icon2("trend")} ${title}</h4>
|
|
78202
78220
|
${items.length === 0 ? `<p class="myio-goals-muted">\u2014</p>` : `<ol>${items.map(
|
|
78203
78221
|
(e, i) => `
|
|
78204
78222
|
<li>
|
|
@@ -78237,9 +78255,9 @@ function openGoalsPanel(params) {
|
|
|
78237
78255
|
const version2 = state6.goals ? state6.goals.version : 0;
|
|
78238
78256
|
const crumb = `
|
|
78239
78257
|
<nav class="myio-goals-crumb">
|
|
78240
|
-
<button data-action="crumb-months" class="${state6.level === "month" ? "active" : ""}">${
|
|
78241
|
-
${state6.selectedMonth ? `${
|
|
78242
|
-
${state6.selectedMonth && state6.selectedDay && state6.level === "hour" ? `${
|
|
78258
|
+
<button data-action="crumb-months" class="${state6.level === "month" ? "active" : ""}">${icon2("home")} ${i18n2.breadcrumbYear.replace("{year}", state6.year)}</button>
|
|
78259
|
+
${state6.selectedMonth ? `${icon2("chevron")}<button data-action="crumb-days" class="${state6.level === "day" ? "active" : ""}">${i18n2.months[state6.selectedMonth]}</button>` : ""}
|
|
78260
|
+
${state6.selectedMonth && state6.selectedDay && state6.level === "hour" ? `${icon2("chevron")}<span class="active">${i18n2.breadcrumbDay.replace("{day}", Number(state6.selectedDay))}</span>` : ""}
|
|
78243
78261
|
</nav>`;
|
|
78244
78262
|
const emptyHint = state6.level === "month" && monthlyFilledCount() === 0 && version2 === 0 ? `<p class="myio-goals-muted">${i18n2.empty}</p>` : "";
|
|
78245
78263
|
const drillHint = state6.level !== "hour" ? `<p class="myio-goals-microhint">${state6.level === "month" ? i18n2.drill.openMonthHint : i18n2.drill.openDayHint}</p>` : "";
|
|
@@ -78249,14 +78267,14 @@ function openGoalsPanel(params) {
|
|
|
78249
78267
|
const confirmed = node && node.derived === false;
|
|
78250
78268
|
const cellLabel = state6.level === "month" ? i18n2.months[key] : state6.level === "day" ? i18n2.dayCell.replace("{day}", Number(key)) : `${key}:00`;
|
|
78251
78269
|
const canDrill = state6.level !== "hour";
|
|
78252
|
-
const labelEl = canDrill ? `<button class="myio-goals-cell-drill" data-action="${state6.level === "month" ? "open-month" : "open-day"}" data-key="${key}" title="${i18n2.drill.openTitle}">${cellLabel} ${
|
|
78270
|
+
const labelEl = canDrill ? `<button class="myio-goals-cell-drill" data-action="${state6.level === "month" ? "open-month" : "open-day"}" data-key="${key}" title="${i18n2.drill.openTitle}">${cellLabel} ${icon2("chevron-sm")}</button>` : `<span class="myio-goals-cell-label">${cellLabel}</span>`;
|
|
78253
78271
|
const val = state6.draft[key] !== void 0 ? esc4(state6.draft[key]) : "";
|
|
78254
78272
|
const minAttr = cfg.allowsNegative ? "" : 'min="0"';
|
|
78255
78273
|
return `
|
|
78256
78274
|
<div class="myio-goals-cell">
|
|
78257
78275
|
<div class="myio-goals-cell-head">
|
|
78258
78276
|
${labelEl}
|
|
78259
|
-
${
|
|
78277
|
+
${icon2("pencil-sm")}
|
|
78260
78278
|
</div>
|
|
78261
78279
|
<div class="myio-goals-cell-input">
|
|
78262
78280
|
<input type="number" step="any" ${minAttr} data-cell="${key}" value="${val}" placeholder="\u2014" />
|
|
@@ -78266,7 +78284,7 @@ function openGoalsPanel(params) {
|
|
|
78266
78284
|
</div>`;
|
|
78267
78285
|
}).join("");
|
|
78268
78286
|
const totalLabel = state6.level === "month" ? avg ? i18n2.summary.yearAverage : i18n2.summary.yearTotal : state6.level === "day" ? avg ? i18n2.monthAverage : i18n2.monthTotal : avg ? i18n2.dayAverage : i18n2.dayTotal;
|
|
78269
|
-
const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` :
|
|
78287
|
+
const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon2("sigma");
|
|
78270
78288
|
const total = computedTotal();
|
|
78271
78289
|
return `
|
|
78272
78290
|
<div class="myio-goals-editor">
|
|
@@ -78279,7 +78297,7 @@ function openGoalsPanel(params) {
|
|
|
78279
78297
|
<span class="myio-goals-total-val" id="myio-goals-computed-total">${total === null ? "\u2014" : fmt2(total)}</span>
|
|
78280
78298
|
</div>
|
|
78281
78299
|
<div class="myio-goals-legend">
|
|
78282
|
-
<span>${
|
|
78300
|
+
<span>${icon2("pencil-sm")} ${i18n2.legendEditable}</span>
|
|
78283
78301
|
<span>${glyph} ${i18n2.legendComputed}</span>
|
|
78284
78302
|
</div>
|
|
78285
78303
|
</div>`;
|
|
@@ -78300,12 +78318,12 @@ function openGoalsPanel(params) {
|
|
|
78300
78318
|
const diff = Math.max(0, Date.now() - then);
|
|
78301
78319
|
const s = Math.floor(diff / 1e3);
|
|
78302
78320
|
const m = Math.floor(s / 60);
|
|
78303
|
-
const
|
|
78304
|
-
const d = Math.floor(
|
|
78321
|
+
const h3 = Math.floor(m / 60);
|
|
78322
|
+
const d = Math.floor(h3 / 24);
|
|
78305
78323
|
const T = i18n2.time;
|
|
78306
78324
|
if (s < 60) return T.now;
|
|
78307
78325
|
if (m < 60) return T.min.replace("{n}", m);
|
|
78308
|
-
if (
|
|
78326
|
+
if (h3 < 24) return T.hour.replace("{n}", h3);
|
|
78309
78327
|
if (d < 30) return T.day.replace("{n}", d);
|
|
78310
78328
|
return new Date(iso).toLocaleDateString(locale);
|
|
78311
78329
|
}
|
|
@@ -78314,7 +78332,7 @@ function openGoalsPanel(params) {
|
|
|
78314
78332
|
const history = state6.goals && state6.goals.history || [];
|
|
78315
78333
|
const version2 = state6.goals ? state6.goals.version : 0;
|
|
78316
78334
|
const DETAIL_PREVIEW = 8;
|
|
78317
|
-
const items = history.length === 0 ? `<div class="myio-goals-center myio-goals-center-col myio-goals-hist-empty">${
|
|
78335
|
+
const items = history.length === 0 ? `<div class="myio-goals-center myio-goals-center-col myio-goals-hist-empty">${icon2("clock")}<p>${i18n2.history.empty}</p></div>` : `<ol class="myio-goals-timeline">${history.map((ev, idx) => {
|
|
78318
78336
|
const actor = ev.actor ? `${String(ev.actor).slice(0, 8)}\u2026` : i18n2.history.system;
|
|
78319
78337
|
const extra = ev.bucketCount - (ev.details ? ev.details.length : 0);
|
|
78320
78338
|
const chips = (ev.details || []).slice(0, DETAIL_PREVIEW).map(
|
|
@@ -78323,7 +78341,7 @@ function openGoalsPanel(params) {
|
|
|
78323
78341
|
const more = extra > 0 ? `<span class="myio-goals-tl-more">${i18n2.history.moreDetails.replace("{n}", extra)}</span>` : "";
|
|
78324
78342
|
return `
|
|
78325
78343
|
<li class="myio-goals-tl-item">
|
|
78326
|
-
<span class="myio-goals-tl-dot">${
|
|
78344
|
+
<span class="myio-goals-tl-dot">${icon2(ev.source === "IMPORT" ? "upload-sm" : ev.source === "DELETE" ? "trash-sm" : "pencil-sm")}</span>
|
|
78327
78345
|
<div class="myio-goals-tl-head">
|
|
78328
78346
|
<span class="myio-goals-tl-title">${i18n2.history.source[ev.source] || i18n2.history.source.EDIT}</span>
|
|
78329
78347
|
<span class="myio-goals-tl-ver">v${ev.version}</span>
|
|
@@ -78336,7 +78354,7 @@ function openGoalsPanel(params) {
|
|
|
78336
78354
|
return `
|
|
78337
78355
|
<div class="myio-goals-history">
|
|
78338
78356
|
<div class="myio-goals-history-head">
|
|
78339
|
-
<h3>${
|
|
78357
|
+
<h3>${icon2("clock")} ${i18n2.history.title}</h3>
|
|
78340
78358
|
<span class="myio-goals-history-meta">${i18n2.domains[state6.domain]} \xB7 ${state6.year} \xB7 ${i18n2.currentVersion.replace("{n}", version2)}</span>
|
|
78341
78359
|
</div>
|
|
78342
78360
|
${items}
|
|
@@ -78348,7 +78366,7 @@ function openGoalsPanel(params) {
|
|
|
78348
78366
|
<div class="myio-goals-import-dialog">
|
|
78349
78367
|
<div class="myio-goals-import-card">
|
|
78350
78368
|
<div class="myio-goals-import-header">
|
|
78351
|
-
<span class="myio-goals-import-icon">${
|
|
78369
|
+
<span class="myio-goals-import-icon">${icon2("upload")}</span>
|
|
78352
78370
|
<div>
|
|
78353
78371
|
<h3>${i18n2.import.title}</h3>
|
|
78354
78372
|
<p>${i18n2.import.subtitle.replace("{domain}", i18n2.domains[state6.domain]).replace("{year}", state6.year)}</p>
|
|
@@ -78383,9 +78401,9 @@ ${state6.year}-03-15T08,15`;
|
|
|
78383
78401
|
<div class="myio-goals-import-inputhead">
|
|
78384
78402
|
<label>${i18n2.import.csvLabel}</label>
|
|
78385
78403
|
<div class="myio-goals-import-links">
|
|
78386
|
-
<button data-action="download-template">${
|
|
78387
|
-
<button data-action="download-hourly">${
|
|
78388
|
-
<button data-action="import-upload">${
|
|
78404
|
+
<button data-action="download-template">${icon2("download")} ${i18n2.import.downloadTemplate}</button>
|
|
78405
|
+
<button data-action="download-hourly">${icon2("download")} ${i18n2.import.downloadHourlyExample}</button>
|
|
78406
|
+
<button data-action="import-upload">${icon2("upload")} ${i18n2.import.uploadFile}</button>
|
|
78389
78407
|
<input type="file" id="myio-goals-csv-file" accept=".csv,.txt,text/csv,text/plain" style="display:none" />
|
|
78390
78408
|
</div>
|
|
78391
78409
|
</div>
|
|
@@ -78398,22 +78416,22 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78398
78416
|
</div>`;
|
|
78399
78417
|
}
|
|
78400
78418
|
if (state6.saveError && state6.conflictVersion === null) {
|
|
78401
|
-
html += `<div class="myio-goals-alert myio-goals-alert-red">${
|
|
78419
|
+
html += `<div class="myio-goals-alert myio-goals-alert-red">${icon2("alert")} ${esc4(state6.saveError)}</div>`;
|
|
78402
78420
|
}
|
|
78403
78421
|
if (state6.conflictVersion !== null) {
|
|
78404
|
-
html += `<div class="myio-goals-alert myio-goals-alert-amber">${
|
|
78422
|
+
html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon2("alert")} ${i18n2.import.conflict}</div>`;
|
|
78405
78423
|
}
|
|
78406
78424
|
if (result) html += renderImportSummary(result, counts);
|
|
78407
78425
|
return html;
|
|
78408
78426
|
}
|
|
78409
78427
|
function renderImportSummary(result, counts) {
|
|
78410
78428
|
const persisted = result.dryRun === false;
|
|
78411
|
-
const badge = persisted ? `<span class="myio-goals-chip myio-goals-chip-accent">${
|
|
78429
|
+
const badge = persisted ? `<span class="myio-goals-chip myio-goals-chip-accent">${icon2("check")} ${i18n2.import.appliedBadge.replace("{version}", result.version || 0)}</span>` : `<span class="myio-goals-chip myio-goals-chip-mono">${i18n2.import.previewBadge}</span>`;
|
|
78412
78430
|
let html = `
|
|
78413
78431
|
<div class="myio-goals-import-summary">
|
|
78414
78432
|
<div class="myio-goals-import-counts">
|
|
78415
|
-
<span class="myio-goals-chip myio-goals-chip-accent">${
|
|
78416
|
-
${result.errorCount > 0 ? `<span class="myio-goals-chip myio-goals-chip-red">${
|
|
78433
|
+
<span class="myio-goals-chip myio-goals-chip-accent">${icon2("check")} ${i18n2.import.okCount.replace("{n}", result.okCount)}</span>
|
|
78434
|
+
${result.errorCount > 0 ? `<span class="myio-goals-chip myio-goals-chip-red">${icon2("alert")} ${i18n2.import.errorCount.replace("{n}", result.errorCount)}</span>` : ""}
|
|
78417
78435
|
${badge}
|
|
78418
78436
|
</div>`;
|
|
78419
78437
|
if (!persisted && counts && result.okCount > 0) {
|
|
@@ -78427,7 +78445,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78427
78445
|
<div class="myio-goals-import-diags">
|
|
78428
78446
|
<p class="myio-goals-import-diags-title">${i18n2.import.diagnosticsTitle}</p>
|
|
78429
78447
|
<ul>${result.diagnostics.map(
|
|
78430
|
-
(d) => `<li>${
|
|
78448
|
+
(d) => `<li>${icon2("alert-sm")} <span><span class="myio-goals-diag-line">${i18n2.import.line.replace("{line}", d.line)}</span>${d.bucket ? ` <span class="myio-goals-diag-bucket">[${esc4(d.bucket)}]</span>` : ""} ${esc4(d.reason)}</span></li>`
|
|
78431
78449
|
).join("")}</ul>
|
|
78432
78450
|
</div>`;
|
|
78433
78451
|
}
|
|
@@ -78447,7 +78465,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78447
78465
|
}
|
|
78448
78466
|
const canPreview = state6.csv.trim().length > 0 && !state6.saving;
|
|
78449
78467
|
const canConfirm = !!state6.importPreview && state6.importPreview.okCount > 0 && !state6.saving && !state6.importApplied;
|
|
78450
|
-
const right = state6.importPreview ? `<button class="myio-goals-btn myio-goals-btn-primary" data-action="import-confirm" ${canConfirm ? "" : "disabled"}>${
|
|
78468
|
+
const right = state6.importPreview ? `<button class="myio-goals-btn myio-goals-btn-primary" data-action="import-confirm" ${canConfirm ? "" : "disabled"}>${icon2("upload")} ${i18n2.import.confirm.replace("{n}", state6.importPreview.okCount)}</button>` : `<button class="myio-goals-btn myio-goals-btn-primary" data-action="import-preview" ${canPreview ? "" : "disabled"}>${icon2("upload")} ${i18n2.import.preview}</button>`;
|
|
78451
78469
|
return `
|
|
78452
78470
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="import-close" ${state6.saving ? "disabled" : ""}>${i18n2.import.cancel}</button>
|
|
78453
78471
|
${right}`;
|
|
@@ -78459,7 +78477,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78459
78477
|
if (body) body.innerHTML = renderImportInner();
|
|
78460
78478
|
if (footer) footer.innerHTML = renderImportFooter();
|
|
78461
78479
|
}
|
|
78462
|
-
function
|
|
78480
|
+
function icon2(name) {
|
|
78463
78481
|
const S2 = (p2) => `<svg class="myio-goals-ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${p2}</svg>`;
|
|
78464
78482
|
switch (name) {
|
|
78465
78483
|
case "target":
|
|
@@ -82001,7 +82019,7 @@ var EnergySummaryTooltip = {
|
|
|
82001
82019
|
}))
|
|
82002
82020
|
});
|
|
82003
82021
|
categories.forEach((cat, catIndex) => {
|
|
82004
|
-
const
|
|
82022
|
+
const icon2 = CATEGORY_ICONS[cat.id] || CATEGORY_ICONS.outros;
|
|
82005
82023
|
const hasChildren = cat.children && cat.children.length > 0;
|
|
82006
82024
|
const hasShoppingBreakdown = cat.byShoppingBreakdown && cat.byShoppingBreakdown.length > 0;
|
|
82007
82025
|
const isExpandable = hasChildren || hasShoppingBreakdown;
|
|
@@ -82011,7 +82029,7 @@ var EnergySummaryTooltip = {
|
|
|
82011
82029
|
${isExpandable ? `
|
|
82012
82030
|
<button class="energy-summary-tooltip__expand-toggle" data-target="cat-${catIndex}" title="Expandir">+</button>
|
|
82013
82031
|
` : ""}
|
|
82014
|
-
<span class="energy-summary-tooltip__category-icon">${
|
|
82032
|
+
<span class="energy-summary-tooltip__category-icon">${icon2}</span>
|
|
82015
82033
|
<span>${cat.name}</span>
|
|
82016
82034
|
</span>
|
|
82017
82035
|
<span class="energy-summary-tooltip__category-count">${cat.deviceCount}</span>
|
|
@@ -82678,10 +82696,10 @@ var EnergySummaryTooltip = {
|
|
|
82678
82696
|
return;
|
|
82679
82697
|
}
|
|
82680
82698
|
this._cancelDevicePopupDelayedHide();
|
|
82681
|
-
const
|
|
82699
|
+
const icon2 = this._getStatusIcon(statusKey);
|
|
82682
82700
|
const content = this._buildDeviceListContent(statusKey, label, count);
|
|
82683
82701
|
InfoTooltip2.show(triggerElement, {
|
|
82684
|
-
icon,
|
|
82702
|
+
icon: icon2,
|
|
82685
82703
|
title: `${label} (${count})`,
|
|
82686
82704
|
content
|
|
82687
82705
|
});
|
|
@@ -83995,7 +84013,7 @@ var WaterSummaryTooltip = {
|
|
|
83995
84013
|
return html;
|
|
83996
84014
|
}
|
|
83997
84015
|
categories.forEach((cat, catIndex) => {
|
|
83998
|
-
const
|
|
84016
|
+
const icon2 = WATER_CATEGORY_ICONS[cat.id] || WATER_CATEGORY_ICONS.areaComum;
|
|
83999
84017
|
const hasChildren = cat.children && cat.children.length > 0;
|
|
84000
84018
|
const hasShoppingBreakdown = cat.byShoppingBreakdown && cat.byShoppingBreakdown.length > 0;
|
|
84001
84019
|
const isExpandable = hasChildren || hasShoppingBreakdown;
|
|
@@ -84005,7 +84023,7 @@ var WaterSummaryTooltip = {
|
|
|
84005
84023
|
${isExpandable ? `
|
|
84006
84024
|
<button class="water-summary-tooltip__expand-toggle" data-target="water-cat-${catIndex}" title="Expandir">+</button>
|
|
84007
84025
|
` : ""}
|
|
84008
|
-
<span class="water-summary-tooltip__category-icon">${
|
|
84026
|
+
<span class="water-summary-tooltip__category-icon">${icon2}</span>
|
|
84009
84027
|
<span>${cat.name}</span>
|
|
84010
84028
|
</span>
|
|
84011
84029
|
<span class="water-summary-tooltip__category-count">${cat.deviceCount}</span>
|
|
@@ -84603,10 +84621,10 @@ var WaterSummaryTooltip = {
|
|
|
84603
84621
|
return;
|
|
84604
84622
|
}
|
|
84605
84623
|
this._cancelDevicePopupDelayedHide();
|
|
84606
|
-
const
|
|
84624
|
+
const icon2 = this._getStatusIcon(statusKey);
|
|
84607
84625
|
const content = this._buildDeviceListContent(statusKey, label, count);
|
|
84608
84626
|
InfoTooltip2.show(triggerElement, {
|
|
84609
|
-
icon,
|
|
84627
|
+
icon: icon2,
|
|
84610
84628
|
title: `${label} (${count})`,
|
|
84611
84629
|
content
|
|
84612
84630
|
});
|
|
@@ -86198,10 +86216,10 @@ function generateContentHTML(data) {
|
|
|
86198
86216
|
<div class="myio-temp-sensor-tooltip__list">
|
|
86199
86217
|
${displayDevices.map((d) => {
|
|
86200
86218
|
const statusClass = d.status === "ok" ? "ok" : d.status === "warn" ? "warn" : "unknown";
|
|
86201
|
-
const
|
|
86219
|
+
const icon2 = d.status === "ok" ? "\u2714" : d.status === "warn" ? "\u26A0" : "?";
|
|
86202
86220
|
return `
|
|
86203
86221
|
<div class="myio-temp-sensor-tooltip__list-item myio-temp-sensor-tooltip__list-item--${statusClass}">
|
|
86204
|
-
<span class="myio-temp-sensor-tooltip__list-icon">${
|
|
86222
|
+
<span class="myio-temp-sensor-tooltip__list-icon">${icon2}</span>
|
|
86205
86223
|
<span class="myio-temp-sensor-tooltip__list-name">${d.name}</span>
|
|
86206
86224
|
<span class="myio-temp-sensor-tooltip__list-value">${d.temp.toFixed(1)}\xB0C</span>
|
|
86207
86225
|
</div>
|
|
@@ -87059,7 +87077,7 @@ function generateHeaderHTML5(data) {
|
|
|
87059
87077
|
</div>
|
|
87060
87078
|
`;
|
|
87061
87079
|
}
|
|
87062
|
-
function generateDomainHTML(domain,
|
|
87080
|
+
function generateDomainHTML(domain, icon2, name, counts, isTemperature = false) {
|
|
87063
87081
|
const isExpanded = state5.expandedDomains.has(domain);
|
|
87064
87082
|
const expandedClass = isExpanded ? "expanded" : "";
|
|
87065
87083
|
let detailsHTML = "";
|
|
@@ -87096,7 +87114,7 @@ function generateDomainHTML(domain, icon, name, counts, isTemperature = false) {
|
|
|
87096
87114
|
<div class="myio-contract-summary-tooltip__domain ${expandedClass}" data-domain="${domain}">
|
|
87097
87115
|
<div class="myio-contract-summary-tooltip__domain-header" data-toggle-domain="${domain}">
|
|
87098
87116
|
<div class="myio-contract-summary-tooltip__domain-info">
|
|
87099
|
-
<span class="myio-contract-summary-tooltip__domain-icon">${
|
|
87117
|
+
<span class="myio-contract-summary-tooltip__domain-icon">${icon2}</span>
|
|
87100
87118
|
<span class="myio-contract-summary-tooltip__domain-name">${name}</span>
|
|
87101
87119
|
</div>
|
|
87102
87120
|
<div style="display: flex; align-items: center; gap: 8px;">
|
|
@@ -93236,11 +93254,11 @@ function renderRow(row, level) {
|
|
|
93236
93254
|
const pct = row.pct;
|
|
93237
93255
|
const caret = hasChildren ? `<button class="myio-gbt__caret${open ? " is-open" : ""}" data-caret="${id}" title="Expandir/recolher">\u25B8</button>` : `<span class="myio-gbt__caret-spacer"></span>`;
|
|
93238
93256
|
const swatch = row.color ? `<span class="myio-gbt__swatch" style="background:${esc6(row.color)}"></span>` : "";
|
|
93239
|
-
const
|
|
93257
|
+
const icon2 = row.icon ? `<span class="myio-gbt__icon">${esc6(row.icon)}</span>` : "";
|
|
93240
93258
|
const chipHtml = row.delta ? renderDeltaChip(row.delta) : "";
|
|
93241
93259
|
const pctHtml = !row.delta && pct != null && isFinite(pct) ? `<span class="myio-gbt__pct">${esc6(fmtPct3(pct))}</span>` : "";
|
|
93242
93260
|
const rowClass = level > 0 ? "myio-gbt__row myio-gbt__row--child" : "myio-gbt__row";
|
|
93243
|
-
let html = `<div class="${rowClass}">` + caret + swatch +
|
|
93261
|
+
let html = `<div class="${rowClass}">` + caret + swatch + icon2 + `<span class="myio-gbt__label">${esc6(row.label)}</span><span class="myio-gbt__value">${esc6(row.valueText)}</span>` + chipHtml + pctHtml + `</div>`;
|
|
93244
93262
|
if (hasChildren) {
|
|
93245
93263
|
const childHtml = row.children.map((c) => renderRow(c, level + 1)).join("");
|
|
93246
93264
|
html += `<div class="myio-gbt__children${open ? " is-open" : ""}" data-children="${id}">${childHtml}</div>`;
|
|
@@ -93275,16 +93293,16 @@ function createGoalsBarTooltip(opts) {
|
|
|
93275
93293
|
function positionAt(clientX, clientY) {
|
|
93276
93294
|
const rect = el2.getBoundingClientRect();
|
|
93277
93295
|
const w = rect.width || 280;
|
|
93278
|
-
const
|
|
93296
|
+
const h3 = rect.height || 200;
|
|
93279
93297
|
const pad = 12;
|
|
93280
93298
|
const gap = 16;
|
|
93281
93299
|
let left = clientX + gap;
|
|
93282
93300
|
let top = clientY + gap;
|
|
93283
93301
|
if (left + w > window.innerWidth - pad) left = clientX - w - gap;
|
|
93284
93302
|
if (left < pad) left = Math.max(pad, (window.innerWidth - w) / 2);
|
|
93285
|
-
if (top +
|
|
93303
|
+
if (top + h3 > window.innerHeight - pad) top = clientY - h3 - gap;
|
|
93286
93304
|
if (top < pad) top = pad;
|
|
93287
|
-
if (top +
|
|
93305
|
+
if (top + h3 > window.innerHeight - pad) top = Math.max(pad, window.innerHeight - h3 - pad);
|
|
93288
93306
|
el2.style.left = `${Math.round(left)}px`;
|
|
93289
93307
|
el2.style.top = `${Math.round(top)}px`;
|
|
93290
93308
|
}
|
|
@@ -93524,13 +93542,13 @@ function _buildDayBoundaries(startISO, endISO) {
|
|
|
93524
93542
|
}
|
|
93525
93543
|
function _buildHourBoundaries(dateISO) {
|
|
93526
93544
|
const result = [];
|
|
93527
|
-
for (let
|
|
93545
|
+
for (let h3 = 0; h3 < 24; h3++) {
|
|
93528
93546
|
const start = /* @__PURE__ */ new Date(`${dateISO}T00:00:00`);
|
|
93529
|
-
start.setHours(
|
|
93547
|
+
start.setHours(h3, 0, 0, 0);
|
|
93530
93548
|
const end = new Date(start);
|
|
93531
|
-
end.setHours(
|
|
93549
|
+
end.setHours(h3, 59, 59, 999);
|
|
93532
93550
|
result.push({
|
|
93533
|
-
label: `${String(
|
|
93551
|
+
label: `${String(h3).padStart(2, "0")}h`,
|
|
93534
93552
|
startTs: start.getTime(),
|
|
93535
93553
|
endTs: end.getTime()
|
|
93536
93554
|
});
|
|
@@ -96905,7 +96923,7 @@ var MODE_DEFAULTS = {
|
|
|
96905
96923
|
}
|
|
96906
96924
|
};
|
|
96907
96925
|
function mixHex2(hexA, hexB, pctB) {
|
|
96908
|
-
const n = (
|
|
96926
|
+
const n = (h3) => parseInt(h3.slice(1), 16);
|
|
96909
96927
|
const a = n(hexA);
|
|
96910
96928
|
const b = n(hexB);
|
|
96911
96929
|
const ch = (sa, sb) => Math.round(sa + (sb - sa) * pctB);
|
|
@@ -97851,11 +97869,11 @@ var TariffApiClient = class {
|
|
|
97851
97869
|
this.basePath = config2.basePath ?? "api/v1";
|
|
97852
97870
|
}
|
|
97853
97871
|
authHeaders() {
|
|
97854
|
-
const
|
|
97855
|
-
if (this.cfg.apiKey)
|
|
97856
|
-
if (this.cfg.jwt)
|
|
97857
|
-
if (this.cfg.tenantId)
|
|
97858
|
-
return
|
|
97872
|
+
const h3 = {};
|
|
97873
|
+
if (this.cfg.apiKey) h3["X-API-Key"] = this.cfg.apiKey;
|
|
97874
|
+
if (this.cfg.jwt) h3["Authorization"] = `Bearer ${this.cfg.jwt}`;
|
|
97875
|
+
if (this.cfg.tenantId) h3["X-Tenant-Id"] = this.cfg.tenantId;
|
|
97876
|
+
return h3;
|
|
97859
97877
|
}
|
|
97860
97878
|
/** Read the tariff tree. `granularity` defaults to `day` server-side. */
|
|
97861
97879
|
async getTariff(sel, granularity = "hour") {
|
|
@@ -98117,7 +98135,7 @@ function bandToPanelEntry(band, customerId) {
|
|
|
98117
98135
|
function expandDayToHourBuckets(date, price) {
|
|
98118
98136
|
assertValidCivilDate(date);
|
|
98119
98137
|
const out = [];
|
|
98120
|
-
for (let
|
|
98138
|
+
for (let h3 = 0; h3 < 24; h3++) out.push({ level: "HOUR", ref: `${date}T${pad23(h3)}`, price });
|
|
98121
98139
|
return out;
|
|
98122
98140
|
}
|
|
98123
98141
|
function expandBandHours(date, startHour, endHour, price) {
|
|
@@ -98126,7 +98144,7 @@ function expandBandHours(date, startHour, endHour, price) {
|
|
|
98126
98144
|
throw new Error(`Invalid hour band ${startHour}-${endHour} for ${date}`);
|
|
98127
98145
|
}
|
|
98128
98146
|
const out = [];
|
|
98129
|
-
for (let
|
|
98147
|
+
for (let h3 = startHour; h3 <= endHour; h3++) out.push({ level: "HOUR", ref: `${date}T${pad23(h3)}`, price });
|
|
98130
98148
|
return out;
|
|
98131
98149
|
}
|
|
98132
98150
|
function bandDateBounds(band) {
|
|
@@ -98176,12 +98194,12 @@ function expandBandToHourBucketsByYear(band) {
|
|
|
98176
98194
|
function collapseHoursToBands(date, hours, dims) {
|
|
98177
98195
|
const sorted = [...hours].sort((a, b) => a.hour - b.hour);
|
|
98178
98196
|
const runs = [];
|
|
98179
|
-
for (const
|
|
98197
|
+
for (const h3 of sorted) {
|
|
98180
98198
|
const cur = runs[runs.length - 1];
|
|
98181
|
-
if (cur &&
|
|
98182
|
-
cur.endHour =
|
|
98199
|
+
if (cur && h3.hour === cur.endHour + 1 && h3.price === cur.price) {
|
|
98200
|
+
cur.endHour = h3.hour;
|
|
98183
98201
|
} else {
|
|
98184
|
-
runs.push({ startHour:
|
|
98202
|
+
runs.push({ startHour: h3.hour, endHour: h3.hour, price: h3.price });
|
|
98185
98203
|
}
|
|
98186
98204
|
}
|
|
98187
98205
|
return runs.map(
|
|
@@ -98201,13 +98219,13 @@ function dayNodeToHours(node) {
|
|
|
98201
98219
|
const hourly = node.hourly || {};
|
|
98202
98220
|
const hourKeys = Object.keys(hourly);
|
|
98203
98221
|
if (hourKeys.length === 0) {
|
|
98204
|
-
return dayPrice != null ? Array.from({ length: 24 }, (_,
|
|
98222
|
+
return dayPrice != null ? Array.from({ length: 24 }, (_, h3) => ({ hour: h3, price: dayPrice })) : null;
|
|
98205
98223
|
}
|
|
98206
98224
|
const out = [];
|
|
98207
|
-
for (let
|
|
98208
|
-
const ov = hourly[String(
|
|
98225
|
+
for (let h3 = 0; h3 < 24; h3++) {
|
|
98226
|
+
const ov = hourly[String(h3)];
|
|
98209
98227
|
const price = ov && typeof ov.price === "string" ? ov.price : dayPrice;
|
|
98210
|
-
if (price != null) out.push({ hour:
|
|
98228
|
+
if (price != null) out.push({ hour: h3, price });
|
|
98211
98229
|
}
|
|
98212
98230
|
return out.length ? out : null;
|
|
98213
98231
|
}
|
|
@@ -98994,11 +99012,11 @@ var GoalsMoneyClient = class {
|
|
|
98994
99012
|
this.basePath = config2.basePath ?? "api/v1";
|
|
98995
99013
|
}
|
|
98996
99014
|
authHeaders() {
|
|
98997
|
-
const
|
|
98998
|
-
if (this.cfg.apiKey)
|
|
98999
|
-
if (this.cfg.jwt)
|
|
99000
|
-
if (this.cfg.tenantId)
|
|
99001
|
-
return
|
|
99015
|
+
const h3 = {};
|
|
99016
|
+
if (this.cfg.apiKey) h3["X-API-Key"] = this.cfg.apiKey;
|
|
99017
|
+
if (this.cfg.jwt) h3["Authorization"] = `Bearer ${this.cfg.jwt}`;
|
|
99018
|
+
if (this.cfg.tenantId) h3["X-Tenant-Id"] = this.cfg.tenantId;
|
|
99019
|
+
return h3;
|
|
99002
99020
|
}
|
|
99003
99021
|
goalsPath(sel) {
|
|
99004
99022
|
return `/customers/${encodeURIComponent(sel.customerId)}/goals`;
|
|
@@ -103905,14 +103923,14 @@ function renderLojasStep3(state6, modalId, colors2, t) {
|
|
|
103905
103923
|
}
|
|
103906
103924
|
function renderAttrRow(key, value, readonly, suggestion, colors2, modalId, t, isFetchable = false, helpText) {
|
|
103907
103925
|
const hasValue = value !== null && value !== void 0 && value !== "";
|
|
103908
|
-
const
|
|
103926
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
103909
103927
|
const inputBorder = hasValue ? colors2.border : colors2.warning;
|
|
103910
103928
|
return `
|
|
103911
103929
|
<div style="
|
|
103912
103930
|
display: flex; align-items: center; gap: 12px;
|
|
103913
103931
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
103914
103932
|
">
|
|
103915
|
-
<span style="font-size: 16px;">${
|
|
103933
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
103916
103934
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
|
|
103917
103935
|
${key}
|
|
103918
103936
|
${helpText ? `<span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>` : ""}
|
|
@@ -103947,7 +103965,7 @@ function renderAttrRow(key, value, readonly, suggestion, colors2, modalId, t, is
|
|
|
103947
103965
|
}
|
|
103948
103966
|
function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
|
|
103949
103967
|
const hasValue = !!value;
|
|
103950
|
-
const
|
|
103968
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
103951
103969
|
const options = [
|
|
103952
103970
|
"3F_MEDIDOR",
|
|
103953
103971
|
"HIDROMETRO",
|
|
@@ -103966,7 +103984,7 @@ function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
|
|
|
103966
103984
|
display: flex; align-items: center; gap: 12px;
|
|
103967
103985
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
103968
103986
|
">
|
|
103969
|
-
<span style="font-size: 16px;">${
|
|
103987
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
103970
103988
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500;">deviceType</span>
|
|
103971
103989
|
<div style="flex: 1;">
|
|
103972
103990
|
<select id="${modalId}-deviceType" style="
|
|
@@ -103992,7 +104010,7 @@ function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
|
|
|
103992
104010
|
}
|
|
103993
104011
|
function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
|
|
103994
104012
|
const hasValue = !!value;
|
|
103995
|
-
const
|
|
104013
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
103996
104014
|
const profiles = getSuggestedProfiles(deviceType);
|
|
103997
104015
|
const helpText = "IMPORTANTE: deviceType + deviceProfile definem o tipo do device. Se ambos = 3F_MEDIDOR \u2192 device \xE9 LOJA (energia). Se ambos = HIDROMETRO \u2192 device \xE9 LOJA (\xE1gua).";
|
|
103998
104016
|
return `
|
|
@@ -104000,7 +104018,7 @@ function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
|
|
|
104000
104018
|
display: flex; align-items: center; gap: 12px;
|
|
104001
104019
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
104002
104020
|
">
|
|
104003
|
-
<span style="font-size: 16px;">${
|
|
104021
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
104004
104022
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
|
|
104005
104023
|
deviceProfile
|
|
104006
104024
|
<span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>
|
|
@@ -104021,7 +104039,7 @@ function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
|
|
|
104021
104039
|
}
|
|
104022
104040
|
function renderEntityLabelRow(currentLabel, deviceName, colors2, modalId, t) {
|
|
104023
104041
|
const hasValue = !!currentLabel;
|
|
104024
|
-
const
|
|
104042
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
104025
104043
|
const suggestedValue = currentLabel || deviceName;
|
|
104026
104044
|
const helpText = "Etiqueta do dispositivo (entityLabel) - aparece no nome exibido da entidade no ThingsBoard";
|
|
104027
104045
|
return `
|
|
@@ -104029,7 +104047,7 @@ function renderEntityLabelRow(currentLabel, deviceName, colors2, modalId, t) {
|
|
|
104029
104047
|
display: flex; align-items: center; gap: 12px;
|
|
104030
104048
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
104031
104049
|
">
|
|
104032
|
-
<span style="font-size: 16px;">${
|
|
104050
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
104033
104051
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
|
|
104034
104052
|
etiqueta
|
|
104035
104053
|
<span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>
|
|
@@ -104303,8 +104321,8 @@ async function openClearGcdrIdsModal(state6) {
|
|
|
104303
104321
|
</div>
|
|
104304
104322
|
</div>`;
|
|
104305
104323
|
}
|
|
104306
|
-
function keyBadges(
|
|
104307
|
-
return keys.filter((k) =>
|
|
104324
|
+
function keyBadges(present2, keys) {
|
|
104325
|
+
return keys.filter((k) => present2[k]).map((k) => `<span style="font-size:9px; background:rgba(220,38,38,0.25); color:#fca5a5; padding:1px 5px; border-radius:3px; margin:1px; display:inline-block;">${k}</span>`).join("");
|
|
104308
104326
|
}
|
|
104309
104327
|
function tableHtml(rows, keys) {
|
|
104310
104328
|
if (rows.length === 0) return '<div style="font-size:12px;color:#6b7280;padding:6px 0;">Nenhum item a limpar.</div>';
|
|
@@ -104365,13 +104383,13 @@ async function openClearGcdrIdsModal(state6) {
|
|
|
104365
104383
|
await Promise.all(chunks[ci].map(async (entity) => {
|
|
104366
104384
|
const tbId = entity.id?.id || "";
|
|
104367
104385
|
const name = entity.name || entity.label || tbId;
|
|
104368
|
-
let
|
|
104386
|
+
let present2 = {};
|
|
104369
104387
|
try {
|
|
104370
104388
|
const attrs = await fetchAttrs(tbId);
|
|
104371
|
-
for (const k of keysToCheck)
|
|
104389
|
+
for (const k of keysToCheck) present2[k] = attrs[k] != null && attrs[k] !== "";
|
|
104372
104390
|
} catch {
|
|
104373
104391
|
}
|
|
104374
|
-
targetRows.push({ tbId, name, entityType, present, hasAny: keysToCheck.some((k) =>
|
|
104392
|
+
targetRows.push({ tbId, name, entityType, present: present2, hasAny: keysToCheck.some((k) => present2[k]) });
|
|
104375
104393
|
}));
|
|
104376
104394
|
const done = deviceRows.length + assetRows.length;
|
|
104377
104395
|
const bodyEl = overlay.querySelector("#gcdr-clear-body");
|
|
@@ -107781,6 +107799,2089 @@ function openGenericModal(params) {
|
|
|
107781
107799
|
};
|
|
107782
107800
|
}
|
|
107783
107801
|
|
|
107802
|
+
// src/components/myio-gcdr-login/dom.ts
|
|
107803
|
+
function h2(doc, tag, attrs = {}, ...children) {
|
|
107804
|
+
const el2 = doc.createElement(tag);
|
|
107805
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
107806
|
+
if (v === null || v === void 0 || v === false) continue;
|
|
107807
|
+
if (k === "class") el2.className = String(v);
|
|
107808
|
+
else if (k === "text") el2.textContent = String(v);
|
|
107809
|
+
else el2.setAttribute(k, v === true ? "" : String(v));
|
|
107810
|
+
}
|
|
107811
|
+
for (const c of children) {
|
|
107812
|
+
if (c === null || c === void 0 || c === false) continue;
|
|
107813
|
+
el2.appendChild(typeof c === "string" ? doc.createTextNode(c) : c);
|
|
107814
|
+
}
|
|
107815
|
+
return el2;
|
|
107816
|
+
}
|
|
107817
|
+
function icon(doc, markup, cls) {
|
|
107818
|
+
const span = doc.createElement("span");
|
|
107819
|
+
if (cls) span.className = cls;
|
|
107820
|
+
span.setAttribute("aria-hidden", "true");
|
|
107821
|
+
span.innerHTML = markup;
|
|
107822
|
+
return span;
|
|
107823
|
+
}
|
|
107824
|
+
function safeCall(label, fn, ...args) {
|
|
107825
|
+
if (!fn) return;
|
|
107826
|
+
try {
|
|
107827
|
+
const r = fn(...args);
|
|
107828
|
+
if (r && typeof r.catch === "function") {
|
|
107829
|
+
r.catch(() => console.error(`[MYIO Login] ${label} failed`));
|
|
107830
|
+
}
|
|
107831
|
+
} catch {
|
|
107832
|
+
console.error(`[MYIO Login] ${label} failed`);
|
|
107833
|
+
}
|
|
107834
|
+
}
|
|
107835
|
+
function storageGet(key) {
|
|
107836
|
+
try {
|
|
107837
|
+
return typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
|
|
107838
|
+
} catch {
|
|
107839
|
+
return null;
|
|
107840
|
+
}
|
|
107841
|
+
}
|
|
107842
|
+
function storageSet(key, value) {
|
|
107843
|
+
try {
|
|
107844
|
+
if (typeof localStorage === "undefined") return;
|
|
107845
|
+
if (value === null) localStorage.removeItem(key);
|
|
107846
|
+
else localStorage.setItem(key, value);
|
|
107847
|
+
} catch {
|
|
107848
|
+
}
|
|
107849
|
+
}
|
|
107850
|
+
function prefersDark() {
|
|
107851
|
+
try {
|
|
107852
|
+
return typeof matchMedia === "function" && matchMedia("(prefers-color-scheme: dark)").matches;
|
|
107853
|
+
} catch {
|
|
107854
|
+
return false;
|
|
107855
|
+
}
|
|
107856
|
+
}
|
|
107857
|
+
function isCoarsePointer() {
|
|
107858
|
+
try {
|
|
107859
|
+
return typeof matchMedia === "function" && matchMedia("(pointer: coarse)").matches;
|
|
107860
|
+
} catch {
|
|
107861
|
+
return false;
|
|
107862
|
+
}
|
|
107863
|
+
}
|
|
107864
|
+
|
|
107865
|
+
// src/components/myio-gcdr-login/icons.ts
|
|
107866
|
+
var svg = (body, size = 16) => `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${body}</svg>`;
|
|
107867
|
+
var ICONS = {
|
|
107868
|
+
eye: (s) => svg('<path d="M2.06 12.35a1 1 0 0 1 0-.7 10.75 10.75 0 0 1 19.88 0 1 1 0 0 1 0 .7 10.75 10.75 0 0 1-19.88 0"/><circle cx="12" cy="12" r="3"/>', s),
|
|
107869
|
+
eyeOff: (s) => svg('<path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c4.97 0 8.9 3.12 10 7a10.7 10.7 0 0 1-1.67 3.13"/><path d="M14.08 14.16a3 3 0 1 1-4.24-4.24"/><path d="M17.48 17.5A10.7 10.7 0 0 1 12 19c-4.97 0-8.9-3.12-10-7a10.7 10.7 0 0 1 4.52-5.5"/><path d="m2 2 20 20"/>', s),
|
|
107870
|
+
lock: (s) => svg('<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>', s),
|
|
107871
|
+
shieldAlert: (s) => svg('<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/><path d="M12 8v4"/><path d="M12 16h.01"/>', s),
|
|
107872
|
+
alert: (s) => svg('<circle cx="12" cy="12" r="10"/><line x1="12" x2="12" y1="8" y2="12"/><line x1="12" x2="12.01" y1="16" y2="16"/>', s),
|
|
107873
|
+
info: (s) => svg('<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>', s),
|
|
107874
|
+
sun: (s) => svg('<circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/>', s),
|
|
107875
|
+
moon: (s) => svg('<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>', s),
|
|
107876
|
+
globe: (s) => svg('<circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/>', s),
|
|
107877
|
+
x: (s) => svg('<path d="M18 6 6 18"/><path d="m6 6 12 12"/>', s),
|
|
107878
|
+
arrowLeft: (s) => svg('<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>', s),
|
|
107879
|
+
chevronRight: (s) => svg('<path d="m9 18 6-6-6-6"/>', s),
|
|
107880
|
+
external: (s) => svg('<path d="M7 7h10v10"/><path d="M7 17 17 7"/>', s),
|
|
107881
|
+
book: (s) => svg('<path d="M4 19.5v-15A2.5 2.5 0 0 1 6.5 2H20v20H6.5a2.5 2.5 0 0 1 0-5H20"/>', s),
|
|
107882
|
+
headset: (s) => svg('<path d="M3 11h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-5Zm0 0a9 9 0 1 1 18 0m0 0v5a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3Z"/><path d="M21 16v2a4 4 0 0 1-4 4h-5"/>', s),
|
|
107883
|
+
plug: (s) => svg('<path d="M12 22v-5"/><path d="M9 8V2"/><path d="M15 8V2"/><path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/>', s),
|
|
107884
|
+
grid: (s) => svg('<rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/>', s),
|
|
107885
|
+
building: (s) => svg('<rect width="16" height="20" x="4" y="2" rx="2" ry="2"/><path d="M9 22v-4h6v4"/><path d="M8 6h.01"/><path d="M16 6h.01"/><path d="M12 6h.01"/><path d="M12 10h.01"/><path d="M12 14h.01"/><path d="M16 10h.01"/><path d="M16 14h.01"/><path d="M8 10h.01"/><path d="M8 14h.01"/>', s),
|
|
107886
|
+
activity: (s) => svg('<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"/>', s),
|
|
107887
|
+
spinner: (s) => svg('<path d="M21 12a9 9 0 1 1-6.219-8.56"/>', s)
|
|
107888
|
+
};
|
|
107889
|
+
|
|
107890
|
+
// src/components/myio-gcdr-login/about.ts
|
|
107891
|
+
var CATEGORIES = [
|
|
107892
|
+
{ key: "wiki", icon: "book", items: [
|
|
107893
|
+
{ key: "wikiHome", to: "/wiki/p", web: true },
|
|
107894
|
+
{ key: "wikiSearch", to: "/wiki/p/search", web: true },
|
|
107895
|
+
{ key: "accountGuide", to: "/wiki/p/User-Guides/acesso-a-conta", web: true }
|
|
107896
|
+
] },
|
|
107897
|
+
{ key: "support", icon: "headset", items: [
|
|
107898
|
+
{ key: "openTicket", to: "/support", web: true },
|
|
107899
|
+
{ key: "forgotPassword", to: "/forgot-password", web: true }
|
|
107900
|
+
] },
|
|
107901
|
+
{ key: "integrations", icon: "plug", items: [
|
|
107902
|
+
{ key: "docsAlarms", to: "https://alarms-api.a.myio-bas.com/docs" },
|
|
107903
|
+
{ key: "docsGcdr", to: "https://gcdr-api.a.myio-bas.com/docs/" },
|
|
107904
|
+
{ key: "docsIngestion", to: "https://api.data.apps.myio-bas.com/api/docs/" },
|
|
107905
|
+
{ key: "docsThingsboard", to: "https://dashboard.myio-bas.com/swagger-ui/index.html" },
|
|
107906
|
+
{ key: "integrationsGuide", to: "/wiki/p/Integrations/index", web: true },
|
|
107907
|
+
{ key: "newIntegration", to: "/wiki/p/integrations/new", web: true }
|
|
107908
|
+
] },
|
|
107909
|
+
{ key: "systems", icon: "grid", items: [
|
|
107910
|
+
{ key: "app", to: "https://app.apps.myio-bas.com" },
|
|
107911
|
+
{ key: "dashboards", to: "https://dashboard.myio-bas.com" },
|
|
107912
|
+
{ key: "alarms", to: "https://alarms-web.a.myio-bas.com" }
|
|
107913
|
+
] },
|
|
107914
|
+
{ key: "institutional", icon: "building", items: [
|
|
107915
|
+
{ key: "site", to: "https://myio.com.br" },
|
|
107916
|
+
{ key: "privacy", to: "https://myio.com.br/politica-de-privacidade" },
|
|
107917
|
+
{ key: "terms" }
|
|
107918
|
+
] },
|
|
107919
|
+
{ key: "status", icon: "activity", items: [{ key: "gcdrHealth", health: true }] }
|
|
107920
|
+
];
|
|
107921
|
+
function defaultSupportHref(webUrl) {
|
|
107922
|
+
return webUrl ? `${webUrl.replace(/\/+$/, "")}/support` : void 0;
|
|
107923
|
+
}
|
|
107924
|
+
function renderAbout(el2, ctx, t, opts) {
|
|
107925
|
+
const doc = el2.ownerDocument;
|
|
107926
|
+
const { body } = ctx.panel({ eyebrow: t("about.eyebrow"), fill: true, logo: false, bandColor: opts.bandColor ?? "#2E8B57" });
|
|
107927
|
+
const web = opts.webUrl?.replace(/\/+$/, "");
|
|
107928
|
+
const visibleCats = CATEGORIES.filter((c) => c.key === "status" ? !!opts.healthUrl : true);
|
|
107929
|
+
let healthAbort = null;
|
|
107930
|
+
const showGrid = () => {
|
|
107931
|
+
body.textContent = "";
|
|
107932
|
+
const title = h2(doc, "h2", { class: "myio-gcdr-about__title" }, `${t("about.title")} `, h2(doc, "em", { text: t("about.titleHighlight") }));
|
|
107933
|
+
const intro = h2(doc, "p", { class: "myio-gcdr-about__intro", text: t("about.text") });
|
|
107934
|
+
const grid = h2(doc, "div", { class: "myio-gcdr-about__grid" });
|
|
107935
|
+
for (const c of visibleCats) {
|
|
107936
|
+
const btn = h2(
|
|
107937
|
+
doc,
|
|
107938
|
+
"button",
|
|
107939
|
+
{ type: "button", class: "myio-gcdr-about__tile" },
|
|
107940
|
+
icon(doc, ICONS[c.icon](22), "myio-gcdr-about__tileicon"),
|
|
107941
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: t(`about.cat.${c.key}`) }),
|
|
107942
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletext", text: t(`about.cat.${c.key}.text`) })
|
|
107943
|
+
);
|
|
107944
|
+
btn.addEventListener("click", () => showCategory(c));
|
|
107945
|
+
grid.appendChild(btn);
|
|
107946
|
+
}
|
|
107947
|
+
body.append(title, intro, grid, h2(doc, "p", { class: "myio-gcdr-about__tagline", text: t("about.tagline") }));
|
|
107948
|
+
};
|
|
107949
|
+
const showCategory = (c) => {
|
|
107950
|
+
body.textContent = "";
|
|
107951
|
+
const back = h2(doc, "button", { type: "button", class: "myio-gcdr-login__link myio-gcdr-about__back" }, icon(doc, ICONS.arrowLeft(14)), ` ${t("about.back")}`);
|
|
107952
|
+
back.addEventListener("click", () => {
|
|
107953
|
+
showGrid();
|
|
107954
|
+
body.querySelector("button")?.focus();
|
|
107955
|
+
});
|
|
107956
|
+
const title = h2(doc, "h2", { class: "myio-gcdr-about__title", text: t(`about.cat.${c.key}`) });
|
|
107957
|
+
const grid = h2(doc, "div", { class: "myio-gcdr-about__grid" });
|
|
107958
|
+
for (const it of c.items) {
|
|
107959
|
+
const label = t(`about.item.${it.key}`);
|
|
107960
|
+
if (it.health) {
|
|
107961
|
+
const dot = h2(doc, "span", { class: "myio-gcdr-about__dot", "data-state": "checking" });
|
|
107962
|
+
const state6 = h2(doc, "span", { class: "myio-gcdr-about__health", role: "status" }, dot, h2(doc, "span", { text: t("about.health.checking") }));
|
|
107963
|
+
grid.appendChild(h2(
|
|
107964
|
+
doc,
|
|
107965
|
+
"div",
|
|
107966
|
+
{ class: "myio-gcdr-about__tile", "aria-disabled": "true" },
|
|
107967
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
|
|
107968
|
+
state6
|
|
107969
|
+
));
|
|
107970
|
+
checkHealth(dot, state6.lastChild);
|
|
107971
|
+
continue;
|
|
107972
|
+
}
|
|
107973
|
+
const href = it.to ? it.web ? web ? `${web}${it.to}` : void 0 : it.to : void 0;
|
|
107974
|
+
if (it.web && !href) continue;
|
|
107975
|
+
if (!href) {
|
|
107976
|
+
grid.appendChild(h2(
|
|
107977
|
+
doc,
|
|
107978
|
+
"div",
|
|
107979
|
+
{ class: "myio-gcdr-about__tile", "aria-disabled": "true" },
|
|
107980
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
|
|
107981
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletext", text: t("about.soon") })
|
|
107982
|
+
));
|
|
107983
|
+
continue;
|
|
107984
|
+
}
|
|
107985
|
+
grid.appendChild(h2(
|
|
107986
|
+
doc,
|
|
107987
|
+
"a",
|
|
107988
|
+
{ class: "myio-gcdr-about__tile", href, target: "_blank", rel: "noopener noreferrer" },
|
|
107989
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
|
|
107990
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletext" }, `${t("about.open")} `, icon(doc, ICONS.external(12)))
|
|
107991
|
+
));
|
|
107992
|
+
}
|
|
107993
|
+
body.append(back, title, grid);
|
|
107994
|
+
back.focus();
|
|
107995
|
+
};
|
|
107996
|
+
const checkHealth = (dot, label) => {
|
|
107997
|
+
if (!opts.healthUrl) return;
|
|
107998
|
+
const f = opts.fetchImpl ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
|
|
107999
|
+
if (!f) return;
|
|
108000
|
+
healthAbort?.abort();
|
|
108001
|
+
const ac = new AbortController();
|
|
108002
|
+
healthAbort = ac;
|
|
108003
|
+
const timer = setTimeout(() => ac.abort(), 5e3);
|
|
108004
|
+
f(opts.healthUrl, { signal: ac.signal, credentials: "omit" }).then((r) => r.ok).catch(() => false).then((up4) => {
|
|
108005
|
+
clearTimeout(timer);
|
|
108006
|
+
if (ac.signal.aborted && healthAbort !== ac) return;
|
|
108007
|
+
dot.setAttribute("data-state", up4 ? "online" : "offline");
|
|
108008
|
+
label.textContent = t(up4 ? "about.health.online" : "about.health.offline");
|
|
108009
|
+
});
|
|
108010
|
+
};
|
|
108011
|
+
showGrid();
|
|
108012
|
+
return () => healthAbort?.abort();
|
|
108013
|
+
}
|
|
108014
|
+
function renderSignedOutPrompt(el2, ctx, text2) {
|
|
108015
|
+
const doc = el2.ownerDocument;
|
|
108016
|
+
const { body } = ctx.panel({ eyebrow: "", fill: true, logo: false });
|
|
108017
|
+
const band = body.parentElement?.querySelector(".myio-gcdr-panel__band");
|
|
108018
|
+
band?.remove();
|
|
108019
|
+
body.appendChild(
|
|
108020
|
+
h2(
|
|
108021
|
+
doc,
|
|
108022
|
+
"div",
|
|
108023
|
+
{ class: "myio-gcdr-prompt" },
|
|
108024
|
+
icon(doc, ICONS.lock(28), "myio-gcdr-prompt__icon"),
|
|
108025
|
+
h2(doc, "p", { class: "myio-gcdr-prompt__text", text: text2 })
|
|
108026
|
+
)
|
|
108027
|
+
);
|
|
108028
|
+
}
|
|
108029
|
+
|
|
108030
|
+
// src/components/myio-gcdr-login/i18n.ts
|
|
108031
|
+
var PT = {
|
|
108032
|
+
"login.eyebrow": "Acesso",
|
|
108033
|
+
"login.title": "Login",
|
|
108034
|
+
"login.email": "E-mail",
|
|
108035
|
+
"login.password": "Senha",
|
|
108036
|
+
"login.rememberMe": "Lembrar de mim",
|
|
108037
|
+
"login.forgotPassword": "Esqueceu a senha?",
|
|
108038
|
+
"login.signIn": "Entrar",
|
|
108039
|
+
"login.signingIn": "Entrando...",
|
|
108040
|
+
"login.noAccount": "N\xE3o tem uma conta?",
|
|
108041
|
+
"login.createAccount": "Criar conta",
|
|
108042
|
+
"login.emailRequired": "Informe o seu e-mail.",
|
|
108043
|
+
"login.emailInvalid": "Informe um e-mail v\xE1lido, como nome@empresa.com.",
|
|
108044
|
+
"login.emailPlaceholder": "nome@empresa.com",
|
|
108045
|
+
// new
|
|
108046
|
+
"login.passwordRequired": "Informe a sua senha.",
|
|
108047
|
+
"login.showPassword": "Mostrar senha",
|
|
108048
|
+
"login.hidePassword": "Ocultar senha",
|
|
108049
|
+
"login.capsLockOn": "Caps Lock est\xE1 ativado.",
|
|
108050
|
+
"login.notYou": "N\xE3o \xE9 voc\xEA?",
|
|
108051
|
+
"login.askAdmin": "Precisa de acesso? Fale com o administrador do sistema.",
|
|
108052
|
+
"login.newTab": "(abre em nova aba)",
|
|
108053
|
+
"login.gcdrWeb": "Entrar pelo GCDR Web",
|
|
108054
|
+
"login.support": "Falar com o suporte",
|
|
108055
|
+
"login.leaving": "Saindo...",
|
|
108056
|
+
"errors.invalidCredentials": "E-mail ou senha inv\xE1lidos",
|
|
108057
|
+
"errors.networkError": "Erro de conex\xE3o. Verifique sua internet.",
|
|
108058
|
+
"errors.loginFailed": "N\xE3o foi poss\xEDvel entrar no momento. Tente novamente em instantes.",
|
|
108059
|
+
"errors.lockedTitle": "Conta bloqueada",
|
|
108060
|
+
"errors.lockedText": "Esta conta foi bloqueada ap\xF3s 6 tentativas de login com senha incorreta (ou por um administrador). Por seguran\xE7a, somente um administrador pode liberar o acesso \u2014 os administradores j\xE1 foram avisados por e-mail.",
|
|
108061
|
+
"errors.attemptsLeft_one": "Senha incorreta \u2014 resta {{count}} tentativa.",
|
|
108062
|
+
"errors.attemptsLeft_other": "Senha incorreta \u2014 restam {{count}} tentativas.",
|
|
108063
|
+
"errors.lastAttempt": "Senha incorreta \u2014 esta \xE9 a sua \xFAltima tentativa.",
|
|
108064
|
+
"errors.lockWarning": "Na 6\xAA senha errada a conta \xE9 bloqueada e s\xF3 um administrador consegue liberar. Se n\xE3o lembra a senha, redefina agora em vez de tentar de novo.",
|
|
108065
|
+
"errors.goToForgot": "Esqueci minha senha \u2014 redefinir agora",
|
|
108066
|
+
"errors.invalidWithAttempts_one": "E-mail ou senha inv\xE1lidos. Resta {{count}} tentativa antes do bloqueio.",
|
|
108067
|
+
"errors.invalidWithAttempts_other": "E-mail ou senha inv\xE1lidos. Restam {{count}} tentativas antes do bloqueio.",
|
|
108068
|
+
"errors.captchaFailed": "N\xE3o foi poss\xEDvel confirmar que voc\xEA n\xE3o \xE9 um rob\xF4. Aguarde a verifica\xE7\xE3o e tente de novo.",
|
|
108069
|
+
// new
|
|
108070
|
+
"errors.tooManyRequests": "Muitas tentativas. Aguarde alguns minutos e tente novamente.",
|
|
108071
|
+
"errors.timeout": "O servidor demorou para responder. Tente novamente.",
|
|
108072
|
+
"errors.integrationError": "N\xE3o foi poss\xEDvel entrar no momento. Tente novamente em instantes.",
|
|
108073
|
+
"errors.mfaUnsupported": "Esta conta exige verifica\xE7\xE3o em duas etapas, ainda n\xE3o dispon\xEDvel nesta tela.",
|
|
108074
|
+
"errors.postLoginFailed": "N\xE3o foi poss\xEDvel concluir a entrada. Tente novamente.",
|
|
108075
|
+
"errors.leaveFailed": "N\xE3o foi poss\xEDvel sair agora. Tente novamente.",
|
|
108076
|
+
"errors.captchaLoadFailed": "N\xE3o foi poss\xEDvel carregar a verifica\xE7\xE3o.",
|
|
108077
|
+
"errors.invalidCredentialsHelp": "Confira o e-mail digitado. Se estiver correto e voc\xEA tiver certeza da senha, sua conta pode ainda n\xE3o estar liberada \u2014 {{who}}.",
|
|
108078
|
+
"errors.helpSupport": "fale com o suporte",
|
|
108079
|
+
"errors.helpAdmin": "fale com o administrador do sistema",
|
|
108080
|
+
"notice.sessionExpired": "Sua sess\xE3o expirou. Por favor, entre novamente.",
|
|
108081
|
+
"notice.sessionExpiredModal": "Sua sess\xE3o expirou. Entre novamente \u2014 esta tela ser\xE1 mantida.",
|
|
108082
|
+
"aside.signedOutPrompt": "Fa\xE7a o login para ter acesso \xE0s funcionalidades.",
|
|
108083
|
+
"about.eyebrow": "Sobre a MYIO",
|
|
108084
|
+
"about.title": "Medi\xE7\xE3o e atua\xE7\xE3o remota",
|
|
108085
|
+
"about.titleHighlight": "IoT",
|
|
108086
|
+
"about.text": "Escolha um assunto para ver o que voc\xEA pode acessar sem entrar na conta.",
|
|
108087
|
+
"about.tagline": "Efici\xEAncia | Seguran\xE7a | Sustentabilidade",
|
|
108088
|
+
"about.health.checking": "Verificando\u2026",
|
|
108089
|
+
"about.health.online": "No ar",
|
|
108090
|
+
"about.health.offline": "Indispon\xEDvel",
|
|
108091
|
+
"about.back": "Voltar",
|
|
108092
|
+
"about.open": "Abrir",
|
|
108093
|
+
"about.soon": "Em breve",
|
|
108094
|
+
"about.cat.wiki": "Wiki",
|
|
108095
|
+
"about.cat.wiki.text": "Base de conhecimento, guias e respostas.",
|
|
108096
|
+
"about.cat.support": "Atendimento",
|
|
108097
|
+
"about.cat.support.text": "Chamados, tickets e d\xFAvidas.",
|
|
108098
|
+
"about.cat.integrations": "Integra\xE7\xF5es",
|
|
108099
|
+
"about.cat.integrations.text": "Documenta\xE7\xE3o das APIs e guias de integra\xE7\xE3o.",
|
|
108100
|
+
"about.cat.systems": "Sistemas",
|
|
108101
|
+
"about.cat.systems.text": "Acesso aos sistemas MYIO.",
|
|
108102
|
+
"about.cat.institutional": "Institucional",
|
|
108103
|
+
"about.cat.institutional.text": "Sobre a MYIO, site, privacidade e termos.",
|
|
108104
|
+
"about.cat.status": "Status",
|
|
108105
|
+
"about.cat.status.text": "Situa\xE7\xE3o dos sistemas agora.",
|
|
108106
|
+
"about.item.wikiHome": "Wiki p\xFAblica",
|
|
108107
|
+
"about.item.wikiSearch": "Buscar na wiki",
|
|
108108
|
+
"about.item.accountGuide": "Acesso \xE0 conta",
|
|
108109
|
+
"about.item.openTicket": "Abrir chamado",
|
|
108110
|
+
"about.item.forgotPassword": "Esqueci minha senha",
|
|
108111
|
+
"about.item.docsAlarms": "Alarms",
|
|
108112
|
+
"about.item.docsGcdr": "GCDR",
|
|
108113
|
+
"about.item.docsIngestion": "Ingestion",
|
|
108114
|
+
"about.item.docsThingsboard": "ThingsBoard",
|
|
108115
|
+
"about.item.integrationsGuide": "Guia de integra\xE7\xF5es",
|
|
108116
|
+
"about.item.newIntegration": "Cadastrar integra\xE7\xE3o",
|
|
108117
|
+
"about.item.app": "App MYIO",
|
|
108118
|
+
"about.item.dashboards": "Dashboards",
|
|
108119
|
+
"about.item.alarms": "Alarmes",
|
|
108120
|
+
"about.item.site": "Site da MYIO",
|
|
108121
|
+
"about.item.privacy": "Privacidade",
|
|
108122
|
+
"about.item.terms": "Termos de servi\xE7o",
|
|
108123
|
+
"about.item.gcdrHealth": "GCDR",
|
|
108124
|
+
"toolbar.toDark": "Usar tema escuro",
|
|
108125
|
+
"toolbar.toLight": "Usar tema claro",
|
|
108126
|
+
"toolbar.language": "Idioma",
|
|
108127
|
+
"modal.close": "Fechar"
|
|
108128
|
+
};
|
|
108129
|
+
var EN = {
|
|
108130
|
+
"login.eyebrow": "Access",
|
|
108131
|
+
"login.title": "Login",
|
|
108132
|
+
"login.email": "Email",
|
|
108133
|
+
"login.password": "Password",
|
|
108134
|
+
"login.rememberMe": "Remember me",
|
|
108135
|
+
"login.forgotPassword": "Forgot password?",
|
|
108136
|
+
"login.signIn": "Sign In",
|
|
108137
|
+
"login.signingIn": "Signing in...",
|
|
108138
|
+
"login.noAccount": "Don't have an account?",
|
|
108139
|
+
"login.createAccount": "Create account",
|
|
108140
|
+
"login.emailRequired": "Enter your e-mail.",
|
|
108141
|
+
"login.emailInvalid": "Enter a valid e-mail, like name@company.com.",
|
|
108142
|
+
"login.emailPlaceholder": "name@company.com",
|
|
108143
|
+
"login.passwordRequired": "Enter your password.",
|
|
108144
|
+
"login.showPassword": "Show password",
|
|
108145
|
+
"login.hidePassword": "Hide password",
|
|
108146
|
+
"login.capsLockOn": "Caps Lock is on.",
|
|
108147
|
+
"login.notYou": "Not you?",
|
|
108148
|
+
"login.askAdmin": "Need access? Contact your system administrator.",
|
|
108149
|
+
"login.newTab": "(opens in a new tab)",
|
|
108150
|
+
"login.gcdrWeb": "Sign in on GCDR Web",
|
|
108151
|
+
"login.support": "Contact support",
|
|
108152
|
+
"login.leaving": "Leaving...",
|
|
108153
|
+
"errors.invalidCredentials": "Invalid e-mail or password",
|
|
108154
|
+
"errors.networkError": "Network error. Please check your connection.",
|
|
108155
|
+
"errors.loginFailed": "Unable to sign in right now. Please try again shortly.",
|
|
108156
|
+
"errors.lockedTitle": "Account locked",
|
|
108157
|
+
"errors.lockedText": "This account was locked after 6 sign-in attempts with a wrong password (or by an administrator). For security, only an administrator can unlock it \u2014 the administrators were already notified by e-mail.",
|
|
108158
|
+
"errors.attemptsLeft_one": "Wrong password \u2014 {{count}} attempt left.",
|
|
108159
|
+
"errors.attemptsLeft_other": "Wrong password \u2014 {{count}} attempts left.",
|
|
108160
|
+
"errors.lastAttempt": "Wrong password \u2014 this is your last attempt.",
|
|
108161
|
+
"errors.lockWarning": "On the 6th wrong password the account is locked and only an administrator can unlock it. If you don't remember the password, reset it now instead of trying again.",
|
|
108162
|
+
"errors.goToForgot": "Forgot my password \u2014 reset now",
|
|
108163
|
+
"errors.invalidWithAttempts_one": "Invalid e-mail or password. {{count}} attempt left before the lock.",
|
|
108164
|
+
"errors.invalidWithAttempts_other": "Invalid e-mail or password. {{count}} attempts left before the lock.",
|
|
108165
|
+
"errors.captchaFailed": "Could not confirm you are not a robot. Wait for the check and try again.",
|
|
108166
|
+
"errors.tooManyRequests": "Too many attempts. Wait a few minutes and try again.",
|
|
108167
|
+
"errors.timeout": "The server took too long to answer. Please try again.",
|
|
108168
|
+
"errors.integrationError": "Unable to sign in right now. Please try again shortly.",
|
|
108169
|
+
"errors.mfaUnsupported": "This account requires two-step verification, not yet available on this screen.",
|
|
108170
|
+
"errors.postLoginFailed": "Could not finish signing in. Please try again.",
|
|
108171
|
+
"errors.leaveFailed": "Could not leave right now. Please try again.",
|
|
108172
|
+
"errors.captchaLoadFailed": "Could not load the verification.",
|
|
108173
|
+
"errors.invalidCredentialsHelp": "Check the e-mail you typed. If it is right and you are sure of the password, your account may not be enabled yet \u2014 {{who}}.",
|
|
108174
|
+
"errors.helpSupport": "contact support",
|
|
108175
|
+
"errors.helpAdmin": "contact your system administrator",
|
|
108176
|
+
"notice.sessionExpired": "Your session has expired. Please sign in again.",
|
|
108177
|
+
"notice.sessionExpiredModal": "Your session has expired. Sign in again \u2014 this screen will be kept.",
|
|
108178
|
+
"aside.signedOutPrompt": "Sign in to access the features.",
|
|
108179
|
+
"about.eyebrow": "About MYIO",
|
|
108180
|
+
"about.title": "Remote metering and control",
|
|
108181
|
+
"about.titleHighlight": "IoT",
|
|
108182
|
+
"about.text": "Pick a subject to see what you can reach without signing in.",
|
|
108183
|
+
"about.tagline": "Efficiency | Safety | Sustainability",
|
|
108184
|
+
"about.health.checking": "Checking\u2026",
|
|
108185
|
+
"about.health.online": "Up",
|
|
108186
|
+
"about.health.offline": "Unavailable",
|
|
108187
|
+
"about.back": "Back",
|
|
108188
|
+
"about.open": "Open",
|
|
108189
|
+
"about.soon": "Coming soon",
|
|
108190
|
+
"about.cat.wiki": "Wiki",
|
|
108191
|
+
"about.cat.wiki.text": "Knowledge base, guides and answers.",
|
|
108192
|
+
"about.cat.support": "Support",
|
|
108193
|
+
"about.cat.support.text": "Tickets and questions.",
|
|
108194
|
+
"about.cat.integrations": "Integrations",
|
|
108195
|
+
"about.cat.integrations.text": "API documentation and integration guides.",
|
|
108196
|
+
"about.cat.systems": "Systems",
|
|
108197
|
+
"about.cat.systems.text": "Access to the MYIO systems.",
|
|
108198
|
+
"about.cat.institutional": "About us",
|
|
108199
|
+
"about.cat.institutional.text": "About MYIO, website, privacy and terms.",
|
|
108200
|
+
"about.cat.status": "Status",
|
|
108201
|
+
"about.cat.status.text": "How the systems are right now.",
|
|
108202
|
+
"about.item.wikiHome": "Public wiki",
|
|
108203
|
+
"about.item.wikiSearch": "Search the wiki",
|
|
108204
|
+
"about.item.accountGuide": "Account access",
|
|
108205
|
+
"about.item.openTicket": "Open a ticket",
|
|
108206
|
+
"about.item.forgotPassword": "Forgot my password",
|
|
108207
|
+
"about.item.docsAlarms": "Alarms",
|
|
108208
|
+
"about.item.docsGcdr": "GCDR",
|
|
108209
|
+
"about.item.docsIngestion": "Ingestion",
|
|
108210
|
+
"about.item.docsThingsboard": "ThingsBoard",
|
|
108211
|
+
"about.item.integrationsGuide": "Integrations guide",
|
|
108212
|
+
"about.item.newIntegration": "Submit an integration",
|
|
108213
|
+
"about.item.app": "MYIO App",
|
|
108214
|
+
"about.item.dashboards": "Dashboards",
|
|
108215
|
+
"about.item.alarms": "Alarms",
|
|
108216
|
+
"about.item.site": "MYIO website",
|
|
108217
|
+
"about.item.privacy": "Privacy",
|
|
108218
|
+
"about.item.terms": "Terms of service",
|
|
108219
|
+
"about.item.gcdrHealth": "GCDR",
|
|
108220
|
+
"toolbar.toDark": "Use dark theme",
|
|
108221
|
+
"toolbar.toLight": "Use light theme",
|
|
108222
|
+
"toolbar.language": "Language",
|
|
108223
|
+
"modal.close": "Close"
|
|
108224
|
+
};
|
|
108225
|
+
var DICTIONARIES = { "pt-BR": PT, en: EN };
|
|
108226
|
+
function interpolate(text2, vars) {
|
|
108227
|
+
if (!vars) return text2;
|
|
108228
|
+
return text2.replace(/\{\{(\w+)\}\}/g, (_m, k) => vars[k] != null ? String(vars[k]) : "");
|
|
108229
|
+
}
|
|
108230
|
+
function translate(locale, key, vars, overrides) {
|
|
108231
|
+
let k = key;
|
|
108232
|
+
if (vars && typeof vars.count === "number") {
|
|
108233
|
+
const cat = new Intl.PluralRules(locale).select(vars.count);
|
|
108234
|
+
k = `${key}_${cat === "one" ? "one" : "other"}`;
|
|
108235
|
+
}
|
|
108236
|
+
const text2 = overrides?.[locale]?.[k] ?? DICTIONARIES[locale][k] ?? overrides?.["pt-BR"]?.[k] ?? DICTIONARIES["pt-BR"][k] ?? k;
|
|
108237
|
+
return interpolate(text2, vars);
|
|
108238
|
+
}
|
|
108239
|
+
function localize(value, locale) {
|
|
108240
|
+
if (value == null) return "";
|
|
108241
|
+
if (typeof value === "string") return value;
|
|
108242
|
+
return value[locale] ?? value["pt-BR"] ?? value.en ?? "";
|
|
108243
|
+
}
|
|
108244
|
+
function detectLocale(stored) {
|
|
108245
|
+
if (stored === "pt-BR" || stored === "en") return stored;
|
|
108246
|
+
const nav = typeof navigator !== "undefined" ? navigator.language || "" : "";
|
|
108247
|
+
return nav.toLowerCase().startsWith("en") ? "en" : "pt-BR";
|
|
108248
|
+
}
|
|
108249
|
+
|
|
108250
|
+
// src/components/myio-gcdr-login/styles.ts
|
|
108251
|
+
var STYLE_VERSION = "1";
|
|
108252
|
+
var STYLE_ATTR = "data-myio-gcdr-version";
|
|
108253
|
+
var REFS_ATTR = "data-myio-gcdr-refs";
|
|
108254
|
+
var FONT_ID = "myio-gcdr-font-nunito";
|
|
108255
|
+
var CSS3 = `
|
|
108256
|
+
.myio-gcdr-shell, .myio-gcdr-overlay {
|
|
108257
|
+
--myio-gcdr-accent: #6B4ABF;
|
|
108258
|
+
--myio-gcdr-accent-hover: #5A3CA8;
|
|
108259
|
+
--myio-gcdr-card: #FBFAFE;
|
|
108260
|
+
--myio-gcdr-ring: #E1DAF4;
|
|
108261
|
+
--myio-gcdr-title: #1E1B2E;
|
|
108262
|
+
--myio-gcdr-text: #55506A;
|
|
108263
|
+
--myio-gcdr-footer: #F0ECFA;
|
|
108264
|
+
--myio-gcdr-input: #FFFFFF;
|
|
108265
|
+
--myio-gcdr-input-border: #D1D5DB;
|
|
108266
|
+
--myio-gcdr-link: #6B4ABF;
|
|
108267
|
+
--myio-gcdr-pill: rgba(255,255,255,0.70);
|
|
108268
|
+
--myio-gcdr-aside-band: #2E8B57;
|
|
108269
|
+
box-sizing: border-box;
|
|
108270
|
+
font-family: 'Nunito', ui-sans-serif, system-ui, sans-serif;
|
|
108271
|
+
line-height: 1.5;
|
|
108272
|
+
color: var(--myio-gcdr-title);
|
|
108273
|
+
-webkit-font-smoothing: antialiased;
|
|
108274
|
+
}
|
|
108275
|
+
.myio-gcdr-shell[data-theme="dark"], .myio-gcdr-overlay[data-theme="dark"] {
|
|
108276
|
+
--myio-gcdr-card: #1E1A2E;
|
|
108277
|
+
--myio-gcdr-ring: #3A3158;
|
|
108278
|
+
--myio-gcdr-title: #FFFFFF;
|
|
108279
|
+
--myio-gcdr-text: #D1D5DB;
|
|
108280
|
+
--myio-gcdr-footer: #251F3A;
|
|
108281
|
+
--myio-gcdr-input: #2B2440;
|
|
108282
|
+
--myio-gcdr-input-border: #3A3158;
|
|
108283
|
+
--myio-gcdr-link: #B9A5F0;
|
|
108284
|
+
--myio-gcdr-pill: rgba(43,36,64,0.80);
|
|
108285
|
+
}
|
|
108286
|
+
.myio-gcdr-shell [hidden], .myio-gcdr-overlay [hidden] { display: none !important; }
|
|
108287
|
+
.myio-gcdr-shell *, .myio-gcdr-shell *::before, .myio-gcdr-shell *::after,
|
|
108288
|
+
.myio-gcdr-overlay *, .myio-gcdr-overlay *::before, .myio-gcdr-overlay *::after { box-sizing: border-box; }
|
|
108289
|
+
|
|
108290
|
+
/* \u2500\u2500 Shell \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
108291
|
+
.myio-gcdr-shell {
|
|
108292
|
+
position: relative; min-height: 100%; width: 100%;
|
|
108293
|
+
display: flex; flex-direction: column; align-items: center;
|
|
108294
|
+
padding: 16px; isolation: isolate;
|
|
108295
|
+
}
|
|
108296
|
+
.myio-gcdr-shell__wallpaper {
|
|
108297
|
+
position: absolute; inset: 0; z-index: -1; overflow: hidden;
|
|
108298
|
+
background-color: #EEEAF8;
|
|
108299
|
+
background-image: var(--myio-gcdr-wp, none), linear-gradient(180deg, #DCD2F3 0%, #EEEAF8 45%, #F7F5FC 100%);
|
|
108300
|
+
background-position: center; background-size: cover; background-repeat: no-repeat;
|
|
108301
|
+
}
|
|
108302
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper {
|
|
108303
|
+
background-color: #15121F;
|
|
108304
|
+
background-image: var(--myio-gcdr-wp, none), linear-gradient(180deg, #1B1530 0%, #15121F 45%, #111827 100%);
|
|
108305
|
+
}
|
|
108306
|
+
.myio-gcdr-shell__wallpaper::before { content: ''; position: absolute; inset: 0;
|
|
108307
|
+
background: rgba(255,255,255,0.22); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
|
|
108308
|
+
.myio-gcdr-shell__wallpaper::after { content: ''; position: absolute; inset: 0;
|
|
108309
|
+
background: linear-gradient(135deg, rgba(107,74,191,0.34) 0%, rgba(107,74,191,0.14) 50%, rgba(107,74,191,0.34) 100%); }
|
|
108310
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper::before { background: rgba(255,255,255,0.05); }
|
|
108311
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper::after {
|
|
108312
|
+
background: linear-gradient(135deg, rgba(45,22,105,0.55) 0%, rgba(27,21,48,0.30) 50%, rgba(45,22,105,0.55) 100%); }
|
|
108313
|
+
|
|
108314
|
+
.myio-gcdr-shell__top { width: 100%; }
|
|
108315
|
+
.myio-gcdr-shell__block { width: 100%; max-width: 28rem; margin: auto 0; display: flex; flex-direction: column; }
|
|
108316
|
+
.myio-gcdr-shell[data-size="lg"] .myio-gcdr-shell__block { max-width: 32rem; }
|
|
108317
|
+
.myio-gcdr-shell[data-size="xl"] .myio-gcdr-shell__block { max-width: 37rem; }
|
|
108318
|
+
@media (min-width: 1024px) {
|
|
108319
|
+
.myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__block { max-width: 72rem; }
|
|
108320
|
+
}
|
|
108321
|
+
.myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 28rem; }
|
|
108322
|
+
@media (min-width: 640px) { .myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 42rem; } }
|
|
108323
|
+
@media (min-width: 1024px) { .myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 1800px; padding: 0 12px; } }
|
|
108324
|
+
|
|
108325
|
+
.myio-gcdr-shell__toprow { display: flex; justify-content: flex-end; margin-bottom: 12px; }
|
|
108326
|
+
.myio-gcdr-shell__pill {
|
|
108327
|
+
display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; justify-content: flex-end;
|
|
108328
|
+
border-radius: 9999px; background: var(--myio-gcdr-pill); padding: 4px 8px;
|
|
108329
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.05); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
|
|
108330
|
+
}
|
|
108331
|
+
.myio-gcdr-shell__iconbtn {
|
|
108332
|
+
display: inline-flex; align-items: center; gap: 6px; min-height: 36px; min-width: 36px; justify-content: center;
|
|
108333
|
+
border: 0; background: transparent; color: var(--myio-gcdr-text); border-radius: 8px; padding: 6px 10px;
|
|
108334
|
+
font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
|
|
108335
|
+
}
|
|
108336
|
+
.myio-gcdr-shell__iconbtn:hover { background: rgba(107,74,191,0.10); color: var(--myio-gcdr-title); }
|
|
108337
|
+
.myio-gcdr-shell__iconbtn:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108338
|
+
|
|
108339
|
+
.myio-gcdr-shell__split { display: flex; flex-direction: column; gap: 24px; }
|
|
108340
|
+
@media (min-width: 1024px) {
|
|
108341
|
+
.myio-gcdr-shell__split { flex-direction: row; align-items: stretch; }
|
|
108342
|
+
.myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__split { height: clamp(600px, calc(100vh - 10rem), 880px); }
|
|
108343
|
+
.myio-gcdr-shell__aside { flex: 1 1 0; min-width: 0; display: flex; }
|
|
108344
|
+
.myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__main { flex: 0 0 28rem; }
|
|
108345
|
+
.myio-gcdr-shell[data-width="cockpit"][data-has-aside="true"] .myio-gcdr-shell__main { flex: 1 1 0; }
|
|
108346
|
+
}
|
|
108347
|
+
.myio-gcdr-shell__main { display: flex; min-width: 0; min-height: 0; }
|
|
108348
|
+
.myio-gcdr-shell__main > * { flex: 1 1 auto; min-width: 0; }
|
|
108349
|
+
@media (max-width: 1023.98px) {
|
|
108350
|
+
.myio-gcdr-shell[data-aside-compact="hide"] .myio-gcdr-shell__aside { display: none; }
|
|
108351
|
+
.myio-gcdr-shell[data-aside-compact="stack"] .myio-gcdr-shell__aside { order: 2; display: flex; }
|
|
108352
|
+
}
|
|
108353
|
+
.myio-gcdr-shell__aside[hidden], .myio-gcdr-shell__below[hidden], .myio-gcdr-shell__top[hidden] { display: none !important; }
|
|
108354
|
+
.myio-gcdr-shell__below { margin-top: 16px; text-align: center; }
|
|
108355
|
+
.myio-gcdr-shell__build { display: inline-block; font-size: 12px; color: #55506A; border-radius: 9999px;
|
|
108356
|
+
background: var(--myio-gcdr-pill); padding: 4px 12px; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
|
|
108357
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__build { color: #E5E7EB; }
|
|
108358
|
+
.myio-gcdr-shell__slot:focus { outline: none; }
|
|
108359
|
+
.myio-gcdr-sr { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
|
|
108360
|
+
|
|
108361
|
+
/* \u2500\u2500 Card panel \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
108362
|
+
.myio-gcdr-panel {
|
|
108363
|
+
display: flex; flex-direction: column; overflow: hidden; width: 100%;
|
|
108364
|
+
border-radius: 16px; background: var(--myio-gcdr-card);
|
|
108365
|
+
box-shadow: 0 18px 50px rgba(40,20,90,0.30), 0 0 0 1px var(--myio-gcdr-ring);
|
|
108366
|
+
}
|
|
108367
|
+
.myio-gcdr-panel[data-fill="true"] { height: 100%; }
|
|
108368
|
+
.myio-gcdr-panel__band {
|
|
108369
|
+
position: relative; display: flex; flex-shrink: 0; align-items: center; justify-content: space-between; gap: 16px;
|
|
108370
|
+
height: 68px; padding: 0 32px; background: var(--myio-gcdr-band, var(--myio-gcdr-accent));
|
|
108371
|
+
}
|
|
108372
|
+
.myio-gcdr-panel__tint { position: absolute; inset: 0; background: var(--myio-gcdr-tint, transparent); pointer-events: none; }
|
|
108373
|
+
.myio-gcdr-panel__eyebrow { position: relative; font-size: 14px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.14em; color: #FFFFFF; }
|
|
108374
|
+
.myio-gcdr-panel__logo { position: relative; height: 28px; width: auto; display: block; }
|
|
108375
|
+
.myio-gcdr-panel__wordmark { position: relative; color: #fff; font-weight: 900; font-size: 20px; letter-spacing: 0.04em; }
|
|
108376
|
+
.myio-gcdr-panel__body { padding: 28px 32px 32px; flex: 1 1 auto; overflow-y: auto; min-height: 0; }
|
|
108377
|
+
.myio-gcdr-panel__title { margin: 0 0 20px; font-size: 26px; font-weight: 800; line-height: 1.2; color: var(--myio-gcdr-title); }
|
|
108378
|
+
.myio-gcdr-panel__footer { padding: 16px 32px; text-align: center; font-size: 14px; color: var(--myio-gcdr-text);
|
|
108379
|
+
background: var(--myio-gcdr-footer); border-top: 1px solid var(--myio-gcdr-ring); }
|
|
108380
|
+
|
|
108381
|
+
/* \u2500\u2500 Form \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
108382
|
+
.myio-gcdr-login__form { display: flex; flex-direction: column; gap: 20px; margin: 0; }
|
|
108383
|
+
.myio-gcdr-login__field { display: flex; flex-direction: column; gap: 6px; }
|
|
108384
|
+
.myio-gcdr-login__label { font-size: 14px; font-weight: 700; color: var(--myio-gcdr-title); }
|
|
108385
|
+
.myio-gcdr-login__control { position: relative; display: flex; }
|
|
108386
|
+
.myio-gcdr-login__input {
|
|
108387
|
+
width: 100%; font: inherit; font-size: 16px; color: var(--myio-gcdr-title);
|
|
108388
|
+
background: var(--myio-gcdr-input); border: 1px solid var(--myio-gcdr-input-border);
|
|
108389
|
+
border-radius: 12px; padding: 10px 14px; outline: none; transition: border-color .15s, box-shadow .15s;
|
|
108390
|
+
}
|
|
108391
|
+
.myio-gcdr-login__input::placeholder { color: #9CA3AF; }
|
|
108392
|
+
.myio-gcdr-login__input:focus { border-color: var(--myio-gcdr-accent); box-shadow: 0 0 0 3px rgba(107,74,191,0.30); }
|
|
108393
|
+
.myio-gcdr-login__input[aria-invalid="true"] { border-color: #FCA5A5; }
|
|
108394
|
+
.myio-gcdr-login__input[readonly] { opacity: .75; }
|
|
108395
|
+
.myio-gcdr-login__input--password { padding-right: 48px; }
|
|
108396
|
+
.myio-gcdr-login__eye {
|
|
108397
|
+
position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 40px; height: 40px;
|
|
108398
|
+
display: inline-flex; align-items: center; justify-content: center; border: 0; background: transparent;
|
|
108399
|
+
color: var(--myio-gcdr-text); border-radius: 8px; cursor: pointer;
|
|
108400
|
+
}
|
|
108401
|
+
.myio-gcdr-login__eye:focus-visible { outline: 2px solid var(--myio-gcdr-accent); }
|
|
108402
|
+
.myio-gcdr-login__fielderror { font-size: 13px; color: #DC2626; }
|
|
108403
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-login__fielderror { color: #FCA5A5; }
|
|
108404
|
+
.myio-gcdr-login__hint { font-size: 12px; color: #B45309; }
|
|
108405
|
+
.myio-gcdr-login__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
|
|
108406
|
+
.myio-gcdr-login__remember { display: inline-flex; align-items: center; gap: 8px; font-size: 14px; color: var(--myio-gcdr-text); cursor: pointer; min-height: 32px; }
|
|
108407
|
+
.myio-gcdr-login__remember input { width: 16px; height: 16px; accent-color: var(--myio-gcdr-accent); }
|
|
108408
|
+
.myio-gcdr-login__link { font-size: 14px; font-weight: 600; color: var(--myio-gcdr-link); text-decoration: none; background: none; border: 0; padding: 0; cursor: pointer; font-family: inherit; }
|
|
108409
|
+
.myio-gcdr-login__link:hover { color: var(--myio-gcdr-accent-hover); text-decoration: underline; }
|
|
108410
|
+
.myio-gcdr-login__submit {
|
|
108411
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 48px;
|
|
108412
|
+
border: 0; border-radius: 12px; padding: 12px 24px; font: inherit; font-size: 16px; font-weight: 700;
|
|
108413
|
+
color: #fff; background: var(--myio-gcdr-accent); cursor: pointer; transition: background .15s, opacity .15s;
|
|
108414
|
+
}
|
|
108415
|
+
.myio-gcdr-login__submit:hover { background: var(--myio-gcdr-accent-hover); }
|
|
108416
|
+
.myio-gcdr-login__submit[aria-disabled="true"], .myio-gcdr-login__submit:disabled { opacity: .55; cursor: not-allowed; }
|
|
108417
|
+
.myio-gcdr-login__submit:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108418
|
+
.myio-gcdr-login__submit[data-style="hotPage"] { border-radius: 10px; min-height: 52px; font-size: 17px; letter-spacing: .01em; box-shadow: 0 6px 16px rgba(107,74,191,0.35); }
|
|
108419
|
+
.myio-gcdr-login__spin { display: inline-flex; animation: myio-gcdr-spin 0.9s linear infinite; }
|
|
108420
|
+
@keyframes myio-gcdr-spin { to { transform: rotate(360deg); } }
|
|
108421
|
+
|
|
108422
|
+
/* \u2500\u2500 Banners \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
108423
|
+
.myio-gcdr-login__alerts { display: flex; flex-direction: column; gap: 12px; }
|
|
108424
|
+
.myio-gcdr-login__alerts:empty { display: none; }
|
|
108425
|
+
.myio-gcdr-login__alerts:not(:empty) { margin-bottom: 20px; }
|
|
108426
|
+
.myio-gcdr-login__field > .myio-gcdr-login__link { align-self: flex-start; }
|
|
108427
|
+
.myio-gcdr-banner { display: flex; gap: 10px; align-items: flex-start; border-radius: 12px; padding: 12px 14px; font-size: 14px; line-height: 1.45; border: 1px solid; }
|
|
108428
|
+
.myio-gcdr-banner:focus { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108429
|
+
.myio-gcdr-banner__icon { flex-shrink: 0; margin-top: 2px; }
|
|
108430
|
+
.myio-gcdr-banner__body { display: flex; flex-direction: column; gap: 6px; }
|
|
108431
|
+
.myio-gcdr-banner__title { font-weight: 800; }
|
|
108432
|
+
.myio-gcdr-banner--error { background: #FEF2F2; border-color: #FECACA; color: #991B1B; }
|
|
108433
|
+
.myio-gcdr-banner--warning { background: #FFFBEB; border-color: #FDE68A; color: #92400E; }
|
|
108434
|
+
.myio-gcdr-banner--info { background: #F5F3FF; border-color: #DDD6FE; color: #4C1D95; }
|
|
108435
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-banner--error { background: rgba(127,29,29,0.35); border-color: rgba(248,113,113,0.45); color: #FECACA; }
|
|
108436
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-banner--warning { background: rgba(120,53,15,0.35); border-color: rgba(251,191,36,0.45); color: #FDE68A; }
|
|
108437
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-banner--info { background: rgba(76,29,149,0.35); border-color: rgba(167,139,250,0.45); color: #DDD6FE; }
|
|
108438
|
+
.myio-gcdr-banner a, .myio-gcdr-banner button { color: inherit; font-weight: 700; text-decoration: underline; background: none; border: 0; padding: 0; font: inherit; cursor: pointer; text-align: left; }
|
|
108439
|
+
|
|
108440
|
+
/* \u2500\u2500 Aside: about / signed-out prompt \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
108441
|
+
.myio-gcdr-about__intro { color: var(--myio-gcdr-text); font-size: 14px; margin: 0 0 16px; }
|
|
108442
|
+
.myio-gcdr-about__title { font-size: 24px; font-weight: 800; margin: 0 0 6px; color: var(--myio-gcdr-title); }
|
|
108443
|
+
.myio-gcdr-about__title em { font-style: normal; color: var(--myio-gcdr-aside-band); }
|
|
108444
|
+
.myio-gcdr-about__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
|
|
108445
|
+
.myio-gcdr-about__tile {
|
|
108446
|
+
display: flex; flex-direction: column; gap: 6px; text-align: left; padding: 14px; border-radius: 12px; min-height: 110px;
|
|
108447
|
+
border: 1px solid var(--myio-gcdr-ring); background: var(--myio-gcdr-input); color: var(--myio-gcdr-title);
|
|
108448
|
+
font: inherit; cursor: pointer; text-decoration: none; transition: transform .15s, box-shadow .15s;
|
|
108449
|
+
}
|
|
108450
|
+
.myio-gcdr-about__tile:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(40,20,90,0.12); }
|
|
108451
|
+
.myio-gcdr-about__tile:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108452
|
+
.myio-gcdr-about__tile[aria-disabled="true"] { opacity: .6; cursor: default; }
|
|
108453
|
+
.myio-gcdr-about__tileicon { color: var(--myio-gcdr-aside-band); }
|
|
108454
|
+
.myio-gcdr-about__tiletitle { font-weight: 800; font-size: 15px; }
|
|
108455
|
+
.myio-gcdr-about__tiletext { font-size: 13px; color: var(--myio-gcdr-text); }
|
|
108456
|
+
.myio-gcdr-about__back { margin-bottom: 12px; }
|
|
108457
|
+
.myio-gcdr-about__tagline { margin-top: 16px; font-size: 13px; font-weight: 700; color: var(--myio-gcdr-text); text-align: center; }
|
|
108458
|
+
.myio-gcdr-about__health { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; }
|
|
108459
|
+
.myio-gcdr-about__dot { width: 8px; height: 8px; border-radius: 50%; background: #9CA3AF; }
|
|
108460
|
+
.myio-gcdr-about__dot[data-state="online"] { background: #16A34A; }
|
|
108461
|
+
.myio-gcdr-about__dot[data-state="offline"] { background: #DC2626; }
|
|
108462
|
+
.myio-gcdr-prompt { display: flex; flex: 1; flex-direction: column; align-items: center; justify-content: center; gap: 16px; padding: 32px 20px; text-align: center; height: 100%; }
|
|
108463
|
+
.myio-gcdr-prompt__icon { display: inline-flex; width: 56px; height: 56px; align-items: center; justify-content: center; border-radius: 50%; background: #6B4ABF; color: #fff; }
|
|
108464
|
+
.myio-gcdr-prompt__text { margin: 0; font-size: 22px; font-weight: 800; line-height: 1.35; color: var(--myio-gcdr-title); }
|
|
108465
|
+
|
|
108466
|
+
/* \u2500\u2500 Modal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
108467
|
+
.myio-gcdr-overlay { position: fixed; inset: 0; overflow-y: auto; display: flex; }
|
|
108468
|
+
.myio-gcdr-overlay[data-scope="element"] { position: absolute; }
|
|
108469
|
+
.myio-gcdr-overlay__layer { position: fixed; inset: 0; pointer-events: none; }
|
|
108470
|
+
.myio-gcdr-overlay[data-scope="element"] .myio-gcdr-overlay__layer { position: absolute; }
|
|
108471
|
+
.myio-gcdr-overlay__content { position: relative; width: 100%; min-height: 100%; display: flex; }
|
|
108472
|
+
.myio-gcdr-overlay__content > .myio-gcdr-shell { min-height: 100%; background: transparent; }
|
|
108473
|
+
.myio-gcdr-overlay__close { position: absolute; top: 12px; right: 12px; z-index: 2; }
|
|
108474
|
+
@media (prefers-reduced-motion: reduce) {
|
|
108475
|
+
.myio-gcdr-shell *, .myio-gcdr-overlay * { transition: none !important; animation: none !important; }
|
|
108476
|
+
}
|
|
108477
|
+
`;
|
|
108478
|
+
function rootTarget(container) {
|
|
108479
|
+
const root = container.getRootNode ? container.getRootNode() : document;
|
|
108480
|
+
const doc = container.ownerDocument || document;
|
|
108481
|
+
if (typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot) return { head: root, doc };
|
|
108482
|
+
return { head: doc.head || doc.documentElement, doc };
|
|
108483
|
+
}
|
|
108484
|
+
function acquireStyles(container, opts = {}) {
|
|
108485
|
+
const { head, doc } = rootTarget(container);
|
|
108486
|
+
if (opts.loadFont !== false && !doc.getElementById(FONT_ID)) {
|
|
108487
|
+
const link = doc.createElement("link");
|
|
108488
|
+
link.id = FONT_ID;
|
|
108489
|
+
link.rel = "stylesheet";
|
|
108490
|
+
link.href = "https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&display=swap";
|
|
108491
|
+
doc.head?.appendChild(link);
|
|
108492
|
+
}
|
|
108493
|
+
let style = head.querySelector(`style[${STYLE_ATTR}="${STYLE_VERSION}"]`);
|
|
108494
|
+
if (!style) {
|
|
108495
|
+
style = doc.createElement("style");
|
|
108496
|
+
style.setAttribute(STYLE_ATTR, STYLE_VERSION);
|
|
108497
|
+
style.setAttribute(REFS_ATTR, "0");
|
|
108498
|
+
if (opts.nonce) style.setAttribute("nonce", opts.nonce);
|
|
108499
|
+
style.textContent = CSS3;
|
|
108500
|
+
head.appendChild(style);
|
|
108501
|
+
}
|
|
108502
|
+
const el2 = style;
|
|
108503
|
+
el2.setAttribute(REFS_ATTR, String((parseInt(el2.getAttribute(REFS_ATTR) || "0", 10) || 0) + 1));
|
|
108504
|
+
let released = false;
|
|
108505
|
+
return () => {
|
|
108506
|
+
if (released) return;
|
|
108507
|
+
released = true;
|
|
108508
|
+
const n = (parseInt(el2.getAttribute(REFS_ATTR) || "1", 10) || 1) - 1;
|
|
108509
|
+
if (n <= 0) el2.remove();
|
|
108510
|
+
else el2.setAttribute(REFS_ATTR, String(n));
|
|
108511
|
+
};
|
|
108512
|
+
}
|
|
108513
|
+
|
|
108514
|
+
// src/components/myio-gcdr-login/shell.ts
|
|
108515
|
+
var SLOT_NAMES = ["top", "topRight", "aside", "main", "below"];
|
|
108516
|
+
function buildPanel(doc, el2, opts, locale, defaultLogoUrl) {
|
|
108517
|
+
const root = h2(doc, "section", { class: "myio-gcdr-panel", "data-fill": opts.fill ? "true" : null });
|
|
108518
|
+
if (opts.accent) root.style.setProperty("--myio-gcdr-accent", opts.accent);
|
|
108519
|
+
if (opts.bandColor) root.style.setProperty("--myio-gcdr-band", opts.bandColor);
|
|
108520
|
+
if (opts.tint) root.style.setProperty("--myio-gcdr-tint", opts.tint);
|
|
108521
|
+
const band = h2(doc, "header", { class: "myio-gcdr-panel__band" });
|
|
108522
|
+
if (opts.tint) band.appendChild(h2(doc, "span", { class: "myio-gcdr-panel__tint", "aria-hidden": "true" }));
|
|
108523
|
+
band.appendChild(h2(doc, "span", { class: "myio-gcdr-panel__eyebrow", text: localize(opts.eyebrow, locale) }));
|
|
108524
|
+
if (opts.logo !== false) {
|
|
108525
|
+
const url = opts.logoUrl ?? defaultLogoUrl;
|
|
108526
|
+
const wordmark = () => h2(doc, "span", { class: "myio-gcdr-panel__wordmark", text: "MYIO" });
|
|
108527
|
+
if (url) {
|
|
108528
|
+
const img = h2(doc, "img", { class: "myio-gcdr-panel__logo", src: url, alt: "MYIO" });
|
|
108529
|
+
img.addEventListener("error", () => img.replaceWith(wordmark()), { once: true });
|
|
108530
|
+
band.appendChild(img);
|
|
108531
|
+
} else band.appendChild(wordmark());
|
|
108532
|
+
}
|
|
108533
|
+
root.appendChild(band);
|
|
108534
|
+
const body = h2(doc, "div", { class: "myio-gcdr-panel__body" });
|
|
108535
|
+
let title;
|
|
108536
|
+
if (opts.title) {
|
|
108537
|
+
title = h2(doc, "h1", { class: "myio-gcdr-panel__title", text: localize(opts.title, locale), tabindex: "-1" });
|
|
108538
|
+
body.appendChild(title);
|
|
108539
|
+
}
|
|
108540
|
+
root.appendChild(body);
|
|
108541
|
+
let footer;
|
|
108542
|
+
if (opts.footer) {
|
|
108543
|
+
footer = h2(doc, "footer", { class: "myio-gcdr-panel__footer" });
|
|
108544
|
+
root.appendChild(footer);
|
|
108545
|
+
}
|
|
108546
|
+
el2.appendChild(root);
|
|
108547
|
+
return { root, body, footer, title };
|
|
108548
|
+
}
|
|
108549
|
+
function createShellImpl(container, options = {}, internals = {}) {
|
|
108550
|
+
if (!(container instanceof HTMLElement)) throw new TypeError("[MYIO Login] container must be an HTMLElement");
|
|
108551
|
+
const doc = container.ownerDocument;
|
|
108552
|
+
const prefix = options.storageKeyPrefix ?? "myio.login.";
|
|
108553
|
+
const releaseStyles = acquireStyles(container, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
|
|
108554
|
+
let themeSetting = options.theme ?? (storageGet(`${prefix}theme`) || "system");
|
|
108555
|
+
let locale = options.locale ?? detectLocale(storageGet(`${prefix}locale`));
|
|
108556
|
+
let size = options.size ?? "md";
|
|
108557
|
+
let width = options.width ?? "auto";
|
|
108558
|
+
const show = { themeToggle: options.show?.themeToggle !== false, languageSelector: options.show?.languageSelector !== false };
|
|
108559
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
108560
|
+
let destroyed = false;
|
|
108561
|
+
const resolvedTheme = () => themeSetting === "system" ? prefersDark() ? "dark" : "light" : themeSetting;
|
|
108562
|
+
const t = (key, vars) => translate(locale, key, vars, internals.messages);
|
|
108563
|
+
container.textContent = "";
|
|
108564
|
+
const root = h2(doc, "div", {
|
|
108565
|
+
class: "myio-gcdr-shell",
|
|
108566
|
+
"data-theme": resolvedTheme(),
|
|
108567
|
+
"data-size": size,
|
|
108568
|
+
"data-width": width,
|
|
108569
|
+
"data-aside-compact": options.asideCompact ?? "hide",
|
|
108570
|
+
"data-has-aside": "false",
|
|
108571
|
+
lang: locale
|
|
108572
|
+
});
|
|
108573
|
+
const wallpaper = h2(doc, "div", { class: "myio-gcdr-shell__wallpaper", "aria-hidden": "true" });
|
|
108574
|
+
const live = h2(doc, "div", { class: "myio-gcdr-sr", "aria-live": "polite", role: "status" });
|
|
108575
|
+
const top = h2(doc, "div", { class: "myio-gcdr-shell__top myio-gcdr-shell__slot", hidden: true });
|
|
108576
|
+
const block = h2(doc, "div", { class: "myio-gcdr-shell__block" });
|
|
108577
|
+
const toprow = h2(doc, "div", { class: "myio-gcdr-shell__toprow" });
|
|
108578
|
+
const pill = h2(doc, "div", { class: "myio-gcdr-shell__pill" });
|
|
108579
|
+
const langBtn = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn" });
|
|
108580
|
+
const themeBtn = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn" });
|
|
108581
|
+
const topRight = h2(doc, "div", { class: "myio-gcdr-shell__slot", style: "display:contents" });
|
|
108582
|
+
pill.append(langBtn, themeBtn, topRight);
|
|
108583
|
+
toprow.appendChild(pill);
|
|
108584
|
+
const split = h2(doc, "div", { class: "myio-gcdr-shell__split" });
|
|
108585
|
+
const aside = h2(doc, "section", { class: "myio-gcdr-shell__aside myio-gcdr-shell__slot", hidden: true, tabindex: "-1" });
|
|
108586
|
+
const main = h2(doc, "section", { class: "myio-gcdr-shell__main myio-gcdr-shell__slot", tabindex: "-1" });
|
|
108587
|
+
split.append(aside, main);
|
|
108588
|
+
const below = h2(doc, "div", { class: "myio-gcdr-shell__below myio-gcdr-shell__slot", hidden: true });
|
|
108589
|
+
block.append(toprow, split, below);
|
|
108590
|
+
root.append(wallpaper, live, top, block);
|
|
108591
|
+
container.appendChild(root);
|
|
108592
|
+
const applyWallpaper = () => {
|
|
108593
|
+
const wp = options.wallpaper;
|
|
108594
|
+
if (wp === false) {
|
|
108595
|
+
wallpaper.hidden = true;
|
|
108596
|
+
return;
|
|
108597
|
+
}
|
|
108598
|
+
wallpaper.hidden = false;
|
|
108599
|
+
const dark = resolvedTheme() === "dark";
|
|
108600
|
+
let portrait = false;
|
|
108601
|
+
try {
|
|
108602
|
+
portrait = typeof matchMedia === "function" && matchMedia("(orientation: portrait)").matches;
|
|
108603
|
+
} catch {
|
|
108604
|
+
}
|
|
108605
|
+
const url = wp ? dark ? portrait ? wp.mobileDark ?? wp.dark : wp.dark : portrait ? wp.mobileLight ?? wp.light : wp.light : void 0;
|
|
108606
|
+
if (url) wallpaper.style.setProperty("--myio-gcdr-wp", `url("${url.replace(/"/g, "%22")}")`);
|
|
108607
|
+
else wallpaper.style.removeProperty("--myio-gcdr-wp");
|
|
108608
|
+
};
|
|
108609
|
+
const renderControls = () => {
|
|
108610
|
+
langBtn.hidden = !show.languageSelector;
|
|
108611
|
+
themeBtn.hidden = !show.themeToggle;
|
|
108612
|
+
langBtn.textContent = "";
|
|
108613
|
+
langBtn.append(icon(doc, ICONS.globe(16)), h2(doc, "span", { text: locale === "en" ? "EN" : "PT" }));
|
|
108614
|
+
langBtn.setAttribute("aria-label", `${t("toolbar.language")}: ${locale === "en" ? "English" : "Portugu\xEAs"}`);
|
|
108615
|
+
const dark = resolvedTheme() === "dark";
|
|
108616
|
+
themeBtn.textContent = "";
|
|
108617
|
+
themeBtn.append(icon(doc, dark ? ICONS.sun(16) : ICONS.moon(16)));
|
|
108618
|
+
const lbl = dark ? t("toolbar.toLight") : t("toolbar.toDark");
|
|
108619
|
+
themeBtn.setAttribute("aria-label", lbl);
|
|
108620
|
+
themeBtn.setAttribute("title", lbl);
|
|
108621
|
+
};
|
|
108622
|
+
const emit = (what) => {
|
|
108623
|
+
for (const fn of Array.from(listeners)) safeCall("listener", fn, what);
|
|
108624
|
+
};
|
|
108625
|
+
const applyTheme = () => {
|
|
108626
|
+
root.setAttribute("data-theme", resolvedTheme());
|
|
108627
|
+
applyWallpaper();
|
|
108628
|
+
renderControls();
|
|
108629
|
+
emit("theme");
|
|
108630
|
+
};
|
|
108631
|
+
const applyLocale = () => {
|
|
108632
|
+
root.setAttribute("lang", locale);
|
|
108633
|
+
renderControls();
|
|
108634
|
+
emit("locale");
|
|
108635
|
+
};
|
|
108636
|
+
langBtn.addEventListener("click", () => {
|
|
108637
|
+
locale = locale === "en" ? "pt-BR" : "en";
|
|
108638
|
+
storageSet(`${prefix}locale`, locale);
|
|
108639
|
+
applyLocale();
|
|
108640
|
+
safeCall("onLocaleChange", options.onLocaleChange, locale);
|
|
108641
|
+
});
|
|
108642
|
+
themeBtn.addEventListener("click", () => {
|
|
108643
|
+
themeSetting = resolvedTheme() === "dark" ? "light" : "dark";
|
|
108644
|
+
storageSet(`${prefix}theme`, themeSetting);
|
|
108645
|
+
applyTheme();
|
|
108646
|
+
safeCall("onThemeChange", options.onThemeChange, themeSetting);
|
|
108647
|
+
});
|
|
108648
|
+
let mql = null;
|
|
108649
|
+
const onScheme = () => {
|
|
108650
|
+
if (themeSetting === "system") applyTheme();
|
|
108651
|
+
};
|
|
108652
|
+
try {
|
|
108653
|
+
if (typeof matchMedia === "function") {
|
|
108654
|
+
mql = matchMedia("(prefers-color-scheme: dark)");
|
|
108655
|
+
mql.addEventListener?.("change", onScheme);
|
|
108656
|
+
}
|
|
108657
|
+
} catch {
|
|
108658
|
+
mql = null;
|
|
108659
|
+
}
|
|
108660
|
+
const contextFor = (el2, signal) => ({
|
|
108661
|
+
get theme() {
|
|
108662
|
+
return resolvedTheme();
|
|
108663
|
+
},
|
|
108664
|
+
get locale() {
|
|
108665
|
+
return locale;
|
|
108666
|
+
},
|
|
108667
|
+
signal,
|
|
108668
|
+
on(event, fn) {
|
|
108669
|
+
const l = (w) => {
|
|
108670
|
+
if (w === event) fn(event === "theme" ? resolvedTheme() : locale);
|
|
108671
|
+
};
|
|
108672
|
+
listeners.add(l);
|
|
108673
|
+
const off = () => listeners.delete(l);
|
|
108674
|
+
signal.addEventListener("abort", off, { once: true });
|
|
108675
|
+
return off;
|
|
108676
|
+
},
|
|
108677
|
+
panel: (opts) => buildPanel(doc, el2, opts, locale, internals.logoUrl)
|
|
108678
|
+
});
|
|
108679
|
+
const slots = {};
|
|
108680
|
+
const slotEls = { top, topRight, aside, main, below };
|
|
108681
|
+
for (const n of SLOT_NAMES) slots[n] = { el: slotEls[n], kind: "empty", busy: false };
|
|
108682
|
+
const updateLayoutFlags = () => {
|
|
108683
|
+
root.setAttribute("data-has-aside", slots.aside.kind === "empty" ? "false" : "true");
|
|
108684
|
+
aside.hidden = slots.aside.kind === "empty";
|
|
108685
|
+
below.hidden = slots.below.kind === "empty";
|
|
108686
|
+
top.hidden = slots.top.kind === "empty";
|
|
108687
|
+
};
|
|
108688
|
+
const renderBuiltIn = (name, el2, ctx, b) => {
|
|
108689
|
+
if (b.kind === "buildInfo") {
|
|
108690
|
+
if (name !== "below") throw new TypeError("[MYIO Login] buildInfo is only valid in the below slot");
|
|
108691
|
+
el2.appendChild(h2(doc, "p", { class: "myio-gcdr-shell__build", text: b.text }));
|
|
108692
|
+
return;
|
|
108693
|
+
}
|
|
108694
|
+
if (name !== "aside") throw new TypeError(`[MYIO Login] ${b.kind} is only valid in the aside slot`);
|
|
108695
|
+
if (b.kind === "about") {
|
|
108696
|
+
const cleanupAbout = renderAbout(el2, ctx, t, { ...internals.about, healthUrl: b.healthUrl ?? false });
|
|
108697
|
+
const off2 = ctx.on("locale", () => {
|
|
108698
|
+
cleanupAbout();
|
|
108699
|
+
el2.textContent = "";
|
|
108700
|
+
renderAbout(el2, ctx, t, { ...internals.about, healthUrl: b.healthUrl ?? false });
|
|
108701
|
+
});
|
|
108702
|
+
return () => {
|
|
108703
|
+
off2();
|
|
108704
|
+
cleanupAbout();
|
|
108705
|
+
};
|
|
108706
|
+
}
|
|
108707
|
+
const text2 = () => b.text ? localize(b.text, locale) : t("aside.signedOutPrompt");
|
|
108708
|
+
renderSignedOutPrompt(el2, ctx, text2());
|
|
108709
|
+
const off = ctx.on("locale", () => {
|
|
108710
|
+
el2.textContent = "";
|
|
108711
|
+
renderSignedOutPrompt(el2, ctx, text2());
|
|
108712
|
+
});
|
|
108713
|
+
return off;
|
|
108714
|
+
};
|
|
108715
|
+
const setSlot = (name, content, opts) => {
|
|
108716
|
+
if (destroyed) return;
|
|
108717
|
+
if (!SLOT_NAMES.includes(name)) throw new TypeError(`[MYIO Login] unknown slot "${String(name)}"`);
|
|
108718
|
+
const s = slots[name];
|
|
108719
|
+
if (s.busy) {
|
|
108720
|
+
s.pending = { content, opts };
|
|
108721
|
+
queueMicrotask(() => {
|
|
108722
|
+
const p = s.pending;
|
|
108723
|
+
s.pending = void 0;
|
|
108724
|
+
if (p) setSlot(name, p.content, p.opts);
|
|
108725
|
+
});
|
|
108726
|
+
return;
|
|
108727
|
+
}
|
|
108728
|
+
const hadFocus = !!doc.activeElement && s.el.contains(doc.activeElement);
|
|
108729
|
+
s.busy = true;
|
|
108730
|
+
try {
|
|
108731
|
+
s.abort?.abort();
|
|
108732
|
+
if (s.cleanup) safeCall("slot cleanup", s.cleanup);
|
|
108733
|
+
s.cleanup = void 0;
|
|
108734
|
+
s.el.textContent = "";
|
|
108735
|
+
s.kind = "empty";
|
|
108736
|
+
if (content) {
|
|
108737
|
+
const ac = new AbortController();
|
|
108738
|
+
s.abort = ac;
|
|
108739
|
+
const ctx = contextFor(s.el, ac.signal);
|
|
108740
|
+
try {
|
|
108741
|
+
const r = typeof content === "function" ? content(s.el, ctx) : renderBuiltIn(name, s.el, ctx, content);
|
|
108742
|
+
if (typeof r === "function") s.cleanup = r;
|
|
108743
|
+
s.kind = typeof content === "function" ? "host" : "builtIn";
|
|
108744
|
+
} catch (err) {
|
|
108745
|
+
if (err instanceof TypeError && String(err.message).startsWith("[MYIO Login]")) throw err;
|
|
108746
|
+
console.error(`[MYIO Login] slot "${name}" renderer failed`);
|
|
108747
|
+
s.el.textContent = "";
|
|
108748
|
+
s.kind = "empty";
|
|
108749
|
+
}
|
|
108750
|
+
}
|
|
108751
|
+
} finally {
|
|
108752
|
+
s.busy = false;
|
|
108753
|
+
updateLayoutFlags();
|
|
108754
|
+
}
|
|
108755
|
+
const focus = opts?.focus ?? "auto";
|
|
108756
|
+
if (focus instanceof HTMLElement) focus.focus();
|
|
108757
|
+
else if (focus === "auto" && hadFocus && s.el.isConnected) {
|
|
108758
|
+
if (!s.el.hasAttribute("tabindex")) s.el.setAttribute("tabindex", "-1");
|
|
108759
|
+
s.el.focus();
|
|
108760
|
+
}
|
|
108761
|
+
if (opts?.announce) announce(localize(opts.announce, locale));
|
|
108762
|
+
};
|
|
108763
|
+
const announce = (text2) => {
|
|
108764
|
+
live.textContent = "";
|
|
108765
|
+
setTimeout(() => {
|
|
108766
|
+
if (!destroyed) live.textContent = text2;
|
|
108767
|
+
}, 30);
|
|
108768
|
+
};
|
|
108769
|
+
applyWallpaper();
|
|
108770
|
+
renderControls();
|
|
108771
|
+
if (options.buildInfo) setSlot("below", { kind: "buildInfo", text: options.buildInfo });
|
|
108772
|
+
const handle = {
|
|
108773
|
+
setSlot,
|
|
108774
|
+
setTheme(th) {
|
|
108775
|
+
if (destroyed) return;
|
|
108776
|
+
themeSetting = th;
|
|
108777
|
+
applyTheme();
|
|
108778
|
+
},
|
|
108779
|
+
setLocale(l) {
|
|
108780
|
+
if (destroyed || l !== "pt-BR" && l !== "en") return;
|
|
108781
|
+
locale = l;
|
|
108782
|
+
applyLocale();
|
|
108783
|
+
},
|
|
108784
|
+
setSize(sz, w) {
|
|
108785
|
+
if (destroyed) return;
|
|
108786
|
+
size = sz;
|
|
108787
|
+
if (w) width = w;
|
|
108788
|
+
root.setAttribute("data-size", size);
|
|
108789
|
+
root.setAttribute("data-width", width);
|
|
108790
|
+
},
|
|
108791
|
+
setShow(sh) {
|
|
108792
|
+
if (destroyed) return;
|
|
108793
|
+
if (sh.themeToggle !== void 0) show.themeToggle = sh.themeToggle;
|
|
108794
|
+
if (sh.languageSelector !== void 0) show.languageSelector = sh.languageSelector;
|
|
108795
|
+
renderControls();
|
|
108796
|
+
},
|
|
108797
|
+
getState() {
|
|
108798
|
+
const st = {};
|
|
108799
|
+
for (const n of SLOT_NAMES) st[n] = slots[n].kind;
|
|
108800
|
+
return { theme: resolvedTheme(), locale, size, width, slots: st };
|
|
108801
|
+
},
|
|
108802
|
+
get element() {
|
|
108803
|
+
return root;
|
|
108804
|
+
},
|
|
108805
|
+
destroy() {
|
|
108806
|
+
if (destroyed) return;
|
|
108807
|
+
for (const n of SLOT_NAMES) {
|
|
108808
|
+
const s = slots[n];
|
|
108809
|
+
s.abort?.abort();
|
|
108810
|
+
if (s.cleanup) safeCall("slot cleanup", s.cleanup);
|
|
108811
|
+
s.cleanup = void 0;
|
|
108812
|
+
}
|
|
108813
|
+
destroyed = true;
|
|
108814
|
+
listeners.clear();
|
|
108815
|
+
mql?.removeEventListener?.("change", onScheme);
|
|
108816
|
+
root.remove();
|
|
108817
|
+
releaseStyles();
|
|
108818
|
+
},
|
|
108819
|
+
t,
|
|
108820
|
+
contextFor,
|
|
108821
|
+
onChange(fn) {
|
|
108822
|
+
listeners.add(fn);
|
|
108823
|
+
return () => listeners.delete(fn);
|
|
108824
|
+
},
|
|
108825
|
+
announce
|
|
108826
|
+
};
|
|
108827
|
+
return handle;
|
|
108828
|
+
}
|
|
108829
|
+
function createMyioGcdrShell(container, options = {}) {
|
|
108830
|
+
const impl = createShellImpl(container, options);
|
|
108831
|
+
return {
|
|
108832
|
+
setSlot: impl.setSlot,
|
|
108833
|
+
setTheme: impl.setTheme,
|
|
108834
|
+
setLocale: impl.setLocale,
|
|
108835
|
+
setSize: impl.setSize,
|
|
108836
|
+
setShow: impl.setShow,
|
|
108837
|
+
getState: impl.getState,
|
|
108838
|
+
get element() {
|
|
108839
|
+
return impl.element;
|
|
108840
|
+
},
|
|
108841
|
+
destroy: impl.destroy
|
|
108842
|
+
};
|
|
108843
|
+
}
|
|
108844
|
+
|
|
108845
|
+
// src/components/myio-gcdr-login/controller.ts
|
|
108846
|
+
var EMAIL_PATTERN = /^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
108847
|
+
function validate(emailRaw, password) {
|
|
108848
|
+
const email = emailRaw.trim();
|
|
108849
|
+
let emailError;
|
|
108850
|
+
if (!email) emailError = "login.emailRequired";
|
|
108851
|
+
else if (!EMAIL_PATTERN.test(email)) emailError = "login.emailInvalid";
|
|
108852
|
+
const passwordError = password.length === 0 ? "login.passwordRequired" : void 0;
|
|
108853
|
+
return { email, emailError, passwordError };
|
|
108854
|
+
}
|
|
108855
|
+
function emailKey(email) {
|
|
108856
|
+
return email.trim().toLowerCase();
|
|
108857
|
+
}
|
|
108858
|
+
var KNOWN = /* @__PURE__ */ new Set([
|
|
108859
|
+
"INVALID_CREDENTIALS",
|
|
108860
|
+
"ACCOUNT_LOCKED",
|
|
108861
|
+
"CAPTCHA_FAILED",
|
|
108862
|
+
"TOO_MANY_REQUESTS",
|
|
108863
|
+
"MFA_REQUIRED",
|
|
108864
|
+
"NETWORK",
|
|
108865
|
+
"TIMEOUT",
|
|
108866
|
+
"SERVER",
|
|
108867
|
+
"INTEGRATION_ERROR",
|
|
108868
|
+
"CUSTOM"
|
|
108869
|
+
]);
|
|
108870
|
+
var ALIASES = {
|
|
108871
|
+
UNAUTHORIZED: "INVALID_CREDENTIALS",
|
|
108872
|
+
HTTP_401: "INVALID_CREDENTIALS",
|
|
108873
|
+
ACCOUNT_PENDING: "INVALID_CREDENTIALS",
|
|
108874
|
+
PENDING_APPROVAL: "INVALID_CREDENTIALS",
|
|
108875
|
+
ACCOUNT_SUSPENDED: "INVALID_CREDENTIALS",
|
|
108876
|
+
ACCOUNT_INACTIVE: "INVALID_CREDENTIALS",
|
|
108877
|
+
EMAIL_NOT_VERIFIED: "INVALID_CREDENTIALS",
|
|
108878
|
+
RATE_LIMITED: "TOO_MANY_REQUESTS",
|
|
108879
|
+
NETWORK_ERROR: "NETWORK"
|
|
108880
|
+
};
|
|
108881
|
+
function normaliseCode(code) {
|
|
108882
|
+
if (typeof code !== "string") return "SERVER";
|
|
108883
|
+
if (KNOWN.has(code)) return code;
|
|
108884
|
+
return ALIASES[code] ?? "SERVER";
|
|
108885
|
+
}
|
|
108886
|
+
function usableCounter(n) {
|
|
108887
|
+
return typeof n === "number" && Number.isInteger(n) && n >= 1 ? n : void 0;
|
|
108888
|
+
}
|
|
108889
|
+
function normaliseResult(raw) {
|
|
108890
|
+
if (!raw || typeof raw !== "object" || typeof raw.ok !== "boolean") {
|
|
108891
|
+
return { kind: "error", code: "INTEGRATION_ERROR" };
|
|
108892
|
+
}
|
|
108893
|
+
const r = raw;
|
|
108894
|
+
if (r.ok) return { kind: "ok", session: r.session };
|
|
108895
|
+
const code = normaliseCode(r.code);
|
|
108896
|
+
return {
|
|
108897
|
+
kind: "error",
|
|
108898
|
+
code,
|
|
108899
|
+
remainingAttempts: code === "INVALID_CREDENTIALS" ? usableCounter(r.remainingAttempts) : void 0,
|
|
108900
|
+
message: code === "CUSTOM" && typeof r.message === "string" ? r.message : void 0,
|
|
108901
|
+
clearPassword: code === "CUSTOM" ? r.clearPassword !== false : void 0
|
|
108902
|
+
};
|
|
108903
|
+
}
|
|
108904
|
+
function normaliseThrown(err) {
|
|
108905
|
+
if (err && typeof err === "object" && err.myioGcdrCode === "TIMEOUT") return "TIMEOUT";
|
|
108906
|
+
return err instanceof TypeError ? "NETWORK" : "SERVER";
|
|
108907
|
+
}
|
|
108908
|
+
var ATTEMPTS_THRESHOLD = 3;
|
|
108909
|
+
function present(o) {
|
|
108910
|
+
switch (o.code) {
|
|
108911
|
+
case "INVALID_CREDENTIALS": {
|
|
108912
|
+
const n = o.remainingAttempts;
|
|
108913
|
+
if (n === void 0)
|
|
108914
|
+
return { tone: "error", keys: ["errors.invalidCredentials"], icon: "alert", clearPassword: true, focus: "password" };
|
|
108915
|
+
if (n > ATTEMPTS_THRESHOLD)
|
|
108916
|
+
return { tone: "error", keys: ["errors.invalidWithAttempts"], count: n, icon: "alert", clearPassword: true, focus: "password" };
|
|
108917
|
+
if (n === 1)
|
|
108918
|
+
return { tone: "warning", keys: ["errors.lastAttempt", "errors.lockWarning"], icon: "shieldAlert", forgotLink: true, clearPassword: true, focus: "password" };
|
|
108919
|
+
return { tone: "warning", keys: ["errors.attemptsLeft", "errors.lockWarning"], count: n, icon: "shieldAlert", forgotLink: true, clearPassword: true, focus: "password" };
|
|
108920
|
+
}
|
|
108921
|
+
case "ACCOUNT_LOCKED":
|
|
108922
|
+
return { tone: "error", keys: ["errors.lockedText"], title: "errors.lockedTitle", icon: "lock", support: true, clearPassword: true, focus: "banner" };
|
|
108923
|
+
case "MFA_REQUIRED":
|
|
108924
|
+
return { tone: "error", keys: ["errors.mfaUnsupported"], icon: "shieldAlert", gcdrWebLink: true, support: true, clearPassword: true, focus: "banner" };
|
|
108925
|
+
case "CAPTCHA_FAILED":
|
|
108926
|
+
return { tone: "error", keys: ["errors.captchaFailed"], icon: "alert", clearPassword: false, focus: "captcha" };
|
|
108927
|
+
case "TOO_MANY_REQUESTS":
|
|
108928
|
+
return { tone: "error", keys: ["errors.tooManyRequests"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108929
|
+
case "NETWORK":
|
|
108930
|
+
return { tone: "error", keys: ["errors.networkError"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108931
|
+
case "TIMEOUT":
|
|
108932
|
+
return { tone: "error", keys: ["errors.timeout"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108933
|
+
case "INTEGRATION_ERROR":
|
|
108934
|
+
return { tone: "error", keys: ["errors.integrationError"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108935
|
+
case "CUSTOM": {
|
|
108936
|
+
const clear = o.clearPassword !== false;
|
|
108937
|
+
return {
|
|
108938
|
+
tone: "error",
|
|
108939
|
+
keys: o.message ? [] : ["errors.loginFailed"],
|
|
108940
|
+
text: o.message,
|
|
108941
|
+
icon: "alert",
|
|
108942
|
+
clearPassword: clear,
|
|
108943
|
+
focus: clear ? "password" : "submit"
|
|
108944
|
+
};
|
|
108945
|
+
}
|
|
108946
|
+
case "SERVER":
|
|
108947
|
+
default:
|
|
108948
|
+
return { tone: "error", keys: ["errors.loginFailed"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108949
|
+
}
|
|
108950
|
+
}
|
|
108951
|
+
|
|
108952
|
+
// src/components/myio-gcdr-login/gcdrClient.ts
|
|
108953
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
108954
|
+
function timeoutError() {
|
|
108955
|
+
const e = new Error("GCDR login timed out");
|
|
108956
|
+
e.myioGcdrCode = "TIMEOUT";
|
|
108957
|
+
return e;
|
|
108958
|
+
}
|
|
108959
|
+
function createMyioGcdrLoginSubmit(options) {
|
|
108960
|
+
if (!options || typeof options.apiUrl !== "string" || !options.apiUrl.trim()) {
|
|
108961
|
+
throw new TypeError("[MYIO Login] gcdr.apiUrl must be a non-empty string");
|
|
108962
|
+
}
|
|
108963
|
+
if (typeof options.tenantId !== "string" || !options.tenantId.trim()) {
|
|
108964
|
+
throw new TypeError("[MYIO Login] gcdr.tenantId must be a non-empty string");
|
|
108965
|
+
}
|
|
108966
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
108967
|
+
if (!(typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0)) {
|
|
108968
|
+
throw new TypeError("[MYIO Login] gcdr.timeoutMs must be a positive number");
|
|
108969
|
+
}
|
|
108970
|
+
const base = options.apiUrl.replace(/\/+$/, "").replace(/\/api\/v\d+$/, "");
|
|
108971
|
+
const url = `${base}/api/v1/auth/login`;
|
|
108972
|
+
return async (input, ctx) => {
|
|
108973
|
+
const doFetch = options.fetch ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
|
|
108974
|
+
if (!doFetch) throw new TypeError("fetch is not available");
|
|
108975
|
+
const ac = new AbortController();
|
|
108976
|
+
let timedOut = false;
|
|
108977
|
+
const onOuterAbort = () => ac.abort();
|
|
108978
|
+
if (ctx?.signal) {
|
|
108979
|
+
if (ctx.signal.aborted) ac.abort();
|
|
108980
|
+
else ctx.signal.addEventListener("abort", onOuterAbort, { once: true });
|
|
108981
|
+
}
|
|
108982
|
+
const timer = setTimeout(() => {
|
|
108983
|
+
timedOut = true;
|
|
108984
|
+
ac.abort();
|
|
108985
|
+
}, timeoutMs);
|
|
108986
|
+
const body = { email: input.email, password: input.password };
|
|
108987
|
+
if (input.captchaToken) body.captchaToken = input.captchaToken;
|
|
108988
|
+
let res;
|
|
108989
|
+
try {
|
|
108990
|
+
res = await doFetch(url, {
|
|
108991
|
+
method: "POST",
|
|
108992
|
+
headers: { "Content-Type": "application/json", "x-tenant-id": options.tenantId, ...options.extraHeaders ?? {} },
|
|
108993
|
+
body: JSON.stringify(body),
|
|
108994
|
+
credentials: "omit",
|
|
108995
|
+
redirect: "error",
|
|
108996
|
+
signal: ac.signal
|
|
108997
|
+
});
|
|
108998
|
+
} catch (err) {
|
|
108999
|
+
if (timedOut) throw timeoutError();
|
|
109000
|
+
if (ac.signal.aborted) throw err;
|
|
109001
|
+
return { ok: false, code: "NETWORK" };
|
|
109002
|
+
} finally {
|
|
109003
|
+
clearTimeout(timer);
|
|
109004
|
+
ctx?.signal?.removeEventListener("abort", onOuterAbort);
|
|
109005
|
+
}
|
|
109006
|
+
let json = void 0;
|
|
109007
|
+
try {
|
|
109008
|
+
json = await res.json();
|
|
109009
|
+
} catch {
|
|
109010
|
+
json = void 0;
|
|
109011
|
+
}
|
|
109012
|
+
return mapGcdrResponse(res.status, json);
|
|
109013
|
+
};
|
|
109014
|
+
}
|
|
109015
|
+
function mapGcdrResponse(status, json) {
|
|
109016
|
+
const j = json && typeof json === "object" ? json : {};
|
|
109017
|
+
if (status >= 200 && status < 300) {
|
|
109018
|
+
const data = j.data;
|
|
109019
|
+
if (data && data.mfaRequired === true) return { ok: false, code: "MFA_REQUIRED" };
|
|
109020
|
+
if (data && typeof data.accessToken === "string" && data.accessToken) return { ok: true, session: data };
|
|
109021
|
+
return { ok: false, code: "INTEGRATION_ERROR" };
|
|
109022
|
+
}
|
|
109023
|
+
const code = typeof j.error?.code === "string" ? j.error.code : void 0;
|
|
109024
|
+
const remaining = j.error?.details?.remainingAttempts;
|
|
109025
|
+
switch (status) {
|
|
109026
|
+
case 400:
|
|
109027
|
+
return { ok: false, code: code === "CAPTCHA_FAILED" ? "CAPTCHA_FAILED" : "SERVER" };
|
|
109028
|
+
case 401:
|
|
109029
|
+
return code === "INVALID_CREDENTIALS" && typeof remaining === "number" ? { ok: false, code: "INVALID_CREDENTIALS", remainingAttempts: remaining } : { ok: false, code: "INVALID_CREDENTIALS" };
|
|
109030
|
+
case 403:
|
|
109031
|
+
return { ok: false, code: code === "ACCOUNT_LOCKED" ? "ACCOUNT_LOCKED" : "SERVER" };
|
|
109032
|
+
case 429:
|
|
109033
|
+
return { ok: false, code: "TOO_MANY_REQUESTS" };
|
|
109034
|
+
default:
|
|
109035
|
+
return { ok: false, code: "SERVER" };
|
|
109036
|
+
}
|
|
109037
|
+
}
|
|
109038
|
+
|
|
109039
|
+
// src/components/myio-gcdr-login/loginView.ts
|
|
109040
|
+
var DEFAULT_SUBMIT_TIMEOUT_MS = 3e4;
|
|
109041
|
+
function fail(msg, code) {
|
|
109042
|
+
const e = new TypeError(`[MYIO Login] ${msg}`);
|
|
109043
|
+
if (code) e.code = code;
|
|
109044
|
+
throw e;
|
|
109045
|
+
}
|
|
109046
|
+
function validateOptions3(container, o) {
|
|
109047
|
+
if (!(container instanceof HTMLElement)) fail("container must be an HTMLElement");
|
|
109048
|
+
if (!o || typeof o !== "object") fail("options are required");
|
|
109049
|
+
const n = [o.onSubmit, o.gcdr, o.auth].filter((x) => x != null).length;
|
|
109050
|
+
if (n !== 1) fail("exactly one of onSubmit, gcdr or auth is required");
|
|
109051
|
+
if (o.auth && o.auth.kind !== "credentials") {
|
|
109052
|
+
fail(`auth.kind "${String(o.auth.kind)}" is not supported`, "MYIO_GCDR_AUTH_UNSUPPORTED");
|
|
109053
|
+
}
|
|
109054
|
+
if (o.auth && typeof o.auth.submit !== "function") fail("auth.submit must be a function");
|
|
109055
|
+
if (o.onSubmit && typeof o.onSubmit !== "function") fail("onSubmit must be a function");
|
|
109056
|
+
if (typeof o.onSuccess !== "function") fail("onSuccess must be a function");
|
|
109057
|
+
if (o.submitTimeoutMs != null && !(Number.isFinite(o.submitTimeoutMs) && o.submitTimeoutMs > 0)) fail("submitTimeoutMs must be a positive number");
|
|
109058
|
+
if (o.captcha) fail("captcha is not available in this version (RFC-0236 PR 2)", "MYIO_GCDR_CAPTCHA_UNSUPPORTED");
|
|
109059
|
+
const kinds = ["about", "signedOutPrompt", "custom", "none"];
|
|
109060
|
+
if (o.aside && !kinds.includes(o.aside.kind)) fail(`unknown aside.kind "${String(o.aside.kind)}"`);
|
|
109061
|
+
if (o.aside?.kind === "custom" && typeof o.aside.render !== "function") fail("aside.render must be a function");
|
|
109062
|
+
if (o.support && (typeof o.support.href !== "string" || !o.support.href)) fail("support.href must be a non-empty string");
|
|
109063
|
+
if (o.embed) {
|
|
109064
|
+
const bad = ["aside", "buildInfo", "theme", "locale", "assets"].filter((k) => o[k] !== void 0);
|
|
109065
|
+
if (o.show?.themeToggle !== void 0 || o.show?.languageSelector !== void 0 || o.show?.wallpaper !== void 0) bad.push("show.(theme|language|wallpaper)");
|
|
109066
|
+
if (bad.length) fail(`with embed, these options belong to the host shell: ${bad.join(", ")}`);
|
|
109067
|
+
if (!o.embed.context || typeof o.embed.context.on !== "function") fail("embed.context must be a slot context");
|
|
109068
|
+
}
|
|
109069
|
+
}
|
|
109070
|
+
function createLoginViewImpl(container, options, internals = {}) {
|
|
109071
|
+
validateOptions3(container, options);
|
|
109072
|
+
const doc = container.ownerDocument;
|
|
109073
|
+
const presentation = internals.presentation ?? "inline";
|
|
109074
|
+
const prefix = options.storageKeyPrefix ?? "myio.login.";
|
|
109075
|
+
const isGcdr = !!options.gcdr;
|
|
109076
|
+
const webUrl = options.links?.gcdrWebUrl?.replace(/\/+$/, "");
|
|
109077
|
+
const strategy = options.gcdr ? createMyioGcdrLoginSubmit(options.gcdr) : options.auth ? options.auth.submit : options.onSubmit;
|
|
109078
|
+
const viewTimeoutMs = isGcdr ? void 0 : options.submitTimeoutMs ?? DEFAULT_SUBMIT_TIMEOUT_MS;
|
|
109079
|
+
let shell;
|
|
109080
|
+
let embedCtx;
|
|
109081
|
+
let releaseEmbedStyles;
|
|
109082
|
+
let cardHost;
|
|
109083
|
+
if (options.embed) {
|
|
109084
|
+
embedCtx = options.embed.context;
|
|
109085
|
+
releaseEmbedStyles = acquireStyles(container, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
|
|
109086
|
+
container.textContent = "";
|
|
109087
|
+
cardHost = container;
|
|
109088
|
+
} else {
|
|
109089
|
+
const wpOpt = internals.shellWallpaper === false || options.show?.wallpaper === false ? false : options.assets?.wallpaper ?? {};
|
|
109090
|
+
shell = createShellImpl(
|
|
109091
|
+
container,
|
|
109092
|
+
{
|
|
109093
|
+
size: options.size ?? "md",
|
|
109094
|
+
theme: options.theme,
|
|
109095
|
+
locale: options.locale,
|
|
109096
|
+
show: { themeToggle: options.show?.themeToggle, languageSelector: options.show?.languageSelector },
|
|
109097
|
+
buildInfo: options.buildInfo,
|
|
109098
|
+
storageKeyPrefix: options.storageKeyPrefix,
|
|
109099
|
+
fonts: options.fonts,
|
|
109100
|
+
cspNonce: options.cspNonce,
|
|
109101
|
+
wallpaper: wpOpt === false ? false : wpOpt,
|
|
109102
|
+
onThemeChange: options.onThemeChange,
|
|
109103
|
+
onLocaleChange: options.onLocaleChange
|
|
109104
|
+
},
|
|
109105
|
+
{
|
|
109106
|
+
messages: options.messages,
|
|
109107
|
+
logoUrl: options.assets?.logoUrl,
|
|
109108
|
+
about: { webUrl, fetchImpl: options.gcdr?.fetch, bandColor: options.brand?.asideHeaderColor }
|
|
109109
|
+
}
|
|
109110
|
+
);
|
|
109111
|
+
cardHost = h2(doc, "div", { style: "display:flex;width:100%" });
|
|
109112
|
+
}
|
|
109113
|
+
const getLocale = () => shell ? shell.getState().locale : embedCtx.locale;
|
|
109114
|
+
const getTheme = () => shell ? shell.getState().theme : embedCtx.theme;
|
|
109115
|
+
const t = (key, vars) => translate(getLocale(), key, vars, options.messages);
|
|
109116
|
+
let phase = "idle";
|
|
109117
|
+
let destroyed = false;
|
|
109118
|
+
let attempt = 0;
|
|
109119
|
+
let attemptAbort = null;
|
|
109120
|
+
let abortCause = null;
|
|
109121
|
+
let successAbort = null;
|
|
109122
|
+
let err = {};
|
|
109123
|
+
let lockedKey = null;
|
|
109124
|
+
let noCounterStreak = 0;
|
|
109125
|
+
let streakKey = null;
|
|
109126
|
+
let notice = options.notice ?? null;
|
|
109127
|
+
let fieldErrors = {};
|
|
109128
|
+
const remembered = storageGet(`${prefix}rememberedEmail`);
|
|
109129
|
+
let emailValue = options.initialEmail ?? remembered ?? "";
|
|
109130
|
+
let rememberValue = !options.initialEmail && !!remembered;
|
|
109131
|
+
let passwordValue = "";
|
|
109132
|
+
let passwordVisible = false;
|
|
109133
|
+
let leaving = false;
|
|
109134
|
+
const linkTarget = options.links?.target ?? (presentation === "modal" ? "_blank" : "_self");
|
|
109135
|
+
const forgot = options.links?.forgotPassword;
|
|
109136
|
+
const forgotShown = forgot === false ? false : !!forgot || isGcdr && !!webUrl;
|
|
109137
|
+
const supportHref = options.support === false ? void 0 : options.support ? options.support.href : (options.aside?.kind ?? "about") === "about" ? defaultSupportHref(webUrl) : void 0;
|
|
109138
|
+
let els = {};
|
|
109139
|
+
const linkEl = (label, target, cls = "myio-gcdr-login__link") => {
|
|
109140
|
+
if (typeof target === "function") {
|
|
109141
|
+
const b = h2(doc, "button", { type: "button", class: cls, text: label });
|
|
109142
|
+
b.addEventListener("click", () => safeCall("link", target, { email: emailValue.trim() }));
|
|
109143
|
+
return b;
|
|
109144
|
+
}
|
|
109145
|
+
const a = h2(doc, "a", { class: cls, href: target, target: linkTarget, rel: linkTarget === "_blank" ? "noopener noreferrer" : null }, label);
|
|
109146
|
+
if (linkTarget === "_blank") a.appendChild(h2(doc, "span", { class: "myio-gcdr-sr", text: ` ${t("login.newTab")}` }));
|
|
109147
|
+
return a;
|
|
109148
|
+
};
|
|
109149
|
+
const forgotTarget = () => !forgotShown ? void 0 : typeof forgot === "string" || typeof forgot === "function" ? forgot : `${webUrl}/forgot-password`;
|
|
109150
|
+
const renderNotice = () => {
|
|
109151
|
+
if (!els.notice) return;
|
|
109152
|
+
els.notice.textContent = "";
|
|
109153
|
+
if (!notice) return;
|
|
109154
|
+
const key = presentation === "modal" ? "notice.sessionExpiredModal" : "notice.sessionExpired";
|
|
109155
|
+
els.notice.appendChild(
|
|
109156
|
+
h2(
|
|
109157
|
+
doc,
|
|
109158
|
+
"div",
|
|
109159
|
+
{ class: "myio-gcdr-banner myio-gcdr-banner--info" },
|
|
109160
|
+
icon(doc, ICONS.info(16), "myio-gcdr-banner__icon"),
|
|
109161
|
+
h2(doc, "div", { class: "myio-gcdr-banner__body" }, h2(doc, "span", { text: t(key) }))
|
|
109162
|
+
)
|
|
109163
|
+
);
|
|
109164
|
+
};
|
|
109165
|
+
const renderAlerts = () => {
|
|
109166
|
+
if (!els.alerts) return;
|
|
109167
|
+
els.alerts.textContent = "";
|
|
109168
|
+
els.banner = void 0;
|
|
109169
|
+
if (!err.pres && !err.messageKey) return;
|
|
109170
|
+
const p = err.pres;
|
|
109171
|
+
const tone = p?.tone ?? "error";
|
|
109172
|
+
const body = h2(doc, "div", { class: "myio-gcdr-banner__body" });
|
|
109173
|
+
if (p?.title) body.appendChild(h2(doc, "span", { class: "myio-gcdr-banner__title", text: t(p.title) }));
|
|
109174
|
+
if (p) {
|
|
109175
|
+
if (p.text) body.appendChild(h2(doc, "span", { text: p.text }));
|
|
109176
|
+
p.keys.forEach((k, i) => body.appendChild(h2(doc, "span", { text: t(k, i === 0 && p.count !== void 0 ? { count: p.count } : void 0) })));
|
|
109177
|
+
if (p.forgotLink) {
|
|
109178
|
+
const ft = forgotTarget();
|
|
109179
|
+
if (ft) body.appendChild(linkEl(t("errors.goToForgot"), ft, ""));
|
|
109180
|
+
}
|
|
109181
|
+
if (p.gcdrWebLink && webUrl) body.appendChild(linkEl(t("login.gcdrWeb"), `${webUrl}/login`, ""));
|
|
109182
|
+
if (p.support && supportHref) body.appendChild(linkEl(t("login.support"), supportHref, ""));
|
|
109183
|
+
} else if (err.messageKey) {
|
|
109184
|
+
body.appendChild(h2(doc, "span", { text: t(err.messageKey) }));
|
|
109185
|
+
}
|
|
109186
|
+
if (err.help) {
|
|
109187
|
+
const who = supportHref ? t("errors.helpSupport") : t("errors.helpAdmin");
|
|
109188
|
+
body.appendChild(h2(doc, "span", { text: t("errors.invalidCredentialsHelp", { who }) }));
|
|
109189
|
+
if (supportHref) body.appendChild(linkEl(t("login.support"), supportHref, ""));
|
|
109190
|
+
}
|
|
109191
|
+
const ic = p?.icon === "lock" ? ICONS.lock(16) : p?.icon === "shieldAlert" ? ICONS.shieldAlert(16) : ICONS.alert(16);
|
|
109192
|
+
const banner = h2(doc, "div", { class: `myio-gcdr-banner myio-gcdr-banner--${tone}`, tabindex: "-1" }, icon(doc, ic, "myio-gcdr-banner__icon"), body);
|
|
109193
|
+
els.alerts.appendChild(banner);
|
|
109194
|
+
els.banner = banner;
|
|
109195
|
+
};
|
|
109196
|
+
const syncControls = () => {
|
|
109197
|
+
if (!els.submit || !els.email || !els.password) return;
|
|
109198
|
+
const busy = phase === "submitting" || phase === "success";
|
|
109199
|
+
const blocked = busy || leaving || !!lockedKey;
|
|
109200
|
+
els.submit.setAttribute("aria-disabled", blocked ? "true" : "false");
|
|
109201
|
+
els.submit.setAttribute("aria-busy", busy ? "true" : "false");
|
|
109202
|
+
if (lockedKey && els.banner) {
|
|
109203
|
+
if (!els.banner.id) els.banner.id = `myio-gcdr-lock-${Math.random().toString(36).slice(2, 8)}`;
|
|
109204
|
+
els.submit.setAttribute("aria-describedby", els.banner.id);
|
|
109205
|
+
} else els.submit.removeAttribute("aria-describedby");
|
|
109206
|
+
els.submit.textContent = "";
|
|
109207
|
+
if (busy) {
|
|
109208
|
+
els.submit.append(icon(doc, ICONS.spinner(18), "myio-gcdr-login__spin"), h2(doc, "span", { text: t("login.signingIn") }));
|
|
109209
|
+
} else els.submit.append(h2(doc, "span", { text: t("login.signIn") }));
|
|
109210
|
+
els.email.readOnly = busy || leaving;
|
|
109211
|
+
els.password.readOnly = busy || leaving;
|
|
109212
|
+
};
|
|
109213
|
+
const render3 = () => {
|
|
109214
|
+
if (destroyed) return;
|
|
109215
|
+
if (els.email) emailValue = els.email.value;
|
|
109216
|
+
if (els.password) passwordValue = els.password.value;
|
|
109217
|
+
const hadFocusId = doc.activeElement && cardHost.contains(doc.activeElement) ? doc.activeElement.getAttribute("data-k") : null;
|
|
109218
|
+
cardHost.textContent = "";
|
|
109219
|
+
const locale = getLocale();
|
|
109220
|
+
const { root, body, footer, title } = buildPanel(
|
|
109221
|
+
doc,
|
|
109222
|
+
cardHost,
|
|
109223
|
+
{ eyebrow: options.brand?.label ?? t("login.eyebrow"), title: t("login.title"), footer: true, accent: options.brand?.accent, bandColor: options.brand?.bandColor, tint: options.brand?.tint, logoUrl: options.assets?.logoUrl },
|
|
109224
|
+
locale
|
|
109225
|
+
);
|
|
109226
|
+
if (options.size && options.embed) root.style.maxWidth = options.size === "xl" ? "37rem" : options.size === "lg" ? "32rem" : "28rem";
|
|
109227
|
+
else if (options.embed) root.style.maxWidth = "28rem";
|
|
109228
|
+
root.style.margin = "0 auto";
|
|
109229
|
+
if (options.brand?.accent) root.style.setProperty("--myio-gcdr-accent-hover", options.brand.accent);
|
|
109230
|
+
root.setAttribute("data-theme", getTheme());
|
|
109231
|
+
els = { root, title };
|
|
109232
|
+
const noticeEl = h2(doc, "div", { class: "myio-gcdr-login__alerts", role: "status", "aria-live": "polite" });
|
|
109233
|
+
const alerts = h2(doc, "div", { class: "myio-gcdr-login__alerts", role: "alert" });
|
|
109234
|
+
els.notice = noticeEl;
|
|
109235
|
+
els.alerts = alerts;
|
|
109236
|
+
const form = h2(doc, "form", { class: "myio-gcdr-login__form", novalidate: true });
|
|
109237
|
+
const uid2 = Math.random().toString(36).slice(2, 8);
|
|
109238
|
+
const email = h2(doc, "input", {
|
|
109239
|
+
id: `myio-gcdr-email-${uid2}`,
|
|
109240
|
+
"data-k": "email",
|
|
109241
|
+
class: "myio-gcdr-login__input",
|
|
109242
|
+
type: "email",
|
|
109243
|
+
inputmode: "email",
|
|
109244
|
+
autocomplete: "username",
|
|
109245
|
+
autocapitalize: "none",
|
|
109246
|
+
spellcheck: "false",
|
|
109247
|
+
placeholder: t("login.emailPlaceholder"),
|
|
109248
|
+
"aria-invalid": fieldErrors.email ? "true" : "false"
|
|
109249
|
+
});
|
|
109250
|
+
email.value = emailValue;
|
|
109251
|
+
const emailErr = h2(doc, "span", { id: `myio-gcdr-email-err-${uid2}`, class: "myio-gcdr-login__fielderror", text: fieldErrors.email ? t(fieldErrors.email) : "" });
|
|
109252
|
+
if (fieldErrors.email) email.setAttribute("aria-describedby", emailErr.id);
|
|
109253
|
+
const emailField = h2(
|
|
109254
|
+
doc,
|
|
109255
|
+
"div",
|
|
109256
|
+
{ class: "myio-gcdr-login__field" },
|
|
109257
|
+
h2(doc, "label", { class: "myio-gcdr-login__label", for: email.id, text: t("login.email") }),
|
|
109258
|
+
email,
|
|
109259
|
+
fieldErrors.email ? emailErr : null
|
|
109260
|
+
);
|
|
109261
|
+
if (options.initialEmail) {
|
|
109262
|
+
const notYou = h2(doc, "button", { type: "button", class: "myio-gcdr-login__link", text: t("login.notYou") });
|
|
109263
|
+
notYou.addEventListener("click", () => {
|
|
109264
|
+
email.value = "";
|
|
109265
|
+
emailValue = "";
|
|
109266
|
+
onEmailInput();
|
|
109267
|
+
email.focus();
|
|
109268
|
+
});
|
|
109269
|
+
emailField.appendChild(notYou);
|
|
109270
|
+
}
|
|
109271
|
+
const password = h2(doc, "input", {
|
|
109272
|
+
id: `myio-gcdr-pass-${uid2}`,
|
|
109273
|
+
"data-k": "password",
|
|
109274
|
+
class: "myio-gcdr-login__input myio-gcdr-login__input--password",
|
|
109275
|
+
type: passwordVisible ? "text" : "password",
|
|
109276
|
+
autocomplete: "current-password",
|
|
109277
|
+
enterkeyhint: "go",
|
|
109278
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
109279
|
+
"aria-invalid": fieldErrors.password ? "true" : "false"
|
|
109280
|
+
});
|
|
109281
|
+
password.value = passwordValue;
|
|
109282
|
+
const passErr = h2(doc, "span", { id: `myio-gcdr-pass-err-${uid2}`, class: "myio-gcdr-login__fielderror", text: fieldErrors.password ? t(fieldErrors.password) : "" });
|
|
109283
|
+
if (fieldErrors.password) password.setAttribute("aria-describedby", passErr.id);
|
|
109284
|
+
const control = h2(doc, "div", { class: "myio-gcdr-login__control" }, password);
|
|
109285
|
+
if (options.show?.passwordToggle !== false) {
|
|
109286
|
+
const eye = h2(doc, "button", { type: "button", class: "myio-gcdr-login__eye", "aria-pressed": passwordVisible ? "true" : "false", "aria-label": t(passwordVisible ? "login.hidePassword" : "login.showPassword"), "aria-controls": password.id });
|
|
109287
|
+
eye.appendChild(icon(doc, passwordVisible ? ICONS.eyeOff(18) : ICONS.eye(18)));
|
|
109288
|
+
eye.addEventListener("click", () => {
|
|
109289
|
+
passwordVisible = !passwordVisible;
|
|
109290
|
+
password.type = passwordVisible ? "text" : "password";
|
|
109291
|
+
eye.setAttribute("aria-pressed", passwordVisible ? "true" : "false");
|
|
109292
|
+
eye.setAttribute("aria-label", t(passwordVisible ? "login.hidePassword" : "login.showPassword"));
|
|
109293
|
+
eye.textContent = "";
|
|
109294
|
+
eye.appendChild(icon(doc, passwordVisible ? ICONS.eyeOff(18) : ICONS.eye(18)));
|
|
109295
|
+
});
|
|
109296
|
+
control.appendChild(eye);
|
|
109297
|
+
}
|
|
109298
|
+
const caps = h2(doc, "span", { class: "myio-gcdr-login__hint", "aria-live": "polite" });
|
|
109299
|
+
const capsCheck = (e) => {
|
|
109300
|
+
const on = typeof e.getModifierState === "function" && e.getModifierState("CapsLock");
|
|
109301
|
+
caps.textContent = on ? t("login.capsLockOn") : "";
|
|
109302
|
+
};
|
|
109303
|
+
password.addEventListener("keydown", capsCheck);
|
|
109304
|
+
password.addEventListener("keyup", capsCheck);
|
|
109305
|
+
const passField = h2(
|
|
109306
|
+
doc,
|
|
109307
|
+
"div",
|
|
109308
|
+
{ class: "myio-gcdr-login__field" },
|
|
109309
|
+
h2(doc, "label", { class: "myio-gcdr-login__label", for: password.id, text: t("login.password") }),
|
|
109310
|
+
control,
|
|
109311
|
+
caps,
|
|
109312
|
+
fieldErrors.password ? passErr : null
|
|
109313
|
+
);
|
|
109314
|
+
const row = h2(doc, "div", { class: "myio-gcdr-login__row" });
|
|
109315
|
+
if (options.show?.rememberMe !== false) {
|
|
109316
|
+
const cb = h2(doc, "input", { type: "checkbox" });
|
|
109317
|
+
cb.checked = rememberValue;
|
|
109318
|
+
cb.addEventListener("change", () => {
|
|
109319
|
+
rememberValue = cb.checked;
|
|
109320
|
+
});
|
|
109321
|
+
row.appendChild(h2(doc, "label", { class: "myio-gcdr-login__remember" }, cb, h2(doc, "span", { text: t("login.rememberMe") })));
|
|
109322
|
+
} else row.appendChild(h2(doc, "span"));
|
|
109323
|
+
const ft = forgotTarget();
|
|
109324
|
+
if (ft) row.appendChild(linkEl(t("login.forgotPassword"), ft));
|
|
109325
|
+
const submit = h2(doc, "button", { type: "submit", "data-k": "submit", class: "myio-gcdr-login__submit", "data-style": options.submitStyle ?? "auth" });
|
|
109326
|
+
form.append(emailField, passField, row, submit);
|
|
109327
|
+
form.addEventListener("submit", (e) => {
|
|
109328
|
+
e.preventDefault();
|
|
109329
|
+
void doSubmit();
|
|
109330
|
+
});
|
|
109331
|
+
email.addEventListener("input", () => {
|
|
109332
|
+
emailValue = email.value;
|
|
109333
|
+
onEmailInput();
|
|
109334
|
+
});
|
|
109335
|
+
password.addEventListener("input", () => {
|
|
109336
|
+
passwordValue = password.value;
|
|
109337
|
+
if (fieldErrors.password) {
|
|
109338
|
+
fieldErrors.password = validate(email.value, password.value).passwordError;
|
|
109339
|
+
if (!fieldErrors.password) {
|
|
109340
|
+
password.setAttribute("aria-invalid", "false");
|
|
109341
|
+
passErr.remove();
|
|
109342
|
+
}
|
|
109343
|
+
}
|
|
109344
|
+
});
|
|
109345
|
+
body.append(noticeEl, alerts, form);
|
|
109346
|
+
if (footer) {
|
|
109347
|
+
const reg = options.links?.register;
|
|
109348
|
+
if (reg) {
|
|
109349
|
+
footer.append(h2(doc, "span", { text: `${t("login.noAccount")} ` }), linkEl(t("login.createAccount"), reg));
|
|
109350
|
+
} else footer.appendChild(h2(doc, "span", { text: options.footerText ? localize(options.footerText, locale) : t("login.askAdmin") }));
|
|
109351
|
+
internals.decorateFooter?.(footer, api);
|
|
109352
|
+
}
|
|
109353
|
+
els = { ...els, email, password, submit, caps };
|
|
109354
|
+
renderNotice();
|
|
109355
|
+
renderAlerts();
|
|
109356
|
+
syncControls();
|
|
109357
|
+
if (hadFocusId) cardHost.querySelector(`[data-k="${hadFocusId}"]`)?.focus();
|
|
109358
|
+
};
|
|
109359
|
+
const onEmailInput = () => {
|
|
109360
|
+
const key = emailKey(emailValue);
|
|
109361
|
+
if (fieldErrors.email) {
|
|
109362
|
+
fieldErrors.email = validate(emailValue, "").emailError;
|
|
109363
|
+
if (!fieldErrors.email) render3();
|
|
109364
|
+
}
|
|
109365
|
+
if (lockedKey && key !== lockedKey) {
|
|
109366
|
+
lockedKey = null;
|
|
109367
|
+
err = {};
|
|
109368
|
+
renderAlerts();
|
|
109369
|
+
syncControls();
|
|
109370
|
+
}
|
|
109371
|
+
if (streakKey && key !== streakKey) {
|
|
109372
|
+
noCounterStreak = 0;
|
|
109373
|
+
streakKey = null;
|
|
109374
|
+
}
|
|
109375
|
+
};
|
|
109376
|
+
const focusTarget = (f) => {
|
|
109377
|
+
const el2 = f === "password" ? els.password : f === "email" ? els.email : f === "banner" ? els.banner : els.submit;
|
|
109378
|
+
el2?.focus();
|
|
109379
|
+
};
|
|
109380
|
+
const setError = (code, pres, opts) => {
|
|
109381
|
+
err = { code, pres, help: opts.help };
|
|
109382
|
+
if (pres.clearPassword && els.password) {
|
|
109383
|
+
els.password.value = "";
|
|
109384
|
+
passwordValue = "";
|
|
109385
|
+
}
|
|
109386
|
+
renderAlerts();
|
|
109387
|
+
syncControls();
|
|
109388
|
+
focusTarget(pres.focus);
|
|
109389
|
+
if (opts.notify !== false) safeCall("onError", options.onError, { code, remainingAttempts: opts.remaining });
|
|
109390
|
+
};
|
|
109391
|
+
const doSubmit = async () => {
|
|
109392
|
+
if (destroyed || phase !== "idle" || leaving || lockedKey) return;
|
|
109393
|
+
const email = els.email.value;
|
|
109394
|
+
const password = els.password.value;
|
|
109395
|
+
const v = validate(email, password);
|
|
109396
|
+
fieldErrors = { email: v.emailError, password: v.passwordError };
|
|
109397
|
+
if (v.emailError || v.passwordError) {
|
|
109398
|
+
render3();
|
|
109399
|
+
(v.emailError ? els.email : els.password)?.focus();
|
|
109400
|
+
return;
|
|
109401
|
+
}
|
|
109402
|
+
fieldErrors = {};
|
|
109403
|
+
attempt += 1;
|
|
109404
|
+
const my = attempt;
|
|
109405
|
+
phase = "submitting";
|
|
109406
|
+
err = { ...err, pres: void 0, messageKey: void 0, help: false, code: void 0 };
|
|
109407
|
+
if (passwordVisible) {
|
|
109408
|
+
passwordVisible = false;
|
|
109409
|
+
els.password.type = "password";
|
|
109410
|
+
}
|
|
109411
|
+
renderAlerts();
|
|
109412
|
+
syncControls();
|
|
109413
|
+
const ac = new AbortController();
|
|
109414
|
+
attemptAbort = ac;
|
|
109415
|
+
abortCause = null;
|
|
109416
|
+
let timer;
|
|
109417
|
+
const timeout = new Promise((_, reject) => {
|
|
109418
|
+
if (viewTimeoutMs) timer = setTimeout(() => {
|
|
109419
|
+
abortCause = "timeout";
|
|
109420
|
+
ac.abort();
|
|
109421
|
+
reject(Object.assign(new Error("timeout"), { myioGcdrCode: "TIMEOUT" }));
|
|
109422
|
+
}, viewTimeoutMs);
|
|
109423
|
+
});
|
|
109424
|
+
let outcome;
|
|
109425
|
+
try {
|
|
109426
|
+
const raw = await Promise.race([strategy({ email: v.email, password, remember: rememberValue, locale: getLocale() }, { signal: ac.signal, attempt: my }), timeout]);
|
|
109427
|
+
outcome = normaliseResult(raw);
|
|
109428
|
+
if (outcome.kind === "error" && outcome.code === "INTEGRATION_ERROR" && !(raw && typeof raw === "object" && typeof raw.ok === "boolean")) {
|
|
109429
|
+
console.error("[MYIO Login] INTEGRATION_ERROR: invalid onSubmit result");
|
|
109430
|
+
}
|
|
109431
|
+
} catch (e) {
|
|
109432
|
+
outcome = { kind: "thrown", err: e };
|
|
109433
|
+
} finally {
|
|
109434
|
+
if (timer) clearTimeout(timer);
|
|
109435
|
+
}
|
|
109436
|
+
if (destroyed || my !== attempt || abortCause === "destroy" || abortCause === "exit") return;
|
|
109437
|
+
attemptAbort = null;
|
|
109438
|
+
if (outcome.kind === "thrown") {
|
|
109439
|
+
phase = "idle";
|
|
109440
|
+
const code = abortCause === "timeout" ? "TIMEOUT" : normaliseThrown(outcome.err);
|
|
109441
|
+
setError(code, present({ kind: "error", code }), {});
|
|
109442
|
+
return;
|
|
109443
|
+
}
|
|
109444
|
+
if (outcome.kind === "error") {
|
|
109445
|
+
phase = "idle";
|
|
109446
|
+
const k = emailKey(v.email);
|
|
109447
|
+
let help = false;
|
|
109448
|
+
if (outcome.code === "INVALID_CREDENTIALS" && outcome.remainingAttempts === void 0) {
|
|
109449
|
+
noCounterStreak = streakKey === k ? noCounterStreak + 1 : 1;
|
|
109450
|
+
streakKey = k;
|
|
109451
|
+
help = noCounterStreak >= 2;
|
|
109452
|
+
} else {
|
|
109453
|
+
noCounterStreak = 0;
|
|
109454
|
+
streakKey = null;
|
|
109455
|
+
}
|
|
109456
|
+
if (outcome.code === "ACCOUNT_LOCKED") lockedKey = k;
|
|
109457
|
+
setError(outcome.code, present(outcome), { help, remaining: outcome.remainingAttempts });
|
|
109458
|
+
return;
|
|
109459
|
+
}
|
|
109460
|
+
phase = "success";
|
|
109461
|
+
if (els.password) els.password.value = "";
|
|
109462
|
+
passwordValue = "";
|
|
109463
|
+
err = {};
|
|
109464
|
+
noCounterStreak = 0;
|
|
109465
|
+
if (options.show?.rememberMe !== false) storageSet(`${prefix}rememberedEmail`, rememberValue ? v.email : null);
|
|
109466
|
+
renderAlerts();
|
|
109467
|
+
syncControls();
|
|
109468
|
+
const sa = new AbortController();
|
|
109469
|
+
successAbort = sa;
|
|
109470
|
+
try {
|
|
109471
|
+
await options.onSuccess(outcome.session, { signal: sa.signal });
|
|
109472
|
+
} catch {
|
|
109473
|
+
if (destroyed || sa.signal.aborted) return;
|
|
109474
|
+
console.error("[MYIO Login] onSuccess failed");
|
|
109475
|
+
phase = "idle";
|
|
109476
|
+
err = { messageKey: "errors.postLoginFailed", pres: { tone: "error", keys: ["errors.postLoginFailed"], icon: "alert", clearPassword: true, focus: "password" } };
|
|
109477
|
+
renderAlerts();
|
|
109478
|
+
syncControls();
|
|
109479
|
+
els.password?.focus();
|
|
109480
|
+
return;
|
|
109481
|
+
}
|
|
109482
|
+
if (destroyed || sa.signal.aborted) return;
|
|
109483
|
+
internals.afterSuccess?.();
|
|
109484
|
+
};
|
|
109485
|
+
const api = {
|
|
109486
|
+
abortAttempt() {
|
|
109487
|
+
if (attemptAbort) {
|
|
109488
|
+
abortCause = "exit";
|
|
109489
|
+
attemptAbort.abort();
|
|
109490
|
+
attemptAbort = null;
|
|
109491
|
+
attempt += 1;
|
|
109492
|
+
}
|
|
109493
|
+
if (phase === "submitting") phase = "idle";
|
|
109494
|
+
leaving = true;
|
|
109495
|
+
syncControls();
|
|
109496
|
+
},
|
|
109497
|
+
clearPassword() {
|
|
109498
|
+
if (els.password) els.password.value = "";
|
|
109499
|
+
passwordValue = "";
|
|
109500
|
+
},
|
|
109501
|
+
showLeaveFailed() {
|
|
109502
|
+
leaving = false;
|
|
109503
|
+
err = { messageKey: "errors.leaveFailed", pres: { tone: "error", keys: ["errors.leaveFailed"], icon: "alert", clearPassword: false, focus: "submit" } };
|
|
109504
|
+
renderAlerts();
|
|
109505
|
+
syncControls();
|
|
109506
|
+
},
|
|
109507
|
+
t: (k) => t(k),
|
|
109508
|
+
locale: getLocale,
|
|
109509
|
+
phase: () => phase
|
|
109510
|
+
};
|
|
109511
|
+
let offChange;
|
|
109512
|
+
if (shell) {
|
|
109513
|
+
const asideOpt = options.aside ?? { kind: "about" };
|
|
109514
|
+
if (asideOpt.kind === "about") {
|
|
109515
|
+
const healthUrl = asideOpt.healthUrl !== void 0 ? asideOpt.healthUrl : options.gcdr ? `${options.gcdr.apiUrl.replace(/\/+$/, "").replace(/\/api\/v\d+$/, "")}/health` : false;
|
|
109516
|
+
shell.setSlot("aside", { kind: "about", healthUrl });
|
|
109517
|
+
} else if (asideOpt.kind === "signedOutPrompt") shell.setSlot("aside", { kind: "signedOutPrompt", text: asideOpt.text });
|
|
109518
|
+
else if (asideOpt.kind === "custom") shell.setSlot("aside", asideOpt.render);
|
|
109519
|
+
shell.setSlot("main", (el2) => {
|
|
109520
|
+
el2.appendChild(cardHost);
|
|
109521
|
+
});
|
|
109522
|
+
offChange = shell.onChange(() => render3());
|
|
109523
|
+
} else if (embedCtx) {
|
|
109524
|
+
const offT = embedCtx.on("theme", () => render3());
|
|
109525
|
+
const offL = embedCtx.on("locale", () => render3());
|
|
109526
|
+
offChange = () => {
|
|
109527
|
+
offT();
|
|
109528
|
+
offL();
|
|
109529
|
+
};
|
|
109530
|
+
embedCtx.signal.addEventListener("abort", () => handle.destroy(), { once: true });
|
|
109531
|
+
}
|
|
109532
|
+
render3();
|
|
109533
|
+
const autoFocus = options.autoFocus ?? !isCoarsePointer();
|
|
109534
|
+
if (autoFocus && presentation === "inline") (options.initialEmail ? els.password : els.email)?.focus();
|
|
109535
|
+
const restricted = shell ? {
|
|
109536
|
+
setSlot: (name, content, o) => {
|
|
109537
|
+
if (name === "main") fail("the main slot belongs to the login view");
|
|
109538
|
+
shell.setSlot(name, content, o);
|
|
109539
|
+
},
|
|
109540
|
+
setShow: (s) => shell.setShow(s)
|
|
109541
|
+
} : void 0;
|
|
109542
|
+
const handle = {
|
|
109543
|
+
getState() {
|
|
109544
|
+
return {
|
|
109545
|
+
phase: destroyed ? "destroyed" : leaving ? "leaving" : phase,
|
|
109546
|
+
error: err.code,
|
|
109547
|
+
message: err.messageKey ?? err.pres?.keys[0],
|
|
109548
|
+
locked: !!lockedKey,
|
|
109549
|
+
notice: notice?.code,
|
|
109550
|
+
captcha: "none",
|
|
109551
|
+
email: emailValue.trim() || void 0,
|
|
109552
|
+
locale: getLocale(),
|
|
109553
|
+
theme: getTheme()
|
|
109554
|
+
};
|
|
109555
|
+
},
|
|
109556
|
+
setLocale(l) {
|
|
109557
|
+
if (shell) shell.setLocale(l);
|
|
109558
|
+
},
|
|
109559
|
+
setTheme(th) {
|
|
109560
|
+
if (shell) shell.setTheme(th);
|
|
109561
|
+
},
|
|
109562
|
+
showError(code, extra) {
|
|
109563
|
+
if (destroyed) return;
|
|
109564
|
+
const o = normaliseResult({ ok: false, code, remainingAttempts: extra?.remainingAttempts, message: extra?.message });
|
|
109565
|
+
if (o.kind !== "error") return;
|
|
109566
|
+
if (o.code === "ACCOUNT_LOCKED") lockedKey = emailKey(emailValue);
|
|
109567
|
+
const pres = present(o);
|
|
109568
|
+
err = { code: o.code, pres };
|
|
109569
|
+
renderAlerts();
|
|
109570
|
+
syncControls();
|
|
109571
|
+
},
|
|
109572
|
+
clearError() {
|
|
109573
|
+
if (destroyed) return;
|
|
109574
|
+
err = {};
|
|
109575
|
+
lockedKey = null;
|
|
109576
|
+
renderAlerts();
|
|
109577
|
+
syncControls();
|
|
109578
|
+
},
|
|
109579
|
+
setNotice(n) {
|
|
109580
|
+
if (destroyed) return;
|
|
109581
|
+
notice = n && n.code === "SESSION_EXPIRED" ? n : null;
|
|
109582
|
+
renderNotice();
|
|
109583
|
+
},
|
|
109584
|
+
reset() {
|
|
109585
|
+
if (destroyed || phase !== "success") return;
|
|
109586
|
+
successAbort?.abort();
|
|
109587
|
+
phase = "idle";
|
|
109588
|
+
syncControls();
|
|
109589
|
+
},
|
|
109590
|
+
focus() {
|
|
109591
|
+
(options.initialEmail ? els.password : els.email)?.focus();
|
|
109592
|
+
},
|
|
109593
|
+
get shell() {
|
|
109594
|
+
return restricted;
|
|
109595
|
+
},
|
|
109596
|
+
destroy() {
|
|
109597
|
+
if (destroyed) return;
|
|
109598
|
+
destroyed = true;
|
|
109599
|
+
abortCause = "destroy";
|
|
109600
|
+
attemptAbort?.abort();
|
|
109601
|
+
successAbort?.abort();
|
|
109602
|
+
offChange?.();
|
|
109603
|
+
if (els.password) els.password.value = "";
|
|
109604
|
+
passwordValue = "";
|
|
109605
|
+
if (shell) shell.destroy();
|
|
109606
|
+
else {
|
|
109607
|
+
cardHost.textContent = "";
|
|
109608
|
+
releaseEmbedStyles?.();
|
|
109609
|
+
}
|
|
109610
|
+
},
|
|
109611
|
+
_api: api
|
|
109612
|
+
};
|
|
109613
|
+
return handle;
|
|
109614
|
+
}
|
|
109615
|
+
function createMyioGcdrLoginView(container, options) {
|
|
109616
|
+
const impl = createLoginViewImpl(container, options, { presentation: "inline" });
|
|
109617
|
+
const { _api, ...pub } = impl;
|
|
109618
|
+
void _api;
|
|
109619
|
+
return Object.defineProperty(pub, "shell", { get: () => impl.shell, enumerable: true });
|
|
109620
|
+
}
|
|
109621
|
+
|
|
109622
|
+
// src/components/myio-gcdr-login/modal.ts
|
|
109623
|
+
var MODAL_ATTR = "data-myio-gcdr-modal";
|
|
109624
|
+
var LOCK_ATTR = "data-myio-gcdr-scroll-lock";
|
|
109625
|
+
var INERT_PREV = "data-myio-gcdr-inert-prev";
|
|
109626
|
+
function isMyioGcdrLoginModalOpen(target) {
|
|
109627
|
+
if (target instanceof HTMLElement) return !!target.querySelector(`:scope > [${MODAL_ATTR}]`);
|
|
109628
|
+
const doc = target ?? (typeof document !== "undefined" ? document : void 0);
|
|
109629
|
+
return !!doc?.querySelector(`[${MODAL_ATTR}]`);
|
|
109630
|
+
}
|
|
109631
|
+
function conflict() {
|
|
109632
|
+
const e = new Error("[MYIO Login] a login modal is already open here");
|
|
109633
|
+
e.code = "LOGIN_MODAL_ALREADY_OPEN";
|
|
109634
|
+
throw e;
|
|
109635
|
+
}
|
|
109636
|
+
function openMyioGcdrLoginModal(options) {
|
|
109637
|
+
const ov = options.overlay ?? {};
|
|
109638
|
+
const scopeEl = typeof ov.scope === "object" && ov.scope ? ov.scope.element : null;
|
|
109639
|
+
const doc = scopeEl?.ownerDocument ?? document;
|
|
109640
|
+
const viewport = !scopeEl;
|
|
109641
|
+
const dismissible = ov.dismissible === true;
|
|
109642
|
+
if (viewport && !dismissible && !ov.exit) {
|
|
109643
|
+
throw new TypeError("[MYIO Login] a viewport modal that is not dismissible needs overlay.exit (a way out)");
|
|
109644
|
+
}
|
|
109645
|
+
if (ov.exit && (!ov.exit.href || typeof ov.exit.href !== "string")) throw new TypeError("[MYIO Login] overlay.exit.href is required");
|
|
109646
|
+
if (ov.secondaryAction) {
|
|
109647
|
+
const e = new TypeError("[MYIO Login] overlay.secondaryAction is not available in this version (RFC-0236 PR 4)");
|
|
109648
|
+
e.code = "MYIO_GCDR_SECONDARY_UNSUPPORTED";
|
|
109649
|
+
throw e;
|
|
109650
|
+
}
|
|
109651
|
+
if (viewport ? isMyioGcdrLoginModalOpen(doc) : isMyioGcdrLoginModalOpen(scopeEl)) conflict();
|
|
109652
|
+
const backdrop = ov.backdrop ?? "solid";
|
|
109653
|
+
const opacity = typeof ov.opacity === "number" ? Math.min(1, Math.max(0, ov.opacity)) : 0.5;
|
|
109654
|
+
const blur = typeof ov.blur === "number" ? ov.blur : backdrop === "blur" ? 8 : 4;
|
|
109655
|
+
const previouslyFocused = doc.activeElement;
|
|
109656
|
+
const releaseStyles = acquireStyles(viewport ? doc.body : scopeEl, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
|
|
109657
|
+
const overlay = h2(doc, "div", {
|
|
109658
|
+
class: "myio-gcdr-overlay",
|
|
109659
|
+
[MODAL_ATTR]: "1",
|
|
109660
|
+
role: "dialog",
|
|
109661
|
+
"aria-modal": viewport ? "true" : null,
|
|
109662
|
+
"data-scope": viewport ? "viewport" : "element",
|
|
109663
|
+
"data-backdrop": backdrop
|
|
109664
|
+
});
|
|
109665
|
+
overlay.style.zIndex = String(ov.zIndex ?? 1e4);
|
|
109666
|
+
const layers = [];
|
|
109667
|
+
const layer = (bg, extra = "") => {
|
|
109668
|
+
const l = h2(doc, "div", { class: "myio-gcdr-overlay__layer", "aria-hidden": "true" });
|
|
109669
|
+
l.setAttribute("style", `background:${bg};${extra}`);
|
|
109670
|
+
layers.push(l);
|
|
109671
|
+
overlay.appendChild(l);
|
|
109672
|
+
return l;
|
|
109673
|
+
};
|
|
109674
|
+
const paintBackdrop = (dark) => {
|
|
109675
|
+
layers.splice(0).forEach((l) => l.remove());
|
|
109676
|
+
const blurCss = `-webkit-backdrop-filter:blur(${blur}px);backdrop-filter:blur(${blur}px)`;
|
|
109677
|
+
if (backdrop === "blur") {
|
|
109678
|
+
layer(`rgba(20,12,40,${opacity})`, blurCss);
|
|
109679
|
+
} else {
|
|
109680
|
+
layer(dark ? "linear-gradient(180deg,#1B1530 0%,#15121F 45%,#111827 100%)" : "linear-gradient(180deg,#DCD2F3 0%,#EEEAF8 45%,#F7F5FC 100%)");
|
|
109681
|
+
if (backdrop === "image" && options.assets?.wallpaper) {
|
|
109682
|
+
const wp = options.assets.wallpaper;
|
|
109683
|
+
let portrait = false;
|
|
109684
|
+
try {
|
|
109685
|
+
portrait = matchMedia("(orientation: portrait)").matches;
|
|
109686
|
+
} catch {
|
|
109687
|
+
}
|
|
109688
|
+
const url = dark ? portrait ? wp.mobileDark ?? wp.dark : wp.dark : portrait ? wp.mobileLight ?? wp.light : wp.light;
|
|
109689
|
+
if (url) layer(`url("${url.replace(/"/g, "%22")}") center/cover no-repeat`);
|
|
109690
|
+
}
|
|
109691
|
+
layer(`rgba(255,255,255,${(dark ? 0.1 : 0.44) * opacity})`, blurCss);
|
|
109692
|
+
layer(dark ? "linear-gradient(135deg,rgba(45,22,105,.55) 0%,rgba(27,21,48,.30) 50%,rgba(45,22,105,.55) 100%)" : "linear-gradient(135deg,rgba(107,74,191,.34) 0%,rgba(107,74,191,.14) 50%,rgba(107,74,191,.34) 100%)");
|
|
109693
|
+
}
|
|
109694
|
+
layers.forEach((l) => overlay.insertBefore(l, content));
|
|
109695
|
+
};
|
|
109696
|
+
const content = h2(doc, "div", { class: "myio-gcdr-overlay__content" });
|
|
109697
|
+
overlay.appendChild(content);
|
|
109698
|
+
let restoreStatic = null;
|
|
109699
|
+
if (viewport) doc.body.appendChild(overlay);
|
|
109700
|
+
else {
|
|
109701
|
+
const el2 = scopeEl;
|
|
109702
|
+
if (getComputedStyle(el2).position === "static") {
|
|
109703
|
+
const prev = el2.style.position;
|
|
109704
|
+
el2.style.position = "relative";
|
|
109705
|
+
restoreStatic = () => {
|
|
109706
|
+
el2.style.position = prev;
|
|
109707
|
+
};
|
|
109708
|
+
}
|
|
109709
|
+
el2.appendChild(overlay);
|
|
109710
|
+
}
|
|
109711
|
+
let open = true;
|
|
109712
|
+
let closing = false;
|
|
109713
|
+
let exitTimer;
|
|
109714
|
+
const close = (reason) => {
|
|
109715
|
+
if (!open || closing) return;
|
|
109716
|
+
closing = true;
|
|
109717
|
+
if (exitTimer) clearTimeout(exitTimer);
|
|
109718
|
+
mo?.disconnect();
|
|
109719
|
+
try {
|
|
109720
|
+
view.destroy();
|
|
109721
|
+
} catch {
|
|
109722
|
+
}
|
|
109723
|
+
doc.removeEventListener("keydown", onKey, true);
|
|
109724
|
+
overlay.removeEventListener("keydown", onKey, true);
|
|
109725
|
+
if (viewport) {
|
|
109726
|
+
releaseInert();
|
|
109727
|
+
releaseScroll();
|
|
109728
|
+
}
|
|
109729
|
+
overlay.remove();
|
|
109730
|
+
restoreStatic?.();
|
|
109731
|
+
releaseStyles();
|
|
109732
|
+
open = false;
|
|
109733
|
+
if (previouslyFocused && previouslyFocused.isConnected && typeof previouslyFocused.focus === "function") previouslyFocused.focus();
|
|
109734
|
+
else if (viewport) doc.body.focus?.();
|
|
109735
|
+
safeCall("onClose", options.onClose, reason);
|
|
109736
|
+
};
|
|
109737
|
+
const { overlay: _o, onOpen, onClose, ...viewOpts } = options;
|
|
109738
|
+
void _o;
|
|
109739
|
+
void onClose;
|
|
109740
|
+
const view = createLoginViewImpl(content, { ...viewOpts, aside: options.aside ?? { kind: "none" }, autoFocus: false }, {
|
|
109741
|
+
presentation: "modal",
|
|
109742
|
+
shellWallpaper: false,
|
|
109743
|
+
afterSuccess: () => {
|
|
109744
|
+
if (ov.closeOnSuccess !== false) close("success");
|
|
109745
|
+
},
|
|
109746
|
+
decorateFooter: (footer, api) => {
|
|
109747
|
+
if (!ov.exit) return;
|
|
109748
|
+
const label = localize(ov.exit.label, api.locale());
|
|
109749
|
+
const a = h2(doc, "a", { class: "myio-gcdr-login__link", href: ov.exit.href, style: "display:inline-block;margin-left:12px" }, label);
|
|
109750
|
+
a.addEventListener("click", () => {
|
|
109751
|
+
if (api.phase() === "success") return;
|
|
109752
|
+
api.abortAttempt();
|
|
109753
|
+
api.clearPassword();
|
|
109754
|
+
a.textContent = api.t("login.leaving");
|
|
109755
|
+
a.setAttribute("aria-busy", "true");
|
|
109756
|
+
exitTimer = setTimeout(() => {
|
|
109757
|
+
if (!open) return;
|
|
109758
|
+
a.textContent = label;
|
|
109759
|
+
a.removeAttribute("aria-busy");
|
|
109760
|
+
api.showLeaveFailed();
|
|
109761
|
+
a.focus();
|
|
109762
|
+
}, 2e3);
|
|
109763
|
+
});
|
|
109764
|
+
footer.appendChild(a);
|
|
109765
|
+
}
|
|
109766
|
+
});
|
|
109767
|
+
const shellRoot = content.querySelector(".myio-gcdr-shell");
|
|
109768
|
+
const syncTheme = () => {
|
|
109769
|
+
const dark = view.getState().theme === "dark";
|
|
109770
|
+
overlay.setAttribute("data-theme", dark ? "dark" : "light");
|
|
109771
|
+
paintBackdrop(dark);
|
|
109772
|
+
};
|
|
109773
|
+
syncTheme();
|
|
109774
|
+
const mo = shellRoot ? new MutationObserver(syncTheme) : null;
|
|
109775
|
+
mo?.observe(shellRoot, { attributes: true, attributeFilter: ["data-theme"] });
|
|
109776
|
+
if (backdrop === "blur" && options.show?.themeToggle === void 0) view.shell?.setShow({ themeToggle: false });
|
|
109777
|
+
const title = content.querySelector(".myio-gcdr-panel__title");
|
|
109778
|
+
if (title) {
|
|
109779
|
+
if (!title.id) title.id = `myio-gcdr-title-${Math.random().toString(36).slice(2, 8)}`;
|
|
109780
|
+
overlay.setAttribute("aria-labelledby", title.id);
|
|
109781
|
+
}
|
|
109782
|
+
if (dismissible) {
|
|
109783
|
+
const x = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn myio-gcdr-overlay__close", "aria-label": view._api.t("modal.close") });
|
|
109784
|
+
x.appendChild(icon(doc, ICONS.x(18)));
|
|
109785
|
+
x.addEventListener("click", () => {
|
|
109786
|
+
const p = view.getState().phase;
|
|
109787
|
+
if (p !== "submitting" && p !== "success") close("dismiss");
|
|
109788
|
+
});
|
|
109789
|
+
content.appendChild(x);
|
|
109790
|
+
}
|
|
109791
|
+
const inerted = [];
|
|
109792
|
+
const releaseInert = () => {
|
|
109793
|
+
for (const el2 of inerted) {
|
|
109794
|
+
const prev = el2.getAttribute(INERT_PREV);
|
|
109795
|
+
if (prev === "true") el2.setAttribute("inert", "");
|
|
109796
|
+
else el2.removeAttribute("inert");
|
|
109797
|
+
el2.removeAttribute(INERT_PREV);
|
|
109798
|
+
}
|
|
109799
|
+
inerted.length = 0;
|
|
109800
|
+
};
|
|
109801
|
+
let scrollPrev = null;
|
|
109802
|
+
const releaseScroll = () => {
|
|
109803
|
+
const html = doc.documentElement;
|
|
109804
|
+
const n = Math.max(0, (parseInt(html.getAttribute(LOCK_ATTR) || "1", 10) || 1) - 1);
|
|
109805
|
+
if (n === 0) {
|
|
109806
|
+
html.removeAttribute(LOCK_ATTR);
|
|
109807
|
+
if (scrollPrev) {
|
|
109808
|
+
html.style.overflow = scrollPrev.html;
|
|
109809
|
+
doc.body.style.overflow = scrollPrev.body;
|
|
109810
|
+
}
|
|
109811
|
+
} else html.setAttribute(LOCK_ATTR, String(n));
|
|
109812
|
+
};
|
|
109813
|
+
if (viewport) {
|
|
109814
|
+
for (const el2 of Array.from(doc.body.children)) {
|
|
109815
|
+
if (el2 === overlay || el2.tagName === "SCRIPT" || el2.tagName === "STYLE") continue;
|
|
109816
|
+
el2.setAttribute(INERT_PREV, el2.hasAttribute("inert") ? "true" : "false");
|
|
109817
|
+
el2.setAttribute("inert", "");
|
|
109818
|
+
inerted.push(el2);
|
|
109819
|
+
}
|
|
109820
|
+
const html = doc.documentElement;
|
|
109821
|
+
const n = parseInt(html.getAttribute(LOCK_ATTR) || "0", 10) || 0;
|
|
109822
|
+
if (n === 0) scrollPrev = { html: html.style.overflow, body: doc.body.style.overflow };
|
|
109823
|
+
html.setAttribute(LOCK_ATTR, String(n + 1));
|
|
109824
|
+
html.style.overflow = "hidden";
|
|
109825
|
+
doc.body.style.overflow = "hidden";
|
|
109826
|
+
}
|
|
109827
|
+
const focusables = () => Array.from(overlay.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select,textarea,[tabindex]:not([tabindex="-1"])')).filter((el2) => !el2.hidden && el2.offsetParent !== null);
|
|
109828
|
+
const onKey = (e) => {
|
|
109829
|
+
if (!open) return;
|
|
109830
|
+
if (e.key === "Escape" && dismissible) {
|
|
109831
|
+
const p = view.getState().phase;
|
|
109832
|
+
if (p !== "submitting" && p !== "success") {
|
|
109833
|
+
e.preventDefault();
|
|
109834
|
+
close("dismiss");
|
|
109835
|
+
}
|
|
109836
|
+
return;
|
|
109837
|
+
}
|
|
109838
|
+
if (e.key === "Tab" && viewport) {
|
|
109839
|
+
const list = focusables();
|
|
109840
|
+
if (!list.length) return;
|
|
109841
|
+
const first = list[0];
|
|
109842
|
+
const last = list[list.length - 1];
|
|
109843
|
+
const active = doc.activeElement;
|
|
109844
|
+
if (e.shiftKey && (active === first || !overlay.contains(active))) {
|
|
109845
|
+
e.preventDefault();
|
|
109846
|
+
last.focus();
|
|
109847
|
+
} else if (!e.shiftKey && (active === last || !overlay.contains(active))) {
|
|
109848
|
+
e.preventDefault();
|
|
109849
|
+
first.focus();
|
|
109850
|
+
}
|
|
109851
|
+
}
|
|
109852
|
+
};
|
|
109853
|
+
if (viewport) doc.addEventListener("keydown", onKey, true);
|
|
109854
|
+
else overlay.addEventListener("keydown", onKey, true);
|
|
109855
|
+
const emailInput = content.querySelector('[data-k="email"]');
|
|
109856
|
+
const passInput = content.querySelector('[data-k="password"]');
|
|
109857
|
+
const coarse = (() => {
|
|
109858
|
+
try {
|
|
109859
|
+
return matchMedia("(pointer: coarse)").matches;
|
|
109860
|
+
} catch {
|
|
109861
|
+
return false;
|
|
109862
|
+
}
|
|
109863
|
+
})();
|
|
109864
|
+
const wantInput = options.autoFocus ?? !coarse;
|
|
109865
|
+
((wantInput ? options.initialEmail ? passInput : emailInput : title) ?? title)?.focus();
|
|
109866
|
+
safeCall("onOpen", onOpen);
|
|
109867
|
+
const handle = {
|
|
109868
|
+
getState: () => view.getState(),
|
|
109869
|
+
setLocale: (l) => view.setLocale(l),
|
|
109870
|
+
setTheme: (th) => view.setTheme(th),
|
|
109871
|
+
showError: (c, x) => view.showError(c, x),
|
|
109872
|
+
clearError: () => view.clearError(),
|
|
109873
|
+
setNotice: (n) => view.setNotice(n),
|
|
109874
|
+
reset: () => view.reset(),
|
|
109875
|
+
focus: () => view.focus(),
|
|
109876
|
+
close: () => close("api"),
|
|
109877
|
+
destroy: () => close("api"),
|
|
109878
|
+
get isOpen() {
|
|
109879
|
+
return open;
|
|
109880
|
+
}
|
|
109881
|
+
};
|
|
109882
|
+
return handle;
|
|
109883
|
+
}
|
|
109884
|
+
|
|
107784
109885
|
// src/components/img-gallery/ScrollableTabs.ts
|
|
107785
109886
|
var STYLE_ID11 = "myio-tabs-styles";
|
|
107786
109887
|
var FONT_LINK_ID3 = "myio-dialog-font-nunito";
|
|
@@ -108417,13 +110518,13 @@ function createImgGallery(options) {
|
|
|
108417
110518
|
grid.appendChild(item);
|
|
108418
110519
|
});
|
|
108419
110520
|
}
|
|
108420
|
-
function actionBtn(
|
|
110521
|
+
function actionBtn(icon2, label, danger, onClick) {
|
|
108421
110522
|
const b = document.createElement("button");
|
|
108422
110523
|
b.type = "button";
|
|
108423
110524
|
b.className = `myio-gallery__abtn${danger ? " myio-gallery__abtn--danger" : ""}`;
|
|
108424
110525
|
b.setAttribute("aria-label", label);
|
|
108425
110526
|
b.title = label;
|
|
108426
|
-
b.innerHTML =
|
|
110527
|
+
b.innerHTML = icon2;
|
|
108427
110528
|
b.addEventListener("click", onClick);
|
|
108428
110529
|
return b;
|
|
108429
110530
|
}
|
|
@@ -116563,7 +118664,7 @@ var MenuView = class {
|
|
|
116563
118664
|
*/
|
|
116564
118665
|
bindFilterTooltipEvents(listEl) {
|
|
116565
118666
|
const icons = listEl.querySelectorAll(".filter-icon[data-tooltip-type]");
|
|
116566
|
-
icons.forEach((
|
|
118667
|
+
icons.forEach((icon2) => {
|
|
116567
118668
|
const showHandler = (e) => {
|
|
116568
118669
|
e.stopPropagation();
|
|
116569
118670
|
const el2 = e.currentTarget;
|
|
@@ -116574,9 +118675,9 @@ var MenuView = class {
|
|
|
116574
118675
|
const hideHandler = () => {
|
|
116575
118676
|
this.hideFilterTooltips();
|
|
116576
118677
|
};
|
|
116577
|
-
|
|
116578
|
-
|
|
116579
|
-
|
|
118678
|
+
icon2.addEventListener("mouseenter", showHandler);
|
|
118679
|
+
icon2.addEventListener("click", showHandler);
|
|
118680
|
+
icon2.addEventListener("mouseleave", hideHandler);
|
|
116580
118681
|
});
|
|
116581
118682
|
}
|
|
116582
118683
|
/**
|
|
@@ -120398,11 +122499,11 @@ var FilterModalView = class {
|
|
|
120398
122499
|
const allTab = this.filterTabs.find((t) => t.id === "all");
|
|
120399
122500
|
let html = "";
|
|
120400
122501
|
if (allTab) {
|
|
120401
|
-
const
|
|
122502
|
+
const icon2 = FILTER_TAB_ICONS["all"] || "";
|
|
120402
122503
|
html += `
|
|
120403
122504
|
<div class="filter-group filter-group-all">
|
|
120404
122505
|
<button class="filter-tab active" data-filter="all">
|
|
120405
|
-
${
|
|
122506
|
+
${icon2} ${allTab.label} (<span id="countAll">${counts["all"] || 0}</span>)
|
|
120406
122507
|
</button>
|
|
120407
122508
|
</div>
|
|
120408
122509
|
`;
|
|
@@ -120415,12 +122516,12 @@ var FilterModalView = class {
|
|
|
120415
122516
|
<span class="filter-group-label">${group.label}</span>
|
|
120416
122517
|
<div class="filter-group-tabs">
|
|
120417
122518
|
${groupTabs.map((tab) => {
|
|
120418
|
-
const
|
|
122519
|
+
const icon2 = FILTER_TAB_ICONS[tab.id] || "";
|
|
120419
122520
|
const count = counts[tab.id] || 0;
|
|
120420
122521
|
const expandBtn = count > 0 ? `<button class="filter-tab-expand" data-expand-filter="${tab.id}" title="Ver dispositivos">+</button>` : "";
|
|
120421
122522
|
return `
|
|
120422
122523
|
<button class="filter-tab active" data-filter="${tab.id}">
|
|
120423
|
-
${
|
|
122524
|
+
${icon2} ${tab.label} (<span id="count${tab.id.charAt(0).toUpperCase() + tab.id.slice(1)}">${count}</span>)${expandBtn}
|
|
120424
122525
|
</button>
|
|
120425
122526
|
`;
|
|
120426
122527
|
}).join("")}
|
|
@@ -120797,7 +122898,7 @@ var FilterModalView = class {
|
|
|
120797
122898
|
if (!InfoTooltip2?.InfoTooltip) return;
|
|
120798
122899
|
const filterTabConfig = this.filterTabs.find((t) => t.id === filterId);
|
|
120799
122900
|
const label = filterTabConfig?.label || filterId;
|
|
120800
|
-
const
|
|
122901
|
+
const icon2 = FILTER_TAB_ICONS[filterId] || "\u{1F4CB}";
|
|
120801
122902
|
let devicesHtml = "";
|
|
120802
122903
|
if (devices.length === 0) {
|
|
120803
122904
|
devicesHtml = `
|
|
@@ -120849,7 +122950,7 @@ var FilterModalView = class {
|
|
|
120849
122950
|
`;
|
|
120850
122951
|
}
|
|
120851
122952
|
InfoTooltip2.InfoTooltip.show(triggerEl, {
|
|
120852
|
-
icon,
|
|
122953
|
+
icon: icon2,
|
|
120853
122954
|
title: `${label} (${devices.length})`,
|
|
120854
122955
|
content: devicesHtml
|
|
120855
122956
|
});
|
|
@@ -121714,7 +123815,7 @@ var FilterModalComponent = class {
|
|
|
121714
123815
|
}
|
|
121715
123816
|
// ── Private ────────────────────────────────
|
|
121716
123817
|
render() {
|
|
121717
|
-
const { title, icon, categories, sortOptions, devices = [] } = this.options;
|
|
123818
|
+
const { title, icon: icon2, categories, sortOptions, devices = [] } = this.options;
|
|
121718
123819
|
const hasDevices = this.showDeviceGrid && devices.length > 0;
|
|
121719
123820
|
const modalClass = `myio-fm myio-fm--${this.themeMode}${hasDevices ? " myio-fm--with-devices" : ""}`;
|
|
121720
123821
|
const bodyClass = `myio-fm__body${hasDevices ? " myio-fm__body--two-col" : ""}`;
|
|
@@ -121722,7 +123823,7 @@ var FilterModalComponent = class {
|
|
|
121722
123823
|
<div class="${modalClass}">
|
|
121723
123824
|
<div class="myio-fm__header">
|
|
121724
123825
|
<div class="myio-fm__header-left">
|
|
121725
|
-
${
|
|
123826
|
+
${icon2 ? `<span class="myio-fm__icon">${icon2}</span>` : ""}
|
|
121726
123827
|
<h2 class="myio-fm__title">${this.escapeHtml(title)}</h2>
|
|
121727
123828
|
</div>
|
|
121728
123829
|
<button class="myio-fm__close" title="Fechar">
|
|
@@ -121801,7 +123902,7 @@ var FilterModalComponent = class {
|
|
|
121801
123902
|
renderDeviceItem(device) {
|
|
121802
123903
|
const isSelected = this.selectedDeviceIds.has(device.id);
|
|
121803
123904
|
const statusClass = device.status ? `myio-fm__device-status--${device.status}` : "";
|
|
121804
|
-
const
|
|
123905
|
+
const icon2 = device.icon || this.getDefaultDeviceIcon(device.type, device.context);
|
|
121805
123906
|
return `
|
|
121806
123907
|
<div class="myio-fm__device-item${isSelected ? " myio-fm__device-item--selected" : ""}"
|
|
121807
123908
|
data-device-id="${device.id}"
|
|
@@ -121809,7 +123910,7 @@ var FilterModalComponent = class {
|
|
|
121809
123910
|
<div class="myio-fm__device-checkbox">
|
|
121810
123911
|
${ICON_CHECK}
|
|
121811
123912
|
</div>
|
|
121812
|
-
${
|
|
123913
|
+
${icon2 ? `<span class="myio-fm__device-icon">${icon2}</span>` : ""}
|
|
121813
123914
|
<div class="myio-fm__device-info">
|
|
121814
123915
|
<p class="myio-fm__device-label" title="${this.escapeHtml(device.label)}">${this.escapeHtml(device.label)}</p>
|
|
121815
123916
|
${device.type ? `<p class="myio-fm__device-type">${this.escapeHtml(device.type)}</p>` : ""}
|
|
@@ -122577,7 +124678,7 @@ function createCustomerCardV1(params) {
|
|
|
122577
124678
|
|
|
122578
124679
|
// src/components/cards/customer-goals/v1.0.0/styles.ts
|
|
122579
124680
|
var STYLE_ID13 = "myio-customer-goals-card-css";
|
|
122580
|
-
var
|
|
124681
|
+
var CSS4 = `
|
|
122581
124682
|
.myio-cgc{
|
|
122582
124683
|
--cgc-surface:#ffffff;
|
|
122583
124684
|
--cgc-border:#e2e8f0;
|
|
@@ -122680,7 +124781,7 @@ function injectCustomerGoalsCardStyles() {
|
|
|
122680
124781
|
if (document.getElementById(STYLE_ID13)) return;
|
|
122681
124782
|
const tag = document.createElement("style");
|
|
122682
124783
|
tag.id = STYLE_ID13;
|
|
122683
|
-
tag.textContent =
|
|
124784
|
+
tag.textContent = CSS4;
|
|
122684
124785
|
document.head.appendChild(tag);
|
|
122685
124786
|
}
|
|
122686
124787
|
|
|
@@ -123795,13 +125896,13 @@ var EnergyPanelView = class {
|
|
|
123795
125896
|
/**
|
|
123796
125897
|
* Build a single card HTML with the TELEMETRY_INFO-inspired layout
|
|
123797
125898
|
*/
|
|
123798
|
-
buildCardHTML(type,
|
|
125899
|
+
buildCardHTML(type, icon2, title, value, percentage, tooltip) {
|
|
123799
125900
|
const percDisplay = percentage !== null ? `(${percentage}%)` : "";
|
|
123800
125901
|
const tooltipHTML = tooltip ? `<span class="energy-panel__card-tooltip" title="${tooltip}">\u2139\uFE0F</span>` : "";
|
|
123801
125902
|
return `
|
|
123802
125903
|
<div class="energy-panel__card" data-type="${type}">
|
|
123803
125904
|
<div class="energy-panel__card-header">
|
|
123804
|
-
<span class="energy-panel__card-icon">${
|
|
125905
|
+
<span class="energy-panel__card-icon">${icon2}</span>
|
|
123805
125906
|
<h3 class="energy-panel__card-title">${title}</h3>
|
|
123806
125907
|
${tooltipHTML}
|
|
123807
125908
|
</div>
|
|
@@ -126942,7 +129043,7 @@ var HeaderShoppingView = class {
|
|
|
126942
129043
|
emit(event, ...args) {
|
|
126943
129044
|
const handlers = this.eventHandlers.get(event);
|
|
126944
129045
|
if (handlers) {
|
|
126945
|
-
handlers.forEach((
|
|
129046
|
+
handlers.forEach((h3) => h3(...args));
|
|
126946
129047
|
}
|
|
126947
129048
|
}
|
|
126948
129049
|
/**
|
|
@@ -127398,7 +129499,7 @@ function createHeaderShoppingComponent(params) {
|
|
|
127398
129499
|
function emit(event, ...args) {
|
|
127399
129500
|
const handlers = eventHandlers.get(event);
|
|
127400
129501
|
if (handlers) {
|
|
127401
|
-
handlers.forEach((
|
|
129502
|
+
handlers.forEach((h3) => h3(...args));
|
|
127402
129503
|
}
|
|
127403
129504
|
}
|
|
127404
129505
|
function on(event, handler) {
|
|
@@ -128288,7 +130389,7 @@ var MenuShoppingView = class {
|
|
|
128288
130389
|
emit(event, ...args) {
|
|
128289
130390
|
const handlers = this.eventHandlers.get(event);
|
|
128290
130391
|
if (handlers) {
|
|
128291
|
-
handlers.forEach((
|
|
130392
|
+
handlers.forEach((h3) => h3(...args));
|
|
128292
130393
|
}
|
|
128293
130394
|
}
|
|
128294
130395
|
/**
|
|
@@ -128457,7 +130558,7 @@ function createMenuShoppingComponent(params) {
|
|
|
128457
130558
|
function emitEvent(event, ...args) {
|
|
128458
130559
|
const handlers = eventHandlers.get(event);
|
|
128459
130560
|
if (handlers) {
|
|
128460
|
-
handlers.forEach((
|
|
130561
|
+
handlers.forEach((h3) => h3(...args));
|
|
128461
130562
|
}
|
|
128462
130563
|
}
|
|
128463
130564
|
function cleanup() {
|
|
@@ -130450,8 +132551,8 @@ var TelemetryGridShoppingView = class {
|
|
|
130450
132551
|
}
|
|
130451
132552
|
}
|
|
130452
132553
|
}
|
|
130453
|
-
const
|
|
130454
|
-
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${
|
|
132554
|
+
const icon2 = this.isMaximized ? '<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"/>' : '<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/>';
|
|
132555
|
+
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon2}</svg>`;
|
|
130455
132556
|
}
|
|
130456
132557
|
};
|
|
130457
132558
|
|
|
@@ -132382,9 +134483,9 @@ var TelemetryInfoShoppingView = class _TelemetryInfoShoppingView {
|
|
|
132382
134483
|
this.maximizeBtnEl.style.opacity = "0";
|
|
132383
134484
|
}
|
|
132384
134485
|
}
|
|
132385
|
-
const
|
|
134486
|
+
const icon2 = this.isMaximized ? '<path d="M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" fill="currentColor"/>' : '<path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" fill="currentColor"/>';
|
|
132386
134487
|
if (this.maximizeBtnEl) {
|
|
132387
|
-
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${
|
|
134488
|
+
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon2}</svg>`;
|
|
132388
134489
|
}
|
|
132389
134490
|
this.params.onExpandClick?.();
|
|
132390
134491
|
}
|
|
@@ -139424,7 +141525,7 @@ function renderTrendChart(data, options = {}) {
|
|
|
139424
141525
|
Cr\xEDticos
|
|
139425
141526
|
</span>
|
|
139426
141527
|
</div>`;
|
|
139427
|
-
const
|
|
141528
|
+
const svg2 = `
|
|
139428
141529
|
<svg class="alarms-trend-chart" viewBox="0 0 ${width} ${height}" preserveAspectRatio="xMidYMid meet">
|
|
139429
141530
|
<defs>
|
|
139430
141531
|
<linearGradient id="gradTotal" x1="0" y1="0" x2="0" y2="1">
|
|
@@ -139445,7 +141546,7 @@ function renderTrendChart(data, options = {}) {
|
|
|
139445
141546
|
<circle cx="${lastCritical[0].toFixed(1)}" cy="${lastCritical[1].toFixed(1)}" r="4" fill="${criticalColor}" />
|
|
139446
141547
|
${xLabels}
|
|
139447
141548
|
</svg>`;
|
|
139448
|
-
return `<div class="alarms-trend-wrap">${
|
|
141549
|
+
return `<div class="alarms-trend-wrap">${svg2}${legend}</div>`;
|
|
139449
141550
|
}
|
|
139450
141551
|
function renderStateDonutChart(byState, options = {}) {
|
|
139451
141552
|
if (!byState) return renderEmptyChart(200, 200, "Sem dados");
|
|
@@ -140489,8 +142590,8 @@ var AlarmsNotificationsPanelView = class {
|
|
|
140489
142590
|
}
|
|
140490
142591
|
const th = (label, col, extraClass = "") => {
|
|
140491
142592
|
const active = this.sortCol === col;
|
|
140492
|
-
const
|
|
140493
|
-
return `<th class="atbl-th atbl-th--sortable${extraClass ? " " + extraClass : ""}${active ? " is-sorted" : ""}" data-sort-col="${col}">${label}${
|
|
142593
|
+
const icon2 = active ? `<span class="atbl-sort-icon is-active">${this.sortDir === "asc" ? "\u25B2" : "\u25BC"}</span>` : `<span class="atbl-sort-icon">\u21C5</span>`;
|
|
142594
|
+
return `<th class="atbl-th atbl-th--sortable${extraClass ? " " + extraClass : ""}${active ? " is-sorted" : ""}" data-sort-col="${col}">${label}${icon2}</th>`;
|
|
140494
142595
|
};
|
|
140495
142596
|
const rows = alarms.map((alarm) => {
|
|
140496
142597
|
const sev = SEVERITY_CONFIG[alarm.severity];
|
|
@@ -144097,9 +146198,9 @@ function renderDualLineChart(data) {
|
|
|
144097
146198
|
}
|
|
144098
146199
|
function formatTrendIndicator(trend) {
|
|
144099
146200
|
if (trend === void 0 || trend === 0) return "";
|
|
144100
|
-
const
|
|
146201
|
+
const icon2 = trend > 0 ? "\u2191" : "\u2193";
|
|
144101
146202
|
const cls = trend > 0 ? "trend-up" : "trend-down";
|
|
144102
|
-
return `<span class="trend-indicator ${cls}">${
|
|
146203
|
+
return `<span class="trend-indicator ${cls}">${icon2}${Math.abs(trend)}</span>`;
|
|
144103
146204
|
}
|
|
144104
146205
|
function renderStatusDonutChart(kpis, period) {
|
|
144105
146206
|
const offlineCritical = kpis.offlineCriticalCount || 0;
|
|
@@ -144405,10 +146506,10 @@ function formatHoursDisplay(hours) {
|
|
|
144405
146506
|
const mins = Math.round(hours * 60);
|
|
144406
146507
|
return `${mins}min`;
|
|
144407
146508
|
}
|
|
144408
|
-
const
|
|
144409
|
-
const m = Math.round((hours -
|
|
144410
|
-
if (m === 0) return `${
|
|
144411
|
-
return `${
|
|
146509
|
+
const h3 = Math.floor(hours);
|
|
146510
|
+
const m = Math.round((hours - h3) * 60);
|
|
146511
|
+
if (m === 0) return `${h3}h`;
|
|
146512
|
+
return `${h3}h${String(m).padStart(2, "0")}`;
|
|
144412
146513
|
}
|
|
144413
146514
|
function renderMTBFTimelineChart(data) {
|
|
144414
146515
|
if (!data.segments || data.segments.length === 0) {
|
|
@@ -147860,12 +149961,12 @@ var SwitchControlView = class {
|
|
|
147860
149961
|
document.querySelectorAll(`.${SWITCH_CONTROL_CSS_PREFIX}__modal-overlay`).forEach((el2) => el2.remove());
|
|
147861
149962
|
const { labels } = this.settings;
|
|
147862
149963
|
const newStatus = this.state.status === "on" ? "off" : "on";
|
|
147863
|
-
const
|
|
149964
|
+
const icon2 = newStatus === "on" ? "\u{1F4A1}" : "\u{1F50C}";
|
|
147864
149965
|
const modal = document.createElement("div");
|
|
147865
149966
|
modal.className = `${SWITCH_CONTROL_CSS_PREFIX}__modal-overlay`;
|
|
147866
149967
|
modal.innerHTML = `
|
|
147867
149968
|
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal">
|
|
147868
|
-
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-icon">${
|
|
149969
|
+
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-icon">${icon2}</div>
|
|
147869
149970
|
<h3 class="${SWITCH_CONTROL_CSS_PREFIX}__modal-title">${this.escapeHtml(this.state.name)}</h3>
|
|
147870
149971
|
<p class="${SWITCH_CONTROL_CSS_PREFIX}__modal-message">${message}</p>
|
|
147871
149972
|
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-actions">
|
|
@@ -148192,7 +150293,7 @@ var ActionButtonView = class {
|
|
|
148192
150293
|
return classes.join(" ");
|
|
148193
150294
|
}
|
|
148194
150295
|
applyAll() {
|
|
148195
|
-
const { label, icon, variant, color, textColor, borderRadius, disabled, tooltip } = this.settings;
|
|
150296
|
+
const { label, icon: icon2, variant, color, textColor, borderRadius, disabled, tooltip } = this.settings;
|
|
148196
150297
|
this.root.className = this.buildClassName();
|
|
148197
150298
|
this.root.disabled = disabled;
|
|
148198
150299
|
this.root.style.borderRadius = `${borderRadius}px`;
|
|
@@ -148205,8 +150306,8 @@ var ActionButtonView = class {
|
|
|
148205
150306
|
this.root.style.color = textColor || color;
|
|
148206
150307
|
}
|
|
148207
150308
|
let html = "";
|
|
148208
|
-
if (
|
|
148209
|
-
html += `<span class="${ACTION_BUTTON_CSS_PREFIX}__icon">${this.escapeHtml(
|
|
150309
|
+
if (icon2) {
|
|
150310
|
+
html += `<span class="${ACTION_BUTTON_CSS_PREFIX}__icon">${this.escapeHtml(icon2)}</span>`;
|
|
148210
150311
|
}
|
|
148211
150312
|
if (label) {
|
|
148212
150313
|
html += `<span>${this.escapeHtml(label)}</span>`;
|
|
@@ -152476,12 +154577,12 @@ function renderTimelineSVG(data, config2) {
|
|
|
152476
154577
|
const segWidth = Math.max(x2 - x1, 4);
|
|
152477
154578
|
const isOn = seg.state === "on";
|
|
152478
154579
|
const y = isOn ? onY : offY - 15;
|
|
152479
|
-
const
|
|
154580
|
+
const h3 = isOn ? barHeight : 15;
|
|
152480
154581
|
const color = isOn ? onColor : offColor;
|
|
152481
154582
|
const stateClass = isOn ? "on" : "off";
|
|
152482
154583
|
segmentPaths += `
|
|
152483
154584
|
<rect
|
|
152484
|
-
x="${x1}" y="${y}" width="${segWidth}" height="${
|
|
154585
|
+
x="${x1}" y="${y}" width="${segWidth}" height="${h3}"
|
|
152485
154586
|
fill="${color}" rx="3"
|
|
152486
154587
|
class="${ONOFF_TIMELINE_CSS_PREFIX}__segment ${ONOFF_TIMELINE_CSS_PREFIX}__segment--${stateClass}"
|
|
152487
154588
|
data-index="${index}"
|
|
@@ -152489,7 +154590,7 @@ function renderTimelineSVG(data, config2) {
|
|
|
152489
154590
|
`;
|
|
152490
154591
|
if (showDurationLabels && segWidth > 45) {
|
|
152491
154592
|
const centerX = x1 + segWidth / 2;
|
|
152492
|
-
const centerY = y +
|
|
154593
|
+
const centerY = y + h3 / 2 + 3;
|
|
152493
154594
|
durationLabels += `
|
|
152494
154595
|
<text
|
|
152495
154596
|
x="${centerX}" y="${centerY}"
|
|
@@ -152516,7 +154617,7 @@ function renderTimelineSVG(data, config2) {
|
|
|
152516
154617
|
}
|
|
152517
154618
|
tooltipAreas += `
|
|
152518
154619
|
<rect
|
|
152519
|
-
x="${x1}" y="${y}" width="${segWidth}" height="${
|
|
154620
|
+
x="${x1}" y="${y}" width="${segWidth}" height="${h3}"
|
|
152520
154621
|
fill="transparent"
|
|
152521
154622
|
class="tooltip-trigger"
|
|
152522
154623
|
data-state="${stateClass}"
|
|
@@ -153925,15 +156026,15 @@ var OnOffDeviceModalView = class {
|
|
|
153925
156026
|
if (!anchor) return;
|
|
153926
156027
|
const ev = this.evalDeviceStatus();
|
|
153927
156028
|
if (!ev.statusStale && !ev.connectionStale) return;
|
|
153928
|
-
const
|
|
153929
|
-
|
|
153930
|
-
|
|
153931
|
-
|
|
153932
|
-
|
|
153933
|
-
anchor.appendChild(
|
|
156029
|
+
const icon2 = document.createElement("span");
|
|
156030
|
+
icon2.className = `${ON_OFF_MODAL_CSS_PREFIX}__status-warning`;
|
|
156031
|
+
icon2.textContent = "\u26A0\uFE0F";
|
|
156032
|
+
icon2.style.cssText = "cursor: help; font-size: 16px; margin-left: 8px; line-height: 1; user-select: none; display: inline-block;";
|
|
156033
|
+
icon2.setAttribute("aria-label", "Telemetria de status desatualizada");
|
|
156034
|
+
anchor.appendChild(icon2);
|
|
153934
156035
|
const when = formatStatusTimestamp(ev.statusTs);
|
|
153935
156036
|
const lastValue = (ev.value || "\u2014").toString().toUpperCase();
|
|
153936
|
-
this.statusWarnTooltipCleanup = InfoTooltip_default.attach(
|
|
156037
|
+
this.statusWarnTooltipCleanup = InfoTooltip_default.attach(icon2, () => ({
|
|
153937
156038
|
icon: "\u26A0\uFE0F",
|
|
153938
156039
|
title: "Status possivelmente desatualizado",
|
|
153939
156040
|
content: `A \xFAltima telemetria de <b>status</b> foi em <b>${when}</b>, h\xE1 mais de ${STATUS_FRESHNESS_MAX_HOURS} horas.<br><br>O estado exibido (<b>${lastValue}</b>) \xE9 o \xFAltimo conhecido e pode n\xE3o refletir o estado atual do dispositivo.`
|
|
@@ -154072,8 +156173,8 @@ var OnOffDeviceModalView = class {
|
|
|
154072
156173
|
actions.appendChild(btnYes);
|
|
154073
156174
|
actions.appendChild(btnNo);
|
|
154074
156175
|
} else {
|
|
154075
|
-
const
|
|
154076
|
-
msg.textContent = `${
|
|
156176
|
+
const icon2 = type === "success" ? "\u2705" : "\u274C";
|
|
156177
|
+
msg.textContent = `${icon2} ${message}`;
|
|
154077
156178
|
const btnClose = document.createElement("button");
|
|
154078
156179
|
btnClose.textContent = "Fechar";
|
|
154079
156180
|
btnClose.style.cssText = `
|
|
@@ -154207,12 +156308,12 @@ var OnOffDeviceModalView = class {
|
|
|
154207
156308
|
this.updateScheduleButton("\u{1F4C5}", "Agendamento");
|
|
154208
156309
|
}
|
|
154209
156310
|
}
|
|
154210
|
-
updateScheduleButton(
|
|
156311
|
+
updateScheduleButton(icon2, label) {
|
|
154211
156312
|
const btn = this.scheduleButtonContainer?.querySelector(`.${ON_OFF_MODAL_CSS_PREFIX}__schedule-btn`);
|
|
154212
156313
|
if (btn) {
|
|
154213
156314
|
const iconEl = btn.querySelector("[data-icon]");
|
|
154214
156315
|
const labelEl = btn.querySelector("[data-label]");
|
|
154215
|
-
if (iconEl) iconEl.textContent =
|
|
156316
|
+
if (iconEl) iconEl.textContent = icon2;
|
|
154216
156317
|
if (labelEl) labelEl.textContent = label;
|
|
154217
156318
|
}
|
|
154218
156319
|
}
|
|
@@ -159292,10 +161393,10 @@ function renderStep22(plan) {
|
|
|
159292
161393
|
const customers = nonSkip.filter((a) => a.entityKind === "customer");
|
|
159293
161394
|
const assets = nonSkip.filter((a) => a.entityKind === "asset");
|
|
159294
161395
|
const devices = nonSkip.filter((a) => a.entityKind === "device");
|
|
159295
|
-
function sectionHtml(
|
|
161396
|
+
function sectionHtml(icon2, title, actions) {
|
|
159296
161397
|
if (actions.length === 0) return "";
|
|
159297
161398
|
return `
|
|
159298
|
-
<div class="gcdr-section-title">${
|
|
161399
|
+
<div class="gcdr-section-title">${icon2} ${title} (${actions.length})</div>
|
|
159299
161400
|
<ul class="gcdr-action-list">
|
|
159300
161401
|
${actions.map((a) => `
|
|
159301
161402
|
<li class="gcdr-action-item">
|
|
@@ -159986,9 +162087,9 @@ function formatDuration3(ms) {
|
|
|
159986
162087
|
if (!ms) return "";
|
|
159987
162088
|
const min = Math.round(ms / 6e4);
|
|
159988
162089
|
if (min < 60) return `${min} min`;
|
|
159989
|
-
const
|
|
162090
|
+
const h3 = Math.floor(min / 60);
|
|
159990
162091
|
const rem = min % 60;
|
|
159991
|
-
return rem > 0 ? `${
|
|
162092
|
+
return rem > 0 ? `${h3}h ${rem}min` : `${h3}h`;
|
|
159992
162093
|
}
|
|
159993
162094
|
function renderDaysOfWeek(daysOfWeek) {
|
|
159994
162095
|
if (!daysOfWeek) return "";
|
|
@@ -161120,9 +163221,9 @@ var ProvisioningApiClient = class {
|
|
|
161120
163221
|
const newLogs = logs.filter((l) => l.id > lastLogId);
|
|
161121
163222
|
for (const entry of newLogs) {
|
|
161122
163223
|
const time = (entry.timestamp ?? "").split(" ")[1] ?? "";
|
|
161123
|
-
const
|
|
163224
|
+
const icon2 = STEP_ICONS[entry.step] ?? "\u{1F4CB}";
|
|
161124
163225
|
if (entry.level === "INFO" && !entry.message.includes("Progress updated to")) {
|
|
161125
|
-
onLog(`${
|
|
163226
|
+
onLog(`${icon2} [${time}] ${entry.message}`);
|
|
161126
163227
|
}
|
|
161127
163228
|
}
|
|
161128
163229
|
if (newLogs.length > 0) {
|
|
@@ -161245,22 +163346,22 @@ function drawFooter(doc, pageW, pageH, footerH, pageNo, pageCount) {
|
|
|
161245
163346
|
doc.setTextColor(40);
|
|
161246
163347
|
doc.text(label, bx + padX, baseline);
|
|
161247
163348
|
}
|
|
161248
|
-
async function drawTag(doc, x, y, w,
|
|
163349
|
+
async function drawTag(doc, x, y, w, h3, device, gateway, allDevices) {
|
|
161249
163350
|
const FRAME_SCALE_Y = 1.05;
|
|
161250
163351
|
const QR_SCALE = 1.7;
|
|
161251
163352
|
const QR_SHIFT_Y = 3;
|
|
161252
163353
|
const GAP_AFTER_QR = 6;
|
|
161253
|
-
const frameH =
|
|
161254
|
-
const frameY = y - (frameH -
|
|
163354
|
+
const frameH = h3 * FRAME_SCALE_Y;
|
|
163355
|
+
const frameY = y - (frameH - h3) / 2;
|
|
161255
163356
|
doc.setDrawColor(235);
|
|
161256
163357
|
doc.setLineWidth(0.15);
|
|
161257
163358
|
doc.rect(x, frameY, w, frameH);
|
|
161258
|
-
const pad = Math.max(2,
|
|
163359
|
+
const pad = Math.max(2, h3 * 0.05);
|
|
161259
163360
|
const innerX = x + pad;
|
|
161260
163361
|
const innerW = w - pad * 2;
|
|
161261
|
-
const titleAreaH =
|
|
163362
|
+
const titleAreaH = h3 * 0.15;
|
|
161262
163363
|
const qrAreaTop = y + titleAreaH;
|
|
161263
|
-
const qrAreaH =
|
|
163364
|
+
const qrAreaH = h3 - titleAreaH - 12;
|
|
161264
163365
|
const displayName = generateDeviceNameWithPrefix(device, void 0, allDevices);
|
|
161265
163366
|
const rawName = sanitizePdf(displayName);
|
|
161266
163367
|
const nameFont = Math.max(6, Math.min(11, titleAreaH * 0.45));
|
|
@@ -165869,10 +167970,10 @@ ${this._renderToolbar(filteredCount, totalAllUnfiltered)}
|
|
|
165869
167970
|
const collapseAllBtn = this.root.querySelector('[data-action="collapse-all"]');
|
|
165870
167971
|
if (collapseAllBtn) collapseAllBtn.addEventListener("click", () => this._collapseAll());
|
|
165871
167972
|
const groupHeaders = this.root.querySelectorAll("[data-group-toggle]");
|
|
165872
|
-
groupHeaders.forEach((
|
|
165873
|
-
const key =
|
|
165874
|
-
|
|
165875
|
-
|
|
167973
|
+
groupHeaders.forEach((h3) => {
|
|
167974
|
+
const key = h3.getAttribute("data-group-toggle") || "";
|
|
167975
|
+
h3.addEventListener("click", () => this._toggleGroupCollapsed(key));
|
|
167976
|
+
h3.addEventListener("keydown", (e) => {
|
|
165876
167977
|
const ke = e;
|
|
165877
167978
|
if (ke.key === "Enter" || ke.key === " ") {
|
|
165878
167979
|
ke.preventDefault();
|
|
@@ -166404,7 +168505,7 @@ function validateDeviceProductCode(code) {
|
|
|
166404
168505
|
|
|
166405
168506
|
// src/components/cards/central-status/v1.0.0/styles.ts
|
|
166406
168507
|
var STYLE_ID16 = "myio-central-status-card-styles";
|
|
166407
|
-
var
|
|
168508
|
+
var CSS5 = `
|
|
166408
168509
|
.myio-cscard{
|
|
166409
168510
|
--cscard-surface:#ffffff;
|
|
166410
168511
|
--cscard-border:#e2e8f0;
|
|
@@ -166709,7 +168810,7 @@ function injectCentralStatusCardStyles() {
|
|
|
166709
168810
|
if (document.getElementById(STYLE_ID16)) return;
|
|
166710
168811
|
const tag = document.createElement("style");
|
|
166711
168812
|
tag.id = STYLE_ID16;
|
|
166712
|
-
tag.textContent =
|
|
168813
|
+
tag.textContent = CSS5;
|
|
166713
168814
|
document.head.appendChild(tag);
|
|
166714
168815
|
}
|
|
166715
168816
|
|
|
@@ -168312,6 +170413,9 @@ var version = package_default.version || "0.0.0";
|
|
|
168312
170413
|
createModalHeader,
|
|
168313
170414
|
createMoneyVarianceColumn,
|
|
168314
170415
|
createMyIOTheme,
|
|
170416
|
+
createMyioGcdrLoginSubmit,
|
|
170417
|
+
createMyioGcdrLoginView,
|
|
170418
|
+
createMyioGcdrShell,
|
|
168315
170419
|
createNewTicketWizard,
|
|
168316
170420
|
createOnOffDeviceModal,
|
|
168317
170421
|
createOnOffTimelineChart,
|
|
@@ -168552,6 +170656,7 @@ var version = package_default.version || "0.0.0";
|
|
|
168552
170656
|
isInRange,
|
|
168553
170657
|
isLeapYear,
|
|
168554
170658
|
isMoneyColumnConfident,
|
|
170659
|
+
isMyioGcdrLoginModalOpen,
|
|
168555
170660
|
isOnOffDeviceProfile,
|
|
168556
170661
|
isSolenoidDevice,
|
|
168557
170662
|
isStoreDevice,
|
|
@@ -168613,6 +170718,7 @@ var version = package_default.version || "0.0.0";
|
|
|
168613
170718
|
openMeasurementSetupModal,
|
|
168614
170719
|
openMessageDialog,
|
|
168615
170720
|
openMetasGuide,
|
|
170721
|
+
openMyioGcdrLoginModal,
|
|
168616
170722
|
openOnOffDeviceModal,
|
|
168617
170723
|
openOnboardModal,
|
|
168618
170724
|
openOperationalComparisonModal,
|