myio-js-library 0.1.487 → 0.1.489
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 +460 -16
- package/dist/index.d.cts +12 -17
- package/dist/index.js +460 -16
- package/dist/myio-js-library.umd.js +460 -16
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1159,7 +1159,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
1159
1159
|
// package.json
|
|
1160
1160
|
var package_default = {
|
|
1161
1161
|
name: "myio-js-library",
|
|
1162
|
-
version: "0.1.
|
|
1162
|
+
version: "0.1.489",
|
|
1163
1163
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
1164
1164
|
license: "MIT",
|
|
1165
1165
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -88359,6 +88359,9 @@ var UserListTab = class {
|
|
|
88359
88359
|
loading = false;
|
|
88360
88360
|
users = [];
|
|
88361
88361
|
highlightedUserId = null;
|
|
88362
|
+
gcdrConfigs = /* @__PURE__ */ new Map();
|
|
88363
|
+
gcdrSyncing = /* @__PURE__ */ new Set();
|
|
88364
|
+
syncTooltipEl = null;
|
|
88362
88365
|
constructor(config, callbacks) {
|
|
88363
88366
|
this.config = config;
|
|
88364
88367
|
this.callbacks = callbacks;
|
|
@@ -88384,6 +88387,8 @@ var UserListTab = class {
|
|
|
88384
88387
|
<th>Nome</th>
|
|
88385
88388
|
<th>E-mail</th>
|
|
88386
88389
|
<th>Perfil</th>
|
|
88390
|
+
<th>Status</th>
|
|
88391
|
+
<th class="um-col-gcdr">GCDR</th>
|
|
88387
88392
|
<th class="um-col-actions">A\xE7\xF5es</th>
|
|
88388
88393
|
</tr>
|
|
88389
88394
|
</thead>
|
|
@@ -88449,6 +88454,7 @@ var UserListTab = class {
|
|
|
88449
88454
|
this.totalPages = page.totalPages;
|
|
88450
88455
|
this.renderRows();
|
|
88451
88456
|
this.renderPagination(page);
|
|
88457
|
+
this.fetchGcdrConfigsBatch();
|
|
88452
88458
|
} catch (err) {
|
|
88453
88459
|
console.error("[UserListTab] fetchUsers error", err);
|
|
88454
88460
|
this.callbacks.showToast("Erro ao carregar usu\xE1rios. Tente novamente.", "error");
|
|
@@ -88475,11 +88481,36 @@ var UserListTab = class {
|
|
|
88475
88481
|
}
|
|
88476
88482
|
const name = [user.firstName, user.lastName].filter(Boolean).join(" ") || "\u2014";
|
|
88477
88483
|
const role = user.authority === "TENANT_ADMIN" ? "Admin" : "Usu\xE1rio";
|
|
88484
|
+
const statusBadge = this.buildStatusBadge(user);
|
|
88485
|
+
const uid2 = user.id.id;
|
|
88478
88486
|
tr.innerHTML = `
|
|
88479
88487
|
<td>${this.esc(name)}</td>
|
|
88480
88488
|
<td>${this.esc(user.email)}</td>
|
|
88481
88489
|
<td><span class="um-badge um-badge--${user.authority === "TENANT_ADMIN" ? "admin" : "user"}">${role}</span></td>
|
|
88490
|
+
<td>${statusBadge}</td>
|
|
88491
|
+
<td class="um-col-gcdr">
|
|
88492
|
+
<span class="um-sync-icon um-sync-icon--loading" data-sync-uid="${uid2}">
|
|
88493
|
+
<span class="um-spinner" style="width:12px;height:12px;border-width:1.5px;display:block;margin:0 auto;"></span>
|
|
88494
|
+
</span>
|
|
88495
|
+
<button class="um-icon-btn um-force-sync-btn" title="Sincronizar com GCDR" style="margin-left:2px;">
|
|
88496
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
88497
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
88498
|
+
<polyline points="23 4 23 10 17 10"/>
|
|
88499
|
+
<polyline points="1 20 1 14 7 14"/>
|
|
88500
|
+
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
|
|
88501
|
+
</svg>
|
|
88502
|
+
</button>
|
|
88503
|
+
</td>
|
|
88482
88504
|
<td class="um-col-actions">
|
|
88505
|
+
<button class="um-icon-btn um-assign-btn" title="Ver Fun\xE7\xF5es / Pap\xE9is" style="margin-right:4px;">
|
|
88506
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
88507
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
88508
|
+
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
|
|
88509
|
+
<circle cx="9" cy="7" r="4"/>
|
|
88510
|
+
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
|
|
88511
|
+
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
|
88512
|
+
</svg>
|
|
88513
|
+
</button>
|
|
88483
88514
|
<button class="um-icon-btn um-detail-btn" title="Ver Detalhes">
|
|
88484
88515
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
88485
88516
|
stroke-linecap="round" stroke-linejoin="round">
|
|
@@ -88489,6 +88520,11 @@ var UserListTab = class {
|
|
|
88489
88520
|
</td>
|
|
88490
88521
|
`;
|
|
88491
88522
|
tr.querySelector(".um-detail-btn").addEventListener("click", () => this.callbacks.onOpenUserDetail(user, false));
|
|
88523
|
+
tr.querySelector(".um-assign-btn").addEventListener("click", (e) => this.showAssignmentsPopup(user, e.currentTarget));
|
|
88524
|
+
tr.querySelector(".um-force-sync-btn").addEventListener("click", () => this.syncUserToGCDR(user));
|
|
88525
|
+
const syncIcon = tr.querySelector(".um-sync-icon");
|
|
88526
|
+
syncIcon.addEventListener("mouseenter", (e) => this.showSyncTooltip(user, e.currentTarget));
|
|
88527
|
+
syncIcon.addEventListener("mouseleave", () => this.hideSyncTooltip());
|
|
88492
88528
|
tbody.appendChild(tr);
|
|
88493
88529
|
}
|
|
88494
88530
|
}
|
|
@@ -88512,9 +88548,321 @@ var UserListTab = class {
|
|
|
88512
88548
|
if (loadEl) loadEl.style.display = on ? "" : "none";
|
|
88513
88549
|
if (tableWrap) tableWrap.style.opacity = on ? "0.5" : "1";
|
|
88514
88550
|
}
|
|
88551
|
+
buildStatusBadge(user) {
|
|
88552
|
+
const enabled = user.additionalInfo?.userCredentialsEnabled;
|
|
88553
|
+
if (enabled === false) {
|
|
88554
|
+
return `<span class="um-badge um-badge--blocked">Bloqueado</span>`;
|
|
88555
|
+
}
|
|
88556
|
+
return `<span class="um-badge um-badge--active">Ativo</span>`;
|
|
88557
|
+
}
|
|
88558
|
+
gcdrHeaders() {
|
|
88559
|
+
const orch = window.MyIOOrchestrator;
|
|
88560
|
+
return {
|
|
88561
|
+
"Content-Type": "application/json",
|
|
88562
|
+
"X-API-Key": orch?.gcdrApiKey || "",
|
|
88563
|
+
"X-Tenant-ID": orch?.gcdrTenantId || ""
|
|
88564
|
+
};
|
|
88565
|
+
}
|
|
88566
|
+
gcdrBase() {
|
|
88567
|
+
return window.MyIOOrchestrator?.gcdrApiBaseUrl || "";
|
|
88568
|
+
}
|
|
88569
|
+
unwrapList(json) {
|
|
88570
|
+
if (Array.isArray(json)) return json;
|
|
88571
|
+
const j = json;
|
|
88572
|
+
if (j?.data && typeof j.data === "object") {
|
|
88573
|
+
const d = j.data;
|
|
88574
|
+
if (Array.isArray(d.items)) return d.items;
|
|
88575
|
+
if (Array.isArray(d)) return d;
|
|
88576
|
+
}
|
|
88577
|
+
if (Array.isArray(j?.items)) return j.items;
|
|
88578
|
+
return [];
|
|
88579
|
+
}
|
|
88580
|
+
async showAssignmentsPopup(user, anchor) {
|
|
88581
|
+
document.querySelector(".um-assign-popup")?.remove();
|
|
88582
|
+
const popup = document.createElement("div");
|
|
88583
|
+
popup.className = "um-assign-popup";
|
|
88584
|
+
popup.setAttribute("data-theme", this.config.theme || "light");
|
|
88585
|
+
const displayName = [user.firstName, user.lastName].filter(Boolean).join(" ") || user.email;
|
|
88586
|
+
popup.innerHTML = `
|
|
88587
|
+
<div class="um-assign-popup-header">
|
|
88588
|
+
<span class="um-assign-popup-title">\u{1F511} Fun\xE7\xF5es \u2014 ${this.esc(displayName)}</span>
|
|
88589
|
+
<button class="um-assign-popup-close" type="button">\u2715</button>
|
|
88590
|
+
</div>
|
|
88591
|
+
<div class="um-assign-popup-body">
|
|
88592
|
+
<div class="um-assign-popup-loading" style="font-size:12px;color:var(--um-text-muted);padding:8px 0;">
|
|
88593
|
+
<span class="um-spinner" style="display:inline-block;"></span> Carregando...
|
|
88594
|
+
</div>
|
|
88595
|
+
</div>
|
|
88596
|
+
`;
|
|
88597
|
+
document.body.appendChild(popup);
|
|
88598
|
+
const rect = anchor.getBoundingClientRect();
|
|
88599
|
+
const popupW = 320;
|
|
88600
|
+
const left = Math.min(rect.right + 8, window.innerWidth - popupW - 12);
|
|
88601
|
+
popup.style.top = `${Math.max(rect.top - 10, 8)}px`;
|
|
88602
|
+
popup.style.left = `${left}px`;
|
|
88603
|
+
const close = () => popup.remove();
|
|
88604
|
+
popup.querySelector(".um-assign-popup-close").addEventListener("click", close);
|
|
88605
|
+
const outsideHandler = (e) => {
|
|
88606
|
+
if (!popup.contains(e.target) && e.target !== anchor) {
|
|
88607
|
+
close();
|
|
88608
|
+
document.removeEventListener("click", outsideHandler, true);
|
|
88609
|
+
}
|
|
88610
|
+
};
|
|
88611
|
+
setTimeout(() => document.addEventListener("click", outsideHandler, true), 50);
|
|
88612
|
+
const body = popup.querySelector(".um-assign-popup-body");
|
|
88613
|
+
const base = this.gcdrBase();
|
|
88614
|
+
if (!base) {
|
|
88615
|
+
body.innerHTML = `<div style="font-size:12px;color:var(--um-toast-err-text);padding:8px 0;">GCDR n\xE3o configurado.</div>`;
|
|
88616
|
+
return;
|
|
88617
|
+
}
|
|
88618
|
+
try {
|
|
88619
|
+
const res = await fetch(`${base}/authorization/users/${user.id.id}/assignments`, { headers: this.gcdrHeaders() });
|
|
88620
|
+
let assignments = [];
|
|
88621
|
+
if (res.ok) {
|
|
88622
|
+
const json = await res.json();
|
|
88623
|
+
assignments = Array.isArray(json) ? json : json.assignments ?? [];
|
|
88624
|
+
}
|
|
88625
|
+
if (assignments.length === 0) {
|
|
88626
|
+
body.innerHTML = `<div style="font-size:12px;color:var(--um-text-faint);padding:8px 0;">Nenhuma fun\xE7\xE3o atribu\xEDda.</div>`;
|
|
88627
|
+
return;
|
|
88628
|
+
}
|
|
88629
|
+
const statusColors = {
|
|
88630
|
+
active: "var(--um-badge-active-text)",
|
|
88631
|
+
expired: "var(--um-badge-blocked-text)",
|
|
88632
|
+
inactive: "var(--um-text-faint)"
|
|
88633
|
+
};
|
|
88634
|
+
body.innerHTML = assignments.map((a) => {
|
|
88635
|
+
const scopeLabel = a.scope === "*" ? "* (global)" : a.scope.startsWith("customer:") ? `Cliente (${a.scope.replace("customer:", "").slice(0, 8)}...)` : a.scope.startsWith("asset:") ? `Asset (${a.scope.replace("asset:", "").slice(0, 8)}...)` : this.esc(a.scope);
|
|
88636
|
+
const expires = a.expiresAt ? new Date(a.expiresAt).toLocaleDateString("pt-BR") : null;
|
|
88637
|
+
const color = statusColors[a.status] || "var(--um-text-faint)";
|
|
88638
|
+
return `
|
|
88639
|
+
<div class="um-assign-row">
|
|
88640
|
+
<span class="um-assign-role">${this.esc(a.roleDisplayName || a.roleKey)}</span>
|
|
88641
|
+
<span class="um-assign-meta">
|
|
88642
|
+
Escopo: ${scopeLabel}
|
|
88643
|
+
\xB7 <span style="color:${color};font-weight:600;">${a.status}</span>
|
|
88644
|
+
${expires ? ` \xB7 Expira ${expires}` : ""}
|
|
88645
|
+
</span>
|
|
88646
|
+
</div>`;
|
|
88647
|
+
}).join("");
|
|
88648
|
+
} catch {
|
|
88649
|
+
body.innerHTML = `<div style="font-size:12px;color:var(--um-toast-err-text);padding:8px 0;">Erro ao carregar.</div>`;
|
|
88650
|
+
}
|
|
88651
|
+
}
|
|
88515
88652
|
esc(s) {
|
|
88516
88653
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
88517
88654
|
}
|
|
88655
|
+
// ── GCDR Sync Column ─────────────────────────────────────────────────────────
|
|
88656
|
+
async fetchGcdrConfigsBatch() {
|
|
88657
|
+
if (this.users.length === 0) return;
|
|
88658
|
+
const { tbBaseUrl, jwtToken } = this.config;
|
|
88659
|
+
await Promise.allSettled(this.users.map(async (user) => {
|
|
88660
|
+
const uid2 = user.id.id;
|
|
88661
|
+
try {
|
|
88662
|
+
const res = await fetch(
|
|
88663
|
+
`${tbBaseUrl}/api/plugins/telemetry/USER/${uid2}/values/attributes/SERVER_SCOPE?keys=gcdrUserConfigs`,
|
|
88664
|
+
{ headers: { "X-Authorization": `Bearer ${jwtToken}` } }
|
|
88665
|
+
);
|
|
88666
|
+
let cfg = null;
|
|
88667
|
+
if (res.ok) {
|
|
88668
|
+
const attrs = await res.json();
|
|
88669
|
+
const entry = attrs.find((a) => a.key === "gcdrUserConfigs");
|
|
88670
|
+
if (entry?.value && typeof entry.value === "object") {
|
|
88671
|
+
cfg = entry.value;
|
|
88672
|
+
}
|
|
88673
|
+
}
|
|
88674
|
+
this.gcdrConfigs.set(uid2, cfg);
|
|
88675
|
+
this.updateSyncCell(uid2, cfg ? cfg.lastSyncResult ?? "none" : "none", cfg);
|
|
88676
|
+
} catch {
|
|
88677
|
+
this.updateSyncCell(uid2, "none", null);
|
|
88678
|
+
}
|
|
88679
|
+
}));
|
|
88680
|
+
}
|
|
88681
|
+
updateSyncCell(userId, state6, cfg = null) {
|
|
88682
|
+
const iconEl = this.el?.querySelector(`.um-sync-icon[data-sync-uid="${userId}"]`);
|
|
88683
|
+
if (!iconEl) return;
|
|
88684
|
+
iconEl.className = "um-sync-icon";
|
|
88685
|
+
if (state6 === "loading" || state6 === "syncing") {
|
|
88686
|
+
iconEl.innerHTML = `<span class="um-spinner" style="width:12px;height:12px;border-width:1.5px;display:block;margin:0 auto;"></span>`;
|
|
88687
|
+
return;
|
|
88688
|
+
}
|
|
88689
|
+
const gcdrStatus = cfg?.gcdrStatus;
|
|
88690
|
+
let dotClass = "um-sync-dot--none";
|
|
88691
|
+
let dotTitle = "Nunca sincronizado";
|
|
88692
|
+
if (state6 === "success") {
|
|
88693
|
+
dotClass = gcdrStatus === "ACTIVE" ? "um-sync-dot--active" : gcdrStatus === "INACTIVE" || gcdrStatus === "LOCKED" ? "um-sync-dot--warn" : "um-sync-dot--ok";
|
|
88694
|
+
dotTitle = `GCDR: ${gcdrStatus ?? "OK"}`;
|
|
88695
|
+
} else if (state6 === "error") {
|
|
88696
|
+
dotClass = "um-sync-dot--err";
|
|
88697
|
+
dotTitle = cfg?.lastError ?? "Erro";
|
|
88698
|
+
}
|
|
88699
|
+
iconEl.innerHTML = `<span class="um-sync-dot ${dotClass}" title="${this.esc(dotTitle)}"></span>`;
|
|
88700
|
+
}
|
|
88701
|
+
showSyncTooltip(user, anchor) {
|
|
88702
|
+
this.hideSyncTooltip();
|
|
88703
|
+
const uid2 = user.id.id;
|
|
88704
|
+
const cfg = this.gcdrConfigs.get(uid2);
|
|
88705
|
+
const tooltip = document.createElement("div");
|
|
88706
|
+
tooltip.className = "um-sync-tooltip";
|
|
88707
|
+
tooltip.setAttribute("data-theme", this.config.theme || "light");
|
|
88708
|
+
this.syncTooltipEl = tooltip;
|
|
88709
|
+
const syncing = this.gcdrSyncing.has(uid2);
|
|
88710
|
+
const displayName = [user.firstName, user.lastName].filter(Boolean).join(" ") || user.email;
|
|
88711
|
+
let bodyHtml;
|
|
88712
|
+
if (syncing) {
|
|
88713
|
+
bodyHtml = `<div class="um-sync-tooltip-row" style="justify-content:center;padding:8px 0;">
|
|
88714
|
+
<span class="um-spinner" style="width:13px;height:13px;"></span> Sincronizando...
|
|
88715
|
+
</div>`;
|
|
88716
|
+
} else if (!cfg) {
|
|
88717
|
+
bodyHtml = `<div class="um-sync-tooltip-row um-sync-tooltip-row--muted">Nunca sincronizado com GCDR.</div>`;
|
|
88718
|
+
} else {
|
|
88719
|
+
const syncedAt = cfg.syncedAt ? new Date(cfg.syncedAt).toLocaleString("pt-BR") : "\u2014";
|
|
88720
|
+
const updatedAt = cfg.updatedAt ? new Date(cfg.updatedAt).toLocaleString("pt-BR") : "\u2014";
|
|
88721
|
+
const resultColor = cfg.lastSyncResult === "success" ? "var(--um-badge-active-text)" : "var(--um-badge-blocked-text)";
|
|
88722
|
+
bodyHtml = `
|
|
88723
|
+
<div class="um-sync-tooltip-row">
|
|
88724
|
+
<span class="um-sync-tooltip-label">GCDR ID</span>
|
|
88725
|
+
<span class="um-sync-tooltip-value" style="font-family:monospace;font-size:10px;">${cfg.gcdrUserId ? cfg.gcdrUserId.slice(0, 16) + "\u2026" : "\u2014"}</span>
|
|
88726
|
+
</div>
|
|
88727
|
+
<div class="um-sync-tooltip-row">
|
|
88728
|
+
<span class="um-sync-tooltip-label">Status GCDR</span>
|
|
88729
|
+
<span class="um-sync-tooltip-value">${cfg.gcdrStatus ?? "\u2014"}</span>
|
|
88730
|
+
</div>
|
|
88731
|
+
<div class="um-sync-tooltip-row">
|
|
88732
|
+
<span class="um-sync-tooltip-label">\xDAltimo sync</span>
|
|
88733
|
+
<span class="um-sync-tooltip-value">${syncedAt}</span>
|
|
88734
|
+
</div>
|
|
88735
|
+
<div class="um-sync-tooltip-row">
|
|
88736
|
+
<span class="um-sync-tooltip-label">Atualizado</span>
|
|
88737
|
+
<span class="um-sync-tooltip-value">${updatedAt}</span>
|
|
88738
|
+
</div>
|
|
88739
|
+
<div class="um-sync-tooltip-row">
|
|
88740
|
+
<span class="um-sync-tooltip-label">Qtd syncs</span>
|
|
88741
|
+
<span class="um-sync-tooltip-value">${cfg.syncCount ?? 0}</span>
|
|
88742
|
+
</div>
|
|
88743
|
+
<div class="um-sync-tooltip-row">
|
|
88744
|
+
<span class="um-sync-tooltip-label">Resultado</span>
|
|
88745
|
+
<span class="um-sync-tooltip-value" style="color:${resultColor};font-weight:700;">${cfg.lastSyncResult === "success" ? "\u2713 Sucesso" : "\u2717 Erro"}</span>
|
|
88746
|
+
</div>
|
|
88747
|
+
${cfg.lastError ? `<div class="um-sync-tooltip-row um-sync-tooltip-row--error">
|
|
88748
|
+
<span class="um-sync-tooltip-label">Erro</span>
|
|
88749
|
+
<span class="um-sync-tooltip-value">${this.esc(cfg.lastError)}</span>
|
|
88750
|
+
</div>` : ""}
|
|
88751
|
+
`;
|
|
88752
|
+
}
|
|
88753
|
+
tooltip.innerHTML = `
|
|
88754
|
+
<div class="um-sync-tooltip-header">
|
|
88755
|
+
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"
|
|
88756
|
+
stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0;">
|
|
88757
|
+
<polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/>
|
|
88758
|
+
<path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/>
|
|
88759
|
+
</svg>
|
|
88760
|
+
<span>GCDR Sync \u2014 ${this.esc(displayName)}</span>
|
|
88761
|
+
</div>
|
|
88762
|
+
<div class="um-sync-tooltip-body">${bodyHtml}</div>
|
|
88763
|
+
`;
|
|
88764
|
+
const backdrop = this.el.closest(".um-backdrop") ?? document.body;
|
|
88765
|
+
backdrop.appendChild(tooltip);
|
|
88766
|
+
const rect = anchor.getBoundingClientRect();
|
|
88767
|
+
const ttW = 260;
|
|
88768
|
+
let left = rect.right + 8;
|
|
88769
|
+
if (left + ttW > window.innerWidth - 8) left = rect.left - ttW - 8;
|
|
88770
|
+
tooltip.style.left = `${Math.max(4, left)}px`;
|
|
88771
|
+
tooltip.style.top = `${Math.max(4, rect.top - 10)}px`;
|
|
88772
|
+
}
|
|
88773
|
+
hideSyncTooltip() {
|
|
88774
|
+
this.syncTooltipEl?.remove();
|
|
88775
|
+
this.syncTooltipEl = null;
|
|
88776
|
+
}
|
|
88777
|
+
async syncUserToGCDR(user) {
|
|
88778
|
+
const uid2 = user.id.id;
|
|
88779
|
+
if (this.gcdrSyncing.has(uid2)) return;
|
|
88780
|
+
const base = this.gcdrBase();
|
|
88781
|
+
if (!base) {
|
|
88782
|
+
this.callbacks.showToast("GCDR n\xE3o configurado.", "error");
|
|
88783
|
+
return;
|
|
88784
|
+
}
|
|
88785
|
+
this.gcdrSyncing.add(uid2);
|
|
88786
|
+
this.updateSyncCell(uid2, "syncing");
|
|
88787
|
+
const prev = this.gcdrConfigs.get(uid2) ?? null;
|
|
88788
|
+
const syncCount = (prev?.syncCount ?? 0) + 1;
|
|
88789
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
88790
|
+
try {
|
|
88791
|
+
const searchRes = await fetch(
|
|
88792
|
+
`${base}/api/v1/users?search=${encodeURIComponent(user.email)}&customerId=${encodeURIComponent(this.config.customerId)}&limit=10`,
|
|
88793
|
+
{ headers: this.gcdrHeaders() }
|
|
88794
|
+
);
|
|
88795
|
+
let gcdrUser = null;
|
|
88796
|
+
if (searchRes.ok) {
|
|
88797
|
+
const data = await searchRes.json();
|
|
88798
|
+
const items = Array.isArray(data) ? data : data?.data?.items ?? data?.items ?? [];
|
|
88799
|
+
gcdrUser = items.find((u) => u.email?.toLowerCase() === user.email.toLowerCase()) ?? null;
|
|
88800
|
+
}
|
|
88801
|
+
if (!gcdrUser) {
|
|
88802
|
+
const createRes = await fetch(`${base}/api/v1/users`, {
|
|
88803
|
+
method: "POST",
|
|
88804
|
+
headers: this.gcdrHeaders(),
|
|
88805
|
+
body: JSON.stringify({
|
|
88806
|
+
email: user.email,
|
|
88807
|
+
firstName: user.firstName || "",
|
|
88808
|
+
lastName: user.lastName || "",
|
|
88809
|
+
customerId: this.config.customerId,
|
|
88810
|
+
type: "CUSTOMER"
|
|
88811
|
+
})
|
|
88812
|
+
});
|
|
88813
|
+
if (!createRes.ok) throw new Error(`Criar usu\xE1rio GCDR: HTTP ${createRes.status}`);
|
|
88814
|
+
gcdrUser = await createRes.json();
|
|
88815
|
+
}
|
|
88816
|
+
const configs = {
|
|
88817
|
+
gcdrUserId: gcdrUser.id,
|
|
88818
|
+
gcdrStatus: gcdrUser.status,
|
|
88819
|
+
gcdrType: gcdrUser.type,
|
|
88820
|
+
syncedAt: now,
|
|
88821
|
+
syncCount,
|
|
88822
|
+
lastSyncResult: "success",
|
|
88823
|
+
lastError: null,
|
|
88824
|
+
createdAt: prev?.createdAt ?? now,
|
|
88825
|
+
updatedAt: now
|
|
88826
|
+
};
|
|
88827
|
+
await this.saveTBAttribute(uid2, configs);
|
|
88828
|
+
this.gcdrConfigs.set(uid2, configs);
|
|
88829
|
+
this.updateSyncCell(uid2, "success", configs);
|
|
88830
|
+
this.callbacks.showToast(`Sync GCDR conclu\xEDdo \u2014 ${user.email}`, "success");
|
|
88831
|
+
} catch (err) {
|
|
88832
|
+
const configs = {
|
|
88833
|
+
...prev ?? {},
|
|
88834
|
+
syncedAt: now,
|
|
88835
|
+
syncCount,
|
|
88836
|
+
lastSyncResult: "error",
|
|
88837
|
+
lastError: String(err?.message ?? "Erro desconhecido"),
|
|
88838
|
+
updatedAt: now
|
|
88839
|
+
};
|
|
88840
|
+
try {
|
|
88841
|
+
await this.saveTBAttribute(uid2, configs);
|
|
88842
|
+
} catch {
|
|
88843
|
+
}
|
|
88844
|
+
this.gcdrConfigs.set(uid2, configs);
|
|
88845
|
+
this.updateSyncCell(uid2, "error", configs);
|
|
88846
|
+
this.callbacks.showToast(`Erro sync GCDR: ${err?.message || "Falha"}`, "error");
|
|
88847
|
+
} finally {
|
|
88848
|
+
this.gcdrSyncing.delete(uid2);
|
|
88849
|
+
}
|
|
88850
|
+
}
|
|
88851
|
+
async saveTBAttribute(userId, configs) {
|
|
88852
|
+
const { tbBaseUrl, jwtToken } = this.config;
|
|
88853
|
+
const res = await fetch(
|
|
88854
|
+
`${tbBaseUrl}/api/plugins/telemetry/USER/${userId}/attributes/SERVER_SCOPE`,
|
|
88855
|
+
{
|
|
88856
|
+
method: "POST",
|
|
88857
|
+
headers: {
|
|
88858
|
+
"X-Authorization": `Bearer ${jwtToken}`,
|
|
88859
|
+
"Content-Type": "application/json"
|
|
88860
|
+
},
|
|
88861
|
+
body: JSON.stringify({ gcdrUserConfigs: configs })
|
|
88862
|
+
}
|
|
88863
|
+
);
|
|
88864
|
+
if (!res.ok) throw new Error(`Salvar atributo TB: HTTP ${res.status}`);
|
|
88865
|
+
}
|
|
88518
88866
|
};
|
|
88519
88867
|
|
|
88520
88868
|
// src/components/premium-modals/user-management/tabs/NewUserTab.ts
|
|
@@ -90001,7 +90349,12 @@ var UserDetailTab = class {
|
|
|
90001
90349
|
fetch(`${this.gcdrBase()}/roles?limit=100`, { headers: this.gcdrHeaders() }),
|
|
90002
90350
|
fetch(`${this.gcdrBase()}/policies?limit=100`, { headers: this.gcdrHeaders() })
|
|
90003
90351
|
]);
|
|
90004
|
-
|
|
90352
|
+
if (assignRes.ok) {
|
|
90353
|
+
const assignJson = await assignRes.json();
|
|
90354
|
+
this.assignments = Array.isArray(assignJson) ? assignJson : assignJson.assignments ?? [];
|
|
90355
|
+
} else {
|
|
90356
|
+
this.assignments = [];
|
|
90357
|
+
}
|
|
90005
90358
|
this.availableRoles = rolesRes.ok ? this.unwrapList(await rolesRes.json()) : [];
|
|
90006
90359
|
this.availablePolicies = policiesRes.ok ? this.unwrapList(await policiesRes.json()) : [];
|
|
90007
90360
|
this.renderAssignments();
|
|
@@ -90028,11 +90381,12 @@ var UserDetailTab = class {
|
|
|
90028
90381
|
const tbody = document.createElement("tbody");
|
|
90029
90382
|
this.assignments.forEach((a) => {
|
|
90030
90383
|
const tr = document.createElement("tr");
|
|
90031
|
-
const statusColor = a.status === "active" ? "var(--um-badge-
|
|
90384
|
+
const statusColor = a.status === "active" ? "var(--um-badge-active-text)" : a.status === "expired" ? "var(--um-badge-blocked-text)" : "var(--um-text-faint)";
|
|
90032
90385
|
const expiresAt = a.expiresAt ? new Date(a.expiresAt).toLocaleDateString("pt-BR") : "\u2014";
|
|
90386
|
+
const scopeLabel = a.scope === "*" ? "* (global)" : a.scope.startsWith("customer:") ? `Cliente (${a.scope.replace("customer:", "").slice(0, 8)}...)` : a.scope.startsWith("asset:") ? `Asset (${a.scope.replace("asset:", "").slice(0, 8)}...)` : a.scope;
|
|
90033
90387
|
tr.innerHTML = `
|
|
90034
90388
|
<td style="font-weight:500;">${this.esc(a.roleDisplayName || a.roleKey)}</td>
|
|
90035
|
-
<td
|
|
90389
|
+
<td style="font-size:12px;">${this.esc(scopeLabel)}</td>
|
|
90036
90390
|
<td><span style="color:${statusColor};font-weight:600;">${a.status}</span></td>
|
|
90037
90391
|
<td>${expiresAt}</td>
|
|
90038
90392
|
<td style="text-align:center;"><button class="um-btn um-btn--danger um-btn--sm revoke-btn">Revogar</button></td>
|
|
@@ -90142,13 +90496,14 @@ var UserDetailTab = class {
|
|
|
90142
90496
|
const expiresAt = expiresAtRaw ? new Date(expiresAtRaw).toISOString() : null;
|
|
90143
90497
|
const reason = modal.querySelector("[name=reason]").value.trim() || null;
|
|
90144
90498
|
const role = this.availableRoles.find((r) => r.id === roleId);
|
|
90499
|
+
const roleKey = role?.key || role?.id || roleId;
|
|
90145
90500
|
const btn = modal.querySelector(".assign-save");
|
|
90146
90501
|
btn.disabled = true;
|
|
90147
90502
|
btn.textContent = "...";
|
|
90148
90503
|
try {
|
|
90149
90504
|
const body = {
|
|
90150
90505
|
userId: this.user.id.id,
|
|
90151
|
-
|
|
90506
|
+
roleKey,
|
|
90152
90507
|
scope,
|
|
90153
90508
|
expiresAt,
|
|
90154
90509
|
reason
|
|
@@ -91202,6 +91557,12 @@ var UserManagementModalView = class {
|
|
|
91202
91557
|
--um-badge-admin-text: #3b5bdb;
|
|
91203
91558
|
--um-badge-user-bg: #f0fdf4;
|
|
91204
91559
|
--um-badge-user-text: #16a34a;
|
|
91560
|
+
--um-badge-active-bg: #dcfce7;
|
|
91561
|
+
--um-badge-active-text: #15803d;
|
|
91562
|
+
--um-badge-blocked-bg: #fee2e2;
|
|
91563
|
+
--um-badge-blocked-text: #b91c1c;
|
|
91564
|
+
--um-badge-pending-bg: #fef9c3;
|
|
91565
|
+
--um-badge-pending-text: #854d0e;
|
|
91205
91566
|
--um-toast-ok-bg: #f0fdf4;
|
|
91206
91567
|
--um-toast-ok-border: #22c55e;
|
|
91207
91568
|
--um-toast-ok-text: #16a34a;
|
|
@@ -91262,6 +91623,12 @@ var UserManagementModalView = class {
|
|
|
91262
91623
|
--um-badge-admin-text: #60a5fa;
|
|
91263
91624
|
--um-badge-user-bg: #1a2d24;
|
|
91264
91625
|
--um-badge-user-text: #4ade80;
|
|
91626
|
+
--um-badge-active-bg: #14532d;
|
|
91627
|
+
--um-badge-active-text: #86efac;
|
|
91628
|
+
--um-badge-blocked-bg: #450a0a;
|
|
91629
|
+
--um-badge-blocked-text: #fca5a5;
|
|
91630
|
+
--um-badge-pending-bg: #422006;
|
|
91631
|
+
--um-badge-pending-text: #fde68a;
|
|
91265
91632
|
--um-toast-ok-bg: #1e3a2e;
|
|
91266
91633
|
--um-toast-ok-border: #22c55e;
|
|
91267
91634
|
--um-toast-ok-text: #4ade80;
|
|
@@ -91291,14 +91658,21 @@ var UserManagementModalView = class {
|
|
|
91291
91658
|
.um-modal {
|
|
91292
91659
|
background: var(--um-modal-bg);
|
|
91293
91660
|
font-family: 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
91294
|
-
border-radius: 14px; width:
|
|
91661
|
+
border-radius: 14px; width: 96vw; max-width: 1200px;
|
|
91295
91662
|
--modal-header-radius: 14px 14px 0 0;
|
|
91296
|
-
|
|
91663
|
+
height: 84vh; display: flex; flex-direction: column;
|
|
91297
91664
|
box-shadow: var(--um-shadow); overflow: hidden; position: relative;
|
|
91298
91665
|
}
|
|
91299
|
-
@media (max-height: 600px) { .um-modal {
|
|
91666
|
+
@media (max-height: 600px) { .um-modal { height: 96vh; } }
|
|
91300
91667
|
|
|
91301
91668
|
/* Header handled by ModalHeader (RFC-0121) */
|
|
91669
|
+
.um-modal .myio-modal-header__title {
|
|
91670
|
+
font-size: 14px !important;
|
|
91671
|
+
font-weight: 600 !important;
|
|
91672
|
+
}
|
|
91673
|
+
.um-modal .myio-modal-header__icon {
|
|
91674
|
+
font-size: 15px !important;
|
|
91675
|
+
}
|
|
91302
91676
|
|
|
91303
91677
|
/* Force MyIO purple header regardless of light/dark theme \u2014 overrides myio-modal-header--light */
|
|
91304
91678
|
.um-modal .myio-modal-header--light {
|
|
@@ -91397,16 +91771,83 @@ var UserManagementModalView = class {
|
|
|
91397
91771
|
.um-table { width: 100%; border-collapse: collapse; font-size: 13px; }
|
|
91398
91772
|
.um-table th {
|
|
91399
91773
|
text-align: left; padding: 8px 12px;
|
|
91400
|
-
color: var(--um-text-muted); font-weight:
|
|
91774
|
+
color: var(--um-text-muted); font-weight: 600; font-size: 11px;
|
|
91401
91775
|
text-transform: uppercase; letter-spacing: 0.04em;
|
|
91402
91776
|
border-bottom: 1px solid var(--um-border);
|
|
91403
91777
|
}
|
|
91404
91778
|
.um-table td {
|
|
91405
|
-
padding: 10px 12px; color: var(--um-text-
|
|
91779
|
+
padding: 10px 12px; color: var(--um-text-primary); font-weight: 500;
|
|
91406
91780
|
border-bottom: 1px solid var(--um-border-sub);
|
|
91407
91781
|
}
|
|
91408
91782
|
.um-table tr:hover td { background: var(--um-bg-surface); }
|
|
91409
|
-
.um-col-actions { width:
|
|
91783
|
+
.um-col-actions { width: 100px; text-align: center; }
|
|
91784
|
+
.um-col-gcdr { width: 72px; text-align: center; }
|
|
91785
|
+
|
|
91786
|
+
/* Sync status dot */
|
|
91787
|
+
.um-sync-icon { display: inline-flex; align-items: center; justify-content: center; }
|
|
91788
|
+
.um-sync-dot {
|
|
91789
|
+
display: inline-block; width: 10px; height: 10px; border-radius: 50%;
|
|
91790
|
+
flex-shrink: 0;
|
|
91791
|
+
}
|
|
91792
|
+
.um-sync-dot--none { background: var(--um-text-faint); opacity: 0.4; }
|
|
91793
|
+
.um-sync-dot--ok,
|
|
91794
|
+
.um-sync-dot--active { background: var(--um-badge-active-text); }
|
|
91795
|
+
.um-sync-dot--warn { background: var(--um-badge-pending-text); }
|
|
91796
|
+
.um-sync-dot--err { background: var(--um-badge-blocked-text); }
|
|
91797
|
+
|
|
91798
|
+
/* Premium sync tooltip */
|
|
91799
|
+
.um-sync-tooltip {
|
|
91800
|
+
position: fixed; z-index: 100020;
|
|
91801
|
+
background: var(--um-modal-bg); border: 1px solid var(--um-border);
|
|
91802
|
+
border-radius: 10px; box-shadow: 0 8px 32px rgba(0,0,0,0.2);
|
|
91803
|
+
width: 260px; pointer-events: none;
|
|
91804
|
+
font-family: 'Nunito', -apple-system, sans-serif;
|
|
91805
|
+
}
|
|
91806
|
+
.um-sync-tooltip-header {
|
|
91807
|
+
display: flex; align-items: center; gap: 7px;
|
|
91808
|
+
padding: 8px 12px; background: var(--um-accent);
|
|
91809
|
+
border-radius: 10px 10px 0 0;
|
|
91810
|
+
font-size: 11px; font-weight: 700; color: #fff;
|
|
91811
|
+
}
|
|
91812
|
+
.um-sync-tooltip-body {
|
|
91813
|
+
padding: 10px 12px; display: flex; flex-direction: column; gap: 4px;
|
|
91814
|
+
}
|
|
91815
|
+
.um-sync-tooltip-row {
|
|
91816
|
+
display: flex; justify-content: space-between; align-items: flex-start;
|
|
91817
|
+
font-size: 11px; gap: 8px;
|
|
91818
|
+
}
|
|
91819
|
+
.um-sync-tooltip-row--muted { color: var(--um-text-faint); justify-content: center; padding: 4px 0; }
|
|
91820
|
+
.um-sync-tooltip-row--error .um-sync-tooltip-value { color: var(--um-badge-blocked-text); word-break: break-all; }
|
|
91821
|
+
.um-sync-tooltip-label { color: var(--um-text-muted); flex-shrink: 0; }
|
|
91822
|
+
.um-sync-tooltip-value { color: var(--um-text-primary); font-weight: 600; text-align: right; }
|
|
91823
|
+
|
|
91824
|
+
/* Assignments quick-view popup */
|
|
91825
|
+
.um-assign-popup {
|
|
91826
|
+
position: fixed; z-index: 100010;
|
|
91827
|
+
background: var(--um-modal-bg); border: 1px solid var(--um-border);
|
|
91828
|
+
border-radius: 10px; box-shadow: 0 8px 32px rgba(0,0,0,0.18);
|
|
91829
|
+
width: 320px; max-height: 340px; overflow-y: auto;
|
|
91830
|
+
font-family: 'Nunito', -apple-system, sans-serif;
|
|
91831
|
+
}
|
|
91832
|
+
.um-assign-popup-header {
|
|
91833
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
91834
|
+
padding: 10px 14px; background: var(--um-accent);
|
|
91835
|
+
border-radius: 10px 10px 0 0;
|
|
91836
|
+
}
|
|
91837
|
+
.um-assign-popup-title { font-size: 12px; font-weight: 700; color: #fff; }
|
|
91838
|
+
.um-assign-popup-close {
|
|
91839
|
+
background: none; border: none; color: rgba(255,255,255,0.8);
|
|
91840
|
+
font-size: 14px; cursor: pointer; padding: 0 4px; line-height: 1;
|
|
91841
|
+
}
|
|
91842
|
+
.um-assign-popup-body { padding: 10px 14px; }
|
|
91843
|
+
.um-assign-row {
|
|
91844
|
+
display: flex; flex-direction: column; gap: 2px;
|
|
91845
|
+
padding: 7px 0; border-bottom: 1px solid var(--um-border-sub);
|
|
91846
|
+
font-size: 12px;
|
|
91847
|
+
}
|
|
91848
|
+
.um-assign-row:last-child { border-bottom: none; }
|
|
91849
|
+
.um-assign-role { font-weight: 600; color: var(--um-text-primary); }
|
|
91850
|
+
.um-assign-meta { color: var(--um-text-muted); font-size: 11px; }
|
|
91410
91851
|
.um-row--highlight td { background: var(--um-row-highlight) !important; }
|
|
91411
91852
|
|
|
91412
91853
|
.um-list-empty, .um-list-loading, .um-profiles-loading,
|
|
@@ -91442,8 +91883,11 @@ var UserManagementModalView = class {
|
|
|
91442
91883
|
.um-btn--sm { padding: 6px 12px; font-size: 12px; }
|
|
91443
91884
|
|
|
91444
91885
|
.um-badge { display: inline-block; font-size: 10px; font-weight: 600; padding: 2px 8px; border-radius: 9999px; }
|
|
91445
|
-
.um-badge--admin
|
|
91446
|
-
.um-badge--user
|
|
91886
|
+
.um-badge--admin { background: var(--um-badge-admin-bg); color: var(--um-badge-admin-text); }
|
|
91887
|
+
.um-badge--user { background: var(--um-badge-user-bg); color: var(--um-badge-user-text); }
|
|
91888
|
+
.um-badge--active { background: var(--um-badge-active-bg); color: var(--um-badge-active-text); }
|
|
91889
|
+
.um-badge--blocked { background: var(--um-badge-blocked-bg); color: var(--um-badge-blocked-text); }
|
|
91890
|
+
.um-badge--pending { background: var(--um-badge-pending-bg); color: var(--um-badge-pending-text); }
|
|
91447
91891
|
|
|
91448
91892
|
.um-form { display: flex; flex-direction: column; gap: 14px;}
|
|
91449
91893
|
.um-form-row { display: flex; gap: 12px; }
|
|
@@ -136086,7 +136530,7 @@ function bindFilterBar(card, bundle, getViewMode) {
|
|
|
136086
136530
|
const lower = text.toLowerCase();
|
|
136087
136531
|
const types = /* @__PURE__ */ new Set();
|
|
136088
136532
|
bundle.devices.forEach((d) => {
|
|
136089
|
-
const name = (d.displayName || d.name).toLowerCase();
|
|
136533
|
+
const name = (d.entityLabel || d.displayName || d.name).toLowerCase();
|
|
136090
136534
|
if (!lower || name.includes(lower) || d.type.toLowerCase().includes(lower)) {
|
|
136091
136535
|
types.add(d.type);
|
|
136092
136536
|
}
|
|
@@ -136162,7 +136606,7 @@ function renderDevice(device, rules, viewMode = "granular") {
|
|
|
136162
136606
|
<div class="abm-device-header">
|
|
136163
136607
|
<span class="abm-chevron">\u25BE</span>
|
|
136164
136608
|
<span style="font-size:16px;">\u{1F4E1}</span>
|
|
136165
|
-
<span class="abm-device-name">${escHtml3(device.displayName || device.name)}</span>
|
|
136609
|
+
<span class="abm-device-name">${escHtml3(device.entityLabel || device.displayName || device.name)}</span>
|
|
136166
136610
|
${_alarmBadgeHtml(alarmCount)}
|
|
136167
136611
|
<span class="abm-device-type">${escHtml3(device.type)}</span>
|
|
136168
136612
|
</div>
|
|
@@ -136212,7 +136656,7 @@ function renderByRuleView(bundle) {
|
|
|
136212
136656
|
return `
|
|
136213
136657
|
<li class="abm-rule-group-device" data-device-id="${escHtml3(d.id)}">
|
|
136214
136658
|
<span style="font-size:13px;">\u{1F4E1}</span>
|
|
136215
|
-
<span>${escHtml3(d.displayName || d.name)}</span>
|
|
136659
|
+
<span>${escHtml3(d.entityLabel || d.displayName || d.name)}</span>
|
|
136216
136660
|
<span style="font-size:11px;color:#888;">${escHtml3(d.type)}</span>
|
|
136217
136661
|
${overridePart}
|
|
136218
136662
|
</li>`;
|