myio-js-library 0.1.553 → 0.1.554
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 +76 -20
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +76 -20
- package/dist/myio-js-library.umd.js +76 -20
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -899,7 +899,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
899
899
|
// package.json
|
|
900
900
|
var package_default = {
|
|
901
901
|
name: "myio-js-library",
|
|
902
|
-
version: "0.1.
|
|
902
|
+
version: "0.1.554",
|
|
903
903
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
904
904
|
license: "MIT",
|
|
905
905
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -18667,9 +18667,17 @@ function renderCardComponentV5({
|
|
|
18667
18667
|
// Temperatura atual vinda do Ingestion = média das últimas 2 h; true = nenhuma leitura na janela
|
|
18668
18668
|
temperatureNoRecentReading = false,
|
|
18669
18669
|
temperatureSource,
|
|
18670
|
-
// 'ingestion-avg-2h' | 'thingsboard' | undefined
|
|
18670
|
+
// 'ingestion-hourly' | 'ingestion-avg-2h' | 'thingsboard' | undefined
|
|
18671
18671
|
temperatureFetchedAt,
|
|
18672
18672
|
// ms da consulta (rótulo "Atualizado às HH:MM")
|
|
18673
|
+
// Idade da última leitura: 'ok' | 'warning' (10–12 h) | 'stale' (12–24 h) | 'offline' (> 24 h)
|
|
18674
|
+
temperatureFreshness,
|
|
18675
|
+
temperatureHourTs,
|
|
18676
|
+
// início da hora fechada exibida (ms)
|
|
18677
|
+
temperatureLastTs,
|
|
18678
|
+
// instante da última leitura válida (ms)
|
|
18679
|
+
temperatureOffset = 0,
|
|
18680
|
+
// offset aplicado (°C) — marcador igual ao da exclusão de totais
|
|
18673
18681
|
// Per-device exclude_groups_totals attribute (SERVER_SCOPE) — drives the orange marker
|
|
18674
18682
|
excludeGroupsTotals
|
|
18675
18683
|
} = entityObject;
|
|
@@ -18830,8 +18838,29 @@ function renderCardComponentV5({
|
|
|
18830
18838
|
const tankLevelCm = isTankDevice2 ? Number(waterLevel ?? val) : null;
|
|
18831
18839
|
const _pctDecimals = resolvePercentDecimals(percentDecimals);
|
|
18832
18840
|
const showNoTempReading = !!temperatureNoRecentReading && isTemperatureDevice2(deviceType);
|
|
18841
|
+
const _isTempCard = isTemperatureDevice2(deviceType);
|
|
18842
|
+
const showTempWarning = _isTempCard && temperatureFreshness === "warning";
|
|
18843
|
+
const _off = Number(temperatureOffset) || 0;
|
|
18833
18844
|
const tempValueTitle = (() => {
|
|
18834
|
-
if (
|
|
18845
|
+
if (_isTempCard && temperatureSource === "ingestion-hourly") {
|
|
18846
|
+
const tz = { timeZone: "America/Sao_Paulo" };
|
|
18847
|
+
const hm = (ts) => new Date(ts).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit", ...tz });
|
|
18848
|
+
const dm = (ts) => new Date(ts).toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit", ...tz });
|
|
18849
|
+
const ago = (ts) => {
|
|
18850
|
+
const h3 = Math.floor((Date.now() - ts) / 36e5);
|
|
18851
|
+
const m = Math.floor((Date.now() - ts) % 36e5 / 6e4);
|
|
18852
|
+
return h3 > 0 ? `${h3} h ${m} min` : `${m} min`;
|
|
18853
|
+
};
|
|
18854
|
+
const offTxt = _off ? ` \xB7 offset ${_off > 0 ? "+" : "\u2212"}${String(Math.abs(_off)).replace(".", ",")} \xB0C` : "";
|
|
18855
|
+
if (temperatureFreshness === "offline") return "Nenhuma leitura nas \xFAltimas 24 h";
|
|
18856
|
+
if (!temperatureLastTs) return "";
|
|
18857
|
+
const last = `\xFAltima leitura ${dm(temperatureLastTs)} ${hm(temperatureLastTs)} (h\xE1 ${ago(temperatureLastTs)})`;
|
|
18858
|
+
if (temperatureFreshness === "stale") return `Sem leitura nas \xFAltimas 12 h \u2014 ${last}`;
|
|
18859
|
+
const hour = temperatureHourTs ? `M\xE9dia da hora ${dm(temperatureHourTs)} ${hm(temperatureHourTs)}` : "Temperatura";
|
|
18860
|
+
const warn = temperatureFreshness === "warning" ? "\u26A0 Leitura atrasada (10\u201312 h) \u2014 " : "";
|
|
18861
|
+
return `${warn}${hour} \xB7 ${last}${offTxt}`;
|
|
18862
|
+
}
|
|
18863
|
+
if (!_isTempCard || temperatureSource !== "ingestion-avg-2h") return "";
|
|
18835
18864
|
const at = temperatureFetchedAt ? ` \xB7 Atualizado \xE0s ${new Date(temperatureFetchedAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })}` : "";
|
|
18836
18865
|
return showNoTempReading ? `Nenhuma leitura nas \xFAltimas 2 h${at}` : `Temperatura (m\xE9dia das \xFAltimas 2 h)${at}`;
|
|
18837
18866
|
})();
|
|
@@ -18915,6 +18944,22 @@ function renderCardComponentV5({
|
|
|
18915
18944
|
height: 100%;
|
|
18916
18945
|
}
|
|
18917
18946
|
|
|
18947
|
+
/* Temperatura: leitura atrasada (10\u201312 h) \u2014 borda laranja + \u26A0 piscando */
|
|
18948
|
+
.myio-enhanced-card-container-v5.myio-card-temp-warning .device-card-centered {
|
|
18949
|
+
border: 2px solid #f59e0b !important;
|
|
18950
|
+
box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.18) !important;
|
|
18951
|
+
}
|
|
18952
|
+
.myio-temp-warn-icon {
|
|
18953
|
+
margin-left: 4px;
|
|
18954
|
+
font-size: 0.9em;
|
|
18955
|
+
cursor: help;
|
|
18956
|
+
animation: myio-temp-warn-blink 1.2s ease-in-out infinite;
|
|
18957
|
+
}
|
|
18958
|
+
@keyframes myio-temp-warn-blink {
|
|
18959
|
+
0%, 100% { opacity: 1; }
|
|
18960
|
+
50% { opacity: 0.2; }
|
|
18961
|
+
}
|
|
18962
|
+
|
|
18918
18963
|
/* Subtle orange marker \u2014 device flagged in exclude_groups_totals */
|
|
18919
18964
|
.myio-enhanced-card-container-v5.myio-card-excluded::after {
|
|
18920
18965
|
content: '';
|
|
@@ -19204,7 +19249,7 @@ function renderCardComponentV5({
|
|
|
19204
19249
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
19205
19250
|
${icon2}
|
|
19206
19251
|
</span>
|
|
19207
|
-
<span class="consumption-value"${showNoTempReading ? ' style="color:#9ca3af;font-weight:500;font-size:0.85em;"' : ""}${tempValueTitle ? ` title="${tempValueTitle}"` : ""}>${formatCardValue(cardEntity.lastValue, deviceType)}</span
|
|
19252
|
+
<span class="consumption-value"${showNoTempReading ? ' style="color:#9ca3af;font-weight:500;font-size:0.85em;"' : ""}${tempValueTitle ? ` title="${tempValueTitle}"` : ""}>${formatCardValue(cardEntity.lastValue, deviceType)}</span>${showTempWarning ? `<span class="myio-temp-warn-icon" title="${tempValueTitle}" aria-label="Leitura atrasada">\u26A0\uFE0F</span>` : ""}
|
|
19208
19253
|
</div>
|
|
19209
19254
|
</div>
|
|
19210
19255
|
${isTankDevice2 ? `<span class="device-percentage-badge device-tank-level-badge" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important;">${formatTankHeadFromCm(tankLevelCm)}</span>` : !isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
|
|
@@ -19224,6 +19269,8 @@ function renderCardComponentV5({
|
|
|
19224
19269
|
if (_isExcluded) container.classList.add("myio-card-excluded");
|
|
19225
19270
|
} catch (e) {
|
|
19226
19271
|
}
|
|
19272
|
+
if (_isTempCard && _off !== 0) container.classList.add("myio-card-excluded", "myio-card-temp-offset");
|
|
19273
|
+
if (showTempWarning) container.classList.add("myio-card-temp-warning");
|
|
19227
19274
|
if (!document.getElementById("myio-enhanced-card-layout-styles-v5")) {
|
|
19228
19275
|
const layoutStyle = document.createElement("style");
|
|
19229
19276
|
layoutStyle.id = "myio-enhanced-card-layout-styles-v5";
|
|
@@ -33594,7 +33641,11 @@ function buildRow(d, idx, colOpts) {
|
|
|
33594
33641
|
const x = extras(d);
|
|
33595
33642
|
const fmtVal = () => {
|
|
33596
33643
|
if (d.val === null || d.val === void 0) return colOpts?.emptyValueText || "\u2014";
|
|
33597
|
-
|
|
33644
|
+
const dec = colOpts?.valueDecimals;
|
|
33645
|
+
return Number(d.val).toLocaleString(
|
|
33646
|
+
"pt-BR",
|
|
33647
|
+
dec !== void 0 ? { minimumFractionDigits: dec, maximumFractionDigits: dec, useGrouping: false } : { maximumFractionDigits: 3, useGrouping: false }
|
|
33648
|
+
);
|
|
33598
33649
|
};
|
|
33599
33650
|
const pd = resolvePercentDecimals();
|
|
33600
33651
|
const name = d.labelOrName || d.name || "\u2014";
|
|
@@ -33656,6 +33707,9 @@ function escXml(s) {
|
|
|
33656
33707
|
function truncate(s, max) {
|
|
33657
33708
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
33658
33709
|
}
|
|
33710
|
+
function pdfSafe(s) {
|
|
33711
|
+
return String(s).replace(/−/g, "-").replace(/[‐‑]/g, "-").replace(/ /g, " ");
|
|
33712
|
+
}
|
|
33659
33713
|
function exportGridCsv(devices, label, unit, period, customerName) {
|
|
33660
33714
|
const periodLabel2 = fmtPeriod(period);
|
|
33661
33715
|
const metaRows = [
|
|
@@ -33782,14 +33836,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33782
33836
|
doc.setFont("helvetica", "bold");
|
|
33783
33837
|
doc.setFontSize(10);
|
|
33784
33838
|
const titleText = customerName ? `${customerName} \u2014 ${label}` : label;
|
|
33785
|
-
doc.text(titleText, MARGIN, HDR_H / 2 + 1.5);
|
|
33839
|
+
doc.text(pdfSafe(titleText), MARGIN, HDR_H / 2 + 1.5);
|
|
33786
33840
|
doc.setFont("helvetica", "normal");
|
|
33787
33841
|
doc.setFontSize(8);
|
|
33788
33842
|
const periodLabel2 = fmtPeriod(period);
|
|
33789
33843
|
const periodPart = periodLabel2 ? `Per\xEDodo: ${periodLabel2} \u2022 ` : "";
|
|
33790
33844
|
const countLabel = options?.columns?.countLabel || "dispositivo(s)";
|
|
33791
33845
|
const info = `${periodPart}Gerado em: ${generatedAt} \u2022 ${countDataRows(devices)} ${countLabel} \u2022 Unidade: ${unit} \u2022 P\xE1g. ${pageNo2}`;
|
|
33792
|
-
doc.text(info, PW - MARGIN, HDR_H / 2 + 1.5, { align: "right" });
|
|
33846
|
+
doc.text(pdfSafe(info), PW - MARGIN, HDR_H / 2 + 1.5, { align: "right" });
|
|
33793
33847
|
}
|
|
33794
33848
|
function drawColumnHeaders(y) {
|
|
33795
33849
|
doc.setFillColor(...ACCENT_SOFT);
|
|
@@ -33799,7 +33853,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33799
33853
|
doc.setFontSize(7);
|
|
33800
33854
|
cols.forEach((c, ci) => {
|
|
33801
33855
|
const x = colX(ci) + 1.5;
|
|
33802
|
-
doc.text(c.label, x, y + HEAD_H / 2 + 2.5);
|
|
33856
|
+
doc.text(pdfSafe(c.label), x, y + HEAD_H / 2 + 2.5);
|
|
33803
33857
|
});
|
|
33804
33858
|
doc.setDrawColor(200, 195, 220);
|
|
33805
33859
|
doc.setLineWidth(0.2);
|
|
@@ -33816,7 +33870,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33816
33870
|
cols.forEach((c, ci) => {
|
|
33817
33871
|
const x = colX(ci) + 1.5;
|
|
33818
33872
|
const maxChars = Math.floor(colWidths[ci] / 1.8);
|
|
33819
|
-
const text2 = truncate(String(r[c.key]), maxChars);
|
|
33873
|
+
const text2 = truncate(pdfSafe(String(r[c.key])), maxChars);
|
|
33820
33874
|
doc.text(text2, x, y + ROW_H / 2 + 2.2);
|
|
33821
33875
|
});
|
|
33822
33876
|
doc.setDrawColor(230, 228, 240);
|
|
@@ -33829,7 +33883,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33829
33883
|
doc.setTextColor(...ACCENT2);
|
|
33830
33884
|
doc.setFont("helvetica", "bold");
|
|
33831
33885
|
doc.setFontSize(6.5);
|
|
33832
|
-
doc.text(truncate(text2, 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
33886
|
+
doc.text(truncate(pdfSafe(text2), 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
33833
33887
|
}
|
|
33834
33888
|
function drawFooter2() {
|
|
33835
33889
|
doc.setFillColor(250, 249, 255);
|
|
@@ -33857,14 +33911,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33857
33911
|
doc.setTextColor(...ACCENT2);
|
|
33858
33912
|
doc.setFont("helvetica", "bold");
|
|
33859
33913
|
doc.setFontSize(11);
|
|
33860
|
-
doc.text(truncate(kpi.value, 24), cx, y + 6.5, { align: "center" });
|
|
33914
|
+
doc.text(truncate(pdfSafe(kpi.value), 24), cx, y + 6.5, { align: "center" });
|
|
33861
33915
|
doc.setTextColor(110, 110, 120);
|
|
33862
33916
|
doc.setFont("helvetica", "normal");
|
|
33863
33917
|
doc.setFontSize(6.5);
|
|
33864
|
-
doc.text(truncate(kpi.label, 34), cx, y + 10.5, { align: "center" });
|
|
33918
|
+
doc.text(truncate(pdfSafe(kpi.label), 34), cx, y + 10.5, { align: "center" });
|
|
33865
33919
|
if (kpi.sub) {
|
|
33866
33920
|
doc.setFontSize(5.5);
|
|
33867
|
-
doc.text(truncate(kpi.sub, 40), cx, y + 13.5, { align: "center" });
|
|
33921
|
+
doc.text(truncate(pdfSafe(kpi.sub), 40), cx, y + 13.5, { align: "center" });
|
|
33868
33922
|
}
|
|
33869
33923
|
});
|
|
33870
33924
|
}
|
|
@@ -33911,7 +33965,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33911
33965
|
doc.setTextColor(...ACCENT2);
|
|
33912
33966
|
doc.setFont("helvetica", "bold");
|
|
33913
33967
|
doc.setFontSize(12);
|
|
33914
|
-
doc.text(chart.title || "Participa\xE7\xE3o por Dispositivo", MARGIN, titleY);
|
|
33968
|
+
doc.text(pdfSafe(chart.title || "Participa\xE7\xE3o por Dispositivo"), MARGIN, titleY);
|
|
33915
33969
|
const imgTop = titleY + 4;
|
|
33916
33970
|
const availW = TABLE_W;
|
|
33917
33971
|
const availH = MAX_Y - imgTop;
|
|
@@ -36085,7 +36139,7 @@ var DeviceReportModal = class {
|
|
|
36085
36139
|
// Mesmo rótulo da coluna da tela (antes saía "Consumo (°C)" em temperatura)
|
|
36086
36140
|
valueLabel: this.domainConfig.label,
|
|
36087
36141
|
countLabel: this.granularity === "1h" ? "hora(s)" : "dia(s)",
|
|
36088
|
-
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura" } : {}
|
|
36142
|
+
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura", valueDecimals: 2 } : {}
|
|
36089
36143
|
};
|
|
36090
36144
|
}
|
|
36091
36145
|
// Gráfico da página final do PDF = painel da direita da tela
|
|
@@ -39123,7 +39177,7 @@ var AllReportModal = class {
|
|
|
39123
39177
|
// Header row only
|
|
39124
39178
|
["Identificador", "Nome", `Consumo (${this.domainConfig.unit})`],
|
|
39125
39179
|
// Data rows
|
|
39126
|
-
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2)])
|
|
39180
|
+
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2).replace(".", ",")])
|
|
39127
39181
|
];
|
|
39128
39182
|
const csvContent = toCsv(csvData);
|
|
39129
39183
|
this.downloadCSV(csvContent, `relatorio-geral-lojas-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`);
|
|
@@ -39135,7 +39189,7 @@ var AllReportModal = class {
|
|
|
39135
39189
|
const showId = this.showIdentifierColumn(rows);
|
|
39136
39190
|
const idCol = (r) => showId ? [r.identifier] : [];
|
|
39137
39191
|
const idHead = showId ? ["Identificador"] : [];
|
|
39138
|
-
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2);
|
|
39192
|
+
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2).replace(".", ",");
|
|
39139
39193
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
39140
39194
|
const gran = this.granularity;
|
|
39141
39195
|
const fmtStamp = (ts) => {
|
|
@@ -39181,7 +39235,7 @@ var AllReportModal = class {
|
|
|
39181
39235
|
for (const r of rows) {
|
|
39182
39236
|
const raw = r.id && this.temperatureStats.get(r.id)?.series || [];
|
|
39183
39237
|
const pts = gran === "1h" ? this.aggregateHourly(raw, "avg") : this.aggregateDaily(raw, "avg");
|
|
39184
|
-
for (const p2 of pts) series.push([...idCol(r), r.name, fmtTs(p2.timestamp), p2.value
|
|
39238
|
+
for (const p2 of pts) series.push([...idCol(r), r.name, fmtTs(p2.timestamp), n2(p2.value)]);
|
|
39185
39239
|
}
|
|
39186
39240
|
const csvContent = toCsv([...meta, ...summary, [], ...series]);
|
|
39187
39241
|
this.downloadCSV(csvContent, `relatorio-temperatura-${gran}-${date}.csv`);
|
|
@@ -39208,7 +39262,7 @@ var AllReportModal = class {
|
|
|
39208
39262
|
for (const row of sortedData) {
|
|
39209
39263
|
const points = row.id && series.get(row.id) || [];
|
|
39210
39264
|
for (const p of points) {
|
|
39211
|
-
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2)]);
|
|
39265
|
+
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2).replace(".", ",")]);
|
|
39212
39266
|
}
|
|
39213
39267
|
}
|
|
39214
39268
|
if (csvData.length === 1) {
|
|
@@ -39338,7 +39392,9 @@ var AllReportModal = class {
|
|
|
39338
39392
|
{ label: "M\xE1x (\xB0C)", pdfW: 35 }
|
|
39339
39393
|
],
|
|
39340
39394
|
emptyValueText: "Sem leitura",
|
|
39341
|
-
countLabel: "sensor(es)"
|
|
39395
|
+
countLabel: "sensor(es)",
|
|
39396
|
+
valueDecimals: 2
|
|
39397
|
+
// "30,00" como na tela (não "30")
|
|
39342
39398
|
};
|
|
39343
39399
|
}
|
|
39344
39400
|
// Accent hex da paleta do dashboard (tema efetivo) para o PDF/XLS — cai no
|
package/dist/index.d.cts
CHANGED
|
@@ -19449,6 +19449,8 @@ interface GridColumnsOptions {
|
|
|
19449
19449
|
emptyValueText?: string;
|
|
19450
19450
|
/** Rótulo da contagem no header do PDF (default 'dispositivo(s)'; ex.: 'sensor(es)', 'dia(s)'). */
|
|
19451
19451
|
countLabel?: string;
|
|
19452
|
+
/** Casas decimais FIXAS do valor (ex.: 2 → "30,00" como na tela). Default: até 3, sem mínimo. */
|
|
19453
|
+
valueDecimals?: number;
|
|
19452
19454
|
}
|
|
19453
19455
|
declare function exportGridCsv(devices: TelemetryDevice[], label: string, unit: string, period?: ExportPeriod | null, customerName?: string | null): void;
|
|
19454
19456
|
declare function exportGridXls(devices: TelemetryDevice[], label: string, unit: string, period?: ExportPeriod | null, customerName?: string | null, options?: {
|
package/dist/index.d.ts
CHANGED
|
@@ -19449,6 +19449,8 @@ interface GridColumnsOptions {
|
|
|
19449
19449
|
emptyValueText?: string;
|
|
19450
19450
|
/** Rótulo da contagem no header do PDF (default 'dispositivo(s)'; ex.: 'sensor(es)', 'dia(s)'). */
|
|
19451
19451
|
countLabel?: string;
|
|
19452
|
+
/** Casas decimais FIXAS do valor (ex.: 2 → "30,00" como na tela). Default: até 3, sem mínimo. */
|
|
19453
|
+
valueDecimals?: number;
|
|
19452
19454
|
}
|
|
19453
19455
|
declare function exportGridCsv(devices: TelemetryDevice[], label: string, unit: string, period?: ExportPeriod | null, customerName?: string | null): void;
|
|
19454
19456
|
declare function exportGridXls(devices: TelemetryDevice[], label: string, unit: string, period?: ExportPeriod | null, customerName?: string | null, options?: {
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
// package.json
|
|
11
11
|
var package_default = {
|
|
12
12
|
name: "myio-js-library",
|
|
13
|
-
version: "0.1.
|
|
13
|
+
version: "0.1.554",
|
|
14
14
|
description: "A clean, standalone JS SDK for MYIO projects",
|
|
15
15
|
license: "MIT",
|
|
16
16
|
repository: "github:gh-myio/myio-js-library",
|
|
@@ -17053,9 +17053,17 @@ function renderCardComponentV5({
|
|
|
17053
17053
|
// Temperatura atual vinda do Ingestion = média das últimas 2 h; true = nenhuma leitura na janela
|
|
17054
17054
|
temperatureNoRecentReading = false,
|
|
17055
17055
|
temperatureSource,
|
|
17056
|
-
// 'ingestion-avg-2h' | 'thingsboard' | undefined
|
|
17056
|
+
// 'ingestion-hourly' | 'ingestion-avg-2h' | 'thingsboard' | undefined
|
|
17057
17057
|
temperatureFetchedAt,
|
|
17058
17058
|
// ms da consulta (rótulo "Atualizado às HH:MM")
|
|
17059
|
+
// Idade da última leitura: 'ok' | 'warning' (10–12 h) | 'stale' (12–24 h) | 'offline' (> 24 h)
|
|
17060
|
+
temperatureFreshness,
|
|
17061
|
+
temperatureHourTs,
|
|
17062
|
+
// início da hora fechada exibida (ms)
|
|
17063
|
+
temperatureLastTs,
|
|
17064
|
+
// instante da última leitura válida (ms)
|
|
17065
|
+
temperatureOffset = 0,
|
|
17066
|
+
// offset aplicado (°C) — marcador igual ao da exclusão de totais
|
|
17059
17067
|
// Per-device exclude_groups_totals attribute (SERVER_SCOPE) — drives the orange marker
|
|
17060
17068
|
excludeGroupsTotals
|
|
17061
17069
|
} = entityObject;
|
|
@@ -17216,8 +17224,29 @@ function renderCardComponentV5({
|
|
|
17216
17224
|
const tankLevelCm = isTankDevice2 ? Number(waterLevel ?? val) : null;
|
|
17217
17225
|
const _pctDecimals = resolvePercentDecimals(percentDecimals);
|
|
17218
17226
|
const showNoTempReading = !!temperatureNoRecentReading && isTemperatureDevice2(deviceType);
|
|
17227
|
+
const _isTempCard = isTemperatureDevice2(deviceType);
|
|
17228
|
+
const showTempWarning = _isTempCard && temperatureFreshness === "warning";
|
|
17229
|
+
const _off = Number(temperatureOffset) || 0;
|
|
17219
17230
|
const tempValueTitle = (() => {
|
|
17220
|
-
if (
|
|
17231
|
+
if (_isTempCard && temperatureSource === "ingestion-hourly") {
|
|
17232
|
+
const tz = { timeZone: "America/Sao_Paulo" };
|
|
17233
|
+
const hm = (ts) => new Date(ts).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit", ...tz });
|
|
17234
|
+
const dm = (ts) => new Date(ts).toLocaleDateString("pt-BR", { day: "2-digit", month: "2-digit", ...tz });
|
|
17235
|
+
const ago = (ts) => {
|
|
17236
|
+
const h3 = Math.floor((Date.now() - ts) / 36e5);
|
|
17237
|
+
const m = Math.floor((Date.now() - ts) % 36e5 / 6e4);
|
|
17238
|
+
return h3 > 0 ? `${h3} h ${m} min` : `${m} min`;
|
|
17239
|
+
};
|
|
17240
|
+
const offTxt = _off ? ` \xB7 offset ${_off > 0 ? "+" : "\u2212"}${String(Math.abs(_off)).replace(".", ",")} \xB0C` : "";
|
|
17241
|
+
if (temperatureFreshness === "offline") return "Nenhuma leitura nas \xFAltimas 24 h";
|
|
17242
|
+
if (!temperatureLastTs) return "";
|
|
17243
|
+
const last = `\xFAltima leitura ${dm(temperatureLastTs)} ${hm(temperatureLastTs)} (h\xE1 ${ago(temperatureLastTs)})`;
|
|
17244
|
+
if (temperatureFreshness === "stale") return `Sem leitura nas \xFAltimas 12 h \u2014 ${last}`;
|
|
17245
|
+
const hour = temperatureHourTs ? `M\xE9dia da hora ${dm(temperatureHourTs)} ${hm(temperatureHourTs)}` : "Temperatura";
|
|
17246
|
+
const warn = temperatureFreshness === "warning" ? "\u26A0 Leitura atrasada (10\u201312 h) \u2014 " : "";
|
|
17247
|
+
return `${warn}${hour} \xB7 ${last}${offTxt}`;
|
|
17248
|
+
}
|
|
17249
|
+
if (!_isTempCard || temperatureSource !== "ingestion-avg-2h") return "";
|
|
17221
17250
|
const at = temperatureFetchedAt ? ` \xB7 Atualizado \xE0s ${new Date(temperatureFetchedAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" })}` : "";
|
|
17222
17251
|
return showNoTempReading ? `Nenhuma leitura nas \xFAltimas 2 h${at}` : `Temperatura (m\xE9dia das \xFAltimas 2 h)${at}`;
|
|
17223
17252
|
})();
|
|
@@ -17301,6 +17330,22 @@ function renderCardComponentV5({
|
|
|
17301
17330
|
height: 100%;
|
|
17302
17331
|
}
|
|
17303
17332
|
|
|
17333
|
+
/* Temperatura: leitura atrasada (10\u201312 h) \u2014 borda laranja + \u26A0 piscando */
|
|
17334
|
+
.myio-enhanced-card-container-v5.myio-card-temp-warning .device-card-centered {
|
|
17335
|
+
border: 2px solid #f59e0b !important;
|
|
17336
|
+
box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.18) !important;
|
|
17337
|
+
}
|
|
17338
|
+
.myio-temp-warn-icon {
|
|
17339
|
+
margin-left: 4px;
|
|
17340
|
+
font-size: 0.9em;
|
|
17341
|
+
cursor: help;
|
|
17342
|
+
animation: myio-temp-warn-blink 1.2s ease-in-out infinite;
|
|
17343
|
+
}
|
|
17344
|
+
@keyframes myio-temp-warn-blink {
|
|
17345
|
+
0%, 100% { opacity: 1; }
|
|
17346
|
+
50% { opacity: 0.2; }
|
|
17347
|
+
}
|
|
17348
|
+
|
|
17304
17349
|
/* Subtle orange marker \u2014 device flagged in exclude_groups_totals */
|
|
17305
17350
|
.myio-enhanced-card-container-v5.myio-card-excluded::after {
|
|
17306
17351
|
content: '';
|
|
@@ -17590,7 +17635,7 @@ function renderCardComponentV5({
|
|
|
17590
17635
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
17591
17636
|
${icon2}
|
|
17592
17637
|
</span>
|
|
17593
|
-
<span class="consumption-value"${showNoTempReading ? ' style="color:#9ca3af;font-weight:500;font-size:0.85em;"' : ""}${tempValueTitle ? ` title="${tempValueTitle}"` : ""}>${formatCardValue(cardEntity.lastValue, deviceType)}</span
|
|
17638
|
+
<span class="consumption-value"${showNoTempReading ? ' style="color:#9ca3af;font-weight:500;font-size:0.85em;"' : ""}${tempValueTitle ? ` title="${tempValueTitle}"` : ""}>${formatCardValue(cardEntity.lastValue, deviceType)}</span>${showTempWarning ? `<span class="myio-temp-warn-icon" title="${tempValueTitle}" aria-label="Leitura atrasada">\u26A0\uFE0F</span>` : ""}
|
|
17594
17639
|
</div>
|
|
17595
17640
|
</div>
|
|
17596
17641
|
${isTankDevice2 ? `<span class="device-percentage-badge device-tank-level-badge" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important;">${formatTankHeadFromCm(tankLevelCm)}</span>` : !isTermostatoDevice ? `<span class="device-percentage-badge percentage-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; cursor: help;">${percentageForDisplay.toFixed(_pctDecimals).replace(".", ",")}%</span>` : tempDeviationPercent ? `<span class="device-percentage-badge temp-deviation-badge temp-comparison-tooltip-trigger" style="position: absolute; bottom: 12px; right: 12px; z-index: 20; background: none !important; color: ${tempDeviationPercent.isAbove ? "#ef4444" : tempDeviationPercent.isBelow ? "#3b82f6" : "#6b7280"}; font-weight: 600; cursor: help;">${tempDeviationPercent.sign}${tempDeviationPercent.value.toFixed(1)}%</span>` : ""}
|
|
@@ -17610,6 +17655,8 @@ function renderCardComponentV5({
|
|
|
17610
17655
|
if (_isExcluded) container.classList.add("myio-card-excluded");
|
|
17611
17656
|
} catch (e) {
|
|
17612
17657
|
}
|
|
17658
|
+
if (_isTempCard && _off !== 0) container.classList.add("myio-card-excluded", "myio-card-temp-offset");
|
|
17659
|
+
if (showTempWarning) container.classList.add("myio-card-temp-warning");
|
|
17613
17660
|
if (!document.getElementById("myio-enhanced-card-layout-styles-v5")) {
|
|
17614
17661
|
const layoutStyle = document.createElement("style");
|
|
17615
17662
|
layoutStyle.id = "myio-enhanced-card-layout-styles-v5";
|
|
@@ -31980,7 +32027,11 @@ function buildRow(d, idx, colOpts) {
|
|
|
31980
32027
|
const x = extras(d);
|
|
31981
32028
|
const fmtVal = () => {
|
|
31982
32029
|
if (d.val === null || d.val === void 0) return colOpts?.emptyValueText || "\u2014";
|
|
31983
|
-
|
|
32030
|
+
const dec = colOpts?.valueDecimals;
|
|
32031
|
+
return Number(d.val).toLocaleString(
|
|
32032
|
+
"pt-BR",
|
|
32033
|
+
dec !== void 0 ? { minimumFractionDigits: dec, maximumFractionDigits: dec, useGrouping: false } : { maximumFractionDigits: 3, useGrouping: false }
|
|
32034
|
+
);
|
|
31984
32035
|
};
|
|
31985
32036
|
const pd = resolvePercentDecimals();
|
|
31986
32037
|
const name = d.labelOrName || d.name || "\u2014";
|
|
@@ -32042,6 +32093,9 @@ function escXml(s) {
|
|
|
32042
32093
|
function truncate(s, max) {
|
|
32043
32094
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
32044
32095
|
}
|
|
32096
|
+
function pdfSafe(s) {
|
|
32097
|
+
return String(s).replace(/−/g, "-").replace(/[‐‑]/g, "-").replace(/ /g, " ");
|
|
32098
|
+
}
|
|
32045
32099
|
function exportGridCsv(devices, label, unit, period, customerName) {
|
|
32046
32100
|
const periodLabel2 = fmtPeriod(period);
|
|
32047
32101
|
const metaRows = [
|
|
@@ -32168,14 +32222,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32168
32222
|
doc.setFont("helvetica", "bold");
|
|
32169
32223
|
doc.setFontSize(10);
|
|
32170
32224
|
const titleText = customerName ? `${customerName} \u2014 ${label}` : label;
|
|
32171
|
-
doc.text(titleText, MARGIN, HDR_H / 2 + 1.5);
|
|
32225
|
+
doc.text(pdfSafe(titleText), MARGIN, HDR_H / 2 + 1.5);
|
|
32172
32226
|
doc.setFont("helvetica", "normal");
|
|
32173
32227
|
doc.setFontSize(8);
|
|
32174
32228
|
const periodLabel2 = fmtPeriod(period);
|
|
32175
32229
|
const periodPart = periodLabel2 ? `Per\xEDodo: ${periodLabel2} \u2022 ` : "";
|
|
32176
32230
|
const countLabel = options?.columns?.countLabel || "dispositivo(s)";
|
|
32177
32231
|
const info = `${periodPart}Gerado em: ${generatedAt} \u2022 ${countDataRows(devices)} ${countLabel} \u2022 Unidade: ${unit} \u2022 P\xE1g. ${pageNo2}`;
|
|
32178
|
-
doc.text(info, PW - MARGIN, HDR_H / 2 + 1.5, { align: "right" });
|
|
32232
|
+
doc.text(pdfSafe(info), PW - MARGIN, HDR_H / 2 + 1.5, { align: "right" });
|
|
32179
32233
|
}
|
|
32180
32234
|
function drawColumnHeaders(y) {
|
|
32181
32235
|
doc.setFillColor(...ACCENT_SOFT);
|
|
@@ -32185,7 +32239,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32185
32239
|
doc.setFontSize(7);
|
|
32186
32240
|
cols.forEach((c, ci) => {
|
|
32187
32241
|
const x = colX(ci) + 1.5;
|
|
32188
|
-
doc.text(c.label, x, y + HEAD_H / 2 + 2.5);
|
|
32242
|
+
doc.text(pdfSafe(c.label), x, y + HEAD_H / 2 + 2.5);
|
|
32189
32243
|
});
|
|
32190
32244
|
doc.setDrawColor(200, 195, 220);
|
|
32191
32245
|
doc.setLineWidth(0.2);
|
|
@@ -32202,7 +32256,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32202
32256
|
cols.forEach((c, ci) => {
|
|
32203
32257
|
const x = colX(ci) + 1.5;
|
|
32204
32258
|
const maxChars = Math.floor(colWidths[ci] / 1.8);
|
|
32205
|
-
const text2 = truncate(String(r[c.key]), maxChars);
|
|
32259
|
+
const text2 = truncate(pdfSafe(String(r[c.key])), maxChars);
|
|
32206
32260
|
doc.text(text2, x, y + ROW_H / 2 + 2.2);
|
|
32207
32261
|
});
|
|
32208
32262
|
doc.setDrawColor(230, 228, 240);
|
|
@@ -32215,7 +32269,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32215
32269
|
doc.setTextColor(...ACCENT2);
|
|
32216
32270
|
doc.setFont("helvetica", "bold");
|
|
32217
32271
|
doc.setFontSize(6.5);
|
|
32218
|
-
doc.text(truncate(text2, 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
32272
|
+
doc.text(truncate(pdfSafe(text2), 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
32219
32273
|
}
|
|
32220
32274
|
function drawFooter2() {
|
|
32221
32275
|
doc.setFillColor(250, 249, 255);
|
|
@@ -32243,14 +32297,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32243
32297
|
doc.setTextColor(...ACCENT2);
|
|
32244
32298
|
doc.setFont("helvetica", "bold");
|
|
32245
32299
|
doc.setFontSize(11);
|
|
32246
|
-
doc.text(truncate(kpi.value, 24), cx, y + 6.5, { align: "center" });
|
|
32300
|
+
doc.text(truncate(pdfSafe(kpi.value), 24), cx, y + 6.5, { align: "center" });
|
|
32247
32301
|
doc.setTextColor(110, 110, 120);
|
|
32248
32302
|
doc.setFont("helvetica", "normal");
|
|
32249
32303
|
doc.setFontSize(6.5);
|
|
32250
|
-
doc.text(truncate(kpi.label, 34), cx, y + 10.5, { align: "center" });
|
|
32304
|
+
doc.text(truncate(pdfSafe(kpi.label), 34), cx, y + 10.5, { align: "center" });
|
|
32251
32305
|
if (kpi.sub) {
|
|
32252
32306
|
doc.setFontSize(5.5);
|
|
32253
|
-
doc.text(truncate(kpi.sub, 40), cx, y + 13.5, { align: "center" });
|
|
32307
|
+
doc.text(truncate(pdfSafe(kpi.sub), 40), cx, y + 13.5, { align: "center" });
|
|
32254
32308
|
}
|
|
32255
32309
|
});
|
|
32256
32310
|
}
|
|
@@ -32297,7 +32351,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32297
32351
|
doc.setTextColor(...ACCENT2);
|
|
32298
32352
|
doc.setFont("helvetica", "bold");
|
|
32299
32353
|
doc.setFontSize(12);
|
|
32300
|
-
doc.text(chart.title || "Participa\xE7\xE3o por Dispositivo", MARGIN, titleY);
|
|
32354
|
+
doc.text(pdfSafe(chart.title || "Participa\xE7\xE3o por Dispositivo"), MARGIN, titleY);
|
|
32301
32355
|
const imgTop = titleY + 4;
|
|
32302
32356
|
const availW = TABLE_W;
|
|
32303
32357
|
const availH = MAX_Y - imgTop;
|
|
@@ -34471,7 +34525,7 @@ var DeviceReportModal = class {
|
|
|
34471
34525
|
// Mesmo rótulo da coluna da tela (antes saía "Consumo (°C)" em temperatura)
|
|
34472
34526
|
valueLabel: this.domainConfig.label,
|
|
34473
34527
|
countLabel: this.granularity === "1h" ? "hora(s)" : "dia(s)",
|
|
34474
|
-
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura" } : {}
|
|
34528
|
+
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura", valueDecimals: 2 } : {}
|
|
34475
34529
|
};
|
|
34476
34530
|
}
|
|
34477
34531
|
// Gráfico da página final do PDF = painel da direita da tela
|
|
@@ -37509,7 +37563,7 @@ var AllReportModal = class {
|
|
|
37509
37563
|
// Header row only
|
|
37510
37564
|
["Identificador", "Nome", `Consumo (${this.domainConfig.unit})`],
|
|
37511
37565
|
// Data rows
|
|
37512
|
-
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2)])
|
|
37566
|
+
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2).replace(".", ",")])
|
|
37513
37567
|
];
|
|
37514
37568
|
const csvContent = toCsv(csvData);
|
|
37515
37569
|
this.downloadCSV(csvContent, `relatorio-geral-lojas-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`);
|
|
@@ -37521,7 +37575,7 @@ var AllReportModal = class {
|
|
|
37521
37575
|
const showId = this.showIdentifierColumn(rows);
|
|
37522
37576
|
const idCol = (r) => showId ? [r.identifier] : [];
|
|
37523
37577
|
const idHead = showId ? ["Identificador"] : [];
|
|
37524
|
-
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2);
|
|
37578
|
+
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2).replace(".", ",");
|
|
37525
37579
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
37526
37580
|
const gran = this.granularity;
|
|
37527
37581
|
const fmtStamp = (ts) => {
|
|
@@ -37567,7 +37621,7 @@ var AllReportModal = class {
|
|
|
37567
37621
|
for (const r of rows) {
|
|
37568
37622
|
const raw = r.id && this.temperatureStats.get(r.id)?.series || [];
|
|
37569
37623
|
const pts = gran === "1h" ? this.aggregateHourly(raw, "avg") : this.aggregateDaily(raw, "avg");
|
|
37570
|
-
for (const p2 of pts) series.push([...idCol(r), r.name, fmtTs(p2.timestamp), p2.value
|
|
37624
|
+
for (const p2 of pts) series.push([...idCol(r), r.name, fmtTs(p2.timestamp), n2(p2.value)]);
|
|
37571
37625
|
}
|
|
37572
37626
|
const csvContent = toCsv([...meta, ...summary, [], ...series]);
|
|
37573
37627
|
this.downloadCSV(csvContent, `relatorio-temperatura-${gran}-${date}.csv`);
|
|
@@ -37594,7 +37648,7 @@ var AllReportModal = class {
|
|
|
37594
37648
|
for (const row of sortedData) {
|
|
37595
37649
|
const points = row.id && series.get(row.id) || [];
|
|
37596
37650
|
for (const p of points) {
|
|
37597
|
-
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2)]);
|
|
37651
|
+
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2).replace(".", ",")]);
|
|
37598
37652
|
}
|
|
37599
37653
|
}
|
|
37600
37654
|
if (csvData.length === 1) {
|
|
@@ -37724,7 +37778,9 @@ var AllReportModal = class {
|
|
|
37724
37778
|
{ label: "M\xE1x (\xB0C)", pdfW: 35 }
|
|
37725
37779
|
],
|
|
37726
37780
|
emptyValueText: "Sem leitura",
|
|
37727
|
-
countLabel: "sensor(es)"
|
|
37781
|
+
countLabel: "sensor(es)",
|
|
37782
|
+
valueDecimals: 2
|
|
37783
|
+
// "30,00" como na tela (não "30")
|
|
37728
37784
|
};
|
|
37729
37785
|
}
|
|
37730
37786
|
// Accent hex da paleta do dashboard (tema efetivo) para o PDF/XLS — cai no
|