myio-js-library 0.1.546 → 0.1.547
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 +2421 -328
- package/dist/index.d.cts +316 -1
- package/dist/index.d.ts +316 -1
- package/dist/index.js +2414 -326
- package/dist/myio-js-library.umd.js +2411 -326
- 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.547",
|
|
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>
|
|
@@ -18740,7 +18745,7 @@ function renderCardComponentV5({
|
|
|
18740
18745
|
const connectionStatus = mapDeviceToConnectionStatus(deviceStatus);
|
|
18741
18746
|
const isOffline = isDeviceOffline(deviceStatus);
|
|
18742
18747
|
const shouldFlashIcon2 = shouldFlashIcon(deviceStatus);
|
|
18743
|
-
const
|
|
18748
|
+
const icon2 = getDeviceStatusIcon(deviceStatus, deviceType);
|
|
18744
18749
|
const connectionIcon = getConnectionStatusIcon(connectionStatus);
|
|
18745
18750
|
const debugDeviceName = "3F SCMAL3L4304ABC";
|
|
18746
18751
|
const labelStr = String(labelOrName || "");
|
|
@@ -19169,7 +19174,7 @@ function renderCardComponentV5({
|
|
|
19169
19174
|
<div class="device-data-row">
|
|
19170
19175
|
<div class="consumption-main">
|
|
19171
19176
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
19172
|
-
${
|
|
19177
|
+
${icon2}
|
|
19173
19178
|
</span>
|
|
19174
19179
|
<span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType)}</span>
|
|
19175
19180
|
</div>
|
|
@@ -20579,7 +20584,7 @@ function renderCardComponentV6({
|
|
|
20579
20584
|
const connectionStatus = mapDeviceToConnectionStatus(deviceStatus);
|
|
20580
20585
|
const isOffline = isDeviceOffline(deviceStatus);
|
|
20581
20586
|
const shouldFlashIcon2 = shouldFlashIcon(deviceStatus);
|
|
20582
|
-
const
|
|
20587
|
+
const icon2 = getDeviceStatusIcon(deviceStatus, effectiveDeviceType);
|
|
20583
20588
|
const connectionIcon = getConnectionStatusIcon(connectionStatus);
|
|
20584
20589
|
const mapDeviceTypeToIcon = (deviceType2) => {
|
|
20585
20590
|
const category = getDeviceCategory(deviceType2);
|
|
@@ -20961,7 +20966,7 @@ function renderCardComponentV6({
|
|
|
20961
20966
|
<div class="device-data-row">
|
|
20962
20967
|
<div class="consumption-main">
|
|
20963
20968
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
20964
|
-
${
|
|
20969
|
+
${icon2}
|
|
20965
20970
|
</span>
|
|
20966
20971
|
<span class="consumption-value">${formatCardValue(cardEntity.lastValue, deviceType, deviceProfile)}</span>
|
|
20967
20972
|
</div>
|
|
@@ -22510,12 +22515,12 @@ function renderCardAmbienteV6({
|
|
|
22510
22515
|
statusText = isOn2 ? "ON" : "OFF";
|
|
22511
22516
|
stateClass = isOn2 ? "on" : "off";
|
|
22512
22517
|
}
|
|
22513
|
-
const
|
|
22518
|
+
const icon2 = isLamp ? "\u{1F4A1}" : "\u{1F518}";
|
|
22514
22519
|
const deviceEl = document.createElement("div");
|
|
22515
22520
|
deviceEl.className = `myio-ambiente-card__switch-device ${stateClass} ${isLamp ? "lamp" : "remote"}`;
|
|
22516
22521
|
deviceEl.title = device.label || device.name || (isLamp ? "L\xE2mpada" : "Controle");
|
|
22517
22522
|
deviceEl.innerHTML = `
|
|
22518
|
-
<span class="myio-ambiente-card__switch-device-icon">${
|
|
22523
|
+
<span class="myio-ambiente-card__switch-device-icon">${icon2}</span>
|
|
22519
22524
|
<span class="myio-ambiente-card__switch-device-value">${statusText}</span>
|
|
22520
22525
|
`;
|
|
22521
22526
|
scrollContainer.appendChild(deviceEl);
|
|
@@ -22936,10 +22941,10 @@ var HeaderPanelComponent = class {
|
|
|
22936
22941
|
el2.style.display = quantity >= 0 ? "" : "none";
|
|
22937
22942
|
}
|
|
22938
22943
|
}
|
|
22939
|
-
setIcon(
|
|
22940
|
-
this.options.icon =
|
|
22944
|
+
setIcon(icon2) {
|
|
22945
|
+
this.options.icon = icon2;
|
|
22941
22946
|
const el2 = this.root.querySelector(".myio-hp__icon");
|
|
22942
|
-
if (el2) el2.innerHTML =
|
|
22947
|
+
if (el2) el2.innerHTML = icon2;
|
|
22943
22948
|
}
|
|
22944
22949
|
setSubtitle(subtitle) {
|
|
22945
22950
|
this.options.subtitle = subtitle;
|
|
@@ -22998,7 +23003,7 @@ var HeaderPanelComponent = class {
|
|
|
22998
23003
|
render() {
|
|
22999
23004
|
const {
|
|
23000
23005
|
title,
|
|
23001
|
-
icon,
|
|
23006
|
+
icon: icon2,
|
|
23002
23007
|
quantity,
|
|
23003
23008
|
style,
|
|
23004
23009
|
showSearch,
|
|
@@ -23015,10 +23020,10 @@ var HeaderPanelComponent = class {
|
|
|
23015
23020
|
}
|
|
23016
23021
|
const left = document.createElement("div");
|
|
23017
23022
|
left.className = "myio-hp__left";
|
|
23018
|
-
if (
|
|
23023
|
+
if (icon2) {
|
|
23019
23024
|
const iconEl = document.createElement("span");
|
|
23020
23025
|
iconEl.className = "myio-hp__icon";
|
|
23021
|
-
iconEl.innerHTML =
|
|
23026
|
+
iconEl.innerHTML = icon2;
|
|
23022
23027
|
if (style?.iconColor) iconEl.style.color = style.iconColor;
|
|
23023
23028
|
left.appendChild(iconEl);
|
|
23024
23029
|
}
|
|
@@ -23497,10 +23502,10 @@ var EntityListPanel = class {
|
|
|
23497
23502
|
}
|
|
23498
23503
|
}
|
|
23499
23504
|
/** Update icon */
|
|
23500
|
-
setIcon(
|
|
23501
|
-
this.options.icon =
|
|
23505
|
+
setIcon(icon2) {
|
|
23506
|
+
this.options.icon = icon2;
|
|
23502
23507
|
if (this.headerComponent) {
|
|
23503
|
-
this.headerComponent.setIcon(
|
|
23508
|
+
this.headerComponent.setIcon(icon2);
|
|
23504
23509
|
}
|
|
23505
23510
|
}
|
|
23506
23511
|
/** Update background watermark image */
|
|
@@ -23550,7 +23555,7 @@ var EntityListPanel = class {
|
|
|
23550
23555
|
const {
|
|
23551
23556
|
title,
|
|
23552
23557
|
subtitle,
|
|
23553
|
-
icon,
|
|
23558
|
+
icon: icon2,
|
|
23554
23559
|
quantity,
|
|
23555
23560
|
backgroundImage,
|
|
23556
23561
|
searchPlaceholder,
|
|
@@ -23569,7 +23574,7 @@ var EntityListPanel = class {
|
|
|
23569
23574
|
this.headerComponent = new HeaderPanelComponent({
|
|
23570
23575
|
title,
|
|
23571
23576
|
subtitle,
|
|
23572
|
-
icon,
|
|
23577
|
+
icon: icon2,
|
|
23573
23578
|
quantity,
|
|
23574
23579
|
style: titleStyle,
|
|
23575
23580
|
showBottomBorder: false,
|
|
@@ -24050,10 +24055,10 @@ var CardGridPanel = class {
|
|
|
24050
24055
|
}
|
|
24051
24056
|
}
|
|
24052
24057
|
/** Update icon */
|
|
24053
|
-
setIcon(
|
|
24054
|
-
this.options.icon =
|
|
24058
|
+
setIcon(icon2) {
|
|
24059
|
+
this.options.icon = icon2;
|
|
24055
24060
|
if (this.headerComponent) {
|
|
24056
|
-
this.headerComponent.setIcon(
|
|
24061
|
+
this.headerComponent.setIcon(icon2);
|
|
24057
24062
|
}
|
|
24058
24063
|
}
|
|
24059
24064
|
/** Set maximize state without triggering callback (for external reset) */
|
|
@@ -24109,7 +24114,7 @@ var CardGridPanel = class {
|
|
|
24109
24114
|
render() {
|
|
24110
24115
|
const {
|
|
24111
24116
|
title,
|
|
24112
|
-
icon,
|
|
24117
|
+
icon: icon2,
|
|
24113
24118
|
quantity,
|
|
24114
24119
|
gridMinCardWidth,
|
|
24115
24120
|
titleStyle,
|
|
@@ -24124,7 +24129,7 @@ var CardGridPanel = class {
|
|
|
24124
24129
|
this.root.innerHTML = "";
|
|
24125
24130
|
this.headerComponent = new HeaderPanelComponent({
|
|
24126
24131
|
title,
|
|
24127
|
-
icon,
|
|
24132
|
+
icon: icon2,
|
|
24128
24133
|
quantity,
|
|
24129
24134
|
style: titleStyle,
|
|
24130
24135
|
showBottomBorder: true,
|
|
@@ -28263,20 +28268,20 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28263
28268
|
}
|
|
28264
28269
|
const todayStr = (/* @__PURE__ */ new Date()).toLocaleDateString(locale, { day: "2-digit", month: "2-digit", year: "numeric" });
|
|
28265
28270
|
const dateHtml = `<span style="margin-left:8px;font-size:13px;font-weight:400;opacity:0.55;">(${todayStr})</span>`;
|
|
28266
|
-
const
|
|
28271
|
+
const icon2 = (glyph, title) => `<span title="${title}" style="margin-left:8px;cursor:default;font-size:16px;vertical-align:middle;">${glyph}</span>`;
|
|
28267
28272
|
let iconHtml;
|
|
28268
28273
|
if (!hasTelemetryToday()) {
|
|
28269
|
-
iconHtml =
|
|
28274
|
+
iconHtml = icon2("\u274C", "Sem telemetrias de hoje para este dispositivo");
|
|
28270
28275
|
} else if (centralStatus === "offline") {
|
|
28271
|
-
iconHtml =
|
|
28276
|
+
iconHtml = icon2("\u{1F534}", `Central offline (${STATUS_MAX_RETRIES} falhas seguidas)`);
|
|
28272
28277
|
} else if (deviceStatus === "offline") {
|
|
28273
|
-
iconHtml =
|
|
28278
|
+
iconHtml = icon2("\u{1F534}", `Dispositivo offline (${STATUS_MAX_RETRIES} verifica\xE7\xF5es seguidas sem telemetria recente)`);
|
|
28274
28279
|
} else if (centralStatus === "warning") {
|
|
28275
|
-
iconHtml =
|
|
28280
|
+
iconHtml = icon2("\u26A0\uFE0F", `Aten\xE7\xE3o: central sem resposta (tentativa ${centralFailStreak}/${STATUS_MAX_RETRIES})`);
|
|
28276
28281
|
} else if (deviceStatus === "warning") {
|
|
28277
|
-
iconHtml =
|
|
28282
|
+
iconHtml = icon2("\u26A0\uFE0F", `Aten\xE7\xE3o: ${deviceStaleLabel()} (verifica\xE7\xE3o ${deviceStaleStreak}/${STATUS_MAX_RETRIES})`);
|
|
28278
28283
|
} else {
|
|
28279
|
-
iconHtml =
|
|
28284
|
+
iconHtml = icon2("\u2705", "H\xE1 telemetrias de hoje e o dispositivo est\xE1 respondendo");
|
|
28280
28285
|
}
|
|
28281
28286
|
chartTitleEl.innerHTML = `Telemetria em Tempo Real de hoje${dateHtml}${iconHtml}`;
|
|
28282
28287
|
}
|
|
@@ -28647,7 +28652,7 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28647
28652
|
}
|
|
28648
28653
|
injectCardTooltipStyles();
|
|
28649
28654
|
const ok = checkDeviceHistory.filter((r) => r.status === "ok").length;
|
|
28650
|
-
const
|
|
28655
|
+
const fail2 = checkDeviceHistory.filter((r) => r.status === "offline").length;
|
|
28651
28656
|
const total = checkDeviceHistory.length;
|
|
28652
28657
|
const firstTs = checkDeviceHistory[0]?.ts;
|
|
28653
28658
|
const uptimeLabel = firstTs ? (() => {
|
|
@@ -28666,10 +28671,10 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28666
28671
|
minute: "2-digit",
|
|
28667
28672
|
second: "2-digit"
|
|
28668
28673
|
});
|
|
28669
|
-
const
|
|
28670
|
-
return `<div class="rtt-tt-history-row">${
|
|
28674
|
+
const icon2 = r.status === "ok" ? "\u2705" : "\u274C";
|
|
28675
|
+
return `<div class="rtt-tt-history-row">${icon2} ${dt}</div>`;
|
|
28671
28676
|
}).join("");
|
|
28672
|
-
const failBlock =
|
|
28677
|
+
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
28678
|
const tooltip = document.createElement("div");
|
|
28674
28679
|
tooltip.id = "rtt-status-tooltip";
|
|
28675
28680
|
if (currentTheme === "dark") tooltip.dataset["theme"] = "dark";
|
|
@@ -28689,7 +28694,7 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28689
28694
|
${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
28695
|
<div style="font-size:12px;">\u{1F4E1} <b>${ok}</b> chamadas com sucesso${total > 0 ? ` de ${total}` : ""}</div>
|
|
28691
28696
|
<div style="font-size:12px;">\u23F1\uFE0F Monitorando h\xE1: <b>${uptimeLabel}</b></div>
|
|
28692
|
-
${
|
|
28697
|
+
${fail2 > 0 ? `<div style="font-size:12px;color:#e74c3c;">\u274C <b>${fail2}</b> falha${fail2 > 1 ? "s" : ""}</div>` : ""}
|
|
28693
28698
|
</div>
|
|
28694
28699
|
${failBlock}
|
|
28695
28700
|
</div>
|
|
@@ -28739,9 +28744,9 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
28739
28744
|
minute: "2-digit",
|
|
28740
28745
|
second: "2-digit"
|
|
28741
28746
|
}) : "--";
|
|
28742
|
-
function row(
|
|
28747
|
+
function row(icon2, label, value) {
|
|
28743
28748
|
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;">${
|
|
28749
|
+
<span style="font-size:10px;color:#9ca3af;font-weight:500;">${icon2} ${label}</span>
|
|
28745
28750
|
<span style="font-family:monospace;font-size:12px;color:#1f2937;font-weight:600;word-break:break-all;">${value || "\u2014"}</span>
|
|
28746
28751
|
</div>`;
|
|
28747
28752
|
}
|
|
@@ -29189,11 +29194,11 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29189
29194
|
function showCoverageNotice(text2, resume) {
|
|
29190
29195
|
if (!coverageNoticeEl) return;
|
|
29191
29196
|
coverageNoticeEl.textContent = "";
|
|
29192
|
-
const
|
|
29193
|
-
|
|
29197
|
+
const icon2 = document.createElement("span");
|
|
29198
|
+
icon2.textContent = "\u26A0\uFE0F ";
|
|
29194
29199
|
const msg = document.createElement("span");
|
|
29195
29200
|
msg.textContent = text2;
|
|
29196
|
-
coverageNoticeEl.append(
|
|
29201
|
+
coverageNoticeEl.append(icon2, msg);
|
|
29197
29202
|
coverageResume = resume ? { startISO: resume.startISO, endISO: resume.endISO } : null;
|
|
29198
29203
|
if (resume) {
|
|
29199
29204
|
const link = document.createElement("a");
|
|
@@ -29738,8 +29743,8 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29738
29743
|
if (!chart) return;
|
|
29739
29744
|
chart.options.responsive = false;
|
|
29740
29745
|
const w = chartContainer.clientWidth - 40;
|
|
29741
|
-
const
|
|
29742
|
-
chart.resize(Math.max(w, 200), Math.max(
|
|
29746
|
+
const h3 = chartContainer.clientHeight - 60;
|
|
29747
|
+
chart.resize(Math.max(w, 200), Math.max(h3, 120));
|
|
29743
29748
|
})
|
|
29744
29749
|
);
|
|
29745
29750
|
}
|
|
@@ -29885,8 +29890,8 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29885
29890
|
URL.revokeObjectURL(url);
|
|
29886
29891
|
}
|
|
29887
29892
|
function ensureRoom2(doc, nextY, minRoom = 12) {
|
|
29888
|
-
const
|
|
29889
|
-
if (nextY + minRoom >
|
|
29893
|
+
const h3 = doc.internal.pageSize.getHeight();
|
|
29894
|
+
if (nextY + minRoom > h3 - 15) {
|
|
29890
29895
|
doc.addPage();
|
|
29891
29896
|
return 20;
|
|
29892
29897
|
}
|
|
@@ -29985,8 +29990,8 @@ async function openRealTimeTelemetryModal(params) {
|
|
|
29985
29990
|
if (isExpanded) {
|
|
29986
29991
|
chart.options.responsive = false;
|
|
29987
29992
|
const w = chartContainer.clientWidth - 40;
|
|
29988
|
-
const
|
|
29989
|
-
chart.resize(Math.max(w, 200), Math.max(
|
|
29993
|
+
const h3 = chartContainer.clientHeight - 60;
|
|
29994
|
+
chart.resize(Math.max(w, 200), Math.max(h3, 120));
|
|
29990
29995
|
} else {
|
|
29991
29996
|
chart.options.responsive = true;
|
|
29992
29997
|
chartCanvas.style.height = "";
|
|
@@ -30774,10 +30779,10 @@ var BASControlPanel = class {
|
|
|
30774
30779
|
}
|
|
30775
30780
|
return items.join("");
|
|
30776
30781
|
}
|
|
30777
|
-
renderTelemetryItem(label, value, unit,
|
|
30782
|
+
renderTelemetryItem(label, value, unit, icon2) {
|
|
30778
30783
|
return `
|
|
30779
30784
|
<div class="myio-bas-telemetry-item">
|
|
30780
|
-
<span class="myio-bas-telemetry-icon">${
|
|
30785
|
+
<span class="myio-bas-telemetry-icon">${icon2}</span>
|
|
30781
30786
|
<div class="myio-bas-telemetry-content">
|
|
30782
30787
|
<span class="myio-bas-telemetry-label">${label}</span>
|
|
30783
30788
|
<span class="myio-bas-telemetry-value">${value} <span class="myio-bas-telemetry-unit">${unit}</span></span>
|
|
@@ -34143,20 +34148,20 @@ function mixHex(a, b, ratio) {
|
|
|
34143
34148
|
};
|
|
34144
34149
|
return `#${mix(0)}${mix(2)}${mix(4)}`;
|
|
34145
34150
|
}
|
|
34146
|
-
function hslToHex(
|
|
34151
|
+
function hslToHex(h3, s, l) {
|
|
34147
34152
|
const sat = s / 100;
|
|
34148
34153
|
const lig = l / 100;
|
|
34149
|
-
const k = (n) => (n +
|
|
34154
|
+
const k = (n) => (n + h3 / 30) % 12;
|
|
34150
34155
|
const a = sat * Math.min(lig, 1 - lig);
|
|
34151
34156
|
const f = (n) => lig - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
34152
34157
|
const to = (v) => Math.round(v * 255).toString(16).padStart(2, "0");
|
|
34153
34158
|
return `#${to(f(0))}${to(f(8))}${to(f(4))}`;
|
|
34154
34159
|
}
|
|
34155
34160
|
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(
|
|
34161
|
+
let h3 = 5381;
|
|
34162
|
+
for (let i = 0; i < label.length; i++) h3 = (h3 << 5) + h3 + label.charCodeAt(i) | 0;
|
|
34163
|
+
const hue = Math.abs(h3) % 360;
|
|
34164
|
+
const sat = 55 + Math.abs(h3 >> 8) % 25;
|
|
34160
34165
|
return hslToHex(hue, sat, dark ? 58 : 44);
|
|
34161
34166
|
}
|
|
34162
34167
|
function paletteColor(base, index, dark) {
|
|
@@ -34365,11 +34370,11 @@ function createParticipationChart(container, params) {
|
|
|
34365
34370
|
].join(" ");
|
|
34366
34371
|
}
|
|
34367
34372
|
function buildPieSvg2(entries, total) {
|
|
34368
|
-
const
|
|
34373
|
+
const svg2 = document.createElementNS(SVG_NS, "svg");
|
|
34369
34374
|
const SIZE = 300;
|
|
34370
|
-
|
|
34371
|
-
|
|
34372
|
-
|
|
34375
|
+
svg2.setAttribute("viewBox", `0 0 ${SIZE} ${SIZE}`);
|
|
34376
|
+
svg2.setAttribute("preserveAspectRatio", "xMidYMid meet");
|
|
34377
|
+
svg2.setAttribute("role", "img");
|
|
34373
34378
|
const cx = SIZE / 2;
|
|
34374
34379
|
const cy = SIZE / 2;
|
|
34375
34380
|
const ro = 128;
|
|
@@ -34401,7 +34406,7 @@ function createParticipationChart(container, params) {
|
|
|
34401
34406
|
path.addEventListener("mouseleave", () => {
|
|
34402
34407
|
path.style.transform = "";
|
|
34403
34408
|
});
|
|
34404
|
-
|
|
34409
|
+
svg2.appendChild(path);
|
|
34405
34410
|
attachItemTooltip(path, item, pct);
|
|
34406
34411
|
if (pct >= 8) {
|
|
34407
34412
|
const rl = (ro + ri) / 2;
|
|
@@ -34418,10 +34423,10 @@ function createParticipationChart(container, params) {
|
|
|
34418
34423
|
text2.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
|
|
34419
34424
|
text2.setAttribute("pointer-events", "none");
|
|
34420
34425
|
text2.textContent = fmtPct(pct);
|
|
34421
|
-
|
|
34426
|
+
svg2.appendChild(text2);
|
|
34422
34427
|
}
|
|
34423
34428
|
});
|
|
34424
|
-
return
|
|
34429
|
+
return svg2;
|
|
34425
34430
|
}
|
|
34426
34431
|
function buildBarsSvg(entries, total) {
|
|
34427
34432
|
const sorted = [...entries].sort((a, b) => b.item.value - a.item.value);
|
|
@@ -34433,10 +34438,10 @@ function createParticipationChart(container, params) {
|
|
|
34433
34438
|
const maxValue = sorted.reduce((m, e) => Math.max(m, e.item.value), 0);
|
|
34434
34439
|
const textColor = resolvedText();
|
|
34435
34440
|
const mutedColor = resolvedMuted();
|
|
34436
|
-
const
|
|
34437
|
-
|
|
34438
|
-
|
|
34439
|
-
|
|
34441
|
+
const svg2 = document.createElementNS(SVG_NS, "svg");
|
|
34442
|
+
svg2.setAttribute("viewBox", `0 0 ${W} ${H}`);
|
|
34443
|
+
svg2.setAttribute("preserveAspectRatio", "xMidYMin meet");
|
|
34444
|
+
svg2.setAttribute("role", "img");
|
|
34440
34445
|
sorted.forEach(({ item, color }, row) => {
|
|
34441
34446
|
const pct = total > 0 ? item.value / total * 100 : 0;
|
|
34442
34447
|
const y = row * ROW_H + 4;
|
|
@@ -34450,7 +34455,7 @@ function createParticipationChart(container, params) {
|
|
|
34450
34455
|
label.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
|
|
34451
34456
|
const raw = item.label || "";
|
|
34452
34457
|
label.textContent = raw.length > 18 ? `${raw.slice(0, 17)}\u2026` : raw;
|
|
34453
|
-
|
|
34458
|
+
svg2.appendChild(label);
|
|
34454
34459
|
const rect = document.createElementNS(SVG_NS, "rect");
|
|
34455
34460
|
rect.setAttribute("x", String(LABEL_W));
|
|
34456
34461
|
rect.setAttribute("y", String(y + 3));
|
|
@@ -34460,7 +34465,7 @@ function createParticipationChart(container, params) {
|
|
|
34460
34465
|
rect.setAttribute("fill", color);
|
|
34461
34466
|
rect.setAttribute("class", `${PARTICIPATION_CHART_CSS_PREFIX}__bar-rect`);
|
|
34462
34467
|
rect.setAttribute("data-key", keyOf(item));
|
|
34463
|
-
|
|
34468
|
+
svg2.appendChild(rect);
|
|
34464
34469
|
attachItemTooltip(rect, item, pct);
|
|
34465
34470
|
const value = document.createElementNS(SVG_NS, "text");
|
|
34466
34471
|
value.setAttribute("x", String(LABEL_W + barW + 6));
|
|
@@ -34470,9 +34475,9 @@ function createParticipationChart(container, params) {
|
|
|
34470
34475
|
value.setAttribute("font-size", "10.5");
|
|
34471
34476
|
value.setAttribute("font-family", "'Nunito', system-ui, sans-serif");
|
|
34472
34477
|
value.textContent = `${settings.formatValue(item.value)}${settings.unit ? ` ${settings.unit}` : ""} \xB7 ${fmtPct(pct)}`;
|
|
34473
|
-
|
|
34478
|
+
svg2.appendChild(value);
|
|
34474
34479
|
});
|
|
34475
|
-
return
|
|
34480
|
+
return svg2;
|
|
34476
34481
|
}
|
|
34477
34482
|
function buildLegend2(total) {
|
|
34478
34483
|
const legend = document.createElement("div");
|
|
@@ -34538,15 +34543,15 @@ function createParticipationChart(container, params) {
|
|
|
34538
34543
|
root.appendChild(body);
|
|
34539
34544
|
}
|
|
34540
34545
|
async function svgToPng(scale = 2) {
|
|
34541
|
-
const
|
|
34542
|
-
if (!
|
|
34546
|
+
const svg2 = root.querySelector("svg");
|
|
34547
|
+
if (!svg2) {
|
|
34543
34548
|
console.warn("[ParticipationChart] Nada para exportar \u2014 gr\xE1fico vazio.");
|
|
34544
34549
|
return null;
|
|
34545
34550
|
}
|
|
34546
|
-
const vb =
|
|
34551
|
+
const vb = svg2.viewBox.baseVal;
|
|
34547
34552
|
const width = vb && vb.width ? vb.width : 300;
|
|
34548
34553
|
const height = vb && vb.height ? vb.height : 300;
|
|
34549
|
-
const clone =
|
|
34554
|
+
const clone = svg2.cloneNode(true);
|
|
34550
34555
|
clone.setAttribute("xmlns", SVG_NS);
|
|
34551
34556
|
clone.setAttribute("width", String(width));
|
|
34552
34557
|
clone.setAttribute("height", String(height));
|
|
@@ -34882,14 +34887,14 @@ function createExportButton(kind, container, params = {}) {
|
|
|
34882
34887
|
const label = settings.label ?? defaultLabel;
|
|
34883
34888
|
const locked = !!settings.locked;
|
|
34884
34889
|
const disabled = locked || !!settings.disabled;
|
|
34885
|
-
const
|
|
34890
|
+
const icon2 = locked ? LOCK_ICON : settings.icon ?? defaultIcon;
|
|
34886
34891
|
btn.className = `${EXPORT_BUTTON_CSS_PREFIX}${locked ? ` ${EXPORT_BUTTON_CSS_PREFIX}--locked` : ""}`;
|
|
34887
34892
|
btn.disabled = disabled;
|
|
34888
34893
|
btn.style.borderColor = colors2.border;
|
|
34889
34894
|
btn.style.color = colors2.text;
|
|
34890
34895
|
btn.style.background = colors2.bg;
|
|
34891
34896
|
btn.setAttribute("aria-label", label);
|
|
34892
|
-
btn.innerHTML = `${
|
|
34897
|
+
btn.innerHTML = `${icon2 ? `<span class="${EXPORT_BUTTON_CSS_PREFIX}__icon">${icon2}</span>` : ""}${label}`;
|
|
34893
34898
|
tooltipCleanup?.();
|
|
34894
34899
|
tooltipCleanup = null;
|
|
34895
34900
|
const tt = settings.tooltip;
|
|
@@ -40813,11 +40818,11 @@ var PowerLimitsModalView = class {
|
|
|
40813
40818
|
const statusKey = status === "standby" ? "standBy" : status;
|
|
40814
40819
|
const config2 = STATUS_CONFIG[statusKey];
|
|
40815
40820
|
const formValues = this.formData[status];
|
|
40816
|
-
const
|
|
40821
|
+
const icon2 = domainIcons[statusKey];
|
|
40817
40822
|
return `
|
|
40818
40823
|
<div class="myio-power-limits-card-item myio-status-${status}" style="--status-color: ${config2.color}; --status-bg: ${config2.bgColor};">
|
|
40819
40824
|
<div class="myio-card-header">
|
|
40820
|
-
<span class="myio-status-icon">${
|
|
40825
|
+
<span class="myio-status-icon">${icon2}</span>
|
|
40821
40826
|
<span class="myio-status-indicator"></span>
|
|
40822
40827
|
<span class="myio-status-label">${config2.label}</span>
|
|
40823
40828
|
</div>
|
|
@@ -48317,7 +48322,7 @@ var AnnotationsTab = class {
|
|
|
48317
48322
|
const isReject = type === "rejected";
|
|
48318
48323
|
const isComment = type === "comment";
|
|
48319
48324
|
let title;
|
|
48320
|
-
let
|
|
48325
|
+
let icon2;
|
|
48321
48326
|
let headerClass;
|
|
48322
48327
|
let btnClass;
|
|
48323
48328
|
let labelText;
|
|
@@ -48327,7 +48332,7 @@ var AnnotationsTab = class {
|
|
|
48327
48332
|
let isRequired;
|
|
48328
48333
|
if (isApprove) {
|
|
48329
48334
|
title = "Aprovar Anota\xE7\xE3o";
|
|
48330
|
-
|
|
48335
|
+
icon2 = "\u2713";
|
|
48331
48336
|
headerClass = "response-modal__header--approve";
|
|
48332
48337
|
btnClass = "response-modal__btn--approve";
|
|
48333
48338
|
labelText = "Observa\xE7\xE3o (opcional)";
|
|
@@ -48337,7 +48342,7 @@ var AnnotationsTab = class {
|
|
|
48337
48342
|
isRequired = false;
|
|
48338
48343
|
} else if (isReject) {
|
|
48339
48344
|
title = "Rejeitar Anota\xE7\xE3o";
|
|
48340
|
-
|
|
48345
|
+
icon2 = "\u2717";
|
|
48341
48346
|
headerClass = "response-modal__header--reject";
|
|
48342
48347
|
btnClass = "response-modal__btn--reject";
|
|
48343
48348
|
labelText = "Justificativa";
|
|
@@ -48347,7 +48352,7 @@ var AnnotationsTab = class {
|
|
|
48347
48352
|
isRequired = true;
|
|
48348
48353
|
} else if (isComment) {
|
|
48349
48354
|
title = "Adicionar Coment\xE1rio";
|
|
48350
|
-
|
|
48355
|
+
icon2 = "\u{1F4AC}";
|
|
48351
48356
|
headerClass = "response-modal__header--comment";
|
|
48352
48357
|
btnClass = "response-modal__btn--comment";
|
|
48353
48358
|
labelText = "Coment\xE1rio";
|
|
@@ -48357,7 +48362,7 @@ var AnnotationsTab = class {
|
|
|
48357
48362
|
isRequired = true;
|
|
48358
48363
|
} else {
|
|
48359
48364
|
title = "Arquivar Anota\xE7\xE3o";
|
|
48360
|
-
|
|
48365
|
+
icon2 = "\u2B07\uFE0F";
|
|
48361
48366
|
headerClass = "response-modal__header--archive";
|
|
48362
48367
|
btnClass = "response-modal__btn--archive-modal";
|
|
48363
48368
|
labelText = "Justificativa";
|
|
@@ -48371,7 +48376,7 @@ var AnnotationsTab = class {
|
|
|
48371
48376
|
overlay.innerHTML = `
|
|
48372
48377
|
<div class="response-modal">
|
|
48373
48378
|
<div class="response-modal__header ${headerClass}">
|
|
48374
|
-
<span class="response-modal__icon">${
|
|
48379
|
+
<span class="response-modal__icon">${icon2}</span>
|
|
48375
48380
|
<span class="response-modal__title">${title}</span>
|
|
48376
48381
|
</div>
|
|
48377
48382
|
<div class="response-modal__body">
|
|
@@ -50627,9 +50632,9 @@ var AnnotationsTab = class {
|
|
|
50627
50632
|
` : ""}
|
|
50628
50633
|
<div class="annotation-detail__history">
|
|
50629
50634
|
<div class="annotation-detail__history-title">Hist\xF3rico (${annotation.history.length + (annotation.responses?.length || 0)} eventos)</div>
|
|
50630
|
-
${annotation.history.map((
|
|
50635
|
+
${annotation.history.map((h3) => `
|
|
50631
50636
|
<div class="annotation-detail__history-item">
|
|
50632
|
-
<strong>${
|
|
50637
|
+
<strong>${h3.action}</strong> por ${h3.userName} em ${this.formatDate(h3.timestamp)}
|
|
50633
50638
|
</div>
|
|
50634
50639
|
`).join("")}
|
|
50635
50640
|
${(annotation.responses || []).map((r) => `
|
|
@@ -51850,9 +51855,9 @@ function seededRand(seed) {
|
|
|
51850
51855
|
};
|
|
51851
51856
|
}
|
|
51852
51857
|
function hashStr(s) {
|
|
51853
|
-
let
|
|
51854
|
-
for (let i = 0; i < s.length; i++)
|
|
51855
|
-
return Math.abs(
|
|
51858
|
+
let h3 = 0;
|
|
51859
|
+
for (let i = 0; i < s.length; i++) h3 = Math.imul(31, h3) + s.charCodeAt(i) | 0;
|
|
51860
|
+
return Math.abs(h3);
|
|
51856
51861
|
}
|
|
51857
51862
|
function generateBuckets(alarm, devices, period = "mes") {
|
|
51858
51863
|
const count = alarm.occurrenceCount || 1;
|
|
@@ -51937,11 +51942,11 @@ function generateDowDistribution(alarm) {
|
|
|
51937
51942
|
function generateHodDistribution(alarm) {
|
|
51938
51943
|
const count = alarm.occurrenceCount || 1;
|
|
51939
51944
|
const rand = seededRand(hashStr(alarm.id + "hod"));
|
|
51940
|
-
const weights = Array.from({ length: 24 }, (_,
|
|
51941
|
-
if (
|
|
51942
|
-
if (
|
|
51943
|
-
if (
|
|
51944
|
-
if (
|
|
51945
|
+
const weights = Array.from({ length: 24 }, (_, h3) => {
|
|
51946
|
+
if (h3 < 6) return 0.05 + rand() * 0.05;
|
|
51947
|
+
if (h3 < 10) return 0.3 + rand() * 0.3;
|
|
51948
|
+
if (h3 <= 19) return 0.7 + rand() * 0.6;
|
|
51949
|
+
if (h3 <= 22) return 0.3 + rand() * 0.3;
|
|
51945
51950
|
return 0.05 + rand() * 0.05;
|
|
51946
51951
|
});
|
|
51947
51952
|
const wSum = weights.reduce((a, b) => a + b, 0);
|
|
@@ -52074,7 +52079,7 @@ function createHodChart(canvas, vals) {
|
|
|
52074
52079
|
return new Chart2(canvas, {
|
|
52075
52080
|
type: "bar",
|
|
52076
52081
|
data: {
|
|
52077
|
-
labels: Array.from({ length: 24 }, (_,
|
|
52082
|
+
labels: Array.from({ length: 24 }, (_, h3) => `${h3}h`),
|
|
52078
52083
|
datasets: [{
|
|
52079
52084
|
label: "Ocorr\xEAncias",
|
|
52080
52085
|
data: vals,
|
|
@@ -60562,12 +60567,12 @@ var TicketsTab = class {
|
|
|
60562
60567
|
const container = this.config.container;
|
|
60563
60568
|
const toggle = container.querySelector("#ct-new-ticket-toggle");
|
|
60564
60569
|
const body = container.querySelector("#ct-new-ticket-body");
|
|
60565
|
-
const
|
|
60570
|
+
const icon2 = container.querySelector("#ct-collapse-icon");
|
|
60566
60571
|
if (toggle && body) {
|
|
60567
60572
|
toggle.addEventListener("click", () => {
|
|
60568
60573
|
const isOpen = body.style.display !== "none";
|
|
60569
60574
|
body.style.display = isOpen ? "none" : "block";
|
|
60570
|
-
if (
|
|
60575
|
+
if (icon2) icon2.textContent = isOpen ? "\u25BC" : "\u25B2";
|
|
60571
60576
|
});
|
|
60572
60577
|
}
|
|
60573
60578
|
if (this.config.requesterEmail) {
|
|
@@ -60779,13 +60784,13 @@ ${description}` : description;
|
|
|
60779
60784
|
return;
|
|
60780
60785
|
}
|
|
60781
60786
|
area.innerHTML = this._selectedFiles.map((f, i) => {
|
|
60782
|
-
const
|
|
60787
|
+
const icon2 = this._getFileIcon(f);
|
|
60783
60788
|
const isImage = f.type.startsWith("image/");
|
|
60784
60789
|
const tooltip = `${f.name}
|
|
60785
60790
|
${this._formatFileSize(f.size)} \xB7 ${f.type || "arquivo"}`;
|
|
60786
60791
|
return `
|
|
60787
60792
|
<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">${
|
|
60793
|
+
${isImage ? `<img class="ct-file-thumb" src="${URL.createObjectURL(f)}" alt="${this.esc(f.name)}">` : `<span class="ct-file-icon">${icon2}</span>`}
|
|
60789
60794
|
<span class="ct-file-name">${this.esc(f.name.length > 18 ? f.name.slice(0, 16) + "\u2026" : f.name)}</span>
|
|
60790
60795
|
<span class="ct-file-size">${this._formatFileSize(f.size)}</span>
|
|
60791
60796
|
<button type="button" class="ct-file-remove" data-index="${i}" title="Remover">\u2715</button>
|
|
@@ -62448,11 +62453,11 @@ var SettingsModalView = class _SettingsModalView {
|
|
|
62448
62453
|
formatUptime(seconds) {
|
|
62449
62454
|
if (seconds == null || Number.isNaN(seconds)) return "\u2014";
|
|
62450
62455
|
const d = Math.floor(seconds / 86400);
|
|
62451
|
-
const
|
|
62456
|
+
const h3 = Math.floor(seconds % 86400 / 3600);
|
|
62452
62457
|
const m = Math.floor(seconds % 3600 / 60);
|
|
62453
62458
|
const parts = [];
|
|
62454
62459
|
if (d > 0) parts.push(`${d}d`);
|
|
62455
|
-
if (
|
|
62460
|
+
if (h3 > 0 || d > 0) parts.push(`${h3}h`);
|
|
62456
62461
|
parts.push(`${m}min`);
|
|
62457
62462
|
return parts.join(" ");
|
|
62458
62463
|
}
|
|
@@ -65551,11 +65556,11 @@ function formatIsoRelativeSimple(iso) {
|
|
|
65551
65556
|
function formatUptime(seconds) {
|
|
65552
65557
|
if (seconds == null || Number.isNaN(seconds)) return "\u2014";
|
|
65553
65558
|
const d = Math.floor(seconds / 86400);
|
|
65554
|
-
const
|
|
65559
|
+
const h3 = Math.floor(seconds % 86400 / 3600);
|
|
65555
65560
|
const m = Math.floor(seconds % 3600 / 60);
|
|
65556
65561
|
const parts = [];
|
|
65557
65562
|
if (d > 0) parts.push(`${d}d`);
|
|
65558
|
-
if (
|
|
65563
|
+
if (h3 > 0 || d > 0) parts.push(`${h3}h`);
|
|
65559
65564
|
parts.push(`${m}min`);
|
|
65560
65565
|
return parts.join(" ");
|
|
65561
65566
|
}
|
|
@@ -68610,7 +68615,7 @@ var WelcomeModalView = class _WelcomeModalView {
|
|
|
68610
68615
|
const meta = card.metaCounts || {};
|
|
68611
68616
|
const details = card.metaDetails || {};
|
|
68612
68617
|
const loadingBody = '<div style="opacity:.7;padding:6px 0">Carregando\u2026</div>';
|
|
68613
|
-
const header = (
|
|
68618
|
+
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
68619
|
const row = (titleHtml, subHtml) => `<div style="padding:6px 0;border-top:1px solid #334155">
|
|
68615
68620
|
<div style="font-weight:600">${titleHtml}</div>
|
|
68616
68621
|
${subHtml ? `<div style="opacity:.7">${subHtml}</div>` : ""}
|
|
@@ -69295,15 +69300,15 @@ var WelcomeModalView = class _WelcomeModalView {
|
|
|
69295
69300
|
if (svgIcon) {
|
|
69296
69301
|
ctaBtn.appendChild(svgIcon);
|
|
69297
69302
|
} else {
|
|
69298
|
-
const
|
|
69299
|
-
|
|
69300
|
-
|
|
69301
|
-
|
|
69302
|
-
|
|
69303
|
-
|
|
69304
|
-
|
|
69305
|
-
|
|
69306
|
-
ctaBtn.appendChild(
|
|
69303
|
+
const svg2 = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
69304
|
+
svg2.setAttribute("viewBox", "0 0 24 24");
|
|
69305
|
+
svg2.setAttribute("fill", "none");
|
|
69306
|
+
svg2.setAttribute("stroke", "currentColor");
|
|
69307
|
+
svg2.setAttribute("stroke-width", "2");
|
|
69308
|
+
svg2.setAttribute("stroke-linecap", "round");
|
|
69309
|
+
svg2.setAttribute("stroke-linejoin", "round");
|
|
69310
|
+
svg2.innerHTML = '<line x1="5" y1="12" x2="19" y2="12" /><polyline points="12 5 19 12 12 19" />';
|
|
69311
|
+
ctaBtn.appendChild(svg2);
|
|
69307
69312
|
}
|
|
69308
69313
|
}
|
|
69309
69314
|
}
|
|
@@ -71164,10 +71169,10 @@ function createHeaderComponent(params) {
|
|
|
71164
71169
|
const categoriesHtml = categories.map((c) => {
|
|
71165
71170
|
const name = String(c?.name ?? c?.label ?? "Categoria");
|
|
71166
71171
|
const deviceCount = Number(c?.deviceCount ?? c?.count ?? 0);
|
|
71167
|
-
const
|
|
71172
|
+
const icon2 = String(c?.icon ?? "");
|
|
71168
71173
|
return `
|
|
71169
71174
|
<div class="myio-info-tooltip__row" style="padding: 6px 0; gap: 8px;">
|
|
71170
|
-
<span class="myio-info-tooltip__label">${
|
|
71175
|
+
<span class="myio-info-tooltip__label">${icon2 ? `${icon2} ` : ""}${name}</span>
|
|
71171
71176
|
<span class="myio-info-tooltip__value myio-info-tooltip__value--highlight">${deviceCount}</span>
|
|
71172
71177
|
</div>
|
|
71173
71178
|
`;
|
|
@@ -72465,11 +72470,11 @@ function createOverlay() {
|
|
|
72465
72470
|
overlay.style.setProperty("--fc-primary-hover", colors.primaryHover);
|
|
72466
72471
|
return overlay;
|
|
72467
72472
|
}
|
|
72468
|
-
function createAlertBox(
|
|
72473
|
+
function createAlertBox(icon2, title, message, buttonLabel) {
|
|
72469
72474
|
const box = document.createElement("div");
|
|
72470
72475
|
box.className = "myio-footer-alert-box";
|
|
72471
72476
|
box.innerHTML = `
|
|
72472
|
-
<div class="myio-footer-alert-icon">${
|
|
72477
|
+
<div class="myio-footer-alert-icon">${icon2}</div>
|
|
72473
72478
|
<h2 class="myio-footer-alert-title">${title}</h2>
|
|
72474
72479
|
<p class="myio-footer-alert-message">${message}</p>
|
|
72475
72480
|
<button class="myio-footer-alert-button" type="button">${buttonLabel}</button>
|
|
@@ -75889,8 +75894,8 @@ function addCanvasToPdf(doc, canvas, x = 10, y = 20, maxWmm = 190) {
|
|
|
75889
75894
|
return y + mmH;
|
|
75890
75895
|
}
|
|
75891
75896
|
function ensureRoom(doc, nextY, minRoom = 40) {
|
|
75892
|
-
const
|
|
75893
|
-
if (nextY + minRoom >
|
|
75897
|
+
const h3 = doc.internal.pageSize.getHeight();
|
|
75898
|
+
if (nextY + minRoom > h3) {
|
|
75894
75899
|
doc.addPage();
|
|
75895
75900
|
return 20;
|
|
75896
75901
|
}
|
|
@@ -77647,9 +77652,9 @@ function openGoalsPanel(params) {
|
|
|
77647
77652
|
};
|
|
77648
77653
|
const onWriteFailure = (res) => {
|
|
77649
77654
|
state6.saving = false;
|
|
77650
|
-
const
|
|
77651
|
-
if (
|
|
77652
|
-
state6.conflictVersion =
|
|
77655
|
+
const conflict2 = readVersionConflict(res);
|
|
77656
|
+
if (conflict2 !== null) {
|
|
77657
|
+
state6.conflictVersion = conflict2;
|
|
77653
77658
|
state6.conflict = true;
|
|
77654
77659
|
state6.pendingReapply = dirtySnapshot;
|
|
77655
77660
|
reload();
|
|
@@ -77715,9 +77720,9 @@ function openGoalsPanel(params) {
|
|
|
77715
77720
|
reload();
|
|
77716
77721
|
return;
|
|
77717
77722
|
}
|
|
77718
|
-
const
|
|
77719
|
-
if (
|
|
77720
|
-
state6.conflictVersion =
|
|
77723
|
+
const conflict2 = readVersionConflict(res);
|
|
77724
|
+
if (conflict2 !== null) {
|
|
77725
|
+
state6.conflictVersion = conflict2;
|
|
77721
77726
|
state6.conflict = true;
|
|
77722
77727
|
reload();
|
|
77723
77728
|
} else {
|
|
@@ -77739,9 +77744,9 @@ function openGoalsPanel(params) {
|
|
|
77739
77744
|
reload();
|
|
77740
77745
|
return;
|
|
77741
77746
|
}
|
|
77742
|
-
const
|
|
77743
|
-
if (
|
|
77744
|
-
state6.conflictVersion =
|
|
77747
|
+
const conflict2 = readVersionConflict(res);
|
|
77748
|
+
if (conflict2 !== null) {
|
|
77749
|
+
state6.conflictVersion = conflict2;
|
|
77745
77750
|
state6.conflict = true;
|
|
77746
77751
|
reload();
|
|
77747
77752
|
} else {
|
|
@@ -77767,7 +77772,7 @@ function openGoalsPanel(params) {
|
|
|
77767
77772
|
const value = sampleHourValue();
|
|
77768
77773
|
const day = `${state6.year}-03-15`;
|
|
77769
77774
|
const lines = ["bucket,value"];
|
|
77770
|
-
for (let
|
|
77775
|
+
for (let h3 = 0; h3 < 24; h3++) lines.push(`${day}T${pad2(h3)},${value}`);
|
|
77771
77776
|
return lines.join("\n");
|
|
77772
77777
|
}
|
|
77773
77778
|
function downloadCsv(csv, suffix) {
|
|
@@ -77821,8 +77826,8 @@ function openGoalsPanel(params) {
|
|
|
77821
77826
|
state6.importApplied = res.data;
|
|
77822
77827
|
reload();
|
|
77823
77828
|
} else {
|
|
77824
|
-
const
|
|
77825
|
-
if (
|
|
77829
|
+
const conflict2 = readVersionConflict(res);
|
|
77830
|
+
if (conflict2 !== null) state6.conflictVersion = conflict2;
|
|
77826
77831
|
else state6.saveError = res.error && res.error.message || "Failed to apply import";
|
|
77827
77832
|
}
|
|
77828
77833
|
renderImportBody();
|
|
@@ -78034,19 +78039,19 @@ function openGoalsPanel(params) {
|
|
|
78034
78039
|
if (!yearOptions.includes(state6.year)) yearOptions.unshift(state6.year);
|
|
78035
78040
|
const actions = state6.editing ? `
|
|
78036
78041
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="open-import" ${state6.loading || state6.error ? "disabled" : ""}>
|
|
78037
|
-
${
|
|
78042
|
+
${icon2("upload")} ${i18n2.importBtn}
|
|
78038
78043
|
</button>
|
|
78039
78044
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="view-summary" ${state6.loading ? "disabled" : ""}>
|
|
78040
|
-
${
|
|
78045
|
+
${icon2("eye")} ${i18n2.viewSummary}
|
|
78041
78046
|
</button>
|
|
78042
78047
|
<button class="myio-goals-btn myio-goals-btn-primary" data-action="save" ${state6.loading || state6.error || state6.saving ? "disabled" : ""}>
|
|
78043
|
-
${
|
|
78048
|
+
${icon2("save")} ${state6.saving ? i18n2.saving : i18n2.save}
|
|
78044
78049
|
</button>` : `
|
|
78045
78050
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="download-hourly" ${state6.loading ? "disabled" : ""}>
|
|
78046
|
-
${
|
|
78051
|
+
${icon2("download")} ${i18n2.downloadHourlyExample}
|
|
78047
78052
|
</button>
|
|
78048
78053
|
<button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit" ${state6.loading || state6.error ? "disabled" : ""}>
|
|
78049
|
-
${
|
|
78054
|
+
${icon2("pencil")} ${i18n2.enableEditing}
|
|
78050
78055
|
</button>`;
|
|
78051
78056
|
return `
|
|
78052
78057
|
<div class="myio-goals-toolbar">
|
|
@@ -78064,9 +78069,9 @@ function openGoalsPanel(params) {
|
|
|
78064
78069
|
</select>
|
|
78065
78070
|
</label>
|
|
78066
78071
|
<div class="myio-goals-chips">
|
|
78067
|
-
<span class="myio-goals-chip myio-goals-chip-accent">${
|
|
78072
|
+
<span class="myio-goals-chip myio-goals-chip-accent">${icon2("target")} ${i18n2.domains[state6.domain]} \xB7 ${i18n2.aggregation[cfg.aggregationMethod]}</span>
|
|
78068
78073
|
<span class="myio-goals-chip myio-goals-chip-mono">${unitLabel2()}</span>
|
|
78069
|
-
<span class="myio-goals-chip myio-goals-chip-violet">${
|
|
78074
|
+
<span class="myio-goals-chip myio-goals-chip-violet">${icon2("history")} ${i18n2.currentVersion.replace("{n}", version2)}</span>
|
|
78070
78075
|
${renderMarginChip()}
|
|
78071
78076
|
${renderDeviceGranularityChip()}
|
|
78072
78077
|
${renderCoverageChip()}
|
|
@@ -78133,7 +78138,7 @@ function openGoalsPanel(params) {
|
|
|
78133
78138
|
${state6.saving ? "disabled" : ""} />
|
|
78134
78139
|
<span class="myio-goals-margin-pct">%</span>
|
|
78135
78140
|
<button class="myio-goals-btn myio-goals-btn-outline myio-goals-btn-sm" data-action="save-margin" ${state6.saving ? "disabled" : ""}>
|
|
78136
|
-
${
|
|
78141
|
+
${icon2("save")} ${i18n2.margin.save}
|
|
78137
78142
|
</button>
|
|
78138
78143
|
${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
78144
|
<span class="myio-goals-margin-hint">${i18n2.margin.hint}</span>
|
|
@@ -78142,24 +78147,24 @@ function openGoalsPanel(params) {
|
|
|
78142
78147
|
function renderMessages() {
|
|
78143
78148
|
let html = "";
|
|
78144
78149
|
if (state6.conflict) {
|
|
78145
|
-
html += `<div class="myio-goals-alert myio-goals-alert-amber">${
|
|
78150
|
+
html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon2("alert")} ${i18n2.versionConflict}</div>`;
|
|
78146
78151
|
}
|
|
78147
78152
|
if (state6.saveError && !state6.conflict) {
|
|
78148
|
-
html += `<div class="myio-goals-alert myio-goals-alert-red">${
|
|
78153
|
+
html += `<div class="myio-goals-alert myio-goals-alert-red">${icon2("alert")} ${esc4(state6.saveError)}</div>`;
|
|
78149
78154
|
}
|
|
78150
78155
|
if (state6.saved && !state6.saveError) {
|
|
78151
|
-
html += `<div class="myio-goals-alert myio-goals-alert-green">${
|
|
78156
|
+
html += `<div class="myio-goals-alert myio-goals-alert-green">${icon2("check")} ${i18n2.saveSuccess}</div>`;
|
|
78152
78157
|
}
|
|
78153
78158
|
return html;
|
|
78154
78159
|
}
|
|
78155
78160
|
function renderMain() {
|
|
78156
78161
|
if (state6.loading) {
|
|
78157
|
-
return `<div class="myio-goals-center">${
|
|
78162
|
+
return `<div class="myio-goals-center">${icon2("spinner")} <span>${i18n2.loading}</span></div>`;
|
|
78158
78163
|
}
|
|
78159
78164
|
if (state6.error) {
|
|
78160
78165
|
return `
|
|
78161
78166
|
<div class="myio-goals-center myio-goals-center-col">
|
|
78162
|
-
${
|
|
78167
|
+
${icon2("alert-lg")}
|
|
78163
78168
|
<p>${esc4(state6.error)}</p>
|
|
78164
78169
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="retry">${i18n2.retry}</button>
|
|
78165
78170
|
</div>`;
|
|
@@ -78172,20 +78177,20 @@ function openGoalsPanel(params) {
|
|
|
78172
78177
|
if (!s.hasData) {
|
|
78173
78178
|
return `
|
|
78174
78179
|
<div class="myio-goals-center myio-goals-center-col">
|
|
78175
|
-
${
|
|
78180
|
+
${icon2("target-lg")}
|
|
78176
78181
|
<p>${i18n2.noData.replace("{year}", state6.year)}</p>
|
|
78177
|
-
<button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit">${
|
|
78182
|
+
<button class="myio-goals-btn myio-goals-btn-primary" data-action="enable-edit">${icon2("pencil")} ${i18n2.enableEditing}</button>
|
|
78178
78183
|
</div>`;
|
|
78179
78184
|
}
|
|
78180
78185
|
const avg = isAverage();
|
|
78181
|
-
const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` :
|
|
78186
|
+
const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon2("sigma");
|
|
78182
78187
|
const kpis = [
|
|
78183
|
-
{ ic:
|
|
78188
|
+
{ ic: icon2("calendar"), label: i18n2.summary.year, value: String(state6.year) },
|
|
78184
78189
|
{ ic: glyph, label: avg ? i18n2.summary.yearAverage : i18n2.summary.yearTotal, value: fmt2(s.yearValue) },
|
|
78185
|
-
{ ic:
|
|
78186
|
-
{ ic:
|
|
78187
|
-
{ ic:
|
|
78188
|
-
{ ic:
|
|
78190
|
+
{ ic: icon2("calendar-range"), label: i18n2.summary.monthsWithGoal, value: `${s.monthsWithGoal} / 12` },
|
|
78191
|
+
{ ic: icon2("calendar-days"), label: i18n2.summary.daysWithGoal, value: String(s.daysWithGoal) },
|
|
78192
|
+
{ ic: icon2("trend"), label: i18n2.summary.avgPerMonth, value: fmt2(s.avgPerMonth) },
|
|
78193
|
+
{ ic: icon2("trend"), label: i18n2.summary.avgPerDay, value: fmt2(s.avgPerDay) }
|
|
78189
78194
|
];
|
|
78190
78195
|
const marginPct = currentMarginPct();
|
|
78191
78196
|
const adjAnnual = state6.goals && state6.goals.tree && state6.goals.tree.annual ? state6.goals.tree.annual.adjustedValue : null;
|
|
@@ -78198,7 +78203,7 @@ function openGoalsPanel(params) {
|
|
|
78198
78203
|
}
|
|
78199
78204
|
const topCol = (title, items, labeler) => `
|
|
78200
78205
|
<div class="myio-goals-topcard">
|
|
78201
|
-
<h4>${
|
|
78206
|
+
<h4>${icon2("trend")} ${title}</h4>
|
|
78202
78207
|
${items.length === 0 ? `<p class="myio-goals-muted">\u2014</p>` : `<ol>${items.map(
|
|
78203
78208
|
(e, i) => `
|
|
78204
78209
|
<li>
|
|
@@ -78237,9 +78242,9 @@ function openGoalsPanel(params) {
|
|
|
78237
78242
|
const version2 = state6.goals ? state6.goals.version : 0;
|
|
78238
78243
|
const crumb = `
|
|
78239
78244
|
<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" ? `${
|
|
78245
|
+
<button data-action="crumb-months" class="${state6.level === "month" ? "active" : ""}">${icon2("home")} ${i18n2.breadcrumbYear.replace("{year}", state6.year)}</button>
|
|
78246
|
+
${state6.selectedMonth ? `${icon2("chevron")}<button data-action="crumb-days" class="${state6.level === "day" ? "active" : ""}">${i18n2.months[state6.selectedMonth]}</button>` : ""}
|
|
78247
|
+
${state6.selectedMonth && state6.selectedDay && state6.level === "hour" ? `${icon2("chevron")}<span class="active">${i18n2.breadcrumbDay.replace("{day}", Number(state6.selectedDay))}</span>` : ""}
|
|
78243
78248
|
</nav>`;
|
|
78244
78249
|
const emptyHint = state6.level === "month" && monthlyFilledCount() === 0 && version2 === 0 ? `<p class="myio-goals-muted">${i18n2.empty}</p>` : "";
|
|
78245
78250
|
const drillHint = state6.level !== "hour" ? `<p class="myio-goals-microhint">${state6.level === "month" ? i18n2.drill.openMonthHint : i18n2.drill.openDayHint}</p>` : "";
|
|
@@ -78249,14 +78254,14 @@ function openGoalsPanel(params) {
|
|
|
78249
78254
|
const confirmed = node && node.derived === false;
|
|
78250
78255
|
const cellLabel = state6.level === "month" ? i18n2.months[key] : state6.level === "day" ? i18n2.dayCell.replace("{day}", Number(key)) : `${key}:00`;
|
|
78251
78256
|
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} ${
|
|
78257
|
+
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
78258
|
const val = state6.draft[key] !== void 0 ? esc4(state6.draft[key]) : "";
|
|
78254
78259
|
const minAttr = cfg.allowsNegative ? "" : 'min="0"';
|
|
78255
78260
|
return `
|
|
78256
78261
|
<div class="myio-goals-cell">
|
|
78257
78262
|
<div class="myio-goals-cell-head">
|
|
78258
78263
|
${labelEl}
|
|
78259
|
-
${
|
|
78264
|
+
${icon2("pencil-sm")}
|
|
78260
78265
|
</div>
|
|
78261
78266
|
<div class="myio-goals-cell-input">
|
|
78262
78267
|
<input type="number" step="any" ${minAttr} data-cell="${key}" value="${val}" placeholder="\u2014" />
|
|
@@ -78266,7 +78271,7 @@ function openGoalsPanel(params) {
|
|
|
78266
78271
|
</div>`;
|
|
78267
78272
|
}).join("");
|
|
78268
78273
|
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>` :
|
|
78274
|
+
const glyph = avg ? `<span class="myio-goals-glyph">x\u0304</span>` : icon2("sigma");
|
|
78270
78275
|
const total = computedTotal();
|
|
78271
78276
|
return `
|
|
78272
78277
|
<div class="myio-goals-editor">
|
|
@@ -78279,7 +78284,7 @@ function openGoalsPanel(params) {
|
|
|
78279
78284
|
<span class="myio-goals-total-val" id="myio-goals-computed-total">${total === null ? "\u2014" : fmt2(total)}</span>
|
|
78280
78285
|
</div>
|
|
78281
78286
|
<div class="myio-goals-legend">
|
|
78282
|
-
<span>${
|
|
78287
|
+
<span>${icon2("pencil-sm")} ${i18n2.legendEditable}</span>
|
|
78283
78288
|
<span>${glyph} ${i18n2.legendComputed}</span>
|
|
78284
78289
|
</div>
|
|
78285
78290
|
</div>`;
|
|
@@ -78300,12 +78305,12 @@ function openGoalsPanel(params) {
|
|
|
78300
78305
|
const diff = Math.max(0, Date.now() - then);
|
|
78301
78306
|
const s = Math.floor(diff / 1e3);
|
|
78302
78307
|
const m = Math.floor(s / 60);
|
|
78303
|
-
const
|
|
78304
|
-
const d = Math.floor(
|
|
78308
|
+
const h3 = Math.floor(m / 60);
|
|
78309
|
+
const d = Math.floor(h3 / 24);
|
|
78305
78310
|
const T = i18n2.time;
|
|
78306
78311
|
if (s < 60) return T.now;
|
|
78307
78312
|
if (m < 60) return T.min.replace("{n}", m);
|
|
78308
|
-
if (
|
|
78313
|
+
if (h3 < 24) return T.hour.replace("{n}", h3);
|
|
78309
78314
|
if (d < 30) return T.day.replace("{n}", d);
|
|
78310
78315
|
return new Date(iso).toLocaleDateString(locale);
|
|
78311
78316
|
}
|
|
@@ -78314,7 +78319,7 @@ function openGoalsPanel(params) {
|
|
|
78314
78319
|
const history = state6.goals && state6.goals.history || [];
|
|
78315
78320
|
const version2 = state6.goals ? state6.goals.version : 0;
|
|
78316
78321
|
const DETAIL_PREVIEW = 8;
|
|
78317
|
-
const items = history.length === 0 ? `<div class="myio-goals-center myio-goals-center-col myio-goals-hist-empty">${
|
|
78322
|
+
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
78323
|
const actor = ev.actor ? `${String(ev.actor).slice(0, 8)}\u2026` : i18n2.history.system;
|
|
78319
78324
|
const extra = ev.bucketCount - (ev.details ? ev.details.length : 0);
|
|
78320
78325
|
const chips = (ev.details || []).slice(0, DETAIL_PREVIEW).map(
|
|
@@ -78323,7 +78328,7 @@ function openGoalsPanel(params) {
|
|
|
78323
78328
|
const more = extra > 0 ? `<span class="myio-goals-tl-more">${i18n2.history.moreDetails.replace("{n}", extra)}</span>` : "";
|
|
78324
78329
|
return `
|
|
78325
78330
|
<li class="myio-goals-tl-item">
|
|
78326
|
-
<span class="myio-goals-tl-dot">${
|
|
78331
|
+
<span class="myio-goals-tl-dot">${icon2(ev.source === "IMPORT" ? "upload-sm" : ev.source === "DELETE" ? "trash-sm" : "pencil-sm")}</span>
|
|
78327
78332
|
<div class="myio-goals-tl-head">
|
|
78328
78333
|
<span class="myio-goals-tl-title">${i18n2.history.source[ev.source] || i18n2.history.source.EDIT}</span>
|
|
78329
78334
|
<span class="myio-goals-tl-ver">v${ev.version}</span>
|
|
@@ -78336,7 +78341,7 @@ function openGoalsPanel(params) {
|
|
|
78336
78341
|
return `
|
|
78337
78342
|
<div class="myio-goals-history">
|
|
78338
78343
|
<div class="myio-goals-history-head">
|
|
78339
|
-
<h3>${
|
|
78344
|
+
<h3>${icon2("clock")} ${i18n2.history.title}</h3>
|
|
78340
78345
|
<span class="myio-goals-history-meta">${i18n2.domains[state6.domain]} \xB7 ${state6.year} \xB7 ${i18n2.currentVersion.replace("{n}", version2)}</span>
|
|
78341
78346
|
</div>
|
|
78342
78347
|
${items}
|
|
@@ -78348,7 +78353,7 @@ function openGoalsPanel(params) {
|
|
|
78348
78353
|
<div class="myio-goals-import-dialog">
|
|
78349
78354
|
<div class="myio-goals-import-card">
|
|
78350
78355
|
<div class="myio-goals-import-header">
|
|
78351
|
-
<span class="myio-goals-import-icon">${
|
|
78356
|
+
<span class="myio-goals-import-icon">${icon2("upload")}</span>
|
|
78352
78357
|
<div>
|
|
78353
78358
|
<h3>${i18n2.import.title}</h3>
|
|
78354
78359
|
<p>${i18n2.import.subtitle.replace("{domain}", i18n2.domains[state6.domain]).replace("{year}", state6.year)}</p>
|
|
@@ -78383,9 +78388,9 @@ ${state6.year}-03-15T08,15`;
|
|
|
78383
78388
|
<div class="myio-goals-import-inputhead">
|
|
78384
78389
|
<label>${i18n2.import.csvLabel}</label>
|
|
78385
78390
|
<div class="myio-goals-import-links">
|
|
78386
|
-
<button data-action="download-template">${
|
|
78387
|
-
<button data-action="download-hourly">${
|
|
78388
|
-
<button data-action="import-upload">${
|
|
78391
|
+
<button data-action="download-template">${icon2("download")} ${i18n2.import.downloadTemplate}</button>
|
|
78392
|
+
<button data-action="download-hourly">${icon2("download")} ${i18n2.import.downloadHourlyExample}</button>
|
|
78393
|
+
<button data-action="import-upload">${icon2("upload")} ${i18n2.import.uploadFile}</button>
|
|
78389
78394
|
<input type="file" id="myio-goals-csv-file" accept=".csv,.txt,text/csv,text/plain" style="display:none" />
|
|
78390
78395
|
</div>
|
|
78391
78396
|
</div>
|
|
@@ -78398,22 +78403,22 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78398
78403
|
</div>`;
|
|
78399
78404
|
}
|
|
78400
78405
|
if (state6.saveError && state6.conflictVersion === null) {
|
|
78401
|
-
html += `<div class="myio-goals-alert myio-goals-alert-red">${
|
|
78406
|
+
html += `<div class="myio-goals-alert myio-goals-alert-red">${icon2("alert")} ${esc4(state6.saveError)}</div>`;
|
|
78402
78407
|
}
|
|
78403
78408
|
if (state6.conflictVersion !== null) {
|
|
78404
|
-
html += `<div class="myio-goals-alert myio-goals-alert-amber">${
|
|
78409
|
+
html += `<div class="myio-goals-alert myio-goals-alert-amber">${icon2("alert")} ${i18n2.import.conflict}</div>`;
|
|
78405
78410
|
}
|
|
78406
78411
|
if (result) html += renderImportSummary(result, counts);
|
|
78407
78412
|
return html;
|
|
78408
78413
|
}
|
|
78409
78414
|
function renderImportSummary(result, counts) {
|
|
78410
78415
|
const persisted = result.dryRun === false;
|
|
78411
|
-
const badge = persisted ? `<span class="myio-goals-chip myio-goals-chip-accent">${
|
|
78416
|
+
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
78417
|
let html = `
|
|
78413
78418
|
<div class="myio-goals-import-summary">
|
|
78414
78419
|
<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">${
|
|
78420
|
+
<span class="myio-goals-chip myio-goals-chip-accent">${icon2("check")} ${i18n2.import.okCount.replace("{n}", result.okCount)}</span>
|
|
78421
|
+
${result.errorCount > 0 ? `<span class="myio-goals-chip myio-goals-chip-red">${icon2("alert")} ${i18n2.import.errorCount.replace("{n}", result.errorCount)}</span>` : ""}
|
|
78417
78422
|
${badge}
|
|
78418
78423
|
</div>`;
|
|
78419
78424
|
if (!persisted && counts && result.okCount > 0) {
|
|
@@ -78427,7 +78432,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78427
78432
|
<div class="myio-goals-import-diags">
|
|
78428
78433
|
<p class="myio-goals-import-diags-title">${i18n2.import.diagnosticsTitle}</p>
|
|
78429
78434
|
<ul>${result.diagnostics.map(
|
|
78430
|
-
(d) => `<li>${
|
|
78435
|
+
(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
78436
|
).join("")}</ul>
|
|
78432
78437
|
</div>`;
|
|
78433
78438
|
}
|
|
@@ -78447,7 +78452,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78447
78452
|
}
|
|
78448
78453
|
const canPreview = state6.csv.trim().length > 0 && !state6.saving;
|
|
78449
78454
|
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"}>${
|
|
78455
|
+
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
78456
|
return `
|
|
78452
78457
|
<button class="myio-goals-btn myio-goals-btn-outline" data-action="import-close" ${state6.saving ? "disabled" : ""}>${i18n2.import.cancel}</button>
|
|
78453
78458
|
${right}`;
|
|
@@ -78459,7 +78464,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
|
|
|
78459
78464
|
if (body) body.innerHTML = renderImportInner();
|
|
78460
78465
|
if (footer) footer.innerHTML = renderImportFooter();
|
|
78461
78466
|
}
|
|
78462
|
-
function
|
|
78467
|
+
function icon2(name) {
|
|
78463
78468
|
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
78469
|
switch (name) {
|
|
78465
78470
|
case "target":
|
|
@@ -82001,7 +82006,7 @@ var EnergySummaryTooltip = {
|
|
|
82001
82006
|
}))
|
|
82002
82007
|
});
|
|
82003
82008
|
categories.forEach((cat, catIndex) => {
|
|
82004
|
-
const
|
|
82009
|
+
const icon2 = CATEGORY_ICONS[cat.id] || CATEGORY_ICONS.outros;
|
|
82005
82010
|
const hasChildren = cat.children && cat.children.length > 0;
|
|
82006
82011
|
const hasShoppingBreakdown = cat.byShoppingBreakdown && cat.byShoppingBreakdown.length > 0;
|
|
82007
82012
|
const isExpandable = hasChildren || hasShoppingBreakdown;
|
|
@@ -82011,7 +82016,7 @@ var EnergySummaryTooltip = {
|
|
|
82011
82016
|
${isExpandable ? `
|
|
82012
82017
|
<button class="energy-summary-tooltip__expand-toggle" data-target="cat-${catIndex}" title="Expandir">+</button>
|
|
82013
82018
|
` : ""}
|
|
82014
|
-
<span class="energy-summary-tooltip__category-icon">${
|
|
82019
|
+
<span class="energy-summary-tooltip__category-icon">${icon2}</span>
|
|
82015
82020
|
<span>${cat.name}</span>
|
|
82016
82021
|
</span>
|
|
82017
82022
|
<span class="energy-summary-tooltip__category-count">${cat.deviceCount}</span>
|
|
@@ -82678,10 +82683,10 @@ var EnergySummaryTooltip = {
|
|
|
82678
82683
|
return;
|
|
82679
82684
|
}
|
|
82680
82685
|
this._cancelDevicePopupDelayedHide();
|
|
82681
|
-
const
|
|
82686
|
+
const icon2 = this._getStatusIcon(statusKey);
|
|
82682
82687
|
const content = this._buildDeviceListContent(statusKey, label, count);
|
|
82683
82688
|
InfoTooltip2.show(triggerElement, {
|
|
82684
|
-
icon,
|
|
82689
|
+
icon: icon2,
|
|
82685
82690
|
title: `${label} (${count})`,
|
|
82686
82691
|
content
|
|
82687
82692
|
});
|
|
@@ -83995,7 +84000,7 @@ var WaterSummaryTooltip = {
|
|
|
83995
84000
|
return html;
|
|
83996
84001
|
}
|
|
83997
84002
|
categories.forEach((cat, catIndex) => {
|
|
83998
|
-
const
|
|
84003
|
+
const icon2 = WATER_CATEGORY_ICONS[cat.id] || WATER_CATEGORY_ICONS.areaComum;
|
|
83999
84004
|
const hasChildren = cat.children && cat.children.length > 0;
|
|
84000
84005
|
const hasShoppingBreakdown = cat.byShoppingBreakdown && cat.byShoppingBreakdown.length > 0;
|
|
84001
84006
|
const isExpandable = hasChildren || hasShoppingBreakdown;
|
|
@@ -84005,7 +84010,7 @@ var WaterSummaryTooltip = {
|
|
|
84005
84010
|
${isExpandable ? `
|
|
84006
84011
|
<button class="water-summary-tooltip__expand-toggle" data-target="water-cat-${catIndex}" title="Expandir">+</button>
|
|
84007
84012
|
` : ""}
|
|
84008
|
-
<span class="water-summary-tooltip__category-icon">${
|
|
84013
|
+
<span class="water-summary-tooltip__category-icon">${icon2}</span>
|
|
84009
84014
|
<span>${cat.name}</span>
|
|
84010
84015
|
</span>
|
|
84011
84016
|
<span class="water-summary-tooltip__category-count">${cat.deviceCount}</span>
|
|
@@ -84603,10 +84608,10 @@ var WaterSummaryTooltip = {
|
|
|
84603
84608
|
return;
|
|
84604
84609
|
}
|
|
84605
84610
|
this._cancelDevicePopupDelayedHide();
|
|
84606
|
-
const
|
|
84611
|
+
const icon2 = this._getStatusIcon(statusKey);
|
|
84607
84612
|
const content = this._buildDeviceListContent(statusKey, label, count);
|
|
84608
84613
|
InfoTooltip2.show(triggerElement, {
|
|
84609
|
-
icon,
|
|
84614
|
+
icon: icon2,
|
|
84610
84615
|
title: `${label} (${count})`,
|
|
84611
84616
|
content
|
|
84612
84617
|
});
|
|
@@ -86198,10 +86203,10 @@ function generateContentHTML(data) {
|
|
|
86198
86203
|
<div class="myio-temp-sensor-tooltip__list">
|
|
86199
86204
|
${displayDevices.map((d) => {
|
|
86200
86205
|
const statusClass = d.status === "ok" ? "ok" : d.status === "warn" ? "warn" : "unknown";
|
|
86201
|
-
const
|
|
86206
|
+
const icon2 = d.status === "ok" ? "\u2714" : d.status === "warn" ? "\u26A0" : "?";
|
|
86202
86207
|
return `
|
|
86203
86208
|
<div class="myio-temp-sensor-tooltip__list-item myio-temp-sensor-tooltip__list-item--${statusClass}">
|
|
86204
|
-
<span class="myio-temp-sensor-tooltip__list-icon">${
|
|
86209
|
+
<span class="myio-temp-sensor-tooltip__list-icon">${icon2}</span>
|
|
86205
86210
|
<span class="myio-temp-sensor-tooltip__list-name">${d.name}</span>
|
|
86206
86211
|
<span class="myio-temp-sensor-tooltip__list-value">${d.temp.toFixed(1)}\xB0C</span>
|
|
86207
86212
|
</div>
|
|
@@ -87059,7 +87064,7 @@ function generateHeaderHTML5(data) {
|
|
|
87059
87064
|
</div>
|
|
87060
87065
|
`;
|
|
87061
87066
|
}
|
|
87062
|
-
function generateDomainHTML(domain,
|
|
87067
|
+
function generateDomainHTML(domain, icon2, name, counts, isTemperature = false) {
|
|
87063
87068
|
const isExpanded = state5.expandedDomains.has(domain);
|
|
87064
87069
|
const expandedClass = isExpanded ? "expanded" : "";
|
|
87065
87070
|
let detailsHTML = "";
|
|
@@ -87096,7 +87101,7 @@ function generateDomainHTML(domain, icon, name, counts, isTemperature = false) {
|
|
|
87096
87101
|
<div class="myio-contract-summary-tooltip__domain ${expandedClass}" data-domain="${domain}">
|
|
87097
87102
|
<div class="myio-contract-summary-tooltip__domain-header" data-toggle-domain="${domain}">
|
|
87098
87103
|
<div class="myio-contract-summary-tooltip__domain-info">
|
|
87099
|
-
<span class="myio-contract-summary-tooltip__domain-icon">${
|
|
87104
|
+
<span class="myio-contract-summary-tooltip__domain-icon">${icon2}</span>
|
|
87100
87105
|
<span class="myio-contract-summary-tooltip__domain-name">${name}</span>
|
|
87101
87106
|
</div>
|
|
87102
87107
|
<div style="display: flex; align-items: center; gap: 8px;">
|
|
@@ -93236,11 +93241,11 @@ function renderRow(row, level) {
|
|
|
93236
93241
|
const pct = row.pct;
|
|
93237
93242
|
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
93243
|
const swatch = row.color ? `<span class="myio-gbt__swatch" style="background:${esc6(row.color)}"></span>` : "";
|
|
93239
|
-
const
|
|
93244
|
+
const icon2 = row.icon ? `<span class="myio-gbt__icon">${esc6(row.icon)}</span>` : "";
|
|
93240
93245
|
const chipHtml = row.delta ? renderDeltaChip(row.delta) : "";
|
|
93241
93246
|
const pctHtml = !row.delta && pct != null && isFinite(pct) ? `<span class="myio-gbt__pct">${esc6(fmtPct3(pct))}</span>` : "";
|
|
93242
93247
|
const rowClass = level > 0 ? "myio-gbt__row myio-gbt__row--child" : "myio-gbt__row";
|
|
93243
|
-
let html = `<div class="${rowClass}">` + caret + swatch +
|
|
93248
|
+
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
93249
|
if (hasChildren) {
|
|
93245
93250
|
const childHtml = row.children.map((c) => renderRow(c, level + 1)).join("");
|
|
93246
93251
|
html += `<div class="myio-gbt__children${open ? " is-open" : ""}" data-children="${id}">${childHtml}</div>`;
|
|
@@ -93275,16 +93280,16 @@ function createGoalsBarTooltip(opts) {
|
|
|
93275
93280
|
function positionAt(clientX, clientY) {
|
|
93276
93281
|
const rect = el2.getBoundingClientRect();
|
|
93277
93282
|
const w = rect.width || 280;
|
|
93278
|
-
const
|
|
93283
|
+
const h3 = rect.height || 200;
|
|
93279
93284
|
const pad = 12;
|
|
93280
93285
|
const gap = 16;
|
|
93281
93286
|
let left = clientX + gap;
|
|
93282
93287
|
let top = clientY + gap;
|
|
93283
93288
|
if (left + w > window.innerWidth - pad) left = clientX - w - gap;
|
|
93284
93289
|
if (left < pad) left = Math.max(pad, (window.innerWidth - w) / 2);
|
|
93285
|
-
if (top +
|
|
93290
|
+
if (top + h3 > window.innerHeight - pad) top = clientY - h3 - gap;
|
|
93286
93291
|
if (top < pad) top = pad;
|
|
93287
|
-
if (top +
|
|
93292
|
+
if (top + h3 > window.innerHeight - pad) top = Math.max(pad, window.innerHeight - h3 - pad);
|
|
93288
93293
|
el2.style.left = `${Math.round(left)}px`;
|
|
93289
93294
|
el2.style.top = `${Math.round(top)}px`;
|
|
93290
93295
|
}
|
|
@@ -93524,13 +93529,13 @@ function _buildDayBoundaries(startISO, endISO) {
|
|
|
93524
93529
|
}
|
|
93525
93530
|
function _buildHourBoundaries(dateISO) {
|
|
93526
93531
|
const result = [];
|
|
93527
|
-
for (let
|
|
93532
|
+
for (let h3 = 0; h3 < 24; h3++) {
|
|
93528
93533
|
const start = /* @__PURE__ */ new Date(`${dateISO}T00:00:00`);
|
|
93529
|
-
start.setHours(
|
|
93534
|
+
start.setHours(h3, 0, 0, 0);
|
|
93530
93535
|
const end = new Date(start);
|
|
93531
|
-
end.setHours(
|
|
93536
|
+
end.setHours(h3, 59, 59, 999);
|
|
93532
93537
|
result.push({
|
|
93533
|
-
label: `${String(
|
|
93538
|
+
label: `${String(h3).padStart(2, "0")}h`,
|
|
93534
93539
|
startTs: start.getTime(),
|
|
93535
93540
|
endTs: end.getTime()
|
|
93536
93541
|
});
|
|
@@ -96905,7 +96910,7 @@ var MODE_DEFAULTS = {
|
|
|
96905
96910
|
}
|
|
96906
96911
|
};
|
|
96907
96912
|
function mixHex2(hexA, hexB, pctB) {
|
|
96908
|
-
const n = (
|
|
96913
|
+
const n = (h3) => parseInt(h3.slice(1), 16);
|
|
96909
96914
|
const a = n(hexA);
|
|
96910
96915
|
const b = n(hexB);
|
|
96911
96916
|
const ch = (sa, sb) => Math.round(sa + (sb - sa) * pctB);
|
|
@@ -97851,11 +97856,11 @@ var TariffApiClient = class {
|
|
|
97851
97856
|
this.basePath = config2.basePath ?? "api/v1";
|
|
97852
97857
|
}
|
|
97853
97858
|
authHeaders() {
|
|
97854
|
-
const
|
|
97855
|
-
if (this.cfg.apiKey)
|
|
97856
|
-
if (this.cfg.jwt)
|
|
97857
|
-
if (this.cfg.tenantId)
|
|
97858
|
-
return
|
|
97859
|
+
const h3 = {};
|
|
97860
|
+
if (this.cfg.apiKey) h3["X-API-Key"] = this.cfg.apiKey;
|
|
97861
|
+
if (this.cfg.jwt) h3["Authorization"] = `Bearer ${this.cfg.jwt}`;
|
|
97862
|
+
if (this.cfg.tenantId) h3["X-Tenant-Id"] = this.cfg.tenantId;
|
|
97863
|
+
return h3;
|
|
97859
97864
|
}
|
|
97860
97865
|
/** Read the tariff tree. `granularity` defaults to `day` server-side. */
|
|
97861
97866
|
async getTariff(sel, granularity = "hour") {
|
|
@@ -98117,7 +98122,7 @@ function bandToPanelEntry(band, customerId) {
|
|
|
98117
98122
|
function expandDayToHourBuckets(date, price) {
|
|
98118
98123
|
assertValidCivilDate(date);
|
|
98119
98124
|
const out = [];
|
|
98120
|
-
for (let
|
|
98125
|
+
for (let h3 = 0; h3 < 24; h3++) out.push({ level: "HOUR", ref: `${date}T${pad23(h3)}`, price });
|
|
98121
98126
|
return out;
|
|
98122
98127
|
}
|
|
98123
98128
|
function expandBandHours(date, startHour, endHour, price) {
|
|
@@ -98126,7 +98131,7 @@ function expandBandHours(date, startHour, endHour, price) {
|
|
|
98126
98131
|
throw new Error(`Invalid hour band ${startHour}-${endHour} for ${date}`);
|
|
98127
98132
|
}
|
|
98128
98133
|
const out = [];
|
|
98129
|
-
for (let
|
|
98134
|
+
for (let h3 = startHour; h3 <= endHour; h3++) out.push({ level: "HOUR", ref: `${date}T${pad23(h3)}`, price });
|
|
98130
98135
|
return out;
|
|
98131
98136
|
}
|
|
98132
98137
|
function bandDateBounds(band) {
|
|
@@ -98176,12 +98181,12 @@ function expandBandToHourBucketsByYear(band) {
|
|
|
98176
98181
|
function collapseHoursToBands(date, hours, dims) {
|
|
98177
98182
|
const sorted = [...hours].sort((a, b) => a.hour - b.hour);
|
|
98178
98183
|
const runs = [];
|
|
98179
|
-
for (const
|
|
98184
|
+
for (const h3 of sorted) {
|
|
98180
98185
|
const cur = runs[runs.length - 1];
|
|
98181
|
-
if (cur &&
|
|
98182
|
-
cur.endHour =
|
|
98186
|
+
if (cur && h3.hour === cur.endHour + 1 && h3.price === cur.price) {
|
|
98187
|
+
cur.endHour = h3.hour;
|
|
98183
98188
|
} else {
|
|
98184
|
-
runs.push({ startHour:
|
|
98189
|
+
runs.push({ startHour: h3.hour, endHour: h3.hour, price: h3.price });
|
|
98185
98190
|
}
|
|
98186
98191
|
}
|
|
98187
98192
|
return runs.map(
|
|
@@ -98201,13 +98206,13 @@ function dayNodeToHours(node) {
|
|
|
98201
98206
|
const hourly = node.hourly || {};
|
|
98202
98207
|
const hourKeys = Object.keys(hourly);
|
|
98203
98208
|
if (hourKeys.length === 0) {
|
|
98204
|
-
return dayPrice != null ? Array.from({ length: 24 }, (_,
|
|
98209
|
+
return dayPrice != null ? Array.from({ length: 24 }, (_, h3) => ({ hour: h3, price: dayPrice })) : null;
|
|
98205
98210
|
}
|
|
98206
98211
|
const out = [];
|
|
98207
|
-
for (let
|
|
98208
|
-
const ov = hourly[String(
|
|
98212
|
+
for (let h3 = 0; h3 < 24; h3++) {
|
|
98213
|
+
const ov = hourly[String(h3)];
|
|
98209
98214
|
const price = ov && typeof ov.price === "string" ? ov.price : dayPrice;
|
|
98210
|
-
if (price != null) out.push({ hour:
|
|
98215
|
+
if (price != null) out.push({ hour: h3, price });
|
|
98211
98216
|
}
|
|
98212
98217
|
return out.length ? out : null;
|
|
98213
98218
|
}
|
|
@@ -98994,11 +98999,11 @@ var GoalsMoneyClient = class {
|
|
|
98994
98999
|
this.basePath = config2.basePath ?? "api/v1";
|
|
98995
99000
|
}
|
|
98996
99001
|
authHeaders() {
|
|
98997
|
-
const
|
|
98998
|
-
if (this.cfg.apiKey)
|
|
98999
|
-
if (this.cfg.jwt)
|
|
99000
|
-
if (this.cfg.tenantId)
|
|
99001
|
-
return
|
|
99002
|
+
const h3 = {};
|
|
99003
|
+
if (this.cfg.apiKey) h3["X-API-Key"] = this.cfg.apiKey;
|
|
99004
|
+
if (this.cfg.jwt) h3["Authorization"] = `Bearer ${this.cfg.jwt}`;
|
|
99005
|
+
if (this.cfg.tenantId) h3["X-Tenant-Id"] = this.cfg.tenantId;
|
|
99006
|
+
return h3;
|
|
99002
99007
|
}
|
|
99003
99008
|
goalsPath(sel) {
|
|
99004
99009
|
return `/customers/${encodeURIComponent(sel.customerId)}/goals`;
|
|
@@ -103905,14 +103910,14 @@ function renderLojasStep3(state6, modalId, colors2, t) {
|
|
|
103905
103910
|
}
|
|
103906
103911
|
function renderAttrRow(key, value, readonly, suggestion, colors2, modalId, t, isFetchable = false, helpText) {
|
|
103907
103912
|
const hasValue = value !== null && value !== void 0 && value !== "";
|
|
103908
|
-
const
|
|
103913
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
103909
103914
|
const inputBorder = hasValue ? colors2.border : colors2.warning;
|
|
103910
103915
|
return `
|
|
103911
103916
|
<div style="
|
|
103912
103917
|
display: flex; align-items: center; gap: 12px;
|
|
103913
103918
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
103914
103919
|
">
|
|
103915
|
-
<span style="font-size: 16px;">${
|
|
103920
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
103916
103921
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
|
|
103917
103922
|
${key}
|
|
103918
103923
|
${helpText ? `<span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>` : ""}
|
|
@@ -103947,7 +103952,7 @@ function renderAttrRow(key, value, readonly, suggestion, colors2, modalId, t, is
|
|
|
103947
103952
|
}
|
|
103948
103953
|
function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
|
|
103949
103954
|
const hasValue = !!value;
|
|
103950
|
-
const
|
|
103955
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
103951
103956
|
const options = [
|
|
103952
103957
|
"3F_MEDIDOR",
|
|
103953
103958
|
"HIDROMETRO",
|
|
@@ -103966,7 +103971,7 @@ function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
|
|
|
103966
103971
|
display: flex; align-items: center; gap: 12px;
|
|
103967
103972
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
103968
103973
|
">
|
|
103969
|
-
<span style="font-size: 16px;">${
|
|
103974
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
103970
103975
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500;">deviceType</span>
|
|
103971
103976
|
<div style="flex: 1;">
|
|
103972
103977
|
<select id="${modalId}-deviceType" style="
|
|
@@ -103992,7 +103997,7 @@ function renderDeviceTypeSelect(value, suggested, colors2, modalId, t) {
|
|
|
103992
103997
|
}
|
|
103993
103998
|
function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
|
|
103994
103999
|
const hasValue = !!value;
|
|
103995
|
-
const
|
|
104000
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
103996
104001
|
const profiles = getSuggestedProfiles(deviceType);
|
|
103997
104002
|
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
104003
|
return `
|
|
@@ -104000,7 +104005,7 @@ function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
|
|
|
104000
104005
|
display: flex; align-items: center; gap: 12px;
|
|
104001
104006
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
104002
104007
|
">
|
|
104003
|
-
<span style="font-size: 16px;">${
|
|
104008
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
104004
104009
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
|
|
104005
104010
|
deviceProfile
|
|
104006
104011
|
<span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>
|
|
@@ -104021,7 +104026,7 @@ function renderDeviceProfileSelect(deviceType, value, colors2, modalId) {
|
|
|
104021
104026
|
}
|
|
104022
104027
|
function renderEntityLabelRow(currentLabel, deviceName, colors2, modalId, t) {
|
|
104023
104028
|
const hasValue = !!currentLabel;
|
|
104024
|
-
const
|
|
104029
|
+
const icon2 = hasValue ? "\u2705" : "\u26A0\uFE0F";
|
|
104025
104030
|
const suggestedValue = currentLabel || deviceName;
|
|
104026
104031
|
const helpText = "Etiqueta do dispositivo (entityLabel) - aparece no nome exibido da entidade no ThingsBoard";
|
|
104027
104032
|
return `
|
|
@@ -104029,7 +104034,7 @@ function renderEntityLabelRow(currentLabel, deviceName, colors2, modalId, t) {
|
|
|
104029
104034
|
display: flex; align-items: center; gap: 12px;
|
|
104030
104035
|
padding: 12px 16px; border-bottom: 1px solid ${colors2.border};
|
|
104031
104036
|
">
|
|
104032
|
-
<span style="font-size: 16px;">${
|
|
104037
|
+
<span style="font-size: 16px;">${icon2}</span>
|
|
104033
104038
|
<span style="width: 110px; font-size: 13px; color: ${colors2.textMuted}; font-weight: 500; display: flex; align-items: center; gap: 4px;">
|
|
104034
104039
|
etiqueta
|
|
104035
104040
|
<span title="${helpText}" style="cursor: help; font-size: 12px; color: ${colors2.primary};">\u2139\uFE0F</span>
|
|
@@ -104303,8 +104308,8 @@ async function openClearGcdrIdsModal(state6) {
|
|
|
104303
104308
|
</div>
|
|
104304
104309
|
</div>`;
|
|
104305
104310
|
}
|
|
104306
|
-
function keyBadges(
|
|
104307
|
-
return keys.filter((k) =>
|
|
104311
|
+
function keyBadges(present2, keys) {
|
|
104312
|
+
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
104313
|
}
|
|
104309
104314
|
function tableHtml(rows, keys) {
|
|
104310
104315
|
if (rows.length === 0) return '<div style="font-size:12px;color:#6b7280;padding:6px 0;">Nenhum item a limpar.</div>';
|
|
@@ -104365,13 +104370,13 @@ async function openClearGcdrIdsModal(state6) {
|
|
|
104365
104370
|
await Promise.all(chunks[ci].map(async (entity) => {
|
|
104366
104371
|
const tbId = entity.id?.id || "";
|
|
104367
104372
|
const name = entity.name || entity.label || tbId;
|
|
104368
|
-
let
|
|
104373
|
+
let present2 = {};
|
|
104369
104374
|
try {
|
|
104370
104375
|
const attrs = await fetchAttrs(tbId);
|
|
104371
|
-
for (const k of keysToCheck)
|
|
104376
|
+
for (const k of keysToCheck) present2[k] = attrs[k] != null && attrs[k] !== "";
|
|
104372
104377
|
} catch {
|
|
104373
104378
|
}
|
|
104374
|
-
targetRows.push({ tbId, name, entityType, present, hasAny: keysToCheck.some((k) =>
|
|
104379
|
+
targetRows.push({ tbId, name, entityType, present: present2, hasAny: keysToCheck.some((k) => present2[k]) });
|
|
104375
104380
|
}));
|
|
104376
104381
|
const done = deviceRows.length + assetRows.length;
|
|
104377
104382
|
const bodyEl = overlay.querySelector("#gcdr-clear-body");
|
|
@@ -107781,6 +107786,2089 @@ function openGenericModal(params) {
|
|
|
107781
107786
|
};
|
|
107782
107787
|
}
|
|
107783
107788
|
|
|
107789
|
+
// src/components/myio-gcdr-login/dom.ts
|
|
107790
|
+
function h2(doc, tag, attrs = {}, ...children) {
|
|
107791
|
+
const el2 = doc.createElement(tag);
|
|
107792
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
107793
|
+
if (v === null || v === void 0 || v === false) continue;
|
|
107794
|
+
if (k === "class") el2.className = String(v);
|
|
107795
|
+
else if (k === "text") el2.textContent = String(v);
|
|
107796
|
+
else el2.setAttribute(k, v === true ? "" : String(v));
|
|
107797
|
+
}
|
|
107798
|
+
for (const c of children) {
|
|
107799
|
+
if (c === null || c === void 0 || c === false) continue;
|
|
107800
|
+
el2.appendChild(typeof c === "string" ? doc.createTextNode(c) : c);
|
|
107801
|
+
}
|
|
107802
|
+
return el2;
|
|
107803
|
+
}
|
|
107804
|
+
function icon(doc, markup, cls) {
|
|
107805
|
+
const span = doc.createElement("span");
|
|
107806
|
+
if (cls) span.className = cls;
|
|
107807
|
+
span.setAttribute("aria-hidden", "true");
|
|
107808
|
+
span.innerHTML = markup;
|
|
107809
|
+
return span;
|
|
107810
|
+
}
|
|
107811
|
+
function safeCall(label, fn, ...args) {
|
|
107812
|
+
if (!fn) return;
|
|
107813
|
+
try {
|
|
107814
|
+
const r = fn(...args);
|
|
107815
|
+
if (r && typeof r.catch === "function") {
|
|
107816
|
+
r.catch(() => console.error(`[MYIO Login] ${label} failed`));
|
|
107817
|
+
}
|
|
107818
|
+
} catch {
|
|
107819
|
+
console.error(`[MYIO Login] ${label} failed`);
|
|
107820
|
+
}
|
|
107821
|
+
}
|
|
107822
|
+
function storageGet(key) {
|
|
107823
|
+
try {
|
|
107824
|
+
return typeof localStorage !== "undefined" ? localStorage.getItem(key) : null;
|
|
107825
|
+
} catch {
|
|
107826
|
+
return null;
|
|
107827
|
+
}
|
|
107828
|
+
}
|
|
107829
|
+
function storageSet(key, value) {
|
|
107830
|
+
try {
|
|
107831
|
+
if (typeof localStorage === "undefined") return;
|
|
107832
|
+
if (value === null) localStorage.removeItem(key);
|
|
107833
|
+
else localStorage.setItem(key, value);
|
|
107834
|
+
} catch {
|
|
107835
|
+
}
|
|
107836
|
+
}
|
|
107837
|
+
function prefersDark() {
|
|
107838
|
+
try {
|
|
107839
|
+
return typeof matchMedia === "function" && matchMedia("(prefers-color-scheme: dark)").matches;
|
|
107840
|
+
} catch {
|
|
107841
|
+
return false;
|
|
107842
|
+
}
|
|
107843
|
+
}
|
|
107844
|
+
function isCoarsePointer() {
|
|
107845
|
+
try {
|
|
107846
|
+
return typeof matchMedia === "function" && matchMedia("(pointer: coarse)").matches;
|
|
107847
|
+
} catch {
|
|
107848
|
+
return false;
|
|
107849
|
+
}
|
|
107850
|
+
}
|
|
107851
|
+
|
|
107852
|
+
// src/components/myio-gcdr-login/icons.ts
|
|
107853
|
+
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>`;
|
|
107854
|
+
var ICONS = {
|
|
107855
|
+
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),
|
|
107856
|
+
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),
|
|
107857
|
+
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),
|
|
107858
|
+
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),
|
|
107859
|
+
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),
|
|
107860
|
+
info: (s) => svg('<circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/>', s),
|
|
107861
|
+
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),
|
|
107862
|
+
moon: (s) => svg('<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>', s),
|
|
107863
|
+
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),
|
|
107864
|
+
x: (s) => svg('<path d="M18 6 6 18"/><path d="m6 6 12 12"/>', s),
|
|
107865
|
+
arrowLeft: (s) => svg('<path d="m12 19-7-7 7-7"/><path d="M19 12H5"/>', s),
|
|
107866
|
+
chevronRight: (s) => svg('<path d="m9 18 6-6-6-6"/>', s),
|
|
107867
|
+
external: (s) => svg('<path d="M7 7h10v10"/><path d="M7 17 17 7"/>', s),
|
|
107868
|
+
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),
|
|
107869
|
+
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),
|
|
107870
|
+
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),
|
|
107871
|
+
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),
|
|
107872
|
+
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),
|
|
107873
|
+
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),
|
|
107874
|
+
spinner: (s) => svg('<path d="M21 12a9 9 0 1 1-6.219-8.56"/>', s)
|
|
107875
|
+
};
|
|
107876
|
+
|
|
107877
|
+
// src/components/myio-gcdr-login/about.ts
|
|
107878
|
+
var CATEGORIES = [
|
|
107879
|
+
{ key: "wiki", icon: "book", items: [
|
|
107880
|
+
{ key: "wikiHome", to: "/wiki/p", web: true },
|
|
107881
|
+
{ key: "wikiSearch", to: "/wiki/p/search", web: true },
|
|
107882
|
+
{ key: "accountGuide", to: "/wiki/p/User-Guides/acesso-a-conta", web: true }
|
|
107883
|
+
] },
|
|
107884
|
+
{ key: "support", icon: "headset", items: [
|
|
107885
|
+
{ key: "openTicket", to: "/support", web: true },
|
|
107886
|
+
{ key: "forgotPassword", to: "/forgot-password", web: true }
|
|
107887
|
+
] },
|
|
107888
|
+
{ key: "integrations", icon: "plug", items: [
|
|
107889
|
+
{ key: "docsAlarms", to: "https://alarms-api.a.myio-bas.com/docs" },
|
|
107890
|
+
{ key: "docsGcdr", to: "https://gcdr-api.a.myio-bas.com/docs/" },
|
|
107891
|
+
{ key: "docsIngestion", to: "https://api.data.apps.myio-bas.com/api/docs/" },
|
|
107892
|
+
{ key: "docsThingsboard", to: "https://dashboard.myio-bas.com/swagger-ui/index.html" },
|
|
107893
|
+
{ key: "integrationsGuide", to: "/wiki/p/Integrations/index", web: true },
|
|
107894
|
+
{ key: "newIntegration", to: "/wiki/p/integrations/new", web: true }
|
|
107895
|
+
] },
|
|
107896
|
+
{ key: "systems", icon: "grid", items: [
|
|
107897
|
+
{ key: "app", to: "https://app.apps.myio-bas.com" },
|
|
107898
|
+
{ key: "dashboards", to: "https://dashboard.myio-bas.com" },
|
|
107899
|
+
{ key: "alarms", to: "https://alarms-web.a.myio-bas.com" }
|
|
107900
|
+
] },
|
|
107901
|
+
{ key: "institutional", icon: "building", items: [
|
|
107902
|
+
{ key: "site", to: "https://myio.com.br" },
|
|
107903
|
+
{ key: "privacy", to: "https://myio.com.br/politica-de-privacidade" },
|
|
107904
|
+
{ key: "terms" }
|
|
107905
|
+
] },
|
|
107906
|
+
{ key: "status", icon: "activity", items: [{ key: "gcdrHealth", health: true }] }
|
|
107907
|
+
];
|
|
107908
|
+
function defaultSupportHref(webUrl) {
|
|
107909
|
+
return webUrl ? `${webUrl.replace(/\/+$/, "")}/support` : void 0;
|
|
107910
|
+
}
|
|
107911
|
+
function renderAbout(el2, ctx, t, opts) {
|
|
107912
|
+
const doc = el2.ownerDocument;
|
|
107913
|
+
const { body } = ctx.panel({ eyebrow: t("about.eyebrow"), fill: true, logo: false, bandColor: opts.bandColor ?? "#2E8B57" });
|
|
107914
|
+
const web = opts.webUrl?.replace(/\/+$/, "");
|
|
107915
|
+
const visibleCats = CATEGORIES.filter((c) => c.key === "status" ? !!opts.healthUrl : true);
|
|
107916
|
+
let healthAbort = null;
|
|
107917
|
+
const showGrid = () => {
|
|
107918
|
+
body.textContent = "";
|
|
107919
|
+
const title = h2(doc, "h2", { class: "myio-gcdr-about__title" }, `${t("about.title")} `, h2(doc, "em", { text: t("about.titleHighlight") }));
|
|
107920
|
+
const intro = h2(doc, "p", { class: "myio-gcdr-about__intro", text: t("about.text") });
|
|
107921
|
+
const grid = h2(doc, "div", { class: "myio-gcdr-about__grid" });
|
|
107922
|
+
for (const c of visibleCats) {
|
|
107923
|
+
const btn = h2(
|
|
107924
|
+
doc,
|
|
107925
|
+
"button",
|
|
107926
|
+
{ type: "button", class: "myio-gcdr-about__tile" },
|
|
107927
|
+
icon(doc, ICONS[c.icon](22), "myio-gcdr-about__tileicon"),
|
|
107928
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: t(`about.cat.${c.key}`) }),
|
|
107929
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletext", text: t(`about.cat.${c.key}.text`) })
|
|
107930
|
+
);
|
|
107931
|
+
btn.addEventListener("click", () => showCategory(c));
|
|
107932
|
+
grid.appendChild(btn);
|
|
107933
|
+
}
|
|
107934
|
+
body.append(title, intro, grid, h2(doc, "p", { class: "myio-gcdr-about__tagline", text: t("about.tagline") }));
|
|
107935
|
+
};
|
|
107936
|
+
const showCategory = (c) => {
|
|
107937
|
+
body.textContent = "";
|
|
107938
|
+
const back = h2(doc, "button", { type: "button", class: "myio-gcdr-login__link myio-gcdr-about__back" }, icon(doc, ICONS.arrowLeft(14)), ` ${t("about.back")}`);
|
|
107939
|
+
back.addEventListener("click", () => {
|
|
107940
|
+
showGrid();
|
|
107941
|
+
body.querySelector("button")?.focus();
|
|
107942
|
+
});
|
|
107943
|
+
const title = h2(doc, "h2", { class: "myio-gcdr-about__title", text: t(`about.cat.${c.key}`) });
|
|
107944
|
+
const grid = h2(doc, "div", { class: "myio-gcdr-about__grid" });
|
|
107945
|
+
for (const it of c.items) {
|
|
107946
|
+
const label = t(`about.item.${it.key}`);
|
|
107947
|
+
if (it.health) {
|
|
107948
|
+
const dot = h2(doc, "span", { class: "myio-gcdr-about__dot", "data-state": "checking" });
|
|
107949
|
+
const state6 = h2(doc, "span", { class: "myio-gcdr-about__health", role: "status" }, dot, h2(doc, "span", { text: t("about.health.checking") }));
|
|
107950
|
+
grid.appendChild(h2(
|
|
107951
|
+
doc,
|
|
107952
|
+
"div",
|
|
107953
|
+
{ class: "myio-gcdr-about__tile", "aria-disabled": "true" },
|
|
107954
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
|
|
107955
|
+
state6
|
|
107956
|
+
));
|
|
107957
|
+
checkHealth(dot, state6.lastChild);
|
|
107958
|
+
continue;
|
|
107959
|
+
}
|
|
107960
|
+
const href = it.to ? it.web ? web ? `${web}${it.to}` : void 0 : it.to : void 0;
|
|
107961
|
+
if (it.web && !href) continue;
|
|
107962
|
+
if (!href) {
|
|
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
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletext", text: t("about.soon") })
|
|
107969
|
+
));
|
|
107970
|
+
continue;
|
|
107971
|
+
}
|
|
107972
|
+
grid.appendChild(h2(
|
|
107973
|
+
doc,
|
|
107974
|
+
"a",
|
|
107975
|
+
{ class: "myio-gcdr-about__tile", href, target: "_blank", rel: "noopener noreferrer" },
|
|
107976
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletitle", text: label }),
|
|
107977
|
+
h2(doc, "span", { class: "myio-gcdr-about__tiletext" }, `${t("about.open")} `, icon(doc, ICONS.external(12)))
|
|
107978
|
+
));
|
|
107979
|
+
}
|
|
107980
|
+
body.append(back, title, grid);
|
|
107981
|
+
back.focus();
|
|
107982
|
+
};
|
|
107983
|
+
const checkHealth = (dot, label) => {
|
|
107984
|
+
if (!opts.healthUrl) return;
|
|
107985
|
+
const f = opts.fetchImpl ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
|
|
107986
|
+
if (!f) return;
|
|
107987
|
+
healthAbort?.abort();
|
|
107988
|
+
const ac = new AbortController();
|
|
107989
|
+
healthAbort = ac;
|
|
107990
|
+
const timer = setTimeout(() => ac.abort(), 5e3);
|
|
107991
|
+
f(opts.healthUrl, { signal: ac.signal, credentials: "omit" }).then((r) => r.ok).catch(() => false).then((up4) => {
|
|
107992
|
+
clearTimeout(timer);
|
|
107993
|
+
if (ac.signal.aborted && healthAbort !== ac) return;
|
|
107994
|
+
dot.setAttribute("data-state", up4 ? "online" : "offline");
|
|
107995
|
+
label.textContent = t(up4 ? "about.health.online" : "about.health.offline");
|
|
107996
|
+
});
|
|
107997
|
+
};
|
|
107998
|
+
showGrid();
|
|
107999
|
+
return () => healthAbort?.abort();
|
|
108000
|
+
}
|
|
108001
|
+
function renderSignedOutPrompt(el2, ctx, text2) {
|
|
108002
|
+
const doc = el2.ownerDocument;
|
|
108003
|
+
const { body } = ctx.panel({ eyebrow: "", fill: true, logo: false });
|
|
108004
|
+
const band = body.parentElement?.querySelector(".myio-gcdr-panel__band");
|
|
108005
|
+
band?.remove();
|
|
108006
|
+
body.appendChild(
|
|
108007
|
+
h2(
|
|
108008
|
+
doc,
|
|
108009
|
+
"div",
|
|
108010
|
+
{ class: "myio-gcdr-prompt" },
|
|
108011
|
+
icon(doc, ICONS.lock(28), "myio-gcdr-prompt__icon"),
|
|
108012
|
+
h2(doc, "p", { class: "myio-gcdr-prompt__text", text: text2 })
|
|
108013
|
+
)
|
|
108014
|
+
);
|
|
108015
|
+
}
|
|
108016
|
+
|
|
108017
|
+
// src/components/myio-gcdr-login/i18n.ts
|
|
108018
|
+
var PT = {
|
|
108019
|
+
"login.eyebrow": "Acesso",
|
|
108020
|
+
"login.title": "Login",
|
|
108021
|
+
"login.email": "E-mail",
|
|
108022
|
+
"login.password": "Senha",
|
|
108023
|
+
"login.rememberMe": "Lembrar de mim",
|
|
108024
|
+
"login.forgotPassword": "Esqueceu a senha?",
|
|
108025
|
+
"login.signIn": "Entrar",
|
|
108026
|
+
"login.signingIn": "Entrando...",
|
|
108027
|
+
"login.noAccount": "N\xE3o tem uma conta?",
|
|
108028
|
+
"login.createAccount": "Criar conta",
|
|
108029
|
+
"login.emailRequired": "Informe o seu e-mail.",
|
|
108030
|
+
"login.emailInvalid": "Informe um e-mail v\xE1lido, como nome@empresa.com.",
|
|
108031
|
+
"login.emailPlaceholder": "nome@empresa.com",
|
|
108032
|
+
// new
|
|
108033
|
+
"login.passwordRequired": "Informe a sua senha.",
|
|
108034
|
+
"login.showPassword": "Mostrar senha",
|
|
108035
|
+
"login.hidePassword": "Ocultar senha",
|
|
108036
|
+
"login.capsLockOn": "Caps Lock est\xE1 ativado.",
|
|
108037
|
+
"login.notYou": "N\xE3o \xE9 voc\xEA?",
|
|
108038
|
+
"login.askAdmin": "Precisa de acesso? Fale com o administrador do sistema.",
|
|
108039
|
+
"login.newTab": "(abre em nova aba)",
|
|
108040
|
+
"login.gcdrWeb": "Entrar pelo GCDR Web",
|
|
108041
|
+
"login.support": "Falar com o suporte",
|
|
108042
|
+
"login.leaving": "Saindo...",
|
|
108043
|
+
"errors.invalidCredentials": "E-mail ou senha inv\xE1lidos",
|
|
108044
|
+
"errors.networkError": "Erro de conex\xE3o. Verifique sua internet.",
|
|
108045
|
+
"errors.loginFailed": "N\xE3o foi poss\xEDvel entrar no momento. Tente novamente em instantes.",
|
|
108046
|
+
"errors.lockedTitle": "Conta bloqueada",
|
|
108047
|
+
"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.",
|
|
108048
|
+
"errors.attemptsLeft_one": "Senha incorreta \u2014 resta {{count}} tentativa.",
|
|
108049
|
+
"errors.attemptsLeft_other": "Senha incorreta \u2014 restam {{count}} tentativas.",
|
|
108050
|
+
"errors.lastAttempt": "Senha incorreta \u2014 esta \xE9 a sua \xFAltima tentativa.",
|
|
108051
|
+
"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.",
|
|
108052
|
+
"errors.goToForgot": "Esqueci minha senha \u2014 redefinir agora",
|
|
108053
|
+
"errors.invalidWithAttempts_one": "E-mail ou senha inv\xE1lidos. Resta {{count}} tentativa antes do bloqueio.",
|
|
108054
|
+
"errors.invalidWithAttempts_other": "E-mail ou senha inv\xE1lidos. Restam {{count}} tentativas antes do bloqueio.",
|
|
108055
|
+
"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.",
|
|
108056
|
+
// new
|
|
108057
|
+
"errors.tooManyRequests": "Muitas tentativas. Aguarde alguns minutos e tente novamente.",
|
|
108058
|
+
"errors.timeout": "O servidor demorou para responder. Tente novamente.",
|
|
108059
|
+
"errors.integrationError": "N\xE3o foi poss\xEDvel entrar no momento. Tente novamente em instantes.",
|
|
108060
|
+
"errors.mfaUnsupported": "Esta conta exige verifica\xE7\xE3o em duas etapas, ainda n\xE3o dispon\xEDvel nesta tela.",
|
|
108061
|
+
"errors.postLoginFailed": "N\xE3o foi poss\xEDvel concluir a entrada. Tente novamente.",
|
|
108062
|
+
"errors.leaveFailed": "N\xE3o foi poss\xEDvel sair agora. Tente novamente.",
|
|
108063
|
+
"errors.captchaLoadFailed": "N\xE3o foi poss\xEDvel carregar a verifica\xE7\xE3o.",
|
|
108064
|
+
"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}}.",
|
|
108065
|
+
"errors.helpSupport": "fale com o suporte",
|
|
108066
|
+
"errors.helpAdmin": "fale com o administrador do sistema",
|
|
108067
|
+
"notice.sessionExpired": "Sua sess\xE3o expirou. Por favor, entre novamente.",
|
|
108068
|
+
"notice.sessionExpiredModal": "Sua sess\xE3o expirou. Entre novamente \u2014 esta tela ser\xE1 mantida.",
|
|
108069
|
+
"aside.signedOutPrompt": "Fa\xE7a o login para ter acesso \xE0s funcionalidades.",
|
|
108070
|
+
"about.eyebrow": "Sobre a MYIO",
|
|
108071
|
+
"about.title": "Medi\xE7\xE3o e atua\xE7\xE3o remota",
|
|
108072
|
+
"about.titleHighlight": "IoT",
|
|
108073
|
+
"about.text": "Escolha um assunto para ver o que voc\xEA pode acessar sem entrar na conta.",
|
|
108074
|
+
"about.tagline": "Efici\xEAncia | Seguran\xE7a | Sustentabilidade",
|
|
108075
|
+
"about.health.checking": "Verificando\u2026",
|
|
108076
|
+
"about.health.online": "No ar",
|
|
108077
|
+
"about.health.offline": "Indispon\xEDvel",
|
|
108078
|
+
"about.back": "Voltar",
|
|
108079
|
+
"about.open": "Abrir",
|
|
108080
|
+
"about.soon": "Em breve",
|
|
108081
|
+
"about.cat.wiki": "Wiki",
|
|
108082
|
+
"about.cat.wiki.text": "Base de conhecimento, guias e respostas.",
|
|
108083
|
+
"about.cat.support": "Atendimento",
|
|
108084
|
+
"about.cat.support.text": "Chamados, tickets e d\xFAvidas.",
|
|
108085
|
+
"about.cat.integrations": "Integra\xE7\xF5es",
|
|
108086
|
+
"about.cat.integrations.text": "Documenta\xE7\xE3o das APIs e guias de integra\xE7\xE3o.",
|
|
108087
|
+
"about.cat.systems": "Sistemas",
|
|
108088
|
+
"about.cat.systems.text": "Acesso aos sistemas MYIO.",
|
|
108089
|
+
"about.cat.institutional": "Institucional",
|
|
108090
|
+
"about.cat.institutional.text": "Sobre a MYIO, site, privacidade e termos.",
|
|
108091
|
+
"about.cat.status": "Status",
|
|
108092
|
+
"about.cat.status.text": "Situa\xE7\xE3o dos sistemas agora.",
|
|
108093
|
+
"about.item.wikiHome": "Wiki p\xFAblica",
|
|
108094
|
+
"about.item.wikiSearch": "Buscar na wiki",
|
|
108095
|
+
"about.item.accountGuide": "Acesso \xE0 conta",
|
|
108096
|
+
"about.item.openTicket": "Abrir chamado",
|
|
108097
|
+
"about.item.forgotPassword": "Esqueci minha senha",
|
|
108098
|
+
"about.item.docsAlarms": "Alarms",
|
|
108099
|
+
"about.item.docsGcdr": "GCDR",
|
|
108100
|
+
"about.item.docsIngestion": "Ingestion",
|
|
108101
|
+
"about.item.docsThingsboard": "ThingsBoard",
|
|
108102
|
+
"about.item.integrationsGuide": "Guia de integra\xE7\xF5es",
|
|
108103
|
+
"about.item.newIntegration": "Cadastrar integra\xE7\xE3o",
|
|
108104
|
+
"about.item.app": "App MYIO",
|
|
108105
|
+
"about.item.dashboards": "Dashboards",
|
|
108106
|
+
"about.item.alarms": "Alarmes",
|
|
108107
|
+
"about.item.site": "Site da MYIO",
|
|
108108
|
+
"about.item.privacy": "Privacidade",
|
|
108109
|
+
"about.item.terms": "Termos de servi\xE7o",
|
|
108110
|
+
"about.item.gcdrHealth": "GCDR",
|
|
108111
|
+
"toolbar.toDark": "Usar tema escuro",
|
|
108112
|
+
"toolbar.toLight": "Usar tema claro",
|
|
108113
|
+
"toolbar.language": "Idioma",
|
|
108114
|
+
"modal.close": "Fechar"
|
|
108115
|
+
};
|
|
108116
|
+
var EN = {
|
|
108117
|
+
"login.eyebrow": "Access",
|
|
108118
|
+
"login.title": "Login",
|
|
108119
|
+
"login.email": "Email",
|
|
108120
|
+
"login.password": "Password",
|
|
108121
|
+
"login.rememberMe": "Remember me",
|
|
108122
|
+
"login.forgotPassword": "Forgot password?",
|
|
108123
|
+
"login.signIn": "Sign In",
|
|
108124
|
+
"login.signingIn": "Signing in...",
|
|
108125
|
+
"login.noAccount": "Don't have an account?",
|
|
108126
|
+
"login.createAccount": "Create account",
|
|
108127
|
+
"login.emailRequired": "Enter your e-mail.",
|
|
108128
|
+
"login.emailInvalid": "Enter a valid e-mail, like name@company.com.",
|
|
108129
|
+
"login.emailPlaceholder": "name@company.com",
|
|
108130
|
+
"login.passwordRequired": "Enter your password.",
|
|
108131
|
+
"login.showPassword": "Show password",
|
|
108132
|
+
"login.hidePassword": "Hide password",
|
|
108133
|
+
"login.capsLockOn": "Caps Lock is on.",
|
|
108134
|
+
"login.notYou": "Not you?",
|
|
108135
|
+
"login.askAdmin": "Need access? Contact your system administrator.",
|
|
108136
|
+
"login.newTab": "(opens in a new tab)",
|
|
108137
|
+
"login.gcdrWeb": "Sign in on GCDR Web",
|
|
108138
|
+
"login.support": "Contact support",
|
|
108139
|
+
"login.leaving": "Leaving...",
|
|
108140
|
+
"errors.invalidCredentials": "Invalid e-mail or password",
|
|
108141
|
+
"errors.networkError": "Network error. Please check your connection.",
|
|
108142
|
+
"errors.loginFailed": "Unable to sign in right now. Please try again shortly.",
|
|
108143
|
+
"errors.lockedTitle": "Account locked",
|
|
108144
|
+
"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.",
|
|
108145
|
+
"errors.attemptsLeft_one": "Wrong password \u2014 {{count}} attempt left.",
|
|
108146
|
+
"errors.attemptsLeft_other": "Wrong password \u2014 {{count}} attempts left.",
|
|
108147
|
+
"errors.lastAttempt": "Wrong password \u2014 this is your last attempt.",
|
|
108148
|
+
"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.",
|
|
108149
|
+
"errors.goToForgot": "Forgot my password \u2014 reset now",
|
|
108150
|
+
"errors.invalidWithAttempts_one": "Invalid e-mail or password. {{count}} attempt left before the lock.",
|
|
108151
|
+
"errors.invalidWithAttempts_other": "Invalid e-mail or password. {{count}} attempts left before the lock.",
|
|
108152
|
+
"errors.captchaFailed": "Could not confirm you are not a robot. Wait for the check and try again.",
|
|
108153
|
+
"errors.tooManyRequests": "Too many attempts. Wait a few minutes and try again.",
|
|
108154
|
+
"errors.timeout": "The server took too long to answer. Please try again.",
|
|
108155
|
+
"errors.integrationError": "Unable to sign in right now. Please try again shortly.",
|
|
108156
|
+
"errors.mfaUnsupported": "This account requires two-step verification, not yet available on this screen.",
|
|
108157
|
+
"errors.postLoginFailed": "Could not finish signing in. Please try again.",
|
|
108158
|
+
"errors.leaveFailed": "Could not leave right now. Please try again.",
|
|
108159
|
+
"errors.captchaLoadFailed": "Could not load the verification.",
|
|
108160
|
+
"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}}.",
|
|
108161
|
+
"errors.helpSupport": "contact support",
|
|
108162
|
+
"errors.helpAdmin": "contact your system administrator",
|
|
108163
|
+
"notice.sessionExpired": "Your session has expired. Please sign in again.",
|
|
108164
|
+
"notice.sessionExpiredModal": "Your session has expired. Sign in again \u2014 this screen will be kept.",
|
|
108165
|
+
"aside.signedOutPrompt": "Sign in to access the features.",
|
|
108166
|
+
"about.eyebrow": "About MYIO",
|
|
108167
|
+
"about.title": "Remote metering and control",
|
|
108168
|
+
"about.titleHighlight": "IoT",
|
|
108169
|
+
"about.text": "Pick a subject to see what you can reach without signing in.",
|
|
108170
|
+
"about.tagline": "Efficiency | Safety | Sustainability",
|
|
108171
|
+
"about.health.checking": "Checking\u2026",
|
|
108172
|
+
"about.health.online": "Up",
|
|
108173
|
+
"about.health.offline": "Unavailable",
|
|
108174
|
+
"about.back": "Back",
|
|
108175
|
+
"about.open": "Open",
|
|
108176
|
+
"about.soon": "Coming soon",
|
|
108177
|
+
"about.cat.wiki": "Wiki",
|
|
108178
|
+
"about.cat.wiki.text": "Knowledge base, guides and answers.",
|
|
108179
|
+
"about.cat.support": "Support",
|
|
108180
|
+
"about.cat.support.text": "Tickets and questions.",
|
|
108181
|
+
"about.cat.integrations": "Integrations",
|
|
108182
|
+
"about.cat.integrations.text": "API documentation and integration guides.",
|
|
108183
|
+
"about.cat.systems": "Systems",
|
|
108184
|
+
"about.cat.systems.text": "Access to the MYIO systems.",
|
|
108185
|
+
"about.cat.institutional": "About us",
|
|
108186
|
+
"about.cat.institutional.text": "About MYIO, website, privacy and terms.",
|
|
108187
|
+
"about.cat.status": "Status",
|
|
108188
|
+
"about.cat.status.text": "How the systems are right now.",
|
|
108189
|
+
"about.item.wikiHome": "Public wiki",
|
|
108190
|
+
"about.item.wikiSearch": "Search the wiki",
|
|
108191
|
+
"about.item.accountGuide": "Account access",
|
|
108192
|
+
"about.item.openTicket": "Open a ticket",
|
|
108193
|
+
"about.item.forgotPassword": "Forgot my password",
|
|
108194
|
+
"about.item.docsAlarms": "Alarms",
|
|
108195
|
+
"about.item.docsGcdr": "GCDR",
|
|
108196
|
+
"about.item.docsIngestion": "Ingestion",
|
|
108197
|
+
"about.item.docsThingsboard": "ThingsBoard",
|
|
108198
|
+
"about.item.integrationsGuide": "Integrations guide",
|
|
108199
|
+
"about.item.newIntegration": "Submit an integration",
|
|
108200
|
+
"about.item.app": "MYIO App",
|
|
108201
|
+
"about.item.dashboards": "Dashboards",
|
|
108202
|
+
"about.item.alarms": "Alarms",
|
|
108203
|
+
"about.item.site": "MYIO website",
|
|
108204
|
+
"about.item.privacy": "Privacy",
|
|
108205
|
+
"about.item.terms": "Terms of service",
|
|
108206
|
+
"about.item.gcdrHealth": "GCDR",
|
|
108207
|
+
"toolbar.toDark": "Use dark theme",
|
|
108208
|
+
"toolbar.toLight": "Use light theme",
|
|
108209
|
+
"toolbar.language": "Language",
|
|
108210
|
+
"modal.close": "Close"
|
|
108211
|
+
};
|
|
108212
|
+
var DICTIONARIES = { "pt-BR": PT, en: EN };
|
|
108213
|
+
function interpolate(text2, vars) {
|
|
108214
|
+
if (!vars) return text2;
|
|
108215
|
+
return text2.replace(/\{\{(\w+)\}\}/g, (_m, k) => vars[k] != null ? String(vars[k]) : "");
|
|
108216
|
+
}
|
|
108217
|
+
function translate(locale, key, vars, overrides) {
|
|
108218
|
+
let k = key;
|
|
108219
|
+
if (vars && typeof vars.count === "number") {
|
|
108220
|
+
const cat = new Intl.PluralRules(locale).select(vars.count);
|
|
108221
|
+
k = `${key}_${cat === "one" ? "one" : "other"}`;
|
|
108222
|
+
}
|
|
108223
|
+
const text2 = overrides?.[locale]?.[k] ?? DICTIONARIES[locale][k] ?? overrides?.["pt-BR"]?.[k] ?? DICTIONARIES["pt-BR"][k] ?? k;
|
|
108224
|
+
return interpolate(text2, vars);
|
|
108225
|
+
}
|
|
108226
|
+
function localize(value, locale) {
|
|
108227
|
+
if (value == null) return "";
|
|
108228
|
+
if (typeof value === "string") return value;
|
|
108229
|
+
return value[locale] ?? value["pt-BR"] ?? value.en ?? "";
|
|
108230
|
+
}
|
|
108231
|
+
function detectLocale(stored) {
|
|
108232
|
+
if (stored === "pt-BR" || stored === "en") return stored;
|
|
108233
|
+
const nav = typeof navigator !== "undefined" ? navigator.language || "" : "";
|
|
108234
|
+
return nav.toLowerCase().startsWith("en") ? "en" : "pt-BR";
|
|
108235
|
+
}
|
|
108236
|
+
|
|
108237
|
+
// src/components/myio-gcdr-login/styles.ts
|
|
108238
|
+
var STYLE_VERSION = "1";
|
|
108239
|
+
var STYLE_ATTR = "data-myio-gcdr-version";
|
|
108240
|
+
var REFS_ATTR = "data-myio-gcdr-refs";
|
|
108241
|
+
var FONT_ID = "myio-gcdr-font-nunito";
|
|
108242
|
+
var CSS3 = `
|
|
108243
|
+
.myio-gcdr-shell, .myio-gcdr-overlay {
|
|
108244
|
+
--myio-gcdr-accent: #6B4ABF;
|
|
108245
|
+
--myio-gcdr-accent-hover: #5A3CA8;
|
|
108246
|
+
--myio-gcdr-card: #FBFAFE;
|
|
108247
|
+
--myio-gcdr-ring: #E1DAF4;
|
|
108248
|
+
--myio-gcdr-title: #1E1B2E;
|
|
108249
|
+
--myio-gcdr-text: #55506A;
|
|
108250
|
+
--myio-gcdr-footer: #F0ECFA;
|
|
108251
|
+
--myio-gcdr-input: #FFFFFF;
|
|
108252
|
+
--myio-gcdr-input-border: #D1D5DB;
|
|
108253
|
+
--myio-gcdr-link: #6B4ABF;
|
|
108254
|
+
--myio-gcdr-pill: rgba(255,255,255,0.70);
|
|
108255
|
+
--myio-gcdr-aside-band: #2E8B57;
|
|
108256
|
+
box-sizing: border-box;
|
|
108257
|
+
font-family: 'Nunito', ui-sans-serif, system-ui, sans-serif;
|
|
108258
|
+
line-height: 1.5;
|
|
108259
|
+
color: var(--myio-gcdr-title);
|
|
108260
|
+
-webkit-font-smoothing: antialiased;
|
|
108261
|
+
}
|
|
108262
|
+
.myio-gcdr-shell[data-theme="dark"], .myio-gcdr-overlay[data-theme="dark"] {
|
|
108263
|
+
--myio-gcdr-card: #1E1A2E;
|
|
108264
|
+
--myio-gcdr-ring: #3A3158;
|
|
108265
|
+
--myio-gcdr-title: #FFFFFF;
|
|
108266
|
+
--myio-gcdr-text: #D1D5DB;
|
|
108267
|
+
--myio-gcdr-footer: #251F3A;
|
|
108268
|
+
--myio-gcdr-input: #2B2440;
|
|
108269
|
+
--myio-gcdr-input-border: #3A3158;
|
|
108270
|
+
--myio-gcdr-link: #B9A5F0;
|
|
108271
|
+
--myio-gcdr-pill: rgba(43,36,64,0.80);
|
|
108272
|
+
}
|
|
108273
|
+
.myio-gcdr-shell [hidden], .myio-gcdr-overlay [hidden] { display: none !important; }
|
|
108274
|
+
.myio-gcdr-shell *, .myio-gcdr-shell *::before, .myio-gcdr-shell *::after,
|
|
108275
|
+
.myio-gcdr-overlay *, .myio-gcdr-overlay *::before, .myio-gcdr-overlay *::after { box-sizing: border-box; }
|
|
108276
|
+
|
|
108277
|
+
/* \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 */
|
|
108278
|
+
.myio-gcdr-shell {
|
|
108279
|
+
position: relative; min-height: 100%; width: 100%;
|
|
108280
|
+
display: flex; flex-direction: column; align-items: center;
|
|
108281
|
+
padding: 16px; isolation: isolate;
|
|
108282
|
+
}
|
|
108283
|
+
.myio-gcdr-shell__wallpaper {
|
|
108284
|
+
position: absolute; inset: 0; z-index: -1; overflow: hidden;
|
|
108285
|
+
background-color: #EEEAF8;
|
|
108286
|
+
background-image: var(--myio-gcdr-wp, none), linear-gradient(180deg, #DCD2F3 0%, #EEEAF8 45%, #F7F5FC 100%);
|
|
108287
|
+
background-position: center; background-size: cover; background-repeat: no-repeat;
|
|
108288
|
+
}
|
|
108289
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper {
|
|
108290
|
+
background-color: #15121F;
|
|
108291
|
+
background-image: var(--myio-gcdr-wp, none), linear-gradient(180deg, #1B1530 0%, #15121F 45%, #111827 100%);
|
|
108292
|
+
}
|
|
108293
|
+
.myio-gcdr-shell__wallpaper::before { content: ''; position: absolute; inset: 0;
|
|
108294
|
+
background: rgba(255,255,255,0.22); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); }
|
|
108295
|
+
.myio-gcdr-shell__wallpaper::after { content: ''; position: absolute; inset: 0;
|
|
108296
|
+
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%); }
|
|
108297
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper::before { background: rgba(255,255,255,0.05); }
|
|
108298
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__wallpaper::after {
|
|
108299
|
+
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%); }
|
|
108300
|
+
|
|
108301
|
+
.myio-gcdr-shell__top { width: 100%; }
|
|
108302
|
+
.myio-gcdr-shell__block { width: 100%; max-width: 28rem; margin: auto 0; display: flex; flex-direction: column; }
|
|
108303
|
+
.myio-gcdr-shell[data-size="lg"] .myio-gcdr-shell__block { max-width: 32rem; }
|
|
108304
|
+
.myio-gcdr-shell[data-size="xl"] .myio-gcdr-shell__block { max-width: 37rem; }
|
|
108305
|
+
@media (min-width: 1024px) {
|
|
108306
|
+
.myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__block { max-width: 72rem; }
|
|
108307
|
+
}
|
|
108308
|
+
.myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 28rem; }
|
|
108309
|
+
@media (min-width: 640px) { .myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 42rem; } }
|
|
108310
|
+
@media (min-width: 1024px) { .myio-gcdr-shell[data-width="cockpit"] .myio-gcdr-shell__block { max-width: 1800px; padding: 0 12px; } }
|
|
108311
|
+
|
|
108312
|
+
.myio-gcdr-shell__toprow { display: flex; justify-content: flex-end; margin-bottom: 12px; }
|
|
108313
|
+
.myio-gcdr-shell__pill {
|
|
108314
|
+
display: inline-flex; flex-wrap: wrap; align-items: center; gap: 4px; justify-content: flex-end;
|
|
108315
|
+
border-radius: 9999px; background: var(--myio-gcdr-pill); padding: 4px 8px;
|
|
108316
|
+
box-shadow: 0 1px 2px rgba(0,0,0,0.05); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
|
|
108317
|
+
}
|
|
108318
|
+
.myio-gcdr-shell__iconbtn {
|
|
108319
|
+
display: inline-flex; align-items: center; gap: 6px; min-height: 36px; min-width: 36px; justify-content: center;
|
|
108320
|
+
border: 0; background: transparent; color: var(--myio-gcdr-text); border-radius: 8px; padding: 6px 10px;
|
|
108321
|
+
font: inherit; font-size: 13px; font-weight: 700; cursor: pointer;
|
|
108322
|
+
}
|
|
108323
|
+
.myio-gcdr-shell__iconbtn:hover { background: rgba(107,74,191,0.10); color: var(--myio-gcdr-title); }
|
|
108324
|
+
.myio-gcdr-shell__iconbtn:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108325
|
+
|
|
108326
|
+
.myio-gcdr-shell__split { display: flex; flex-direction: column; gap: 24px; }
|
|
108327
|
+
@media (min-width: 1024px) {
|
|
108328
|
+
.myio-gcdr-shell__split { flex-direction: row; align-items: stretch; }
|
|
108329
|
+
.myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__split { height: clamp(600px, calc(100vh - 10rem), 880px); }
|
|
108330
|
+
.myio-gcdr-shell__aside { flex: 1 1 0; min-width: 0; display: flex; }
|
|
108331
|
+
.myio-gcdr-shell[data-has-aside="true"] .myio-gcdr-shell__main { flex: 0 0 28rem; }
|
|
108332
|
+
.myio-gcdr-shell[data-width="cockpit"][data-has-aside="true"] .myio-gcdr-shell__main { flex: 1 1 0; }
|
|
108333
|
+
}
|
|
108334
|
+
.myio-gcdr-shell__main { display: flex; min-width: 0; min-height: 0; }
|
|
108335
|
+
.myio-gcdr-shell__main > * { flex: 1 1 auto; min-width: 0; }
|
|
108336
|
+
@media (max-width: 1023.98px) {
|
|
108337
|
+
.myio-gcdr-shell[data-aside-compact="hide"] .myio-gcdr-shell__aside { display: none; }
|
|
108338
|
+
.myio-gcdr-shell[data-aside-compact="stack"] .myio-gcdr-shell__aside { order: 2; display: flex; }
|
|
108339
|
+
}
|
|
108340
|
+
.myio-gcdr-shell__aside[hidden], .myio-gcdr-shell__below[hidden], .myio-gcdr-shell__top[hidden] { display: none !important; }
|
|
108341
|
+
.myio-gcdr-shell__below { margin-top: 16px; text-align: center; }
|
|
108342
|
+
.myio-gcdr-shell__build { display: inline-block; font-size: 12px; color: #55506A; border-radius: 9999px;
|
|
108343
|
+
background: var(--myio-gcdr-pill); padding: 4px 12px; -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
|
|
108344
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-shell__build { color: #E5E7EB; }
|
|
108345
|
+
.myio-gcdr-shell__slot:focus { outline: none; }
|
|
108346
|
+
.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; }
|
|
108347
|
+
|
|
108348
|
+
/* \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 */
|
|
108349
|
+
.myio-gcdr-panel {
|
|
108350
|
+
display: flex; flex-direction: column; overflow: hidden; width: 100%;
|
|
108351
|
+
border-radius: 16px; background: var(--myio-gcdr-card);
|
|
108352
|
+
box-shadow: 0 18px 50px rgba(40,20,90,0.30), 0 0 0 1px var(--myio-gcdr-ring);
|
|
108353
|
+
}
|
|
108354
|
+
.myio-gcdr-panel[data-fill="true"] { height: 100%; }
|
|
108355
|
+
.myio-gcdr-panel__band {
|
|
108356
|
+
position: relative; display: flex; flex-shrink: 0; align-items: center; justify-content: space-between; gap: 16px;
|
|
108357
|
+
height: 68px; padding: 0 32px; background: var(--myio-gcdr-band, var(--myio-gcdr-accent));
|
|
108358
|
+
}
|
|
108359
|
+
.myio-gcdr-panel__tint { position: absolute; inset: 0; background: var(--myio-gcdr-tint, transparent); pointer-events: none; }
|
|
108360
|
+
.myio-gcdr-panel__eyebrow { position: relative; font-size: 14px; font-weight: 800; text-transform: uppercase; letter-spacing: 0.14em; color: #FFFFFF; }
|
|
108361
|
+
.myio-gcdr-panel__logo { position: relative; height: 28px; width: auto; display: block; }
|
|
108362
|
+
.myio-gcdr-panel__wordmark { position: relative; color: #fff; font-weight: 900; font-size: 20px; letter-spacing: 0.04em; }
|
|
108363
|
+
.myio-gcdr-panel__body { padding: 28px 32px 32px; flex: 1 1 auto; overflow-y: auto; min-height: 0; }
|
|
108364
|
+
.myio-gcdr-panel__title { margin: 0 0 20px; font-size: 26px; font-weight: 800; line-height: 1.2; color: var(--myio-gcdr-title); }
|
|
108365
|
+
.myio-gcdr-panel__footer { padding: 16px 32px; text-align: center; font-size: 14px; color: var(--myio-gcdr-text);
|
|
108366
|
+
background: var(--myio-gcdr-footer); border-top: 1px solid var(--myio-gcdr-ring); }
|
|
108367
|
+
|
|
108368
|
+
/* \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 */
|
|
108369
|
+
.myio-gcdr-login__form { display: flex; flex-direction: column; gap: 20px; margin: 0; }
|
|
108370
|
+
.myio-gcdr-login__field { display: flex; flex-direction: column; gap: 6px; }
|
|
108371
|
+
.myio-gcdr-login__label { font-size: 14px; font-weight: 700; color: var(--myio-gcdr-title); }
|
|
108372
|
+
.myio-gcdr-login__control { position: relative; display: flex; }
|
|
108373
|
+
.myio-gcdr-login__input {
|
|
108374
|
+
width: 100%; font: inherit; font-size: 16px; color: var(--myio-gcdr-title);
|
|
108375
|
+
background: var(--myio-gcdr-input); border: 1px solid var(--myio-gcdr-input-border);
|
|
108376
|
+
border-radius: 12px; padding: 10px 14px; outline: none; transition: border-color .15s, box-shadow .15s;
|
|
108377
|
+
}
|
|
108378
|
+
.myio-gcdr-login__input::placeholder { color: #9CA3AF; }
|
|
108379
|
+
.myio-gcdr-login__input:focus { border-color: var(--myio-gcdr-accent); box-shadow: 0 0 0 3px rgba(107,74,191,0.30); }
|
|
108380
|
+
.myio-gcdr-login__input[aria-invalid="true"] { border-color: #FCA5A5; }
|
|
108381
|
+
.myio-gcdr-login__input[readonly] { opacity: .75; }
|
|
108382
|
+
.myio-gcdr-login__input--password { padding-right: 48px; }
|
|
108383
|
+
.myio-gcdr-login__eye {
|
|
108384
|
+
position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 40px; height: 40px;
|
|
108385
|
+
display: inline-flex; align-items: center; justify-content: center; border: 0; background: transparent;
|
|
108386
|
+
color: var(--myio-gcdr-text); border-radius: 8px; cursor: pointer;
|
|
108387
|
+
}
|
|
108388
|
+
.myio-gcdr-login__eye:focus-visible { outline: 2px solid var(--myio-gcdr-accent); }
|
|
108389
|
+
.myio-gcdr-login__fielderror { font-size: 13px; color: #DC2626; }
|
|
108390
|
+
.myio-gcdr-shell[data-theme="dark"] .myio-gcdr-login__fielderror { color: #FCA5A5; }
|
|
108391
|
+
.myio-gcdr-login__hint { font-size: 12px; color: #B45309; }
|
|
108392
|
+
.myio-gcdr-login__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
|
|
108393
|
+
.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; }
|
|
108394
|
+
.myio-gcdr-login__remember input { width: 16px; height: 16px; accent-color: var(--myio-gcdr-accent); }
|
|
108395
|
+
.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; }
|
|
108396
|
+
.myio-gcdr-login__link:hover { color: var(--myio-gcdr-accent-hover); text-decoration: underline; }
|
|
108397
|
+
.myio-gcdr-login__submit {
|
|
108398
|
+
display: inline-flex; align-items: center; justify-content: center; gap: 8px; width: 100%; min-height: 48px;
|
|
108399
|
+
border: 0; border-radius: 12px; padding: 12px 24px; font: inherit; font-size: 16px; font-weight: 700;
|
|
108400
|
+
color: #fff; background: var(--myio-gcdr-accent); cursor: pointer; transition: background .15s, opacity .15s;
|
|
108401
|
+
}
|
|
108402
|
+
.myio-gcdr-login__submit:hover { background: var(--myio-gcdr-accent-hover); }
|
|
108403
|
+
.myio-gcdr-login__submit[aria-disabled="true"], .myio-gcdr-login__submit:disabled { opacity: .55; cursor: not-allowed; }
|
|
108404
|
+
.myio-gcdr-login__submit:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108405
|
+
.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); }
|
|
108406
|
+
.myio-gcdr-login__spin { display: inline-flex; animation: myio-gcdr-spin 0.9s linear infinite; }
|
|
108407
|
+
@keyframes myio-gcdr-spin { to { transform: rotate(360deg); } }
|
|
108408
|
+
|
|
108409
|
+
/* \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 */
|
|
108410
|
+
.myio-gcdr-login__alerts { display: flex; flex-direction: column; gap: 12px; }
|
|
108411
|
+
.myio-gcdr-login__alerts:empty { display: none; }
|
|
108412
|
+
.myio-gcdr-login__alerts:not(:empty) { margin-bottom: 20px; }
|
|
108413
|
+
.myio-gcdr-login__field > .myio-gcdr-login__link { align-self: flex-start; }
|
|
108414
|
+
.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; }
|
|
108415
|
+
.myio-gcdr-banner:focus { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108416
|
+
.myio-gcdr-banner__icon { flex-shrink: 0; margin-top: 2px; }
|
|
108417
|
+
.myio-gcdr-banner__body { display: flex; flex-direction: column; gap: 6px; }
|
|
108418
|
+
.myio-gcdr-banner__title { font-weight: 800; }
|
|
108419
|
+
.myio-gcdr-banner--error { background: #FEF2F2; border-color: #FECACA; color: #991B1B; }
|
|
108420
|
+
.myio-gcdr-banner--warning { background: #FFFBEB; border-color: #FDE68A; color: #92400E; }
|
|
108421
|
+
.myio-gcdr-banner--info { background: #F5F3FF; border-color: #DDD6FE; color: #4C1D95; }
|
|
108422
|
+
.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; }
|
|
108423
|
+
.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; }
|
|
108424
|
+
.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; }
|
|
108425
|
+
.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; }
|
|
108426
|
+
|
|
108427
|
+
/* \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 */
|
|
108428
|
+
.myio-gcdr-about__intro { color: var(--myio-gcdr-text); font-size: 14px; margin: 0 0 16px; }
|
|
108429
|
+
.myio-gcdr-about__title { font-size: 24px; font-weight: 800; margin: 0 0 6px; color: var(--myio-gcdr-title); }
|
|
108430
|
+
.myio-gcdr-about__title em { font-style: normal; color: var(--myio-gcdr-aside-band); }
|
|
108431
|
+
.myio-gcdr-about__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
|
|
108432
|
+
.myio-gcdr-about__tile {
|
|
108433
|
+
display: flex; flex-direction: column; gap: 6px; text-align: left; padding: 14px; border-radius: 12px; min-height: 110px;
|
|
108434
|
+
border: 1px solid var(--myio-gcdr-ring); background: var(--myio-gcdr-input); color: var(--myio-gcdr-title);
|
|
108435
|
+
font: inherit; cursor: pointer; text-decoration: none; transition: transform .15s, box-shadow .15s;
|
|
108436
|
+
}
|
|
108437
|
+
.myio-gcdr-about__tile:hover { transform: translateY(-1px); box-shadow: 0 6px 16px rgba(40,20,90,0.12); }
|
|
108438
|
+
.myio-gcdr-about__tile:focus-visible { outline: 2px solid var(--myio-gcdr-accent); outline-offset: 2px; }
|
|
108439
|
+
.myio-gcdr-about__tile[aria-disabled="true"] { opacity: .6; cursor: default; }
|
|
108440
|
+
.myio-gcdr-about__tileicon { color: var(--myio-gcdr-aside-band); }
|
|
108441
|
+
.myio-gcdr-about__tiletitle { font-weight: 800; font-size: 15px; }
|
|
108442
|
+
.myio-gcdr-about__tiletext { font-size: 13px; color: var(--myio-gcdr-text); }
|
|
108443
|
+
.myio-gcdr-about__back { margin-bottom: 12px; }
|
|
108444
|
+
.myio-gcdr-about__tagline { margin-top: 16px; font-size: 13px; font-weight: 700; color: var(--myio-gcdr-text); text-align: center; }
|
|
108445
|
+
.myio-gcdr-about__health { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; }
|
|
108446
|
+
.myio-gcdr-about__dot { width: 8px; height: 8px; border-radius: 50%; background: #9CA3AF; }
|
|
108447
|
+
.myio-gcdr-about__dot[data-state="online"] { background: #16A34A; }
|
|
108448
|
+
.myio-gcdr-about__dot[data-state="offline"] { background: #DC2626; }
|
|
108449
|
+
.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%; }
|
|
108450
|
+
.myio-gcdr-prompt__icon { display: inline-flex; width: 56px; height: 56px; align-items: center; justify-content: center; border-radius: 50%; background: #6B4ABF; color: #fff; }
|
|
108451
|
+
.myio-gcdr-prompt__text { margin: 0; font-size: 22px; font-weight: 800; line-height: 1.35; color: var(--myio-gcdr-title); }
|
|
108452
|
+
|
|
108453
|
+
/* \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 */
|
|
108454
|
+
.myio-gcdr-overlay { position: fixed; inset: 0; overflow-y: auto; display: flex; }
|
|
108455
|
+
.myio-gcdr-overlay[data-scope="element"] { position: absolute; }
|
|
108456
|
+
.myio-gcdr-overlay__layer { position: fixed; inset: 0; pointer-events: none; }
|
|
108457
|
+
.myio-gcdr-overlay[data-scope="element"] .myio-gcdr-overlay__layer { position: absolute; }
|
|
108458
|
+
.myio-gcdr-overlay__content { position: relative; width: 100%; min-height: 100%; display: flex; }
|
|
108459
|
+
.myio-gcdr-overlay__content > .myio-gcdr-shell { min-height: 100%; background: transparent; }
|
|
108460
|
+
.myio-gcdr-overlay__close { position: absolute; top: 12px; right: 12px; z-index: 2; }
|
|
108461
|
+
@media (prefers-reduced-motion: reduce) {
|
|
108462
|
+
.myio-gcdr-shell *, .myio-gcdr-overlay * { transition: none !important; animation: none !important; }
|
|
108463
|
+
}
|
|
108464
|
+
`;
|
|
108465
|
+
function rootTarget(container) {
|
|
108466
|
+
const root = container.getRootNode ? container.getRootNode() : document;
|
|
108467
|
+
const doc = container.ownerDocument || document;
|
|
108468
|
+
if (typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot) return { head: root, doc };
|
|
108469
|
+
return { head: doc.head || doc.documentElement, doc };
|
|
108470
|
+
}
|
|
108471
|
+
function acquireStyles(container, opts = {}) {
|
|
108472
|
+
const { head, doc } = rootTarget(container);
|
|
108473
|
+
if (opts.loadFont !== false && !doc.getElementById(FONT_ID)) {
|
|
108474
|
+
const link = doc.createElement("link");
|
|
108475
|
+
link.id = FONT_ID;
|
|
108476
|
+
link.rel = "stylesheet";
|
|
108477
|
+
link.href = "https://fonts.googleapis.com/css2?family=Nunito:wght@400;500;600;700;800;900&display=swap";
|
|
108478
|
+
doc.head?.appendChild(link);
|
|
108479
|
+
}
|
|
108480
|
+
let style = head.querySelector(`style[${STYLE_ATTR}="${STYLE_VERSION}"]`);
|
|
108481
|
+
if (!style) {
|
|
108482
|
+
style = doc.createElement("style");
|
|
108483
|
+
style.setAttribute(STYLE_ATTR, STYLE_VERSION);
|
|
108484
|
+
style.setAttribute(REFS_ATTR, "0");
|
|
108485
|
+
if (opts.nonce) style.setAttribute("nonce", opts.nonce);
|
|
108486
|
+
style.textContent = CSS3;
|
|
108487
|
+
head.appendChild(style);
|
|
108488
|
+
}
|
|
108489
|
+
const el2 = style;
|
|
108490
|
+
el2.setAttribute(REFS_ATTR, String((parseInt(el2.getAttribute(REFS_ATTR) || "0", 10) || 0) + 1));
|
|
108491
|
+
let released = false;
|
|
108492
|
+
return () => {
|
|
108493
|
+
if (released) return;
|
|
108494
|
+
released = true;
|
|
108495
|
+
const n = (parseInt(el2.getAttribute(REFS_ATTR) || "1", 10) || 1) - 1;
|
|
108496
|
+
if (n <= 0) el2.remove();
|
|
108497
|
+
else el2.setAttribute(REFS_ATTR, String(n));
|
|
108498
|
+
};
|
|
108499
|
+
}
|
|
108500
|
+
|
|
108501
|
+
// src/components/myio-gcdr-login/shell.ts
|
|
108502
|
+
var SLOT_NAMES = ["top", "topRight", "aside", "main", "below"];
|
|
108503
|
+
function buildPanel(doc, el2, opts, locale, defaultLogoUrl) {
|
|
108504
|
+
const root = h2(doc, "section", { class: "myio-gcdr-panel", "data-fill": opts.fill ? "true" : null });
|
|
108505
|
+
if (opts.accent) root.style.setProperty("--myio-gcdr-accent", opts.accent);
|
|
108506
|
+
if (opts.bandColor) root.style.setProperty("--myio-gcdr-band", opts.bandColor);
|
|
108507
|
+
if (opts.tint) root.style.setProperty("--myio-gcdr-tint", opts.tint);
|
|
108508
|
+
const band = h2(doc, "header", { class: "myio-gcdr-panel__band" });
|
|
108509
|
+
if (opts.tint) band.appendChild(h2(doc, "span", { class: "myio-gcdr-panel__tint", "aria-hidden": "true" }));
|
|
108510
|
+
band.appendChild(h2(doc, "span", { class: "myio-gcdr-panel__eyebrow", text: localize(opts.eyebrow, locale) }));
|
|
108511
|
+
if (opts.logo !== false) {
|
|
108512
|
+
const url = opts.logoUrl ?? defaultLogoUrl;
|
|
108513
|
+
const wordmark = () => h2(doc, "span", { class: "myio-gcdr-panel__wordmark", text: "MYIO" });
|
|
108514
|
+
if (url) {
|
|
108515
|
+
const img = h2(doc, "img", { class: "myio-gcdr-panel__logo", src: url, alt: "MYIO" });
|
|
108516
|
+
img.addEventListener("error", () => img.replaceWith(wordmark()), { once: true });
|
|
108517
|
+
band.appendChild(img);
|
|
108518
|
+
} else band.appendChild(wordmark());
|
|
108519
|
+
}
|
|
108520
|
+
root.appendChild(band);
|
|
108521
|
+
const body = h2(doc, "div", { class: "myio-gcdr-panel__body" });
|
|
108522
|
+
let title;
|
|
108523
|
+
if (opts.title) {
|
|
108524
|
+
title = h2(doc, "h1", { class: "myio-gcdr-panel__title", text: localize(opts.title, locale), tabindex: "-1" });
|
|
108525
|
+
body.appendChild(title);
|
|
108526
|
+
}
|
|
108527
|
+
root.appendChild(body);
|
|
108528
|
+
let footer;
|
|
108529
|
+
if (opts.footer) {
|
|
108530
|
+
footer = h2(doc, "footer", { class: "myio-gcdr-panel__footer" });
|
|
108531
|
+
root.appendChild(footer);
|
|
108532
|
+
}
|
|
108533
|
+
el2.appendChild(root);
|
|
108534
|
+
return { root, body, footer, title };
|
|
108535
|
+
}
|
|
108536
|
+
function createShellImpl(container, options = {}, internals = {}) {
|
|
108537
|
+
if (!(container instanceof HTMLElement)) throw new TypeError("[MYIO Login] container must be an HTMLElement");
|
|
108538
|
+
const doc = container.ownerDocument;
|
|
108539
|
+
const prefix = options.storageKeyPrefix ?? "myio.login.";
|
|
108540
|
+
const releaseStyles = acquireStyles(container, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
|
|
108541
|
+
let themeSetting = options.theme ?? (storageGet(`${prefix}theme`) || "system");
|
|
108542
|
+
let locale = options.locale ?? detectLocale(storageGet(`${prefix}locale`));
|
|
108543
|
+
let size = options.size ?? "md";
|
|
108544
|
+
let width = options.width ?? "auto";
|
|
108545
|
+
const show = { themeToggle: options.show?.themeToggle !== false, languageSelector: options.show?.languageSelector !== false };
|
|
108546
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
108547
|
+
let destroyed = false;
|
|
108548
|
+
const resolvedTheme = () => themeSetting === "system" ? prefersDark() ? "dark" : "light" : themeSetting;
|
|
108549
|
+
const t = (key, vars) => translate(locale, key, vars, internals.messages);
|
|
108550
|
+
container.textContent = "";
|
|
108551
|
+
const root = h2(doc, "div", {
|
|
108552
|
+
class: "myio-gcdr-shell",
|
|
108553
|
+
"data-theme": resolvedTheme(),
|
|
108554
|
+
"data-size": size,
|
|
108555
|
+
"data-width": width,
|
|
108556
|
+
"data-aside-compact": options.asideCompact ?? "hide",
|
|
108557
|
+
"data-has-aside": "false",
|
|
108558
|
+
lang: locale
|
|
108559
|
+
});
|
|
108560
|
+
const wallpaper = h2(doc, "div", { class: "myio-gcdr-shell__wallpaper", "aria-hidden": "true" });
|
|
108561
|
+
const live = h2(doc, "div", { class: "myio-gcdr-sr", "aria-live": "polite", role: "status" });
|
|
108562
|
+
const top = h2(doc, "div", { class: "myio-gcdr-shell__top myio-gcdr-shell__slot", hidden: true });
|
|
108563
|
+
const block = h2(doc, "div", { class: "myio-gcdr-shell__block" });
|
|
108564
|
+
const toprow = h2(doc, "div", { class: "myio-gcdr-shell__toprow" });
|
|
108565
|
+
const pill = h2(doc, "div", { class: "myio-gcdr-shell__pill" });
|
|
108566
|
+
const langBtn = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn" });
|
|
108567
|
+
const themeBtn = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn" });
|
|
108568
|
+
const topRight = h2(doc, "div", { class: "myio-gcdr-shell__slot", style: "display:contents" });
|
|
108569
|
+
pill.append(langBtn, themeBtn, topRight);
|
|
108570
|
+
toprow.appendChild(pill);
|
|
108571
|
+
const split = h2(doc, "div", { class: "myio-gcdr-shell__split" });
|
|
108572
|
+
const aside = h2(doc, "section", { class: "myio-gcdr-shell__aside myio-gcdr-shell__slot", hidden: true, tabindex: "-1" });
|
|
108573
|
+
const main = h2(doc, "section", { class: "myio-gcdr-shell__main myio-gcdr-shell__slot", tabindex: "-1" });
|
|
108574
|
+
split.append(aside, main);
|
|
108575
|
+
const below = h2(doc, "div", { class: "myio-gcdr-shell__below myio-gcdr-shell__slot", hidden: true });
|
|
108576
|
+
block.append(toprow, split, below);
|
|
108577
|
+
root.append(wallpaper, live, top, block);
|
|
108578
|
+
container.appendChild(root);
|
|
108579
|
+
const applyWallpaper = () => {
|
|
108580
|
+
const wp = options.wallpaper;
|
|
108581
|
+
if (wp === false) {
|
|
108582
|
+
wallpaper.hidden = true;
|
|
108583
|
+
return;
|
|
108584
|
+
}
|
|
108585
|
+
wallpaper.hidden = false;
|
|
108586
|
+
const dark = resolvedTheme() === "dark";
|
|
108587
|
+
let portrait = false;
|
|
108588
|
+
try {
|
|
108589
|
+
portrait = typeof matchMedia === "function" && matchMedia("(orientation: portrait)").matches;
|
|
108590
|
+
} catch {
|
|
108591
|
+
}
|
|
108592
|
+
const url = wp ? dark ? portrait ? wp.mobileDark ?? wp.dark : wp.dark : portrait ? wp.mobileLight ?? wp.light : wp.light : void 0;
|
|
108593
|
+
if (url) wallpaper.style.setProperty("--myio-gcdr-wp", `url("${url.replace(/"/g, "%22")}")`);
|
|
108594
|
+
else wallpaper.style.removeProperty("--myio-gcdr-wp");
|
|
108595
|
+
};
|
|
108596
|
+
const renderControls = () => {
|
|
108597
|
+
langBtn.hidden = !show.languageSelector;
|
|
108598
|
+
themeBtn.hidden = !show.themeToggle;
|
|
108599
|
+
langBtn.textContent = "";
|
|
108600
|
+
langBtn.append(icon(doc, ICONS.globe(16)), h2(doc, "span", { text: locale === "en" ? "EN" : "PT" }));
|
|
108601
|
+
langBtn.setAttribute("aria-label", `${t("toolbar.language")}: ${locale === "en" ? "English" : "Portugu\xEAs"}`);
|
|
108602
|
+
const dark = resolvedTheme() === "dark";
|
|
108603
|
+
themeBtn.textContent = "";
|
|
108604
|
+
themeBtn.append(icon(doc, dark ? ICONS.sun(16) : ICONS.moon(16)));
|
|
108605
|
+
const lbl = dark ? t("toolbar.toLight") : t("toolbar.toDark");
|
|
108606
|
+
themeBtn.setAttribute("aria-label", lbl);
|
|
108607
|
+
themeBtn.setAttribute("title", lbl);
|
|
108608
|
+
};
|
|
108609
|
+
const emit = (what) => {
|
|
108610
|
+
for (const fn of Array.from(listeners)) safeCall("listener", fn, what);
|
|
108611
|
+
};
|
|
108612
|
+
const applyTheme = () => {
|
|
108613
|
+
root.setAttribute("data-theme", resolvedTheme());
|
|
108614
|
+
applyWallpaper();
|
|
108615
|
+
renderControls();
|
|
108616
|
+
emit("theme");
|
|
108617
|
+
};
|
|
108618
|
+
const applyLocale = () => {
|
|
108619
|
+
root.setAttribute("lang", locale);
|
|
108620
|
+
renderControls();
|
|
108621
|
+
emit("locale");
|
|
108622
|
+
};
|
|
108623
|
+
langBtn.addEventListener("click", () => {
|
|
108624
|
+
locale = locale === "en" ? "pt-BR" : "en";
|
|
108625
|
+
storageSet(`${prefix}locale`, locale);
|
|
108626
|
+
applyLocale();
|
|
108627
|
+
safeCall("onLocaleChange", options.onLocaleChange, locale);
|
|
108628
|
+
});
|
|
108629
|
+
themeBtn.addEventListener("click", () => {
|
|
108630
|
+
themeSetting = resolvedTheme() === "dark" ? "light" : "dark";
|
|
108631
|
+
storageSet(`${prefix}theme`, themeSetting);
|
|
108632
|
+
applyTheme();
|
|
108633
|
+
safeCall("onThemeChange", options.onThemeChange, themeSetting);
|
|
108634
|
+
});
|
|
108635
|
+
let mql = null;
|
|
108636
|
+
const onScheme = () => {
|
|
108637
|
+
if (themeSetting === "system") applyTheme();
|
|
108638
|
+
};
|
|
108639
|
+
try {
|
|
108640
|
+
if (typeof matchMedia === "function") {
|
|
108641
|
+
mql = matchMedia("(prefers-color-scheme: dark)");
|
|
108642
|
+
mql.addEventListener?.("change", onScheme);
|
|
108643
|
+
}
|
|
108644
|
+
} catch {
|
|
108645
|
+
mql = null;
|
|
108646
|
+
}
|
|
108647
|
+
const contextFor = (el2, signal) => ({
|
|
108648
|
+
get theme() {
|
|
108649
|
+
return resolvedTheme();
|
|
108650
|
+
},
|
|
108651
|
+
get locale() {
|
|
108652
|
+
return locale;
|
|
108653
|
+
},
|
|
108654
|
+
signal,
|
|
108655
|
+
on(event, fn) {
|
|
108656
|
+
const l = (w) => {
|
|
108657
|
+
if (w === event) fn(event === "theme" ? resolvedTheme() : locale);
|
|
108658
|
+
};
|
|
108659
|
+
listeners.add(l);
|
|
108660
|
+
const off = () => listeners.delete(l);
|
|
108661
|
+
signal.addEventListener("abort", off, { once: true });
|
|
108662
|
+
return off;
|
|
108663
|
+
},
|
|
108664
|
+
panel: (opts) => buildPanel(doc, el2, opts, locale, internals.logoUrl)
|
|
108665
|
+
});
|
|
108666
|
+
const slots = {};
|
|
108667
|
+
const slotEls = { top, topRight, aside, main, below };
|
|
108668
|
+
for (const n of SLOT_NAMES) slots[n] = { el: slotEls[n], kind: "empty", busy: false };
|
|
108669
|
+
const updateLayoutFlags = () => {
|
|
108670
|
+
root.setAttribute("data-has-aside", slots.aside.kind === "empty" ? "false" : "true");
|
|
108671
|
+
aside.hidden = slots.aside.kind === "empty";
|
|
108672
|
+
below.hidden = slots.below.kind === "empty";
|
|
108673
|
+
top.hidden = slots.top.kind === "empty";
|
|
108674
|
+
};
|
|
108675
|
+
const renderBuiltIn = (name, el2, ctx, b) => {
|
|
108676
|
+
if (b.kind === "buildInfo") {
|
|
108677
|
+
if (name !== "below") throw new TypeError("[MYIO Login] buildInfo is only valid in the below slot");
|
|
108678
|
+
el2.appendChild(h2(doc, "p", { class: "myio-gcdr-shell__build", text: b.text }));
|
|
108679
|
+
return;
|
|
108680
|
+
}
|
|
108681
|
+
if (name !== "aside") throw new TypeError(`[MYIO Login] ${b.kind} is only valid in the aside slot`);
|
|
108682
|
+
if (b.kind === "about") {
|
|
108683
|
+
const cleanupAbout = renderAbout(el2, ctx, t, { ...internals.about, healthUrl: b.healthUrl ?? false });
|
|
108684
|
+
const off2 = ctx.on("locale", () => {
|
|
108685
|
+
cleanupAbout();
|
|
108686
|
+
el2.textContent = "";
|
|
108687
|
+
renderAbout(el2, ctx, t, { ...internals.about, healthUrl: b.healthUrl ?? false });
|
|
108688
|
+
});
|
|
108689
|
+
return () => {
|
|
108690
|
+
off2();
|
|
108691
|
+
cleanupAbout();
|
|
108692
|
+
};
|
|
108693
|
+
}
|
|
108694
|
+
const text2 = () => b.text ? localize(b.text, locale) : t("aside.signedOutPrompt");
|
|
108695
|
+
renderSignedOutPrompt(el2, ctx, text2());
|
|
108696
|
+
const off = ctx.on("locale", () => {
|
|
108697
|
+
el2.textContent = "";
|
|
108698
|
+
renderSignedOutPrompt(el2, ctx, text2());
|
|
108699
|
+
});
|
|
108700
|
+
return off;
|
|
108701
|
+
};
|
|
108702
|
+
const setSlot = (name, content, opts) => {
|
|
108703
|
+
if (destroyed) return;
|
|
108704
|
+
if (!SLOT_NAMES.includes(name)) throw new TypeError(`[MYIO Login] unknown slot "${String(name)}"`);
|
|
108705
|
+
const s = slots[name];
|
|
108706
|
+
if (s.busy) {
|
|
108707
|
+
s.pending = { content, opts };
|
|
108708
|
+
queueMicrotask(() => {
|
|
108709
|
+
const p = s.pending;
|
|
108710
|
+
s.pending = void 0;
|
|
108711
|
+
if (p) setSlot(name, p.content, p.opts);
|
|
108712
|
+
});
|
|
108713
|
+
return;
|
|
108714
|
+
}
|
|
108715
|
+
const hadFocus = !!doc.activeElement && s.el.contains(doc.activeElement);
|
|
108716
|
+
s.busy = true;
|
|
108717
|
+
try {
|
|
108718
|
+
s.abort?.abort();
|
|
108719
|
+
if (s.cleanup) safeCall("slot cleanup", s.cleanup);
|
|
108720
|
+
s.cleanup = void 0;
|
|
108721
|
+
s.el.textContent = "";
|
|
108722
|
+
s.kind = "empty";
|
|
108723
|
+
if (content) {
|
|
108724
|
+
const ac = new AbortController();
|
|
108725
|
+
s.abort = ac;
|
|
108726
|
+
const ctx = contextFor(s.el, ac.signal);
|
|
108727
|
+
try {
|
|
108728
|
+
const r = typeof content === "function" ? content(s.el, ctx) : renderBuiltIn(name, s.el, ctx, content);
|
|
108729
|
+
if (typeof r === "function") s.cleanup = r;
|
|
108730
|
+
s.kind = typeof content === "function" ? "host" : "builtIn";
|
|
108731
|
+
} catch (err) {
|
|
108732
|
+
if (err instanceof TypeError && String(err.message).startsWith("[MYIO Login]")) throw err;
|
|
108733
|
+
console.error(`[MYIO Login] slot "${name}" renderer failed`);
|
|
108734
|
+
s.el.textContent = "";
|
|
108735
|
+
s.kind = "empty";
|
|
108736
|
+
}
|
|
108737
|
+
}
|
|
108738
|
+
} finally {
|
|
108739
|
+
s.busy = false;
|
|
108740
|
+
updateLayoutFlags();
|
|
108741
|
+
}
|
|
108742
|
+
const focus = opts?.focus ?? "auto";
|
|
108743
|
+
if (focus instanceof HTMLElement) focus.focus();
|
|
108744
|
+
else if (focus === "auto" && hadFocus && s.el.isConnected) {
|
|
108745
|
+
if (!s.el.hasAttribute("tabindex")) s.el.setAttribute("tabindex", "-1");
|
|
108746
|
+
s.el.focus();
|
|
108747
|
+
}
|
|
108748
|
+
if (opts?.announce) announce(localize(opts.announce, locale));
|
|
108749
|
+
};
|
|
108750
|
+
const announce = (text2) => {
|
|
108751
|
+
live.textContent = "";
|
|
108752
|
+
setTimeout(() => {
|
|
108753
|
+
if (!destroyed) live.textContent = text2;
|
|
108754
|
+
}, 30);
|
|
108755
|
+
};
|
|
108756
|
+
applyWallpaper();
|
|
108757
|
+
renderControls();
|
|
108758
|
+
if (options.buildInfo) setSlot("below", { kind: "buildInfo", text: options.buildInfo });
|
|
108759
|
+
const handle = {
|
|
108760
|
+
setSlot,
|
|
108761
|
+
setTheme(th) {
|
|
108762
|
+
if (destroyed) return;
|
|
108763
|
+
themeSetting = th;
|
|
108764
|
+
applyTheme();
|
|
108765
|
+
},
|
|
108766
|
+
setLocale(l) {
|
|
108767
|
+
if (destroyed || l !== "pt-BR" && l !== "en") return;
|
|
108768
|
+
locale = l;
|
|
108769
|
+
applyLocale();
|
|
108770
|
+
},
|
|
108771
|
+
setSize(sz, w) {
|
|
108772
|
+
if (destroyed) return;
|
|
108773
|
+
size = sz;
|
|
108774
|
+
if (w) width = w;
|
|
108775
|
+
root.setAttribute("data-size", size);
|
|
108776
|
+
root.setAttribute("data-width", width);
|
|
108777
|
+
},
|
|
108778
|
+
setShow(sh) {
|
|
108779
|
+
if (destroyed) return;
|
|
108780
|
+
if (sh.themeToggle !== void 0) show.themeToggle = sh.themeToggle;
|
|
108781
|
+
if (sh.languageSelector !== void 0) show.languageSelector = sh.languageSelector;
|
|
108782
|
+
renderControls();
|
|
108783
|
+
},
|
|
108784
|
+
getState() {
|
|
108785
|
+
const st = {};
|
|
108786
|
+
for (const n of SLOT_NAMES) st[n] = slots[n].kind;
|
|
108787
|
+
return { theme: resolvedTheme(), locale, size, width, slots: st };
|
|
108788
|
+
},
|
|
108789
|
+
get element() {
|
|
108790
|
+
return root;
|
|
108791
|
+
},
|
|
108792
|
+
destroy() {
|
|
108793
|
+
if (destroyed) return;
|
|
108794
|
+
for (const n of SLOT_NAMES) {
|
|
108795
|
+
const s = slots[n];
|
|
108796
|
+
s.abort?.abort();
|
|
108797
|
+
if (s.cleanup) safeCall("slot cleanup", s.cleanup);
|
|
108798
|
+
s.cleanup = void 0;
|
|
108799
|
+
}
|
|
108800
|
+
destroyed = true;
|
|
108801
|
+
listeners.clear();
|
|
108802
|
+
mql?.removeEventListener?.("change", onScheme);
|
|
108803
|
+
root.remove();
|
|
108804
|
+
releaseStyles();
|
|
108805
|
+
},
|
|
108806
|
+
t,
|
|
108807
|
+
contextFor,
|
|
108808
|
+
onChange(fn) {
|
|
108809
|
+
listeners.add(fn);
|
|
108810
|
+
return () => listeners.delete(fn);
|
|
108811
|
+
},
|
|
108812
|
+
announce
|
|
108813
|
+
};
|
|
108814
|
+
return handle;
|
|
108815
|
+
}
|
|
108816
|
+
function createMyioGcdrShell(container, options = {}) {
|
|
108817
|
+
const impl = createShellImpl(container, options);
|
|
108818
|
+
return {
|
|
108819
|
+
setSlot: impl.setSlot,
|
|
108820
|
+
setTheme: impl.setTheme,
|
|
108821
|
+
setLocale: impl.setLocale,
|
|
108822
|
+
setSize: impl.setSize,
|
|
108823
|
+
setShow: impl.setShow,
|
|
108824
|
+
getState: impl.getState,
|
|
108825
|
+
get element() {
|
|
108826
|
+
return impl.element;
|
|
108827
|
+
},
|
|
108828
|
+
destroy: impl.destroy
|
|
108829
|
+
};
|
|
108830
|
+
}
|
|
108831
|
+
|
|
108832
|
+
// src/components/myio-gcdr-login/controller.ts
|
|
108833
|
+
var EMAIL_PATTERN = /^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
108834
|
+
function validate(emailRaw, password) {
|
|
108835
|
+
const email = emailRaw.trim();
|
|
108836
|
+
let emailError;
|
|
108837
|
+
if (!email) emailError = "login.emailRequired";
|
|
108838
|
+
else if (!EMAIL_PATTERN.test(email)) emailError = "login.emailInvalid";
|
|
108839
|
+
const passwordError = password.length === 0 ? "login.passwordRequired" : void 0;
|
|
108840
|
+
return { email, emailError, passwordError };
|
|
108841
|
+
}
|
|
108842
|
+
function emailKey(email) {
|
|
108843
|
+
return email.trim().toLowerCase();
|
|
108844
|
+
}
|
|
108845
|
+
var KNOWN = /* @__PURE__ */ new Set([
|
|
108846
|
+
"INVALID_CREDENTIALS",
|
|
108847
|
+
"ACCOUNT_LOCKED",
|
|
108848
|
+
"CAPTCHA_FAILED",
|
|
108849
|
+
"TOO_MANY_REQUESTS",
|
|
108850
|
+
"MFA_REQUIRED",
|
|
108851
|
+
"NETWORK",
|
|
108852
|
+
"TIMEOUT",
|
|
108853
|
+
"SERVER",
|
|
108854
|
+
"INTEGRATION_ERROR",
|
|
108855
|
+
"CUSTOM"
|
|
108856
|
+
]);
|
|
108857
|
+
var ALIASES = {
|
|
108858
|
+
UNAUTHORIZED: "INVALID_CREDENTIALS",
|
|
108859
|
+
HTTP_401: "INVALID_CREDENTIALS",
|
|
108860
|
+
ACCOUNT_PENDING: "INVALID_CREDENTIALS",
|
|
108861
|
+
PENDING_APPROVAL: "INVALID_CREDENTIALS",
|
|
108862
|
+
ACCOUNT_SUSPENDED: "INVALID_CREDENTIALS",
|
|
108863
|
+
ACCOUNT_INACTIVE: "INVALID_CREDENTIALS",
|
|
108864
|
+
EMAIL_NOT_VERIFIED: "INVALID_CREDENTIALS",
|
|
108865
|
+
RATE_LIMITED: "TOO_MANY_REQUESTS",
|
|
108866
|
+
NETWORK_ERROR: "NETWORK"
|
|
108867
|
+
};
|
|
108868
|
+
function normaliseCode(code) {
|
|
108869
|
+
if (typeof code !== "string") return "SERVER";
|
|
108870
|
+
if (KNOWN.has(code)) return code;
|
|
108871
|
+
return ALIASES[code] ?? "SERVER";
|
|
108872
|
+
}
|
|
108873
|
+
function usableCounter(n) {
|
|
108874
|
+
return typeof n === "number" && Number.isInteger(n) && n >= 1 ? n : void 0;
|
|
108875
|
+
}
|
|
108876
|
+
function normaliseResult(raw) {
|
|
108877
|
+
if (!raw || typeof raw !== "object" || typeof raw.ok !== "boolean") {
|
|
108878
|
+
return { kind: "error", code: "INTEGRATION_ERROR" };
|
|
108879
|
+
}
|
|
108880
|
+
const r = raw;
|
|
108881
|
+
if (r.ok) return { kind: "ok", session: r.session };
|
|
108882
|
+
const code = normaliseCode(r.code);
|
|
108883
|
+
return {
|
|
108884
|
+
kind: "error",
|
|
108885
|
+
code,
|
|
108886
|
+
remainingAttempts: code === "INVALID_CREDENTIALS" ? usableCounter(r.remainingAttempts) : void 0,
|
|
108887
|
+
message: code === "CUSTOM" && typeof r.message === "string" ? r.message : void 0,
|
|
108888
|
+
clearPassword: code === "CUSTOM" ? r.clearPassword !== false : void 0
|
|
108889
|
+
};
|
|
108890
|
+
}
|
|
108891
|
+
function normaliseThrown(err) {
|
|
108892
|
+
if (err && typeof err === "object" && err.myioGcdrCode === "TIMEOUT") return "TIMEOUT";
|
|
108893
|
+
return err instanceof TypeError ? "NETWORK" : "SERVER";
|
|
108894
|
+
}
|
|
108895
|
+
var ATTEMPTS_THRESHOLD = 3;
|
|
108896
|
+
function present(o) {
|
|
108897
|
+
switch (o.code) {
|
|
108898
|
+
case "INVALID_CREDENTIALS": {
|
|
108899
|
+
const n = o.remainingAttempts;
|
|
108900
|
+
if (n === void 0)
|
|
108901
|
+
return { tone: "error", keys: ["errors.invalidCredentials"], icon: "alert", clearPassword: true, focus: "password" };
|
|
108902
|
+
if (n > ATTEMPTS_THRESHOLD)
|
|
108903
|
+
return { tone: "error", keys: ["errors.invalidWithAttempts"], count: n, icon: "alert", clearPassword: true, focus: "password" };
|
|
108904
|
+
if (n === 1)
|
|
108905
|
+
return { tone: "warning", keys: ["errors.lastAttempt", "errors.lockWarning"], icon: "shieldAlert", forgotLink: true, clearPassword: true, focus: "password" };
|
|
108906
|
+
return { tone: "warning", keys: ["errors.attemptsLeft", "errors.lockWarning"], count: n, icon: "shieldAlert", forgotLink: true, clearPassword: true, focus: "password" };
|
|
108907
|
+
}
|
|
108908
|
+
case "ACCOUNT_LOCKED":
|
|
108909
|
+
return { tone: "error", keys: ["errors.lockedText"], title: "errors.lockedTitle", icon: "lock", support: true, clearPassword: true, focus: "banner" };
|
|
108910
|
+
case "MFA_REQUIRED":
|
|
108911
|
+
return { tone: "error", keys: ["errors.mfaUnsupported"], icon: "shieldAlert", gcdrWebLink: true, support: true, clearPassword: true, focus: "banner" };
|
|
108912
|
+
case "CAPTCHA_FAILED":
|
|
108913
|
+
return { tone: "error", keys: ["errors.captchaFailed"], icon: "alert", clearPassword: false, focus: "captcha" };
|
|
108914
|
+
case "TOO_MANY_REQUESTS":
|
|
108915
|
+
return { tone: "error", keys: ["errors.tooManyRequests"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108916
|
+
case "NETWORK":
|
|
108917
|
+
return { tone: "error", keys: ["errors.networkError"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108918
|
+
case "TIMEOUT":
|
|
108919
|
+
return { tone: "error", keys: ["errors.timeout"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108920
|
+
case "INTEGRATION_ERROR":
|
|
108921
|
+
return { tone: "error", keys: ["errors.integrationError"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108922
|
+
case "CUSTOM": {
|
|
108923
|
+
const clear = o.clearPassword !== false;
|
|
108924
|
+
return {
|
|
108925
|
+
tone: "error",
|
|
108926
|
+
keys: o.message ? [] : ["errors.loginFailed"],
|
|
108927
|
+
text: o.message,
|
|
108928
|
+
icon: "alert",
|
|
108929
|
+
clearPassword: clear,
|
|
108930
|
+
focus: clear ? "password" : "submit"
|
|
108931
|
+
};
|
|
108932
|
+
}
|
|
108933
|
+
case "SERVER":
|
|
108934
|
+
default:
|
|
108935
|
+
return { tone: "error", keys: ["errors.loginFailed"], icon: "alert", clearPassword: false, focus: "submit" };
|
|
108936
|
+
}
|
|
108937
|
+
}
|
|
108938
|
+
|
|
108939
|
+
// src/components/myio-gcdr-login/gcdrClient.ts
|
|
108940
|
+
var DEFAULT_TIMEOUT_MS = 15e3;
|
|
108941
|
+
function timeoutError() {
|
|
108942
|
+
const e = new Error("GCDR login timed out");
|
|
108943
|
+
e.myioGcdrCode = "TIMEOUT";
|
|
108944
|
+
return e;
|
|
108945
|
+
}
|
|
108946
|
+
function createMyioGcdrLoginSubmit(options) {
|
|
108947
|
+
if (!options || typeof options.apiUrl !== "string" || !options.apiUrl.trim()) {
|
|
108948
|
+
throw new TypeError("[MYIO Login] gcdr.apiUrl must be a non-empty string");
|
|
108949
|
+
}
|
|
108950
|
+
if (typeof options.tenantId !== "string" || !options.tenantId.trim()) {
|
|
108951
|
+
throw new TypeError("[MYIO Login] gcdr.tenantId must be a non-empty string");
|
|
108952
|
+
}
|
|
108953
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
108954
|
+
if (!(typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0)) {
|
|
108955
|
+
throw new TypeError("[MYIO Login] gcdr.timeoutMs must be a positive number");
|
|
108956
|
+
}
|
|
108957
|
+
const base = options.apiUrl.replace(/\/+$/, "").replace(/\/api\/v\d+$/, "");
|
|
108958
|
+
const url = `${base}/api/v1/auth/login`;
|
|
108959
|
+
return async (input, ctx) => {
|
|
108960
|
+
const doFetch = options.fetch ?? (typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0);
|
|
108961
|
+
if (!doFetch) throw new TypeError("fetch is not available");
|
|
108962
|
+
const ac = new AbortController();
|
|
108963
|
+
let timedOut = false;
|
|
108964
|
+
const onOuterAbort = () => ac.abort();
|
|
108965
|
+
if (ctx?.signal) {
|
|
108966
|
+
if (ctx.signal.aborted) ac.abort();
|
|
108967
|
+
else ctx.signal.addEventListener("abort", onOuterAbort, { once: true });
|
|
108968
|
+
}
|
|
108969
|
+
const timer = setTimeout(() => {
|
|
108970
|
+
timedOut = true;
|
|
108971
|
+
ac.abort();
|
|
108972
|
+
}, timeoutMs);
|
|
108973
|
+
const body = { email: input.email, password: input.password };
|
|
108974
|
+
if (input.captchaToken) body.captchaToken = input.captchaToken;
|
|
108975
|
+
let res;
|
|
108976
|
+
try {
|
|
108977
|
+
res = await doFetch(url, {
|
|
108978
|
+
method: "POST",
|
|
108979
|
+
headers: { "Content-Type": "application/json", "x-tenant-id": options.tenantId, ...options.extraHeaders ?? {} },
|
|
108980
|
+
body: JSON.stringify(body),
|
|
108981
|
+
credentials: "omit",
|
|
108982
|
+
redirect: "error",
|
|
108983
|
+
signal: ac.signal
|
|
108984
|
+
});
|
|
108985
|
+
} catch (err) {
|
|
108986
|
+
if (timedOut) throw timeoutError();
|
|
108987
|
+
if (ac.signal.aborted) throw err;
|
|
108988
|
+
return { ok: false, code: "NETWORK" };
|
|
108989
|
+
} finally {
|
|
108990
|
+
clearTimeout(timer);
|
|
108991
|
+
ctx?.signal?.removeEventListener("abort", onOuterAbort);
|
|
108992
|
+
}
|
|
108993
|
+
let json = void 0;
|
|
108994
|
+
try {
|
|
108995
|
+
json = await res.json();
|
|
108996
|
+
} catch {
|
|
108997
|
+
json = void 0;
|
|
108998
|
+
}
|
|
108999
|
+
return mapGcdrResponse(res.status, json);
|
|
109000
|
+
};
|
|
109001
|
+
}
|
|
109002
|
+
function mapGcdrResponse(status, json) {
|
|
109003
|
+
const j = json && typeof json === "object" ? json : {};
|
|
109004
|
+
if (status >= 200 && status < 300) {
|
|
109005
|
+
const data = j.data;
|
|
109006
|
+
if (data && data.mfaRequired === true) return { ok: false, code: "MFA_REQUIRED" };
|
|
109007
|
+
if (data && typeof data.accessToken === "string" && data.accessToken) return { ok: true, session: data };
|
|
109008
|
+
return { ok: false, code: "INTEGRATION_ERROR" };
|
|
109009
|
+
}
|
|
109010
|
+
const code = typeof j.error?.code === "string" ? j.error.code : void 0;
|
|
109011
|
+
const remaining = j.error?.details?.remainingAttempts;
|
|
109012
|
+
switch (status) {
|
|
109013
|
+
case 400:
|
|
109014
|
+
return { ok: false, code: code === "CAPTCHA_FAILED" ? "CAPTCHA_FAILED" : "SERVER" };
|
|
109015
|
+
case 401:
|
|
109016
|
+
return code === "INVALID_CREDENTIALS" && typeof remaining === "number" ? { ok: false, code: "INVALID_CREDENTIALS", remainingAttempts: remaining } : { ok: false, code: "INVALID_CREDENTIALS" };
|
|
109017
|
+
case 403:
|
|
109018
|
+
return { ok: false, code: code === "ACCOUNT_LOCKED" ? "ACCOUNT_LOCKED" : "SERVER" };
|
|
109019
|
+
case 429:
|
|
109020
|
+
return { ok: false, code: "TOO_MANY_REQUESTS" };
|
|
109021
|
+
default:
|
|
109022
|
+
return { ok: false, code: "SERVER" };
|
|
109023
|
+
}
|
|
109024
|
+
}
|
|
109025
|
+
|
|
109026
|
+
// src/components/myio-gcdr-login/loginView.ts
|
|
109027
|
+
var DEFAULT_SUBMIT_TIMEOUT_MS = 3e4;
|
|
109028
|
+
function fail(msg, code) {
|
|
109029
|
+
const e = new TypeError(`[MYIO Login] ${msg}`);
|
|
109030
|
+
if (code) e.code = code;
|
|
109031
|
+
throw e;
|
|
109032
|
+
}
|
|
109033
|
+
function validateOptions3(container, o) {
|
|
109034
|
+
if (!(container instanceof HTMLElement)) fail("container must be an HTMLElement");
|
|
109035
|
+
if (!o || typeof o !== "object") fail("options are required");
|
|
109036
|
+
const n = [o.onSubmit, o.gcdr, o.auth].filter((x) => x != null).length;
|
|
109037
|
+
if (n !== 1) fail("exactly one of onSubmit, gcdr or auth is required");
|
|
109038
|
+
if (o.auth && o.auth.kind !== "credentials") {
|
|
109039
|
+
fail(`auth.kind "${String(o.auth.kind)}" is not supported`, "MYIO_GCDR_AUTH_UNSUPPORTED");
|
|
109040
|
+
}
|
|
109041
|
+
if (o.auth && typeof o.auth.submit !== "function") fail("auth.submit must be a function");
|
|
109042
|
+
if (o.onSubmit && typeof o.onSubmit !== "function") fail("onSubmit must be a function");
|
|
109043
|
+
if (typeof o.onSuccess !== "function") fail("onSuccess must be a function");
|
|
109044
|
+
if (o.submitTimeoutMs != null && !(Number.isFinite(o.submitTimeoutMs) && o.submitTimeoutMs > 0)) fail("submitTimeoutMs must be a positive number");
|
|
109045
|
+
if (o.captcha) fail("captcha is not available in this version (RFC-0236 PR 2)", "MYIO_GCDR_CAPTCHA_UNSUPPORTED");
|
|
109046
|
+
const kinds = ["about", "signedOutPrompt", "custom", "none"];
|
|
109047
|
+
if (o.aside && !kinds.includes(o.aside.kind)) fail(`unknown aside.kind "${String(o.aside.kind)}"`);
|
|
109048
|
+
if (o.aside?.kind === "custom" && typeof o.aside.render !== "function") fail("aside.render must be a function");
|
|
109049
|
+
if (o.support && (typeof o.support.href !== "string" || !o.support.href)) fail("support.href must be a non-empty string");
|
|
109050
|
+
if (o.embed) {
|
|
109051
|
+
const bad = ["aside", "buildInfo", "theme", "locale", "assets"].filter((k) => o[k] !== void 0);
|
|
109052
|
+
if (o.show?.themeToggle !== void 0 || o.show?.languageSelector !== void 0 || o.show?.wallpaper !== void 0) bad.push("show.(theme|language|wallpaper)");
|
|
109053
|
+
if (bad.length) fail(`with embed, these options belong to the host shell: ${bad.join(", ")}`);
|
|
109054
|
+
if (!o.embed.context || typeof o.embed.context.on !== "function") fail("embed.context must be a slot context");
|
|
109055
|
+
}
|
|
109056
|
+
}
|
|
109057
|
+
function createLoginViewImpl(container, options, internals = {}) {
|
|
109058
|
+
validateOptions3(container, options);
|
|
109059
|
+
const doc = container.ownerDocument;
|
|
109060
|
+
const presentation = internals.presentation ?? "inline";
|
|
109061
|
+
const prefix = options.storageKeyPrefix ?? "myio.login.";
|
|
109062
|
+
const isGcdr = !!options.gcdr;
|
|
109063
|
+
const webUrl = options.links?.gcdrWebUrl?.replace(/\/+$/, "");
|
|
109064
|
+
const strategy = options.gcdr ? createMyioGcdrLoginSubmit(options.gcdr) : options.auth ? options.auth.submit : options.onSubmit;
|
|
109065
|
+
const viewTimeoutMs = isGcdr ? void 0 : options.submitTimeoutMs ?? DEFAULT_SUBMIT_TIMEOUT_MS;
|
|
109066
|
+
let shell;
|
|
109067
|
+
let embedCtx;
|
|
109068
|
+
let releaseEmbedStyles;
|
|
109069
|
+
let cardHost;
|
|
109070
|
+
if (options.embed) {
|
|
109071
|
+
embedCtx = options.embed.context;
|
|
109072
|
+
releaseEmbedStyles = acquireStyles(container, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
|
|
109073
|
+
container.textContent = "";
|
|
109074
|
+
cardHost = container;
|
|
109075
|
+
} else {
|
|
109076
|
+
const wpOpt = internals.shellWallpaper === false || options.show?.wallpaper === false ? false : options.assets?.wallpaper ?? {};
|
|
109077
|
+
shell = createShellImpl(
|
|
109078
|
+
container,
|
|
109079
|
+
{
|
|
109080
|
+
size: options.size ?? "md",
|
|
109081
|
+
theme: options.theme,
|
|
109082
|
+
locale: options.locale,
|
|
109083
|
+
show: { themeToggle: options.show?.themeToggle, languageSelector: options.show?.languageSelector },
|
|
109084
|
+
buildInfo: options.buildInfo,
|
|
109085
|
+
storageKeyPrefix: options.storageKeyPrefix,
|
|
109086
|
+
fonts: options.fonts,
|
|
109087
|
+
cspNonce: options.cspNonce,
|
|
109088
|
+
wallpaper: wpOpt === false ? false : wpOpt,
|
|
109089
|
+
onThemeChange: options.onThemeChange,
|
|
109090
|
+
onLocaleChange: options.onLocaleChange
|
|
109091
|
+
},
|
|
109092
|
+
{
|
|
109093
|
+
messages: options.messages,
|
|
109094
|
+
logoUrl: options.assets?.logoUrl,
|
|
109095
|
+
about: { webUrl, fetchImpl: options.gcdr?.fetch, bandColor: options.brand?.asideHeaderColor }
|
|
109096
|
+
}
|
|
109097
|
+
);
|
|
109098
|
+
cardHost = h2(doc, "div", { style: "display:flex;width:100%" });
|
|
109099
|
+
}
|
|
109100
|
+
const getLocale = () => shell ? shell.getState().locale : embedCtx.locale;
|
|
109101
|
+
const getTheme = () => shell ? shell.getState().theme : embedCtx.theme;
|
|
109102
|
+
const t = (key, vars) => translate(getLocale(), key, vars, options.messages);
|
|
109103
|
+
let phase = "idle";
|
|
109104
|
+
let destroyed = false;
|
|
109105
|
+
let attempt = 0;
|
|
109106
|
+
let attemptAbort = null;
|
|
109107
|
+
let abortCause = null;
|
|
109108
|
+
let successAbort = null;
|
|
109109
|
+
let err = {};
|
|
109110
|
+
let lockedKey = null;
|
|
109111
|
+
let noCounterStreak = 0;
|
|
109112
|
+
let streakKey = null;
|
|
109113
|
+
let notice = options.notice ?? null;
|
|
109114
|
+
let fieldErrors = {};
|
|
109115
|
+
const remembered = storageGet(`${prefix}rememberedEmail`);
|
|
109116
|
+
let emailValue = options.initialEmail ?? remembered ?? "";
|
|
109117
|
+
let rememberValue = !options.initialEmail && !!remembered;
|
|
109118
|
+
let passwordValue = "";
|
|
109119
|
+
let passwordVisible = false;
|
|
109120
|
+
let leaving = false;
|
|
109121
|
+
const linkTarget = options.links?.target ?? (presentation === "modal" ? "_blank" : "_self");
|
|
109122
|
+
const forgot = options.links?.forgotPassword;
|
|
109123
|
+
const forgotShown = forgot === false ? false : !!forgot || isGcdr && !!webUrl;
|
|
109124
|
+
const supportHref = options.support === false ? void 0 : options.support ? options.support.href : (options.aside?.kind ?? "about") === "about" ? defaultSupportHref(webUrl) : void 0;
|
|
109125
|
+
let els = {};
|
|
109126
|
+
const linkEl = (label, target, cls = "myio-gcdr-login__link") => {
|
|
109127
|
+
if (typeof target === "function") {
|
|
109128
|
+
const b = h2(doc, "button", { type: "button", class: cls, text: label });
|
|
109129
|
+
b.addEventListener("click", () => safeCall("link", target, { email: emailValue.trim() }));
|
|
109130
|
+
return b;
|
|
109131
|
+
}
|
|
109132
|
+
const a = h2(doc, "a", { class: cls, href: target, target: linkTarget, rel: linkTarget === "_blank" ? "noopener noreferrer" : null }, label);
|
|
109133
|
+
if (linkTarget === "_blank") a.appendChild(h2(doc, "span", { class: "myio-gcdr-sr", text: ` ${t("login.newTab")}` }));
|
|
109134
|
+
return a;
|
|
109135
|
+
};
|
|
109136
|
+
const forgotTarget = () => !forgotShown ? void 0 : typeof forgot === "string" || typeof forgot === "function" ? forgot : `${webUrl}/forgot-password`;
|
|
109137
|
+
const renderNotice = () => {
|
|
109138
|
+
if (!els.notice) return;
|
|
109139
|
+
els.notice.textContent = "";
|
|
109140
|
+
if (!notice) return;
|
|
109141
|
+
const key = presentation === "modal" ? "notice.sessionExpiredModal" : "notice.sessionExpired";
|
|
109142
|
+
els.notice.appendChild(
|
|
109143
|
+
h2(
|
|
109144
|
+
doc,
|
|
109145
|
+
"div",
|
|
109146
|
+
{ class: "myio-gcdr-banner myio-gcdr-banner--info" },
|
|
109147
|
+
icon(doc, ICONS.info(16), "myio-gcdr-banner__icon"),
|
|
109148
|
+
h2(doc, "div", { class: "myio-gcdr-banner__body" }, h2(doc, "span", { text: t(key) }))
|
|
109149
|
+
)
|
|
109150
|
+
);
|
|
109151
|
+
};
|
|
109152
|
+
const renderAlerts = () => {
|
|
109153
|
+
if (!els.alerts) return;
|
|
109154
|
+
els.alerts.textContent = "";
|
|
109155
|
+
els.banner = void 0;
|
|
109156
|
+
if (!err.pres && !err.messageKey) return;
|
|
109157
|
+
const p = err.pres;
|
|
109158
|
+
const tone = p?.tone ?? "error";
|
|
109159
|
+
const body = h2(doc, "div", { class: "myio-gcdr-banner__body" });
|
|
109160
|
+
if (p?.title) body.appendChild(h2(doc, "span", { class: "myio-gcdr-banner__title", text: t(p.title) }));
|
|
109161
|
+
if (p) {
|
|
109162
|
+
if (p.text) body.appendChild(h2(doc, "span", { text: p.text }));
|
|
109163
|
+
p.keys.forEach((k, i) => body.appendChild(h2(doc, "span", { text: t(k, i === 0 && p.count !== void 0 ? { count: p.count } : void 0) })));
|
|
109164
|
+
if (p.forgotLink) {
|
|
109165
|
+
const ft = forgotTarget();
|
|
109166
|
+
if (ft) body.appendChild(linkEl(t("errors.goToForgot"), ft, ""));
|
|
109167
|
+
}
|
|
109168
|
+
if (p.gcdrWebLink && webUrl) body.appendChild(linkEl(t("login.gcdrWeb"), `${webUrl}/login`, ""));
|
|
109169
|
+
if (p.support && supportHref) body.appendChild(linkEl(t("login.support"), supportHref, ""));
|
|
109170
|
+
} else if (err.messageKey) {
|
|
109171
|
+
body.appendChild(h2(doc, "span", { text: t(err.messageKey) }));
|
|
109172
|
+
}
|
|
109173
|
+
if (err.help) {
|
|
109174
|
+
const who = supportHref ? t("errors.helpSupport") : t("errors.helpAdmin");
|
|
109175
|
+
body.appendChild(h2(doc, "span", { text: t("errors.invalidCredentialsHelp", { who }) }));
|
|
109176
|
+
if (supportHref) body.appendChild(linkEl(t("login.support"), supportHref, ""));
|
|
109177
|
+
}
|
|
109178
|
+
const ic = p?.icon === "lock" ? ICONS.lock(16) : p?.icon === "shieldAlert" ? ICONS.shieldAlert(16) : ICONS.alert(16);
|
|
109179
|
+
const banner = h2(doc, "div", { class: `myio-gcdr-banner myio-gcdr-banner--${tone}`, tabindex: "-1" }, icon(doc, ic, "myio-gcdr-banner__icon"), body);
|
|
109180
|
+
els.alerts.appendChild(banner);
|
|
109181
|
+
els.banner = banner;
|
|
109182
|
+
};
|
|
109183
|
+
const syncControls = () => {
|
|
109184
|
+
if (!els.submit || !els.email || !els.password) return;
|
|
109185
|
+
const busy = phase === "submitting" || phase === "success";
|
|
109186
|
+
const blocked = busy || leaving || !!lockedKey;
|
|
109187
|
+
els.submit.setAttribute("aria-disabled", blocked ? "true" : "false");
|
|
109188
|
+
els.submit.setAttribute("aria-busy", busy ? "true" : "false");
|
|
109189
|
+
if (lockedKey && els.banner) {
|
|
109190
|
+
if (!els.banner.id) els.banner.id = `myio-gcdr-lock-${Math.random().toString(36).slice(2, 8)}`;
|
|
109191
|
+
els.submit.setAttribute("aria-describedby", els.banner.id);
|
|
109192
|
+
} else els.submit.removeAttribute("aria-describedby");
|
|
109193
|
+
els.submit.textContent = "";
|
|
109194
|
+
if (busy) {
|
|
109195
|
+
els.submit.append(icon(doc, ICONS.spinner(18), "myio-gcdr-login__spin"), h2(doc, "span", { text: t("login.signingIn") }));
|
|
109196
|
+
} else els.submit.append(h2(doc, "span", { text: t("login.signIn") }));
|
|
109197
|
+
els.email.readOnly = busy || leaving;
|
|
109198
|
+
els.password.readOnly = busy || leaving;
|
|
109199
|
+
};
|
|
109200
|
+
const render3 = () => {
|
|
109201
|
+
if (destroyed) return;
|
|
109202
|
+
if (els.email) emailValue = els.email.value;
|
|
109203
|
+
if (els.password) passwordValue = els.password.value;
|
|
109204
|
+
const hadFocusId = doc.activeElement && cardHost.contains(doc.activeElement) ? doc.activeElement.getAttribute("data-k") : null;
|
|
109205
|
+
cardHost.textContent = "";
|
|
109206
|
+
const locale = getLocale();
|
|
109207
|
+
const { root, body, footer, title } = buildPanel(
|
|
109208
|
+
doc,
|
|
109209
|
+
cardHost,
|
|
109210
|
+
{ 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 },
|
|
109211
|
+
locale
|
|
109212
|
+
);
|
|
109213
|
+
if (options.size && options.embed) root.style.maxWidth = options.size === "xl" ? "37rem" : options.size === "lg" ? "32rem" : "28rem";
|
|
109214
|
+
else if (options.embed) root.style.maxWidth = "28rem";
|
|
109215
|
+
root.style.margin = "0 auto";
|
|
109216
|
+
if (options.brand?.accent) root.style.setProperty("--myio-gcdr-accent-hover", options.brand.accent);
|
|
109217
|
+
root.setAttribute("data-theme", getTheme());
|
|
109218
|
+
els = { root, title };
|
|
109219
|
+
const noticeEl = h2(doc, "div", { class: "myio-gcdr-login__alerts", role: "status", "aria-live": "polite" });
|
|
109220
|
+
const alerts = h2(doc, "div", { class: "myio-gcdr-login__alerts", role: "alert" });
|
|
109221
|
+
els.notice = noticeEl;
|
|
109222
|
+
els.alerts = alerts;
|
|
109223
|
+
const form = h2(doc, "form", { class: "myio-gcdr-login__form", novalidate: true });
|
|
109224
|
+
const uid2 = Math.random().toString(36).slice(2, 8);
|
|
109225
|
+
const email = h2(doc, "input", {
|
|
109226
|
+
id: `myio-gcdr-email-${uid2}`,
|
|
109227
|
+
"data-k": "email",
|
|
109228
|
+
class: "myio-gcdr-login__input",
|
|
109229
|
+
type: "email",
|
|
109230
|
+
inputmode: "email",
|
|
109231
|
+
autocomplete: "username",
|
|
109232
|
+
autocapitalize: "none",
|
|
109233
|
+
spellcheck: "false",
|
|
109234
|
+
placeholder: t("login.emailPlaceholder"),
|
|
109235
|
+
"aria-invalid": fieldErrors.email ? "true" : "false"
|
|
109236
|
+
});
|
|
109237
|
+
email.value = emailValue;
|
|
109238
|
+
const emailErr = h2(doc, "span", { id: `myio-gcdr-email-err-${uid2}`, class: "myio-gcdr-login__fielderror", text: fieldErrors.email ? t(fieldErrors.email) : "" });
|
|
109239
|
+
if (fieldErrors.email) email.setAttribute("aria-describedby", emailErr.id);
|
|
109240
|
+
const emailField = h2(
|
|
109241
|
+
doc,
|
|
109242
|
+
"div",
|
|
109243
|
+
{ class: "myio-gcdr-login__field" },
|
|
109244
|
+
h2(doc, "label", { class: "myio-gcdr-login__label", for: email.id, text: t("login.email") }),
|
|
109245
|
+
email,
|
|
109246
|
+
fieldErrors.email ? emailErr : null
|
|
109247
|
+
);
|
|
109248
|
+
if (options.initialEmail) {
|
|
109249
|
+
const notYou = h2(doc, "button", { type: "button", class: "myio-gcdr-login__link", text: t("login.notYou") });
|
|
109250
|
+
notYou.addEventListener("click", () => {
|
|
109251
|
+
email.value = "";
|
|
109252
|
+
emailValue = "";
|
|
109253
|
+
onEmailInput();
|
|
109254
|
+
email.focus();
|
|
109255
|
+
});
|
|
109256
|
+
emailField.appendChild(notYou);
|
|
109257
|
+
}
|
|
109258
|
+
const password = h2(doc, "input", {
|
|
109259
|
+
id: `myio-gcdr-pass-${uid2}`,
|
|
109260
|
+
"data-k": "password",
|
|
109261
|
+
class: "myio-gcdr-login__input myio-gcdr-login__input--password",
|
|
109262
|
+
type: passwordVisible ? "text" : "password",
|
|
109263
|
+
autocomplete: "current-password",
|
|
109264
|
+
enterkeyhint: "go",
|
|
109265
|
+
placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
|
|
109266
|
+
"aria-invalid": fieldErrors.password ? "true" : "false"
|
|
109267
|
+
});
|
|
109268
|
+
password.value = passwordValue;
|
|
109269
|
+
const passErr = h2(doc, "span", { id: `myio-gcdr-pass-err-${uid2}`, class: "myio-gcdr-login__fielderror", text: fieldErrors.password ? t(fieldErrors.password) : "" });
|
|
109270
|
+
if (fieldErrors.password) password.setAttribute("aria-describedby", passErr.id);
|
|
109271
|
+
const control = h2(doc, "div", { class: "myio-gcdr-login__control" }, password);
|
|
109272
|
+
if (options.show?.passwordToggle !== false) {
|
|
109273
|
+
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 });
|
|
109274
|
+
eye.appendChild(icon(doc, passwordVisible ? ICONS.eyeOff(18) : ICONS.eye(18)));
|
|
109275
|
+
eye.addEventListener("click", () => {
|
|
109276
|
+
passwordVisible = !passwordVisible;
|
|
109277
|
+
password.type = passwordVisible ? "text" : "password";
|
|
109278
|
+
eye.setAttribute("aria-pressed", passwordVisible ? "true" : "false");
|
|
109279
|
+
eye.setAttribute("aria-label", t(passwordVisible ? "login.hidePassword" : "login.showPassword"));
|
|
109280
|
+
eye.textContent = "";
|
|
109281
|
+
eye.appendChild(icon(doc, passwordVisible ? ICONS.eyeOff(18) : ICONS.eye(18)));
|
|
109282
|
+
});
|
|
109283
|
+
control.appendChild(eye);
|
|
109284
|
+
}
|
|
109285
|
+
const caps = h2(doc, "span", { class: "myio-gcdr-login__hint", "aria-live": "polite" });
|
|
109286
|
+
const capsCheck = (e) => {
|
|
109287
|
+
const on = typeof e.getModifierState === "function" && e.getModifierState("CapsLock");
|
|
109288
|
+
caps.textContent = on ? t("login.capsLockOn") : "";
|
|
109289
|
+
};
|
|
109290
|
+
password.addEventListener("keydown", capsCheck);
|
|
109291
|
+
password.addEventListener("keyup", capsCheck);
|
|
109292
|
+
const passField = h2(
|
|
109293
|
+
doc,
|
|
109294
|
+
"div",
|
|
109295
|
+
{ class: "myio-gcdr-login__field" },
|
|
109296
|
+
h2(doc, "label", { class: "myio-gcdr-login__label", for: password.id, text: t("login.password") }),
|
|
109297
|
+
control,
|
|
109298
|
+
caps,
|
|
109299
|
+
fieldErrors.password ? passErr : null
|
|
109300
|
+
);
|
|
109301
|
+
const row = h2(doc, "div", { class: "myio-gcdr-login__row" });
|
|
109302
|
+
if (options.show?.rememberMe !== false) {
|
|
109303
|
+
const cb = h2(doc, "input", { type: "checkbox" });
|
|
109304
|
+
cb.checked = rememberValue;
|
|
109305
|
+
cb.addEventListener("change", () => {
|
|
109306
|
+
rememberValue = cb.checked;
|
|
109307
|
+
});
|
|
109308
|
+
row.appendChild(h2(doc, "label", { class: "myio-gcdr-login__remember" }, cb, h2(doc, "span", { text: t("login.rememberMe") })));
|
|
109309
|
+
} else row.appendChild(h2(doc, "span"));
|
|
109310
|
+
const ft = forgotTarget();
|
|
109311
|
+
if (ft) row.appendChild(linkEl(t("login.forgotPassword"), ft));
|
|
109312
|
+
const submit = h2(doc, "button", { type: "submit", "data-k": "submit", class: "myio-gcdr-login__submit", "data-style": options.submitStyle ?? "auth" });
|
|
109313
|
+
form.append(emailField, passField, row, submit);
|
|
109314
|
+
form.addEventListener("submit", (e) => {
|
|
109315
|
+
e.preventDefault();
|
|
109316
|
+
void doSubmit();
|
|
109317
|
+
});
|
|
109318
|
+
email.addEventListener("input", () => {
|
|
109319
|
+
emailValue = email.value;
|
|
109320
|
+
onEmailInput();
|
|
109321
|
+
});
|
|
109322
|
+
password.addEventListener("input", () => {
|
|
109323
|
+
passwordValue = password.value;
|
|
109324
|
+
if (fieldErrors.password) {
|
|
109325
|
+
fieldErrors.password = validate(email.value, password.value).passwordError;
|
|
109326
|
+
if (!fieldErrors.password) {
|
|
109327
|
+
password.setAttribute("aria-invalid", "false");
|
|
109328
|
+
passErr.remove();
|
|
109329
|
+
}
|
|
109330
|
+
}
|
|
109331
|
+
});
|
|
109332
|
+
body.append(noticeEl, alerts, form);
|
|
109333
|
+
if (footer) {
|
|
109334
|
+
const reg = options.links?.register;
|
|
109335
|
+
if (reg) {
|
|
109336
|
+
footer.append(h2(doc, "span", { text: `${t("login.noAccount")} ` }), linkEl(t("login.createAccount"), reg));
|
|
109337
|
+
} else footer.appendChild(h2(doc, "span", { text: options.footerText ? localize(options.footerText, locale) : t("login.askAdmin") }));
|
|
109338
|
+
internals.decorateFooter?.(footer, api);
|
|
109339
|
+
}
|
|
109340
|
+
els = { ...els, email, password, submit, caps };
|
|
109341
|
+
renderNotice();
|
|
109342
|
+
renderAlerts();
|
|
109343
|
+
syncControls();
|
|
109344
|
+
if (hadFocusId) cardHost.querySelector(`[data-k="${hadFocusId}"]`)?.focus();
|
|
109345
|
+
};
|
|
109346
|
+
const onEmailInput = () => {
|
|
109347
|
+
const key = emailKey(emailValue);
|
|
109348
|
+
if (fieldErrors.email) {
|
|
109349
|
+
fieldErrors.email = validate(emailValue, "").emailError;
|
|
109350
|
+
if (!fieldErrors.email) render3();
|
|
109351
|
+
}
|
|
109352
|
+
if (lockedKey && key !== lockedKey) {
|
|
109353
|
+
lockedKey = null;
|
|
109354
|
+
err = {};
|
|
109355
|
+
renderAlerts();
|
|
109356
|
+
syncControls();
|
|
109357
|
+
}
|
|
109358
|
+
if (streakKey && key !== streakKey) {
|
|
109359
|
+
noCounterStreak = 0;
|
|
109360
|
+
streakKey = null;
|
|
109361
|
+
}
|
|
109362
|
+
};
|
|
109363
|
+
const focusTarget = (f) => {
|
|
109364
|
+
const el2 = f === "password" ? els.password : f === "email" ? els.email : f === "banner" ? els.banner : els.submit;
|
|
109365
|
+
el2?.focus();
|
|
109366
|
+
};
|
|
109367
|
+
const setError = (code, pres, opts) => {
|
|
109368
|
+
err = { code, pres, help: opts.help };
|
|
109369
|
+
if (pres.clearPassword && els.password) {
|
|
109370
|
+
els.password.value = "";
|
|
109371
|
+
passwordValue = "";
|
|
109372
|
+
}
|
|
109373
|
+
renderAlerts();
|
|
109374
|
+
syncControls();
|
|
109375
|
+
focusTarget(pres.focus);
|
|
109376
|
+
if (opts.notify !== false) safeCall("onError", options.onError, { code, remainingAttempts: opts.remaining });
|
|
109377
|
+
};
|
|
109378
|
+
const doSubmit = async () => {
|
|
109379
|
+
if (destroyed || phase !== "idle" || leaving || lockedKey) return;
|
|
109380
|
+
const email = els.email.value;
|
|
109381
|
+
const password = els.password.value;
|
|
109382
|
+
const v = validate(email, password);
|
|
109383
|
+
fieldErrors = { email: v.emailError, password: v.passwordError };
|
|
109384
|
+
if (v.emailError || v.passwordError) {
|
|
109385
|
+
render3();
|
|
109386
|
+
(v.emailError ? els.email : els.password)?.focus();
|
|
109387
|
+
return;
|
|
109388
|
+
}
|
|
109389
|
+
fieldErrors = {};
|
|
109390
|
+
attempt += 1;
|
|
109391
|
+
const my = attempt;
|
|
109392
|
+
phase = "submitting";
|
|
109393
|
+
err = { ...err, pres: void 0, messageKey: void 0, help: false, code: void 0 };
|
|
109394
|
+
if (passwordVisible) {
|
|
109395
|
+
passwordVisible = false;
|
|
109396
|
+
els.password.type = "password";
|
|
109397
|
+
}
|
|
109398
|
+
renderAlerts();
|
|
109399
|
+
syncControls();
|
|
109400
|
+
const ac = new AbortController();
|
|
109401
|
+
attemptAbort = ac;
|
|
109402
|
+
abortCause = null;
|
|
109403
|
+
let timer;
|
|
109404
|
+
const timeout = new Promise((_, reject) => {
|
|
109405
|
+
if (viewTimeoutMs) timer = setTimeout(() => {
|
|
109406
|
+
abortCause = "timeout";
|
|
109407
|
+
ac.abort();
|
|
109408
|
+
reject(Object.assign(new Error("timeout"), { myioGcdrCode: "TIMEOUT" }));
|
|
109409
|
+
}, viewTimeoutMs);
|
|
109410
|
+
});
|
|
109411
|
+
let outcome;
|
|
109412
|
+
try {
|
|
109413
|
+
const raw = await Promise.race([strategy({ email: v.email, password, remember: rememberValue, locale: getLocale() }, { signal: ac.signal, attempt: my }), timeout]);
|
|
109414
|
+
outcome = normaliseResult(raw);
|
|
109415
|
+
if (outcome.kind === "error" && outcome.code === "INTEGRATION_ERROR" && !(raw && typeof raw === "object" && typeof raw.ok === "boolean")) {
|
|
109416
|
+
console.error("[MYIO Login] INTEGRATION_ERROR: invalid onSubmit result");
|
|
109417
|
+
}
|
|
109418
|
+
} catch (e) {
|
|
109419
|
+
outcome = { kind: "thrown", err: e };
|
|
109420
|
+
} finally {
|
|
109421
|
+
if (timer) clearTimeout(timer);
|
|
109422
|
+
}
|
|
109423
|
+
if (destroyed || my !== attempt || abortCause === "destroy" || abortCause === "exit") return;
|
|
109424
|
+
attemptAbort = null;
|
|
109425
|
+
if (outcome.kind === "thrown") {
|
|
109426
|
+
phase = "idle";
|
|
109427
|
+
const code = abortCause === "timeout" ? "TIMEOUT" : normaliseThrown(outcome.err);
|
|
109428
|
+
setError(code, present({ kind: "error", code }), {});
|
|
109429
|
+
return;
|
|
109430
|
+
}
|
|
109431
|
+
if (outcome.kind === "error") {
|
|
109432
|
+
phase = "idle";
|
|
109433
|
+
const k = emailKey(v.email);
|
|
109434
|
+
let help = false;
|
|
109435
|
+
if (outcome.code === "INVALID_CREDENTIALS" && outcome.remainingAttempts === void 0) {
|
|
109436
|
+
noCounterStreak = streakKey === k ? noCounterStreak + 1 : 1;
|
|
109437
|
+
streakKey = k;
|
|
109438
|
+
help = noCounterStreak >= 2;
|
|
109439
|
+
} else {
|
|
109440
|
+
noCounterStreak = 0;
|
|
109441
|
+
streakKey = null;
|
|
109442
|
+
}
|
|
109443
|
+
if (outcome.code === "ACCOUNT_LOCKED") lockedKey = k;
|
|
109444
|
+
setError(outcome.code, present(outcome), { help, remaining: outcome.remainingAttempts });
|
|
109445
|
+
return;
|
|
109446
|
+
}
|
|
109447
|
+
phase = "success";
|
|
109448
|
+
if (els.password) els.password.value = "";
|
|
109449
|
+
passwordValue = "";
|
|
109450
|
+
err = {};
|
|
109451
|
+
noCounterStreak = 0;
|
|
109452
|
+
if (options.show?.rememberMe !== false) storageSet(`${prefix}rememberedEmail`, rememberValue ? v.email : null);
|
|
109453
|
+
renderAlerts();
|
|
109454
|
+
syncControls();
|
|
109455
|
+
const sa = new AbortController();
|
|
109456
|
+
successAbort = sa;
|
|
109457
|
+
try {
|
|
109458
|
+
await options.onSuccess(outcome.session, { signal: sa.signal });
|
|
109459
|
+
} catch {
|
|
109460
|
+
if (destroyed || sa.signal.aborted) return;
|
|
109461
|
+
console.error("[MYIO Login] onSuccess failed");
|
|
109462
|
+
phase = "idle";
|
|
109463
|
+
err = { messageKey: "errors.postLoginFailed", pres: { tone: "error", keys: ["errors.postLoginFailed"], icon: "alert", clearPassword: true, focus: "password" } };
|
|
109464
|
+
renderAlerts();
|
|
109465
|
+
syncControls();
|
|
109466
|
+
els.password?.focus();
|
|
109467
|
+
return;
|
|
109468
|
+
}
|
|
109469
|
+
if (destroyed || sa.signal.aborted) return;
|
|
109470
|
+
internals.afterSuccess?.();
|
|
109471
|
+
};
|
|
109472
|
+
const api = {
|
|
109473
|
+
abortAttempt() {
|
|
109474
|
+
if (attemptAbort) {
|
|
109475
|
+
abortCause = "exit";
|
|
109476
|
+
attemptAbort.abort();
|
|
109477
|
+
attemptAbort = null;
|
|
109478
|
+
attempt += 1;
|
|
109479
|
+
}
|
|
109480
|
+
if (phase === "submitting") phase = "idle";
|
|
109481
|
+
leaving = true;
|
|
109482
|
+
syncControls();
|
|
109483
|
+
},
|
|
109484
|
+
clearPassword() {
|
|
109485
|
+
if (els.password) els.password.value = "";
|
|
109486
|
+
passwordValue = "";
|
|
109487
|
+
},
|
|
109488
|
+
showLeaveFailed() {
|
|
109489
|
+
leaving = false;
|
|
109490
|
+
err = { messageKey: "errors.leaveFailed", pres: { tone: "error", keys: ["errors.leaveFailed"], icon: "alert", clearPassword: false, focus: "submit" } };
|
|
109491
|
+
renderAlerts();
|
|
109492
|
+
syncControls();
|
|
109493
|
+
},
|
|
109494
|
+
t: (k) => t(k),
|
|
109495
|
+
locale: getLocale,
|
|
109496
|
+
phase: () => phase
|
|
109497
|
+
};
|
|
109498
|
+
let offChange;
|
|
109499
|
+
if (shell) {
|
|
109500
|
+
const asideOpt = options.aside ?? { kind: "about" };
|
|
109501
|
+
if (asideOpt.kind === "about") {
|
|
109502
|
+
const healthUrl = asideOpt.healthUrl !== void 0 ? asideOpt.healthUrl : options.gcdr ? `${options.gcdr.apiUrl.replace(/\/+$/, "").replace(/\/api\/v\d+$/, "")}/health` : false;
|
|
109503
|
+
shell.setSlot("aside", { kind: "about", healthUrl });
|
|
109504
|
+
} else if (asideOpt.kind === "signedOutPrompt") shell.setSlot("aside", { kind: "signedOutPrompt", text: asideOpt.text });
|
|
109505
|
+
else if (asideOpt.kind === "custom") shell.setSlot("aside", asideOpt.render);
|
|
109506
|
+
shell.setSlot("main", (el2) => {
|
|
109507
|
+
el2.appendChild(cardHost);
|
|
109508
|
+
});
|
|
109509
|
+
offChange = shell.onChange(() => render3());
|
|
109510
|
+
} else if (embedCtx) {
|
|
109511
|
+
const offT = embedCtx.on("theme", () => render3());
|
|
109512
|
+
const offL = embedCtx.on("locale", () => render3());
|
|
109513
|
+
offChange = () => {
|
|
109514
|
+
offT();
|
|
109515
|
+
offL();
|
|
109516
|
+
};
|
|
109517
|
+
embedCtx.signal.addEventListener("abort", () => handle.destroy(), { once: true });
|
|
109518
|
+
}
|
|
109519
|
+
render3();
|
|
109520
|
+
const autoFocus = options.autoFocus ?? !isCoarsePointer();
|
|
109521
|
+
if (autoFocus && presentation === "inline") (options.initialEmail ? els.password : els.email)?.focus();
|
|
109522
|
+
const restricted = shell ? {
|
|
109523
|
+
setSlot: (name, content, o) => {
|
|
109524
|
+
if (name === "main") fail("the main slot belongs to the login view");
|
|
109525
|
+
shell.setSlot(name, content, o);
|
|
109526
|
+
},
|
|
109527
|
+
setShow: (s) => shell.setShow(s)
|
|
109528
|
+
} : void 0;
|
|
109529
|
+
const handle = {
|
|
109530
|
+
getState() {
|
|
109531
|
+
return {
|
|
109532
|
+
phase: destroyed ? "destroyed" : leaving ? "leaving" : phase,
|
|
109533
|
+
error: err.code,
|
|
109534
|
+
message: err.messageKey ?? err.pres?.keys[0],
|
|
109535
|
+
locked: !!lockedKey,
|
|
109536
|
+
notice: notice?.code,
|
|
109537
|
+
captcha: "none",
|
|
109538
|
+
email: emailValue.trim() || void 0,
|
|
109539
|
+
locale: getLocale(),
|
|
109540
|
+
theme: getTheme()
|
|
109541
|
+
};
|
|
109542
|
+
},
|
|
109543
|
+
setLocale(l) {
|
|
109544
|
+
if (shell) shell.setLocale(l);
|
|
109545
|
+
},
|
|
109546
|
+
setTheme(th) {
|
|
109547
|
+
if (shell) shell.setTheme(th);
|
|
109548
|
+
},
|
|
109549
|
+
showError(code, extra) {
|
|
109550
|
+
if (destroyed) return;
|
|
109551
|
+
const o = normaliseResult({ ok: false, code, remainingAttempts: extra?.remainingAttempts, message: extra?.message });
|
|
109552
|
+
if (o.kind !== "error") return;
|
|
109553
|
+
if (o.code === "ACCOUNT_LOCKED") lockedKey = emailKey(emailValue);
|
|
109554
|
+
const pres = present(o);
|
|
109555
|
+
err = { code: o.code, pres };
|
|
109556
|
+
renderAlerts();
|
|
109557
|
+
syncControls();
|
|
109558
|
+
},
|
|
109559
|
+
clearError() {
|
|
109560
|
+
if (destroyed) return;
|
|
109561
|
+
err = {};
|
|
109562
|
+
lockedKey = null;
|
|
109563
|
+
renderAlerts();
|
|
109564
|
+
syncControls();
|
|
109565
|
+
},
|
|
109566
|
+
setNotice(n) {
|
|
109567
|
+
if (destroyed) return;
|
|
109568
|
+
notice = n && n.code === "SESSION_EXPIRED" ? n : null;
|
|
109569
|
+
renderNotice();
|
|
109570
|
+
},
|
|
109571
|
+
reset() {
|
|
109572
|
+
if (destroyed || phase !== "success") return;
|
|
109573
|
+
successAbort?.abort();
|
|
109574
|
+
phase = "idle";
|
|
109575
|
+
syncControls();
|
|
109576
|
+
},
|
|
109577
|
+
focus() {
|
|
109578
|
+
(options.initialEmail ? els.password : els.email)?.focus();
|
|
109579
|
+
},
|
|
109580
|
+
get shell() {
|
|
109581
|
+
return restricted;
|
|
109582
|
+
},
|
|
109583
|
+
destroy() {
|
|
109584
|
+
if (destroyed) return;
|
|
109585
|
+
destroyed = true;
|
|
109586
|
+
abortCause = "destroy";
|
|
109587
|
+
attemptAbort?.abort();
|
|
109588
|
+
successAbort?.abort();
|
|
109589
|
+
offChange?.();
|
|
109590
|
+
if (els.password) els.password.value = "";
|
|
109591
|
+
passwordValue = "";
|
|
109592
|
+
if (shell) shell.destroy();
|
|
109593
|
+
else {
|
|
109594
|
+
cardHost.textContent = "";
|
|
109595
|
+
releaseEmbedStyles?.();
|
|
109596
|
+
}
|
|
109597
|
+
},
|
|
109598
|
+
_api: api
|
|
109599
|
+
};
|
|
109600
|
+
return handle;
|
|
109601
|
+
}
|
|
109602
|
+
function createMyioGcdrLoginView(container, options) {
|
|
109603
|
+
const impl = createLoginViewImpl(container, options, { presentation: "inline" });
|
|
109604
|
+
const { _api, ...pub } = impl;
|
|
109605
|
+
void _api;
|
|
109606
|
+
return Object.defineProperty(pub, "shell", { get: () => impl.shell, enumerable: true });
|
|
109607
|
+
}
|
|
109608
|
+
|
|
109609
|
+
// src/components/myio-gcdr-login/modal.ts
|
|
109610
|
+
var MODAL_ATTR = "data-myio-gcdr-modal";
|
|
109611
|
+
var LOCK_ATTR = "data-myio-gcdr-scroll-lock";
|
|
109612
|
+
var INERT_PREV = "data-myio-gcdr-inert-prev";
|
|
109613
|
+
function isMyioGcdrLoginModalOpen(target) {
|
|
109614
|
+
if (target instanceof HTMLElement) return !!target.querySelector(`:scope > [${MODAL_ATTR}]`);
|
|
109615
|
+
const doc = target ?? (typeof document !== "undefined" ? document : void 0);
|
|
109616
|
+
return !!doc?.querySelector(`[${MODAL_ATTR}]`);
|
|
109617
|
+
}
|
|
109618
|
+
function conflict() {
|
|
109619
|
+
const e = new Error("[MYIO Login] a login modal is already open here");
|
|
109620
|
+
e.code = "LOGIN_MODAL_ALREADY_OPEN";
|
|
109621
|
+
throw e;
|
|
109622
|
+
}
|
|
109623
|
+
function openMyioGcdrLoginModal(options) {
|
|
109624
|
+
const ov = options.overlay ?? {};
|
|
109625
|
+
const scopeEl = typeof ov.scope === "object" && ov.scope ? ov.scope.element : null;
|
|
109626
|
+
const doc = scopeEl?.ownerDocument ?? document;
|
|
109627
|
+
const viewport = !scopeEl;
|
|
109628
|
+
const dismissible = ov.dismissible === true;
|
|
109629
|
+
if (viewport && !dismissible && !ov.exit) {
|
|
109630
|
+
throw new TypeError("[MYIO Login] a viewport modal that is not dismissible needs overlay.exit (a way out)");
|
|
109631
|
+
}
|
|
109632
|
+
if (ov.exit && (!ov.exit.href || typeof ov.exit.href !== "string")) throw new TypeError("[MYIO Login] overlay.exit.href is required");
|
|
109633
|
+
if (ov.secondaryAction) {
|
|
109634
|
+
const e = new TypeError("[MYIO Login] overlay.secondaryAction is not available in this version (RFC-0236 PR 4)");
|
|
109635
|
+
e.code = "MYIO_GCDR_SECONDARY_UNSUPPORTED";
|
|
109636
|
+
throw e;
|
|
109637
|
+
}
|
|
109638
|
+
if (viewport ? isMyioGcdrLoginModalOpen(doc) : isMyioGcdrLoginModalOpen(scopeEl)) conflict();
|
|
109639
|
+
const backdrop = ov.backdrop ?? "solid";
|
|
109640
|
+
const opacity = typeof ov.opacity === "number" ? Math.min(1, Math.max(0, ov.opacity)) : 0.5;
|
|
109641
|
+
const blur = typeof ov.blur === "number" ? ov.blur : backdrop === "blur" ? 8 : 4;
|
|
109642
|
+
const previouslyFocused = doc.activeElement;
|
|
109643
|
+
const releaseStyles = acquireStyles(viewport ? doc.body : scopeEl, { nonce: options.cspNonce, loadFont: options.fonts?.load !== false });
|
|
109644
|
+
const overlay = h2(doc, "div", {
|
|
109645
|
+
class: "myio-gcdr-overlay",
|
|
109646
|
+
[MODAL_ATTR]: "1",
|
|
109647
|
+
role: "dialog",
|
|
109648
|
+
"aria-modal": viewport ? "true" : null,
|
|
109649
|
+
"data-scope": viewport ? "viewport" : "element",
|
|
109650
|
+
"data-backdrop": backdrop
|
|
109651
|
+
});
|
|
109652
|
+
overlay.style.zIndex = String(ov.zIndex ?? 1e4);
|
|
109653
|
+
const layers = [];
|
|
109654
|
+
const layer = (bg, extra = "") => {
|
|
109655
|
+
const l = h2(doc, "div", { class: "myio-gcdr-overlay__layer", "aria-hidden": "true" });
|
|
109656
|
+
l.setAttribute("style", `background:${bg};${extra}`);
|
|
109657
|
+
layers.push(l);
|
|
109658
|
+
overlay.appendChild(l);
|
|
109659
|
+
return l;
|
|
109660
|
+
};
|
|
109661
|
+
const paintBackdrop = (dark) => {
|
|
109662
|
+
layers.splice(0).forEach((l) => l.remove());
|
|
109663
|
+
const blurCss = `-webkit-backdrop-filter:blur(${blur}px);backdrop-filter:blur(${blur}px)`;
|
|
109664
|
+
if (backdrop === "blur") {
|
|
109665
|
+
layer(`rgba(20,12,40,${opacity})`, blurCss);
|
|
109666
|
+
} else {
|
|
109667
|
+
layer(dark ? "linear-gradient(180deg,#1B1530 0%,#15121F 45%,#111827 100%)" : "linear-gradient(180deg,#DCD2F3 0%,#EEEAF8 45%,#F7F5FC 100%)");
|
|
109668
|
+
if (backdrop === "image" && options.assets?.wallpaper) {
|
|
109669
|
+
const wp = options.assets.wallpaper;
|
|
109670
|
+
let portrait = false;
|
|
109671
|
+
try {
|
|
109672
|
+
portrait = matchMedia("(orientation: portrait)").matches;
|
|
109673
|
+
} catch {
|
|
109674
|
+
}
|
|
109675
|
+
const url = dark ? portrait ? wp.mobileDark ?? wp.dark : wp.dark : portrait ? wp.mobileLight ?? wp.light : wp.light;
|
|
109676
|
+
if (url) layer(`url("${url.replace(/"/g, "%22")}") center/cover no-repeat`);
|
|
109677
|
+
}
|
|
109678
|
+
layer(`rgba(255,255,255,${(dark ? 0.1 : 0.44) * opacity})`, blurCss);
|
|
109679
|
+
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%)");
|
|
109680
|
+
}
|
|
109681
|
+
layers.forEach((l) => overlay.insertBefore(l, content));
|
|
109682
|
+
};
|
|
109683
|
+
const content = h2(doc, "div", { class: "myio-gcdr-overlay__content" });
|
|
109684
|
+
overlay.appendChild(content);
|
|
109685
|
+
let restoreStatic = null;
|
|
109686
|
+
if (viewport) doc.body.appendChild(overlay);
|
|
109687
|
+
else {
|
|
109688
|
+
const el2 = scopeEl;
|
|
109689
|
+
if (getComputedStyle(el2).position === "static") {
|
|
109690
|
+
const prev = el2.style.position;
|
|
109691
|
+
el2.style.position = "relative";
|
|
109692
|
+
restoreStatic = () => {
|
|
109693
|
+
el2.style.position = prev;
|
|
109694
|
+
};
|
|
109695
|
+
}
|
|
109696
|
+
el2.appendChild(overlay);
|
|
109697
|
+
}
|
|
109698
|
+
let open = true;
|
|
109699
|
+
let closing = false;
|
|
109700
|
+
let exitTimer;
|
|
109701
|
+
const close = (reason) => {
|
|
109702
|
+
if (!open || closing) return;
|
|
109703
|
+
closing = true;
|
|
109704
|
+
if (exitTimer) clearTimeout(exitTimer);
|
|
109705
|
+
mo?.disconnect();
|
|
109706
|
+
try {
|
|
109707
|
+
view.destroy();
|
|
109708
|
+
} catch {
|
|
109709
|
+
}
|
|
109710
|
+
doc.removeEventListener("keydown", onKey, true);
|
|
109711
|
+
overlay.removeEventListener("keydown", onKey, true);
|
|
109712
|
+
if (viewport) {
|
|
109713
|
+
releaseInert();
|
|
109714
|
+
releaseScroll();
|
|
109715
|
+
}
|
|
109716
|
+
overlay.remove();
|
|
109717
|
+
restoreStatic?.();
|
|
109718
|
+
releaseStyles();
|
|
109719
|
+
open = false;
|
|
109720
|
+
if (previouslyFocused && previouslyFocused.isConnected && typeof previouslyFocused.focus === "function") previouslyFocused.focus();
|
|
109721
|
+
else if (viewport) doc.body.focus?.();
|
|
109722
|
+
safeCall("onClose", options.onClose, reason);
|
|
109723
|
+
};
|
|
109724
|
+
const { overlay: _o, onOpen, onClose, ...viewOpts } = options;
|
|
109725
|
+
void _o;
|
|
109726
|
+
void onClose;
|
|
109727
|
+
const view = createLoginViewImpl(content, { ...viewOpts, aside: options.aside ?? { kind: "none" }, autoFocus: false }, {
|
|
109728
|
+
presentation: "modal",
|
|
109729
|
+
shellWallpaper: false,
|
|
109730
|
+
afterSuccess: () => {
|
|
109731
|
+
if (ov.closeOnSuccess !== false) close("success");
|
|
109732
|
+
},
|
|
109733
|
+
decorateFooter: (footer, api) => {
|
|
109734
|
+
if (!ov.exit) return;
|
|
109735
|
+
const label = localize(ov.exit.label, api.locale());
|
|
109736
|
+
const a = h2(doc, "a", { class: "myio-gcdr-login__link", href: ov.exit.href, style: "display:inline-block;margin-left:12px" }, label);
|
|
109737
|
+
a.addEventListener("click", () => {
|
|
109738
|
+
if (api.phase() === "success") return;
|
|
109739
|
+
api.abortAttempt();
|
|
109740
|
+
api.clearPassword();
|
|
109741
|
+
a.textContent = api.t("login.leaving");
|
|
109742
|
+
a.setAttribute("aria-busy", "true");
|
|
109743
|
+
exitTimer = setTimeout(() => {
|
|
109744
|
+
if (!open) return;
|
|
109745
|
+
a.textContent = label;
|
|
109746
|
+
a.removeAttribute("aria-busy");
|
|
109747
|
+
api.showLeaveFailed();
|
|
109748
|
+
a.focus();
|
|
109749
|
+
}, 2e3);
|
|
109750
|
+
});
|
|
109751
|
+
footer.appendChild(a);
|
|
109752
|
+
}
|
|
109753
|
+
});
|
|
109754
|
+
const shellRoot = content.querySelector(".myio-gcdr-shell");
|
|
109755
|
+
const syncTheme = () => {
|
|
109756
|
+
const dark = view.getState().theme === "dark";
|
|
109757
|
+
overlay.setAttribute("data-theme", dark ? "dark" : "light");
|
|
109758
|
+
paintBackdrop(dark);
|
|
109759
|
+
};
|
|
109760
|
+
syncTheme();
|
|
109761
|
+
const mo = shellRoot ? new MutationObserver(syncTheme) : null;
|
|
109762
|
+
mo?.observe(shellRoot, { attributes: true, attributeFilter: ["data-theme"] });
|
|
109763
|
+
if (backdrop === "blur" && options.show?.themeToggle === void 0) view.shell?.setShow({ themeToggle: false });
|
|
109764
|
+
const title = content.querySelector(".myio-gcdr-panel__title");
|
|
109765
|
+
if (title) {
|
|
109766
|
+
if (!title.id) title.id = `myio-gcdr-title-${Math.random().toString(36).slice(2, 8)}`;
|
|
109767
|
+
overlay.setAttribute("aria-labelledby", title.id);
|
|
109768
|
+
}
|
|
109769
|
+
if (dismissible) {
|
|
109770
|
+
const x = h2(doc, "button", { type: "button", class: "myio-gcdr-shell__iconbtn myio-gcdr-overlay__close", "aria-label": view._api.t("modal.close") });
|
|
109771
|
+
x.appendChild(icon(doc, ICONS.x(18)));
|
|
109772
|
+
x.addEventListener("click", () => {
|
|
109773
|
+
const p = view.getState().phase;
|
|
109774
|
+
if (p !== "submitting" && p !== "success") close("dismiss");
|
|
109775
|
+
});
|
|
109776
|
+
content.appendChild(x);
|
|
109777
|
+
}
|
|
109778
|
+
const inerted = [];
|
|
109779
|
+
const releaseInert = () => {
|
|
109780
|
+
for (const el2 of inerted) {
|
|
109781
|
+
const prev = el2.getAttribute(INERT_PREV);
|
|
109782
|
+
if (prev === "true") el2.setAttribute("inert", "");
|
|
109783
|
+
else el2.removeAttribute("inert");
|
|
109784
|
+
el2.removeAttribute(INERT_PREV);
|
|
109785
|
+
}
|
|
109786
|
+
inerted.length = 0;
|
|
109787
|
+
};
|
|
109788
|
+
let scrollPrev = null;
|
|
109789
|
+
const releaseScroll = () => {
|
|
109790
|
+
const html = doc.documentElement;
|
|
109791
|
+
const n = Math.max(0, (parseInt(html.getAttribute(LOCK_ATTR) || "1", 10) || 1) - 1);
|
|
109792
|
+
if (n === 0) {
|
|
109793
|
+
html.removeAttribute(LOCK_ATTR);
|
|
109794
|
+
if (scrollPrev) {
|
|
109795
|
+
html.style.overflow = scrollPrev.html;
|
|
109796
|
+
doc.body.style.overflow = scrollPrev.body;
|
|
109797
|
+
}
|
|
109798
|
+
} else html.setAttribute(LOCK_ATTR, String(n));
|
|
109799
|
+
};
|
|
109800
|
+
if (viewport) {
|
|
109801
|
+
for (const el2 of Array.from(doc.body.children)) {
|
|
109802
|
+
if (el2 === overlay || el2.tagName === "SCRIPT" || el2.tagName === "STYLE") continue;
|
|
109803
|
+
el2.setAttribute(INERT_PREV, el2.hasAttribute("inert") ? "true" : "false");
|
|
109804
|
+
el2.setAttribute("inert", "");
|
|
109805
|
+
inerted.push(el2);
|
|
109806
|
+
}
|
|
109807
|
+
const html = doc.documentElement;
|
|
109808
|
+
const n = parseInt(html.getAttribute(LOCK_ATTR) || "0", 10) || 0;
|
|
109809
|
+
if (n === 0) scrollPrev = { html: html.style.overflow, body: doc.body.style.overflow };
|
|
109810
|
+
html.setAttribute(LOCK_ATTR, String(n + 1));
|
|
109811
|
+
html.style.overflow = "hidden";
|
|
109812
|
+
doc.body.style.overflow = "hidden";
|
|
109813
|
+
}
|
|
109814
|
+
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);
|
|
109815
|
+
const onKey = (e) => {
|
|
109816
|
+
if (!open) return;
|
|
109817
|
+
if (e.key === "Escape" && dismissible) {
|
|
109818
|
+
const p = view.getState().phase;
|
|
109819
|
+
if (p !== "submitting" && p !== "success") {
|
|
109820
|
+
e.preventDefault();
|
|
109821
|
+
close("dismiss");
|
|
109822
|
+
}
|
|
109823
|
+
return;
|
|
109824
|
+
}
|
|
109825
|
+
if (e.key === "Tab" && viewport) {
|
|
109826
|
+
const list = focusables();
|
|
109827
|
+
if (!list.length) return;
|
|
109828
|
+
const first = list[0];
|
|
109829
|
+
const last = list[list.length - 1];
|
|
109830
|
+
const active = doc.activeElement;
|
|
109831
|
+
if (e.shiftKey && (active === first || !overlay.contains(active))) {
|
|
109832
|
+
e.preventDefault();
|
|
109833
|
+
last.focus();
|
|
109834
|
+
} else if (!e.shiftKey && (active === last || !overlay.contains(active))) {
|
|
109835
|
+
e.preventDefault();
|
|
109836
|
+
first.focus();
|
|
109837
|
+
}
|
|
109838
|
+
}
|
|
109839
|
+
};
|
|
109840
|
+
if (viewport) doc.addEventListener("keydown", onKey, true);
|
|
109841
|
+
else overlay.addEventListener("keydown", onKey, true);
|
|
109842
|
+
const emailInput = content.querySelector('[data-k="email"]');
|
|
109843
|
+
const passInput = content.querySelector('[data-k="password"]');
|
|
109844
|
+
const coarse = (() => {
|
|
109845
|
+
try {
|
|
109846
|
+
return matchMedia("(pointer: coarse)").matches;
|
|
109847
|
+
} catch {
|
|
109848
|
+
return false;
|
|
109849
|
+
}
|
|
109850
|
+
})();
|
|
109851
|
+
const wantInput = options.autoFocus ?? !coarse;
|
|
109852
|
+
((wantInput ? options.initialEmail ? passInput : emailInput : title) ?? title)?.focus();
|
|
109853
|
+
safeCall("onOpen", onOpen);
|
|
109854
|
+
const handle = {
|
|
109855
|
+
getState: () => view.getState(),
|
|
109856
|
+
setLocale: (l) => view.setLocale(l),
|
|
109857
|
+
setTheme: (th) => view.setTheme(th),
|
|
109858
|
+
showError: (c, x) => view.showError(c, x),
|
|
109859
|
+
clearError: () => view.clearError(),
|
|
109860
|
+
setNotice: (n) => view.setNotice(n),
|
|
109861
|
+
reset: () => view.reset(),
|
|
109862
|
+
focus: () => view.focus(),
|
|
109863
|
+
close: () => close("api"),
|
|
109864
|
+
destroy: () => close("api"),
|
|
109865
|
+
get isOpen() {
|
|
109866
|
+
return open;
|
|
109867
|
+
}
|
|
109868
|
+
};
|
|
109869
|
+
return handle;
|
|
109870
|
+
}
|
|
109871
|
+
|
|
107784
109872
|
// src/components/img-gallery/ScrollableTabs.ts
|
|
107785
109873
|
var STYLE_ID11 = "myio-tabs-styles";
|
|
107786
109874
|
var FONT_LINK_ID3 = "myio-dialog-font-nunito";
|
|
@@ -108417,13 +110505,13 @@ function createImgGallery(options) {
|
|
|
108417
110505
|
grid.appendChild(item);
|
|
108418
110506
|
});
|
|
108419
110507
|
}
|
|
108420
|
-
function actionBtn(
|
|
110508
|
+
function actionBtn(icon2, label, danger, onClick) {
|
|
108421
110509
|
const b = document.createElement("button");
|
|
108422
110510
|
b.type = "button";
|
|
108423
110511
|
b.className = `myio-gallery__abtn${danger ? " myio-gallery__abtn--danger" : ""}`;
|
|
108424
110512
|
b.setAttribute("aria-label", label);
|
|
108425
110513
|
b.title = label;
|
|
108426
|
-
b.innerHTML =
|
|
110514
|
+
b.innerHTML = icon2;
|
|
108427
110515
|
b.addEventListener("click", onClick);
|
|
108428
110516
|
return b;
|
|
108429
110517
|
}
|
|
@@ -116563,7 +118651,7 @@ var MenuView = class {
|
|
|
116563
118651
|
*/
|
|
116564
118652
|
bindFilterTooltipEvents(listEl) {
|
|
116565
118653
|
const icons = listEl.querySelectorAll(".filter-icon[data-tooltip-type]");
|
|
116566
|
-
icons.forEach((
|
|
118654
|
+
icons.forEach((icon2) => {
|
|
116567
118655
|
const showHandler = (e) => {
|
|
116568
118656
|
e.stopPropagation();
|
|
116569
118657
|
const el2 = e.currentTarget;
|
|
@@ -116574,9 +118662,9 @@ var MenuView = class {
|
|
|
116574
118662
|
const hideHandler = () => {
|
|
116575
118663
|
this.hideFilterTooltips();
|
|
116576
118664
|
};
|
|
116577
|
-
|
|
116578
|
-
|
|
116579
|
-
|
|
118665
|
+
icon2.addEventListener("mouseenter", showHandler);
|
|
118666
|
+
icon2.addEventListener("click", showHandler);
|
|
118667
|
+
icon2.addEventListener("mouseleave", hideHandler);
|
|
116580
118668
|
});
|
|
116581
118669
|
}
|
|
116582
118670
|
/**
|
|
@@ -120398,11 +122486,11 @@ var FilterModalView = class {
|
|
|
120398
122486
|
const allTab = this.filterTabs.find((t) => t.id === "all");
|
|
120399
122487
|
let html = "";
|
|
120400
122488
|
if (allTab) {
|
|
120401
|
-
const
|
|
122489
|
+
const icon2 = FILTER_TAB_ICONS["all"] || "";
|
|
120402
122490
|
html += `
|
|
120403
122491
|
<div class="filter-group filter-group-all">
|
|
120404
122492
|
<button class="filter-tab active" data-filter="all">
|
|
120405
|
-
${
|
|
122493
|
+
${icon2} ${allTab.label} (<span id="countAll">${counts["all"] || 0}</span>)
|
|
120406
122494
|
</button>
|
|
120407
122495
|
</div>
|
|
120408
122496
|
`;
|
|
@@ -120415,12 +122503,12 @@ var FilterModalView = class {
|
|
|
120415
122503
|
<span class="filter-group-label">${group.label}</span>
|
|
120416
122504
|
<div class="filter-group-tabs">
|
|
120417
122505
|
${groupTabs.map((tab) => {
|
|
120418
|
-
const
|
|
122506
|
+
const icon2 = FILTER_TAB_ICONS[tab.id] || "";
|
|
120419
122507
|
const count = counts[tab.id] || 0;
|
|
120420
122508
|
const expandBtn = count > 0 ? `<button class="filter-tab-expand" data-expand-filter="${tab.id}" title="Ver dispositivos">+</button>` : "";
|
|
120421
122509
|
return `
|
|
120422
122510
|
<button class="filter-tab active" data-filter="${tab.id}">
|
|
120423
|
-
${
|
|
122511
|
+
${icon2} ${tab.label} (<span id="count${tab.id.charAt(0).toUpperCase() + tab.id.slice(1)}">${count}</span>)${expandBtn}
|
|
120424
122512
|
</button>
|
|
120425
122513
|
`;
|
|
120426
122514
|
}).join("")}
|
|
@@ -120797,7 +122885,7 @@ var FilterModalView = class {
|
|
|
120797
122885
|
if (!InfoTooltip2?.InfoTooltip) return;
|
|
120798
122886
|
const filterTabConfig = this.filterTabs.find((t) => t.id === filterId);
|
|
120799
122887
|
const label = filterTabConfig?.label || filterId;
|
|
120800
|
-
const
|
|
122888
|
+
const icon2 = FILTER_TAB_ICONS[filterId] || "\u{1F4CB}";
|
|
120801
122889
|
let devicesHtml = "";
|
|
120802
122890
|
if (devices.length === 0) {
|
|
120803
122891
|
devicesHtml = `
|
|
@@ -120849,7 +122937,7 @@ var FilterModalView = class {
|
|
|
120849
122937
|
`;
|
|
120850
122938
|
}
|
|
120851
122939
|
InfoTooltip2.InfoTooltip.show(triggerEl, {
|
|
120852
|
-
icon,
|
|
122940
|
+
icon: icon2,
|
|
120853
122941
|
title: `${label} (${devices.length})`,
|
|
120854
122942
|
content: devicesHtml
|
|
120855
122943
|
});
|
|
@@ -121714,7 +123802,7 @@ var FilterModalComponent = class {
|
|
|
121714
123802
|
}
|
|
121715
123803
|
// ── Private ────────────────────────────────
|
|
121716
123804
|
render() {
|
|
121717
|
-
const { title, icon, categories, sortOptions, devices = [] } = this.options;
|
|
123805
|
+
const { title, icon: icon2, categories, sortOptions, devices = [] } = this.options;
|
|
121718
123806
|
const hasDevices = this.showDeviceGrid && devices.length > 0;
|
|
121719
123807
|
const modalClass = `myio-fm myio-fm--${this.themeMode}${hasDevices ? " myio-fm--with-devices" : ""}`;
|
|
121720
123808
|
const bodyClass = `myio-fm__body${hasDevices ? " myio-fm__body--two-col" : ""}`;
|
|
@@ -121722,7 +123810,7 @@ var FilterModalComponent = class {
|
|
|
121722
123810
|
<div class="${modalClass}">
|
|
121723
123811
|
<div class="myio-fm__header">
|
|
121724
123812
|
<div class="myio-fm__header-left">
|
|
121725
|
-
${
|
|
123813
|
+
${icon2 ? `<span class="myio-fm__icon">${icon2}</span>` : ""}
|
|
121726
123814
|
<h2 class="myio-fm__title">${this.escapeHtml(title)}</h2>
|
|
121727
123815
|
</div>
|
|
121728
123816
|
<button class="myio-fm__close" title="Fechar">
|
|
@@ -121801,7 +123889,7 @@ var FilterModalComponent = class {
|
|
|
121801
123889
|
renderDeviceItem(device) {
|
|
121802
123890
|
const isSelected = this.selectedDeviceIds.has(device.id);
|
|
121803
123891
|
const statusClass = device.status ? `myio-fm__device-status--${device.status}` : "";
|
|
121804
|
-
const
|
|
123892
|
+
const icon2 = device.icon || this.getDefaultDeviceIcon(device.type, device.context);
|
|
121805
123893
|
return `
|
|
121806
123894
|
<div class="myio-fm__device-item${isSelected ? " myio-fm__device-item--selected" : ""}"
|
|
121807
123895
|
data-device-id="${device.id}"
|
|
@@ -121809,7 +123897,7 @@ var FilterModalComponent = class {
|
|
|
121809
123897
|
<div class="myio-fm__device-checkbox">
|
|
121810
123898
|
${ICON_CHECK}
|
|
121811
123899
|
</div>
|
|
121812
|
-
${
|
|
123900
|
+
${icon2 ? `<span class="myio-fm__device-icon">${icon2}</span>` : ""}
|
|
121813
123901
|
<div class="myio-fm__device-info">
|
|
121814
123902
|
<p class="myio-fm__device-label" title="${this.escapeHtml(device.label)}">${this.escapeHtml(device.label)}</p>
|
|
121815
123903
|
${device.type ? `<p class="myio-fm__device-type">${this.escapeHtml(device.type)}</p>` : ""}
|
|
@@ -122577,7 +124665,7 @@ function createCustomerCardV1(params) {
|
|
|
122577
124665
|
|
|
122578
124666
|
// src/components/cards/customer-goals/v1.0.0/styles.ts
|
|
122579
124667
|
var STYLE_ID13 = "myio-customer-goals-card-css";
|
|
122580
|
-
var
|
|
124668
|
+
var CSS4 = `
|
|
122581
124669
|
.myio-cgc{
|
|
122582
124670
|
--cgc-surface:#ffffff;
|
|
122583
124671
|
--cgc-border:#e2e8f0;
|
|
@@ -122680,7 +124768,7 @@ function injectCustomerGoalsCardStyles() {
|
|
|
122680
124768
|
if (document.getElementById(STYLE_ID13)) return;
|
|
122681
124769
|
const tag = document.createElement("style");
|
|
122682
124770
|
tag.id = STYLE_ID13;
|
|
122683
|
-
tag.textContent =
|
|
124771
|
+
tag.textContent = CSS4;
|
|
122684
124772
|
document.head.appendChild(tag);
|
|
122685
124773
|
}
|
|
122686
124774
|
|
|
@@ -123795,13 +125883,13 @@ var EnergyPanelView = class {
|
|
|
123795
125883
|
/**
|
|
123796
125884
|
* Build a single card HTML with the TELEMETRY_INFO-inspired layout
|
|
123797
125885
|
*/
|
|
123798
|
-
buildCardHTML(type,
|
|
125886
|
+
buildCardHTML(type, icon2, title, value, percentage, tooltip) {
|
|
123799
125887
|
const percDisplay = percentage !== null ? `(${percentage}%)` : "";
|
|
123800
125888
|
const tooltipHTML = tooltip ? `<span class="energy-panel__card-tooltip" title="${tooltip}">\u2139\uFE0F</span>` : "";
|
|
123801
125889
|
return `
|
|
123802
125890
|
<div class="energy-panel__card" data-type="${type}">
|
|
123803
125891
|
<div class="energy-panel__card-header">
|
|
123804
|
-
<span class="energy-panel__card-icon">${
|
|
125892
|
+
<span class="energy-panel__card-icon">${icon2}</span>
|
|
123805
125893
|
<h3 class="energy-panel__card-title">${title}</h3>
|
|
123806
125894
|
${tooltipHTML}
|
|
123807
125895
|
</div>
|
|
@@ -126942,7 +129030,7 @@ var HeaderShoppingView = class {
|
|
|
126942
129030
|
emit(event, ...args) {
|
|
126943
129031
|
const handlers = this.eventHandlers.get(event);
|
|
126944
129032
|
if (handlers) {
|
|
126945
|
-
handlers.forEach((
|
|
129033
|
+
handlers.forEach((h3) => h3(...args));
|
|
126946
129034
|
}
|
|
126947
129035
|
}
|
|
126948
129036
|
/**
|
|
@@ -127398,7 +129486,7 @@ function createHeaderShoppingComponent(params) {
|
|
|
127398
129486
|
function emit(event, ...args) {
|
|
127399
129487
|
const handlers = eventHandlers.get(event);
|
|
127400
129488
|
if (handlers) {
|
|
127401
|
-
handlers.forEach((
|
|
129489
|
+
handlers.forEach((h3) => h3(...args));
|
|
127402
129490
|
}
|
|
127403
129491
|
}
|
|
127404
129492
|
function on(event, handler) {
|
|
@@ -128288,7 +130376,7 @@ var MenuShoppingView = class {
|
|
|
128288
130376
|
emit(event, ...args) {
|
|
128289
130377
|
const handlers = this.eventHandlers.get(event);
|
|
128290
130378
|
if (handlers) {
|
|
128291
|
-
handlers.forEach((
|
|
130379
|
+
handlers.forEach((h3) => h3(...args));
|
|
128292
130380
|
}
|
|
128293
130381
|
}
|
|
128294
130382
|
/**
|
|
@@ -128457,7 +130545,7 @@ function createMenuShoppingComponent(params) {
|
|
|
128457
130545
|
function emitEvent(event, ...args) {
|
|
128458
130546
|
const handlers = eventHandlers.get(event);
|
|
128459
130547
|
if (handlers) {
|
|
128460
|
-
handlers.forEach((
|
|
130548
|
+
handlers.forEach((h3) => h3(...args));
|
|
128461
130549
|
}
|
|
128462
130550
|
}
|
|
128463
130551
|
function cleanup() {
|
|
@@ -130450,8 +132538,8 @@ var TelemetryGridShoppingView = class {
|
|
|
130450
132538
|
}
|
|
130451
132539
|
}
|
|
130452
132540
|
}
|
|
130453
|
-
const
|
|
130454
|
-
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${
|
|
132541
|
+
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"/>';
|
|
132542
|
+
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon2}</svg>`;
|
|
130455
132543
|
}
|
|
130456
132544
|
};
|
|
130457
132545
|
|
|
@@ -132382,9 +134470,9 @@ var TelemetryInfoShoppingView = class _TelemetryInfoShoppingView {
|
|
|
132382
134470
|
this.maximizeBtnEl.style.opacity = "0";
|
|
132383
134471
|
}
|
|
132384
134472
|
}
|
|
132385
|
-
const
|
|
134473
|
+
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
134474
|
if (this.maximizeBtnEl) {
|
|
132387
|
-
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${
|
|
134475
|
+
this.maximizeBtnEl.innerHTML = `<svg viewBox="0 0 24 24" width="18" height="18">${icon2}</svg>`;
|
|
132388
134476
|
}
|
|
132389
134477
|
this.params.onExpandClick?.();
|
|
132390
134478
|
}
|
|
@@ -139424,7 +141512,7 @@ function renderTrendChart(data, options = {}) {
|
|
|
139424
141512
|
Cr\xEDticos
|
|
139425
141513
|
</span>
|
|
139426
141514
|
</div>`;
|
|
139427
|
-
const
|
|
141515
|
+
const svg2 = `
|
|
139428
141516
|
<svg class="alarms-trend-chart" viewBox="0 0 ${width} ${height}" preserveAspectRatio="xMidYMid meet">
|
|
139429
141517
|
<defs>
|
|
139430
141518
|
<linearGradient id="gradTotal" x1="0" y1="0" x2="0" y2="1">
|
|
@@ -139445,7 +141533,7 @@ function renderTrendChart(data, options = {}) {
|
|
|
139445
141533
|
<circle cx="${lastCritical[0].toFixed(1)}" cy="${lastCritical[1].toFixed(1)}" r="4" fill="${criticalColor}" />
|
|
139446
141534
|
${xLabels}
|
|
139447
141535
|
</svg>`;
|
|
139448
|
-
return `<div class="alarms-trend-wrap">${
|
|
141536
|
+
return `<div class="alarms-trend-wrap">${svg2}${legend}</div>`;
|
|
139449
141537
|
}
|
|
139450
141538
|
function renderStateDonutChart(byState, options = {}) {
|
|
139451
141539
|
if (!byState) return renderEmptyChart(200, 200, "Sem dados");
|
|
@@ -140489,8 +142577,8 @@ var AlarmsNotificationsPanelView = class {
|
|
|
140489
142577
|
}
|
|
140490
142578
|
const th = (label, col, extraClass = "") => {
|
|
140491
142579
|
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}${
|
|
142580
|
+
const icon2 = active ? `<span class="atbl-sort-icon is-active">${this.sortDir === "asc" ? "\u25B2" : "\u25BC"}</span>` : `<span class="atbl-sort-icon">\u21C5</span>`;
|
|
142581
|
+
return `<th class="atbl-th atbl-th--sortable${extraClass ? " " + extraClass : ""}${active ? " is-sorted" : ""}" data-sort-col="${col}">${label}${icon2}</th>`;
|
|
140494
142582
|
};
|
|
140495
142583
|
const rows = alarms.map((alarm) => {
|
|
140496
142584
|
const sev = SEVERITY_CONFIG[alarm.severity];
|
|
@@ -144097,9 +146185,9 @@ function renderDualLineChart(data) {
|
|
|
144097
146185
|
}
|
|
144098
146186
|
function formatTrendIndicator(trend) {
|
|
144099
146187
|
if (trend === void 0 || trend === 0) return "";
|
|
144100
|
-
const
|
|
146188
|
+
const icon2 = trend > 0 ? "\u2191" : "\u2193";
|
|
144101
146189
|
const cls = trend > 0 ? "trend-up" : "trend-down";
|
|
144102
|
-
return `<span class="trend-indicator ${cls}">${
|
|
146190
|
+
return `<span class="trend-indicator ${cls}">${icon2}${Math.abs(trend)}</span>`;
|
|
144103
146191
|
}
|
|
144104
146192
|
function renderStatusDonutChart(kpis, period) {
|
|
144105
146193
|
const offlineCritical = kpis.offlineCriticalCount || 0;
|
|
@@ -144405,10 +146493,10 @@ function formatHoursDisplay(hours) {
|
|
|
144405
146493
|
const mins = Math.round(hours * 60);
|
|
144406
146494
|
return `${mins}min`;
|
|
144407
146495
|
}
|
|
144408
|
-
const
|
|
144409
|
-
const m = Math.round((hours -
|
|
144410
|
-
if (m === 0) return `${
|
|
144411
|
-
return `${
|
|
146496
|
+
const h3 = Math.floor(hours);
|
|
146497
|
+
const m = Math.round((hours - h3) * 60);
|
|
146498
|
+
if (m === 0) return `${h3}h`;
|
|
146499
|
+
return `${h3}h${String(m).padStart(2, "0")}`;
|
|
144412
146500
|
}
|
|
144413
146501
|
function renderMTBFTimelineChart(data) {
|
|
144414
146502
|
if (!data.segments || data.segments.length === 0) {
|
|
@@ -147860,12 +149948,12 @@ var SwitchControlView = class {
|
|
|
147860
149948
|
document.querySelectorAll(`.${SWITCH_CONTROL_CSS_PREFIX}__modal-overlay`).forEach((el2) => el2.remove());
|
|
147861
149949
|
const { labels } = this.settings;
|
|
147862
149950
|
const newStatus = this.state.status === "on" ? "off" : "on";
|
|
147863
|
-
const
|
|
149951
|
+
const icon2 = newStatus === "on" ? "\u{1F4A1}" : "\u{1F50C}";
|
|
147864
149952
|
const modal = document.createElement("div");
|
|
147865
149953
|
modal.className = `${SWITCH_CONTROL_CSS_PREFIX}__modal-overlay`;
|
|
147866
149954
|
modal.innerHTML = `
|
|
147867
149955
|
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal">
|
|
147868
|
-
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-icon">${
|
|
149956
|
+
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-icon">${icon2}</div>
|
|
147869
149957
|
<h3 class="${SWITCH_CONTROL_CSS_PREFIX}__modal-title">${this.escapeHtml(this.state.name)}</h3>
|
|
147870
149958
|
<p class="${SWITCH_CONTROL_CSS_PREFIX}__modal-message">${message}</p>
|
|
147871
149959
|
<div class="${SWITCH_CONTROL_CSS_PREFIX}__modal-actions">
|
|
@@ -148192,7 +150280,7 @@ var ActionButtonView = class {
|
|
|
148192
150280
|
return classes.join(" ");
|
|
148193
150281
|
}
|
|
148194
150282
|
applyAll() {
|
|
148195
|
-
const { label, icon, variant, color, textColor, borderRadius, disabled, tooltip } = this.settings;
|
|
150283
|
+
const { label, icon: icon2, variant, color, textColor, borderRadius, disabled, tooltip } = this.settings;
|
|
148196
150284
|
this.root.className = this.buildClassName();
|
|
148197
150285
|
this.root.disabled = disabled;
|
|
148198
150286
|
this.root.style.borderRadius = `${borderRadius}px`;
|
|
@@ -148205,8 +150293,8 @@ var ActionButtonView = class {
|
|
|
148205
150293
|
this.root.style.color = textColor || color;
|
|
148206
150294
|
}
|
|
148207
150295
|
let html = "";
|
|
148208
|
-
if (
|
|
148209
|
-
html += `<span class="${ACTION_BUTTON_CSS_PREFIX}__icon">${this.escapeHtml(
|
|
150296
|
+
if (icon2) {
|
|
150297
|
+
html += `<span class="${ACTION_BUTTON_CSS_PREFIX}__icon">${this.escapeHtml(icon2)}</span>`;
|
|
148210
150298
|
}
|
|
148211
150299
|
if (label) {
|
|
148212
150300
|
html += `<span>${this.escapeHtml(label)}</span>`;
|
|
@@ -152476,12 +154564,12 @@ function renderTimelineSVG(data, config2) {
|
|
|
152476
154564
|
const segWidth = Math.max(x2 - x1, 4);
|
|
152477
154565
|
const isOn = seg.state === "on";
|
|
152478
154566
|
const y = isOn ? onY : offY - 15;
|
|
152479
|
-
const
|
|
154567
|
+
const h3 = isOn ? barHeight : 15;
|
|
152480
154568
|
const color = isOn ? onColor : offColor;
|
|
152481
154569
|
const stateClass = isOn ? "on" : "off";
|
|
152482
154570
|
segmentPaths += `
|
|
152483
154571
|
<rect
|
|
152484
|
-
x="${x1}" y="${y}" width="${segWidth}" height="${
|
|
154572
|
+
x="${x1}" y="${y}" width="${segWidth}" height="${h3}"
|
|
152485
154573
|
fill="${color}" rx="3"
|
|
152486
154574
|
class="${ONOFF_TIMELINE_CSS_PREFIX}__segment ${ONOFF_TIMELINE_CSS_PREFIX}__segment--${stateClass}"
|
|
152487
154575
|
data-index="${index}"
|
|
@@ -152489,7 +154577,7 @@ function renderTimelineSVG(data, config2) {
|
|
|
152489
154577
|
`;
|
|
152490
154578
|
if (showDurationLabels && segWidth > 45) {
|
|
152491
154579
|
const centerX = x1 + segWidth / 2;
|
|
152492
|
-
const centerY = y +
|
|
154580
|
+
const centerY = y + h3 / 2 + 3;
|
|
152493
154581
|
durationLabels += `
|
|
152494
154582
|
<text
|
|
152495
154583
|
x="${centerX}" y="${centerY}"
|
|
@@ -152516,7 +154604,7 @@ function renderTimelineSVG(data, config2) {
|
|
|
152516
154604
|
}
|
|
152517
154605
|
tooltipAreas += `
|
|
152518
154606
|
<rect
|
|
152519
|
-
x="${x1}" y="${y}" width="${segWidth}" height="${
|
|
154607
|
+
x="${x1}" y="${y}" width="${segWidth}" height="${h3}"
|
|
152520
154608
|
fill="transparent"
|
|
152521
154609
|
class="tooltip-trigger"
|
|
152522
154610
|
data-state="${stateClass}"
|
|
@@ -153925,15 +156013,15 @@ var OnOffDeviceModalView = class {
|
|
|
153925
156013
|
if (!anchor) return;
|
|
153926
156014
|
const ev = this.evalDeviceStatus();
|
|
153927
156015
|
if (!ev.statusStale && !ev.connectionStale) return;
|
|
153928
|
-
const
|
|
153929
|
-
|
|
153930
|
-
|
|
153931
|
-
|
|
153932
|
-
|
|
153933
|
-
anchor.appendChild(
|
|
156016
|
+
const icon2 = document.createElement("span");
|
|
156017
|
+
icon2.className = `${ON_OFF_MODAL_CSS_PREFIX}__status-warning`;
|
|
156018
|
+
icon2.textContent = "\u26A0\uFE0F";
|
|
156019
|
+
icon2.style.cssText = "cursor: help; font-size: 16px; margin-left: 8px; line-height: 1; user-select: none; display: inline-block;";
|
|
156020
|
+
icon2.setAttribute("aria-label", "Telemetria de status desatualizada");
|
|
156021
|
+
anchor.appendChild(icon2);
|
|
153934
156022
|
const when = formatStatusTimestamp(ev.statusTs);
|
|
153935
156023
|
const lastValue = (ev.value || "\u2014").toString().toUpperCase();
|
|
153936
|
-
this.statusWarnTooltipCleanup = InfoTooltip_default.attach(
|
|
156024
|
+
this.statusWarnTooltipCleanup = InfoTooltip_default.attach(icon2, () => ({
|
|
153937
156025
|
icon: "\u26A0\uFE0F",
|
|
153938
156026
|
title: "Status possivelmente desatualizado",
|
|
153939
156027
|
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 +156160,8 @@ var OnOffDeviceModalView = class {
|
|
|
154072
156160
|
actions.appendChild(btnYes);
|
|
154073
156161
|
actions.appendChild(btnNo);
|
|
154074
156162
|
} else {
|
|
154075
|
-
const
|
|
154076
|
-
msg.textContent = `${
|
|
156163
|
+
const icon2 = type === "success" ? "\u2705" : "\u274C";
|
|
156164
|
+
msg.textContent = `${icon2} ${message}`;
|
|
154077
156165
|
const btnClose = document.createElement("button");
|
|
154078
156166
|
btnClose.textContent = "Fechar";
|
|
154079
156167
|
btnClose.style.cssText = `
|
|
@@ -154207,12 +156295,12 @@ var OnOffDeviceModalView = class {
|
|
|
154207
156295
|
this.updateScheduleButton("\u{1F4C5}", "Agendamento");
|
|
154208
156296
|
}
|
|
154209
156297
|
}
|
|
154210
|
-
updateScheduleButton(
|
|
156298
|
+
updateScheduleButton(icon2, label) {
|
|
154211
156299
|
const btn = this.scheduleButtonContainer?.querySelector(`.${ON_OFF_MODAL_CSS_PREFIX}__schedule-btn`);
|
|
154212
156300
|
if (btn) {
|
|
154213
156301
|
const iconEl = btn.querySelector("[data-icon]");
|
|
154214
156302
|
const labelEl = btn.querySelector("[data-label]");
|
|
154215
|
-
if (iconEl) iconEl.textContent =
|
|
156303
|
+
if (iconEl) iconEl.textContent = icon2;
|
|
154216
156304
|
if (labelEl) labelEl.textContent = label;
|
|
154217
156305
|
}
|
|
154218
156306
|
}
|
|
@@ -159292,10 +161380,10 @@ function renderStep22(plan) {
|
|
|
159292
161380
|
const customers = nonSkip.filter((a) => a.entityKind === "customer");
|
|
159293
161381
|
const assets = nonSkip.filter((a) => a.entityKind === "asset");
|
|
159294
161382
|
const devices = nonSkip.filter((a) => a.entityKind === "device");
|
|
159295
|
-
function sectionHtml(
|
|
161383
|
+
function sectionHtml(icon2, title, actions) {
|
|
159296
161384
|
if (actions.length === 0) return "";
|
|
159297
161385
|
return `
|
|
159298
|
-
<div class="gcdr-section-title">${
|
|
161386
|
+
<div class="gcdr-section-title">${icon2} ${title} (${actions.length})</div>
|
|
159299
161387
|
<ul class="gcdr-action-list">
|
|
159300
161388
|
${actions.map((a) => `
|
|
159301
161389
|
<li class="gcdr-action-item">
|
|
@@ -159986,9 +162074,9 @@ function formatDuration3(ms) {
|
|
|
159986
162074
|
if (!ms) return "";
|
|
159987
162075
|
const min = Math.round(ms / 6e4);
|
|
159988
162076
|
if (min < 60) return `${min} min`;
|
|
159989
|
-
const
|
|
162077
|
+
const h3 = Math.floor(min / 60);
|
|
159990
162078
|
const rem = min % 60;
|
|
159991
|
-
return rem > 0 ? `${
|
|
162079
|
+
return rem > 0 ? `${h3}h ${rem}min` : `${h3}h`;
|
|
159992
162080
|
}
|
|
159993
162081
|
function renderDaysOfWeek(daysOfWeek) {
|
|
159994
162082
|
if (!daysOfWeek) return "";
|
|
@@ -161120,9 +163208,9 @@ var ProvisioningApiClient = class {
|
|
|
161120
163208
|
const newLogs = logs.filter((l) => l.id > lastLogId);
|
|
161121
163209
|
for (const entry of newLogs) {
|
|
161122
163210
|
const time = (entry.timestamp ?? "").split(" ")[1] ?? "";
|
|
161123
|
-
const
|
|
163211
|
+
const icon2 = STEP_ICONS[entry.step] ?? "\u{1F4CB}";
|
|
161124
163212
|
if (entry.level === "INFO" && !entry.message.includes("Progress updated to")) {
|
|
161125
|
-
onLog(`${
|
|
163213
|
+
onLog(`${icon2} [${time}] ${entry.message}`);
|
|
161126
163214
|
}
|
|
161127
163215
|
}
|
|
161128
163216
|
if (newLogs.length > 0) {
|
|
@@ -161245,22 +163333,22 @@ function drawFooter(doc, pageW, pageH, footerH, pageNo, pageCount) {
|
|
|
161245
163333
|
doc.setTextColor(40);
|
|
161246
163334
|
doc.text(label, bx + padX, baseline);
|
|
161247
163335
|
}
|
|
161248
|
-
async function drawTag(doc, x, y, w,
|
|
163336
|
+
async function drawTag(doc, x, y, w, h3, device, gateway, allDevices) {
|
|
161249
163337
|
const FRAME_SCALE_Y = 1.05;
|
|
161250
163338
|
const QR_SCALE = 1.7;
|
|
161251
163339
|
const QR_SHIFT_Y = 3;
|
|
161252
163340
|
const GAP_AFTER_QR = 6;
|
|
161253
|
-
const frameH =
|
|
161254
|
-
const frameY = y - (frameH -
|
|
163341
|
+
const frameH = h3 * FRAME_SCALE_Y;
|
|
163342
|
+
const frameY = y - (frameH - h3) / 2;
|
|
161255
163343
|
doc.setDrawColor(235);
|
|
161256
163344
|
doc.setLineWidth(0.15);
|
|
161257
163345
|
doc.rect(x, frameY, w, frameH);
|
|
161258
|
-
const pad = Math.max(2,
|
|
163346
|
+
const pad = Math.max(2, h3 * 0.05);
|
|
161259
163347
|
const innerX = x + pad;
|
|
161260
163348
|
const innerW = w - pad * 2;
|
|
161261
|
-
const titleAreaH =
|
|
163349
|
+
const titleAreaH = h3 * 0.15;
|
|
161262
163350
|
const qrAreaTop = y + titleAreaH;
|
|
161263
|
-
const qrAreaH =
|
|
163351
|
+
const qrAreaH = h3 - titleAreaH - 12;
|
|
161264
163352
|
const displayName = generateDeviceNameWithPrefix(device, void 0, allDevices);
|
|
161265
163353
|
const rawName = sanitizePdf(displayName);
|
|
161266
163354
|
const nameFont = Math.max(6, Math.min(11, titleAreaH * 0.45));
|
|
@@ -165869,10 +167957,10 @@ ${this._renderToolbar(filteredCount, totalAllUnfiltered)}
|
|
|
165869
167957
|
const collapseAllBtn = this.root.querySelector('[data-action="collapse-all"]');
|
|
165870
167958
|
if (collapseAllBtn) collapseAllBtn.addEventListener("click", () => this._collapseAll());
|
|
165871
167959
|
const groupHeaders = this.root.querySelectorAll("[data-group-toggle]");
|
|
165872
|
-
groupHeaders.forEach((
|
|
165873
|
-
const key =
|
|
165874
|
-
|
|
165875
|
-
|
|
167960
|
+
groupHeaders.forEach((h3) => {
|
|
167961
|
+
const key = h3.getAttribute("data-group-toggle") || "";
|
|
167962
|
+
h3.addEventListener("click", () => this._toggleGroupCollapsed(key));
|
|
167963
|
+
h3.addEventListener("keydown", (e) => {
|
|
165876
167964
|
const ke = e;
|
|
165877
167965
|
if (ke.key === "Enter" || ke.key === " ") {
|
|
165878
167966
|
ke.preventDefault();
|
|
@@ -166404,7 +168492,7 @@ function validateDeviceProductCode(code) {
|
|
|
166404
168492
|
|
|
166405
168493
|
// src/components/cards/central-status/v1.0.0/styles.ts
|
|
166406
168494
|
var STYLE_ID16 = "myio-central-status-card-styles";
|
|
166407
|
-
var
|
|
168495
|
+
var CSS5 = `
|
|
166408
168496
|
.myio-cscard{
|
|
166409
168497
|
--cscard-surface:#ffffff;
|
|
166410
168498
|
--cscard-border:#e2e8f0;
|
|
@@ -166709,7 +168797,7 @@ function injectCentralStatusCardStyles() {
|
|
|
166709
168797
|
if (document.getElementById(STYLE_ID16)) return;
|
|
166710
168798
|
const tag = document.createElement("style");
|
|
166711
168799
|
tag.id = STYLE_ID16;
|
|
166712
|
-
tag.textContent =
|
|
168800
|
+
tag.textContent = CSS5;
|
|
166713
168801
|
document.head.appendChild(tag);
|
|
166714
168802
|
}
|
|
166715
168803
|
|
|
@@ -168312,6 +170400,9 @@ var version = package_default.version || "0.0.0";
|
|
|
168312
170400
|
createModalHeader,
|
|
168313
170401
|
createMoneyVarianceColumn,
|
|
168314
170402
|
createMyIOTheme,
|
|
170403
|
+
createMyioGcdrLoginSubmit,
|
|
170404
|
+
createMyioGcdrLoginView,
|
|
170405
|
+
createMyioGcdrShell,
|
|
168315
170406
|
createNewTicketWizard,
|
|
168316
170407
|
createOnOffDeviceModal,
|
|
168317
170408
|
createOnOffTimelineChart,
|
|
@@ -168552,6 +170643,7 @@ var version = package_default.version || "0.0.0";
|
|
|
168552
170643
|
isInRange,
|
|
168553
170644
|
isLeapYear,
|
|
168554
170645
|
isMoneyColumnConfident,
|
|
170646
|
+
isMyioGcdrLoginModalOpen,
|
|
168555
170647
|
isOnOffDeviceProfile,
|
|
168556
170648
|
isSolenoidDevice,
|
|
168557
170649
|
isStoreDevice,
|
|
@@ -168613,6 +170705,7 @@ var version = package_default.version || "0.0.0";
|
|
|
168613
170705
|
openMeasurementSetupModal,
|
|
168614
170706
|
openMessageDialog,
|
|
168615
170707
|
openMetasGuide,
|
|
170708
|
+
openMyioGcdrLoginModal,
|
|
168616
170709
|
openOnOffDeviceModal,
|
|
168617
170710
|
openOnboardModal,
|
|
168618
170711
|
openOperationalComparisonModal,
|