myio-js-library 0.1.553 → 0.1.555
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 +95 -33
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +95 -33
- package/dist/myio-js-library.umd.js +95 -33
- 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.555",
|
|
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: '';
|
|
@@ -19145,19 +19190,25 @@ function renderCardComponentV5({
|
|
|
19145
19190
|
isOffline
|
|
19146
19191
|
});
|
|
19147
19192
|
const calculateTempDeviationPercent = () => {
|
|
19148
|
-
const currentTemp = Number(val)
|
|
19149
|
-
if (
|
|
19150
|
-
|
|
19151
|
-
|
|
19152
|
-
const deviation = (currentTemp - avgTemp) / avgTemp * 100;
|
|
19153
|
-
return {
|
|
19154
|
-
value: Math.abs(deviation),
|
|
19155
|
-
sign: deviation >= 0 ? "+" : "-",
|
|
19156
|
-
isAbove: deviation > 0,
|
|
19157
|
-
isBelow: deviation < 0
|
|
19158
|
-
};
|
|
19193
|
+
const currentTemp = Number(val);
|
|
19194
|
+
if (!Number.isFinite(currentTemp)) return null;
|
|
19195
|
+
if (temperatureMin === void 0 || temperatureMin === null || temperatureMax === void 0 || temperatureMax === null) {
|
|
19196
|
+
return null;
|
|
19159
19197
|
}
|
|
19160
|
-
|
|
19198
|
+
const min = Number(temperatureMin);
|
|
19199
|
+
const max = Number(temperatureMax);
|
|
19200
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) return null;
|
|
19201
|
+
const fmt1 = (n) => n.toLocaleString("pt-BR", { minimumFractionDigits: 1, maximumFractionDigits: 1 });
|
|
19202
|
+
const range = `Faixa ideal ${fmt1(min)}\u2013${fmt1(max)} \xB0C`;
|
|
19203
|
+
if (currentTemp > max) {
|
|
19204
|
+
const d = currentTemp - max;
|
|
19205
|
+
return { isAbove: true, isBelow: false, value: d, text: `+${fmt1(d)} \xB0C`, title: `${range} \xB7 ${fmt1(d)} \xB0C acima do limite` };
|
|
19206
|
+
}
|
|
19207
|
+
if (currentTemp < min) {
|
|
19208
|
+
const d = min - currentTemp;
|
|
19209
|
+
return { isAbove: false, isBelow: true, value: d, text: `\u2212${fmt1(d)} \xB0C`, title: `${range} \xB7 ${fmt1(d)} \xB0C abaixo do limite` };
|
|
19210
|
+
}
|
|
19211
|
+
return { isAbove: false, isBelow: false, value: 0, text: "na faixa", title: `${range} \xB7 dentro da faixa` };
|
|
19161
19212
|
};
|
|
19162
19213
|
const tempDeviationPercent = isTermostatoDevice && !showNoTempReading ? calculateTempDeviationPercent() : null;
|
|
19163
19214
|
const cardHTML = `
|
|
@@ -19204,10 +19255,10 @@ function renderCardComponentV5({
|
|
|
19204
19255
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
19205
19256
|
${icon2}
|
|
19206
19257
|
</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
|
|
19258
|
+
<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
19259
|
</div>
|
|
19209
19260
|
</div>
|
|
19210
|
-
${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" : "#
|
|
19261
|
+
${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" : "#16a34a"}; font-weight: 600; cursor: help;" title="${tempDeviationPercent.title}">${tempDeviationPercent.text}</span>` : ""}
|
|
19211
19262
|
</div>
|
|
19212
19263
|
</div>
|
|
19213
19264
|
</div>
|
|
@@ -19224,6 +19275,8 @@ function renderCardComponentV5({
|
|
|
19224
19275
|
if (_isExcluded) container.classList.add("myio-card-excluded");
|
|
19225
19276
|
} catch (e) {
|
|
19226
19277
|
}
|
|
19278
|
+
if (_isTempCard && _off !== 0) container.classList.add("myio-card-excluded", "myio-card-temp-offset");
|
|
19279
|
+
if (showTempWarning) container.classList.add("myio-card-temp-warning");
|
|
19227
19280
|
if (!document.getElementById("myio-enhanced-card-layout-styles-v5")) {
|
|
19228
19281
|
const layoutStyle = document.createElement("style");
|
|
19229
19282
|
layoutStyle.id = "myio-enhanced-card-layout-styles-v5";
|
|
@@ -33594,7 +33647,11 @@ function buildRow(d, idx, colOpts) {
|
|
|
33594
33647
|
const x = extras(d);
|
|
33595
33648
|
const fmtVal = () => {
|
|
33596
33649
|
if (d.val === null || d.val === void 0) return colOpts?.emptyValueText || "\u2014";
|
|
33597
|
-
|
|
33650
|
+
const dec = colOpts?.valueDecimals;
|
|
33651
|
+
return Number(d.val).toLocaleString(
|
|
33652
|
+
"pt-BR",
|
|
33653
|
+
dec !== void 0 ? { minimumFractionDigits: dec, maximumFractionDigits: dec, useGrouping: false } : { maximumFractionDigits: 3, useGrouping: false }
|
|
33654
|
+
);
|
|
33598
33655
|
};
|
|
33599
33656
|
const pd = resolvePercentDecimals();
|
|
33600
33657
|
const name = d.labelOrName || d.name || "\u2014";
|
|
@@ -33656,6 +33713,9 @@ function escXml(s) {
|
|
|
33656
33713
|
function truncate(s, max) {
|
|
33657
33714
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
33658
33715
|
}
|
|
33716
|
+
function pdfSafe(s) {
|
|
33717
|
+
return String(s).replace(/−/g, "-").replace(/[‐‑]/g, "-").replace(/ /g, " ");
|
|
33718
|
+
}
|
|
33659
33719
|
function exportGridCsv(devices, label, unit, period, customerName) {
|
|
33660
33720
|
const periodLabel2 = fmtPeriod(period);
|
|
33661
33721
|
const metaRows = [
|
|
@@ -33782,14 +33842,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33782
33842
|
doc.setFont("helvetica", "bold");
|
|
33783
33843
|
doc.setFontSize(10);
|
|
33784
33844
|
const titleText = customerName ? `${customerName} \u2014 ${label}` : label;
|
|
33785
|
-
doc.text(titleText, MARGIN, HDR_H / 2 + 1.5);
|
|
33845
|
+
doc.text(pdfSafe(titleText), MARGIN, HDR_H / 2 + 1.5);
|
|
33786
33846
|
doc.setFont("helvetica", "normal");
|
|
33787
33847
|
doc.setFontSize(8);
|
|
33788
33848
|
const periodLabel2 = fmtPeriod(period);
|
|
33789
33849
|
const periodPart = periodLabel2 ? `Per\xEDodo: ${periodLabel2} \u2022 ` : "";
|
|
33790
33850
|
const countLabel = options?.columns?.countLabel || "dispositivo(s)";
|
|
33791
33851
|
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" });
|
|
33852
|
+
doc.text(pdfSafe(info), PW - MARGIN, HDR_H / 2 + 1.5, { align: "right" });
|
|
33793
33853
|
}
|
|
33794
33854
|
function drawColumnHeaders(y) {
|
|
33795
33855
|
doc.setFillColor(...ACCENT_SOFT);
|
|
@@ -33799,7 +33859,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33799
33859
|
doc.setFontSize(7);
|
|
33800
33860
|
cols.forEach((c, ci) => {
|
|
33801
33861
|
const x = colX(ci) + 1.5;
|
|
33802
|
-
doc.text(c.label, x, y + HEAD_H / 2 + 2.5);
|
|
33862
|
+
doc.text(pdfSafe(c.label), x, y + HEAD_H / 2 + 2.5);
|
|
33803
33863
|
});
|
|
33804
33864
|
doc.setDrawColor(200, 195, 220);
|
|
33805
33865
|
doc.setLineWidth(0.2);
|
|
@@ -33816,7 +33876,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33816
33876
|
cols.forEach((c, ci) => {
|
|
33817
33877
|
const x = colX(ci) + 1.5;
|
|
33818
33878
|
const maxChars = Math.floor(colWidths[ci] / 1.8);
|
|
33819
|
-
const text2 = truncate(String(r[c.key]), maxChars);
|
|
33879
|
+
const text2 = truncate(pdfSafe(String(r[c.key])), maxChars);
|
|
33820
33880
|
doc.text(text2, x, y + ROW_H / 2 + 2.2);
|
|
33821
33881
|
});
|
|
33822
33882
|
doc.setDrawColor(230, 228, 240);
|
|
@@ -33829,7 +33889,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33829
33889
|
doc.setTextColor(...ACCENT2);
|
|
33830
33890
|
doc.setFont("helvetica", "bold");
|
|
33831
33891
|
doc.setFontSize(6.5);
|
|
33832
|
-
doc.text(truncate(text2, 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
33892
|
+
doc.text(truncate(pdfSafe(text2), 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
33833
33893
|
}
|
|
33834
33894
|
function drawFooter2() {
|
|
33835
33895
|
doc.setFillColor(250, 249, 255);
|
|
@@ -33857,14 +33917,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33857
33917
|
doc.setTextColor(...ACCENT2);
|
|
33858
33918
|
doc.setFont("helvetica", "bold");
|
|
33859
33919
|
doc.setFontSize(11);
|
|
33860
|
-
doc.text(truncate(kpi.value, 24), cx, y + 6.5, { align: "center" });
|
|
33920
|
+
doc.text(truncate(pdfSafe(kpi.value), 24), cx, y + 6.5, { align: "center" });
|
|
33861
33921
|
doc.setTextColor(110, 110, 120);
|
|
33862
33922
|
doc.setFont("helvetica", "normal");
|
|
33863
33923
|
doc.setFontSize(6.5);
|
|
33864
|
-
doc.text(truncate(kpi.label, 34), cx, y + 10.5, { align: "center" });
|
|
33924
|
+
doc.text(truncate(pdfSafe(kpi.label), 34), cx, y + 10.5, { align: "center" });
|
|
33865
33925
|
if (kpi.sub) {
|
|
33866
33926
|
doc.setFontSize(5.5);
|
|
33867
|
-
doc.text(truncate(kpi.sub, 40), cx, y + 13.5, { align: "center" });
|
|
33927
|
+
doc.text(truncate(pdfSafe(kpi.sub), 40), cx, y + 13.5, { align: "center" });
|
|
33868
33928
|
}
|
|
33869
33929
|
});
|
|
33870
33930
|
}
|
|
@@ -33911,7 +33971,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
33911
33971
|
doc.setTextColor(...ACCENT2);
|
|
33912
33972
|
doc.setFont("helvetica", "bold");
|
|
33913
33973
|
doc.setFontSize(12);
|
|
33914
|
-
doc.text(chart.title || "Participa\xE7\xE3o por Dispositivo", MARGIN, titleY);
|
|
33974
|
+
doc.text(pdfSafe(chart.title || "Participa\xE7\xE3o por Dispositivo"), MARGIN, titleY);
|
|
33915
33975
|
const imgTop = titleY + 4;
|
|
33916
33976
|
const availW = TABLE_W;
|
|
33917
33977
|
const availH = MAX_Y - imgTop;
|
|
@@ -36085,7 +36145,7 @@ var DeviceReportModal = class {
|
|
|
36085
36145
|
// Mesmo rótulo da coluna da tela (antes saía "Consumo (°C)" em temperatura)
|
|
36086
36146
|
valueLabel: this.domainConfig.label,
|
|
36087
36147
|
countLabel: this.granularity === "1h" ? "hora(s)" : "dia(s)",
|
|
36088
|
-
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura" } : {}
|
|
36148
|
+
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura", valueDecimals: 2 } : {}
|
|
36089
36149
|
};
|
|
36090
36150
|
}
|
|
36091
36151
|
// Gráfico da página final do PDF = painel da direita da tela
|
|
@@ -39123,7 +39183,7 @@ var AllReportModal = class {
|
|
|
39123
39183
|
// Header row only
|
|
39124
39184
|
["Identificador", "Nome", `Consumo (${this.domainConfig.unit})`],
|
|
39125
39185
|
// Data rows
|
|
39126
|
-
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2)])
|
|
39186
|
+
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2).replace(".", ",")])
|
|
39127
39187
|
];
|
|
39128
39188
|
const csvContent = toCsv(csvData);
|
|
39129
39189
|
this.downloadCSV(csvContent, `relatorio-geral-lojas-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`);
|
|
@@ -39135,7 +39195,7 @@ var AllReportModal = class {
|
|
|
39135
39195
|
const showId = this.showIdentifierColumn(rows);
|
|
39136
39196
|
const idCol = (r) => showId ? [r.identifier] : [];
|
|
39137
39197
|
const idHead = showId ? ["Identificador"] : [];
|
|
39138
|
-
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2);
|
|
39198
|
+
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2).replace(".", ",");
|
|
39139
39199
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
39140
39200
|
const gran = this.granularity;
|
|
39141
39201
|
const fmtStamp = (ts) => {
|
|
@@ -39181,7 +39241,7 @@ var AllReportModal = class {
|
|
|
39181
39241
|
for (const r of rows) {
|
|
39182
39242
|
const raw = r.id && this.temperatureStats.get(r.id)?.series || [];
|
|
39183
39243
|
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
|
|
39244
|
+
for (const p2 of pts) series.push([...idCol(r), r.name, fmtTs(p2.timestamp), n2(p2.value)]);
|
|
39185
39245
|
}
|
|
39186
39246
|
const csvContent = toCsv([...meta, ...summary, [], ...series]);
|
|
39187
39247
|
this.downloadCSV(csvContent, `relatorio-temperatura-${gran}-${date}.csv`);
|
|
@@ -39208,7 +39268,7 @@ var AllReportModal = class {
|
|
|
39208
39268
|
for (const row of sortedData) {
|
|
39209
39269
|
const points = row.id && series.get(row.id) || [];
|
|
39210
39270
|
for (const p of points) {
|
|
39211
|
-
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2)]);
|
|
39271
|
+
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2).replace(".", ",")]);
|
|
39212
39272
|
}
|
|
39213
39273
|
}
|
|
39214
39274
|
if (csvData.length === 1) {
|
|
@@ -39338,7 +39398,9 @@ var AllReportModal = class {
|
|
|
39338
39398
|
{ label: "M\xE1x (\xB0C)", pdfW: 35 }
|
|
39339
39399
|
],
|
|
39340
39400
|
emptyValueText: "Sem leitura",
|
|
39341
|
-
countLabel: "sensor(es)"
|
|
39401
|
+
countLabel: "sensor(es)",
|
|
39402
|
+
valueDecimals: 2
|
|
39403
|
+
// "30,00" como na tela (não "30")
|
|
39342
39404
|
};
|
|
39343
39405
|
}
|
|
39344
39406
|
// 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.555",
|
|
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: '';
|
|
@@ -17531,19 +17576,25 @@ function renderCardComponentV5({
|
|
|
17531
17576
|
isOffline
|
|
17532
17577
|
});
|
|
17533
17578
|
const calculateTempDeviationPercent = () => {
|
|
17534
|
-
const currentTemp = Number(val)
|
|
17535
|
-
if (
|
|
17536
|
-
|
|
17537
|
-
|
|
17538
|
-
const deviation = (currentTemp - avgTemp) / avgTemp * 100;
|
|
17539
|
-
return {
|
|
17540
|
-
value: Math.abs(deviation),
|
|
17541
|
-
sign: deviation >= 0 ? "+" : "-",
|
|
17542
|
-
isAbove: deviation > 0,
|
|
17543
|
-
isBelow: deviation < 0
|
|
17544
|
-
};
|
|
17579
|
+
const currentTemp = Number(val);
|
|
17580
|
+
if (!Number.isFinite(currentTemp)) return null;
|
|
17581
|
+
if (temperatureMin === void 0 || temperatureMin === null || temperatureMax === void 0 || temperatureMax === null) {
|
|
17582
|
+
return null;
|
|
17545
17583
|
}
|
|
17546
|
-
|
|
17584
|
+
const min = Number(temperatureMin);
|
|
17585
|
+
const max = Number(temperatureMax);
|
|
17586
|
+
if (!Number.isFinite(min) || !Number.isFinite(max)) return null;
|
|
17587
|
+
const fmt1 = (n) => n.toLocaleString("pt-BR", { minimumFractionDigits: 1, maximumFractionDigits: 1 });
|
|
17588
|
+
const range = `Faixa ideal ${fmt1(min)}\u2013${fmt1(max)} \xB0C`;
|
|
17589
|
+
if (currentTemp > max) {
|
|
17590
|
+
const d = currentTemp - max;
|
|
17591
|
+
return { isAbove: true, isBelow: false, value: d, text: `+${fmt1(d)} \xB0C`, title: `${range} \xB7 ${fmt1(d)} \xB0C acima do limite` };
|
|
17592
|
+
}
|
|
17593
|
+
if (currentTemp < min) {
|
|
17594
|
+
const d = min - currentTemp;
|
|
17595
|
+
return { isAbove: false, isBelow: true, value: d, text: `\u2212${fmt1(d)} \xB0C`, title: `${range} \xB7 ${fmt1(d)} \xB0C abaixo do limite` };
|
|
17596
|
+
}
|
|
17597
|
+
return { isAbove: false, isBelow: false, value: 0, text: "na faixa", title: `${range} \xB7 dentro da faixa` };
|
|
17547
17598
|
};
|
|
17548
17599
|
const tempDeviationPercent = isTermostatoDevice && !showNoTempReading ? calculateTempDeviationPercent() : null;
|
|
17549
17600
|
const cardHTML = `
|
|
@@ -17590,10 +17641,10 @@ function renderCardComponentV5({
|
|
|
17590
17641
|
<span class="flash-icon ${shouldFlashIcon2 ? "flash" : ""}">
|
|
17591
17642
|
${icon2}
|
|
17592
17643
|
</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
|
|
17644
|
+
<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
17645
|
</div>
|
|
17595
17646
|
</div>
|
|
17596
|
-
${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" : "#
|
|
17647
|
+
${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" : "#16a34a"}; font-weight: 600; cursor: help;" title="${tempDeviationPercent.title}">${tempDeviationPercent.text}</span>` : ""}
|
|
17597
17648
|
</div>
|
|
17598
17649
|
</div>
|
|
17599
17650
|
</div>
|
|
@@ -17610,6 +17661,8 @@ function renderCardComponentV5({
|
|
|
17610
17661
|
if (_isExcluded) container.classList.add("myio-card-excluded");
|
|
17611
17662
|
} catch (e) {
|
|
17612
17663
|
}
|
|
17664
|
+
if (_isTempCard && _off !== 0) container.classList.add("myio-card-excluded", "myio-card-temp-offset");
|
|
17665
|
+
if (showTempWarning) container.classList.add("myio-card-temp-warning");
|
|
17613
17666
|
if (!document.getElementById("myio-enhanced-card-layout-styles-v5")) {
|
|
17614
17667
|
const layoutStyle = document.createElement("style");
|
|
17615
17668
|
layoutStyle.id = "myio-enhanced-card-layout-styles-v5";
|
|
@@ -31980,7 +32033,11 @@ function buildRow(d, idx, colOpts) {
|
|
|
31980
32033
|
const x = extras(d);
|
|
31981
32034
|
const fmtVal = () => {
|
|
31982
32035
|
if (d.val === null || d.val === void 0) return colOpts?.emptyValueText || "\u2014";
|
|
31983
|
-
|
|
32036
|
+
const dec = colOpts?.valueDecimals;
|
|
32037
|
+
return Number(d.val).toLocaleString(
|
|
32038
|
+
"pt-BR",
|
|
32039
|
+
dec !== void 0 ? { minimumFractionDigits: dec, maximumFractionDigits: dec, useGrouping: false } : { maximumFractionDigits: 3, useGrouping: false }
|
|
32040
|
+
);
|
|
31984
32041
|
};
|
|
31985
32042
|
const pd = resolvePercentDecimals();
|
|
31986
32043
|
const name = d.labelOrName || d.name || "\u2014";
|
|
@@ -32042,6 +32099,9 @@ function escXml(s) {
|
|
|
32042
32099
|
function truncate(s, max) {
|
|
32043
32100
|
return s.length > max ? s.slice(0, max - 1) + "\u2026" : s;
|
|
32044
32101
|
}
|
|
32102
|
+
function pdfSafe(s) {
|
|
32103
|
+
return String(s).replace(/−/g, "-").replace(/[‐‑]/g, "-").replace(/ /g, " ");
|
|
32104
|
+
}
|
|
32045
32105
|
function exportGridCsv(devices, label, unit, period, customerName) {
|
|
32046
32106
|
const periodLabel2 = fmtPeriod(period);
|
|
32047
32107
|
const metaRows = [
|
|
@@ -32168,14 +32228,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32168
32228
|
doc.setFont("helvetica", "bold");
|
|
32169
32229
|
doc.setFontSize(10);
|
|
32170
32230
|
const titleText = customerName ? `${customerName} \u2014 ${label}` : label;
|
|
32171
|
-
doc.text(titleText, MARGIN, HDR_H / 2 + 1.5);
|
|
32231
|
+
doc.text(pdfSafe(titleText), MARGIN, HDR_H / 2 + 1.5);
|
|
32172
32232
|
doc.setFont("helvetica", "normal");
|
|
32173
32233
|
doc.setFontSize(8);
|
|
32174
32234
|
const periodLabel2 = fmtPeriod(period);
|
|
32175
32235
|
const periodPart = periodLabel2 ? `Per\xEDodo: ${periodLabel2} \u2022 ` : "";
|
|
32176
32236
|
const countLabel = options?.columns?.countLabel || "dispositivo(s)";
|
|
32177
32237
|
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" });
|
|
32238
|
+
doc.text(pdfSafe(info), PW - MARGIN, HDR_H / 2 + 1.5, { align: "right" });
|
|
32179
32239
|
}
|
|
32180
32240
|
function drawColumnHeaders(y) {
|
|
32181
32241
|
doc.setFillColor(...ACCENT_SOFT);
|
|
@@ -32185,7 +32245,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32185
32245
|
doc.setFontSize(7);
|
|
32186
32246
|
cols.forEach((c, ci) => {
|
|
32187
32247
|
const x = colX(ci) + 1.5;
|
|
32188
|
-
doc.text(c.label, x, y + HEAD_H / 2 + 2.5);
|
|
32248
|
+
doc.text(pdfSafe(c.label), x, y + HEAD_H / 2 + 2.5);
|
|
32189
32249
|
});
|
|
32190
32250
|
doc.setDrawColor(200, 195, 220);
|
|
32191
32251
|
doc.setLineWidth(0.2);
|
|
@@ -32202,7 +32262,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32202
32262
|
cols.forEach((c, ci) => {
|
|
32203
32263
|
const x = colX(ci) + 1.5;
|
|
32204
32264
|
const maxChars = Math.floor(colWidths[ci] / 1.8);
|
|
32205
|
-
const text2 = truncate(String(r[c.key]), maxChars);
|
|
32265
|
+
const text2 = truncate(pdfSafe(String(r[c.key])), maxChars);
|
|
32206
32266
|
doc.text(text2, x, y + ROW_H / 2 + 2.2);
|
|
32207
32267
|
});
|
|
32208
32268
|
doc.setDrawColor(230, 228, 240);
|
|
@@ -32215,7 +32275,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32215
32275
|
doc.setTextColor(...ACCENT2);
|
|
32216
32276
|
doc.setFont("helvetica", "bold");
|
|
32217
32277
|
doc.setFontSize(6.5);
|
|
32218
|
-
doc.text(truncate(text2, 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
32278
|
+
doc.text(truncate(pdfSafe(text2), 160), MARGIN + 1.5, y + ROW_H / 2 + 2.2);
|
|
32219
32279
|
}
|
|
32220
32280
|
function drawFooter2() {
|
|
32221
32281
|
doc.setFillColor(250, 249, 255);
|
|
@@ -32243,14 +32303,14 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32243
32303
|
doc.setTextColor(...ACCENT2);
|
|
32244
32304
|
doc.setFont("helvetica", "bold");
|
|
32245
32305
|
doc.setFontSize(11);
|
|
32246
|
-
doc.text(truncate(kpi.value, 24), cx, y + 6.5, { align: "center" });
|
|
32306
|
+
doc.text(truncate(pdfSafe(kpi.value), 24), cx, y + 6.5, { align: "center" });
|
|
32247
32307
|
doc.setTextColor(110, 110, 120);
|
|
32248
32308
|
doc.setFont("helvetica", "normal");
|
|
32249
32309
|
doc.setFontSize(6.5);
|
|
32250
|
-
doc.text(truncate(kpi.label, 34), cx, y + 10.5, { align: "center" });
|
|
32310
|
+
doc.text(truncate(pdfSafe(kpi.label), 34), cx, y + 10.5, { align: "center" });
|
|
32251
32311
|
if (kpi.sub) {
|
|
32252
32312
|
doc.setFontSize(5.5);
|
|
32253
|
-
doc.text(truncate(kpi.sub, 40), cx, y + 13.5, { align: "center" });
|
|
32313
|
+
doc.text(truncate(pdfSafe(kpi.sub), 40), cx, y + 13.5, { align: "center" });
|
|
32254
32314
|
}
|
|
32255
32315
|
});
|
|
32256
32316
|
}
|
|
@@ -32297,7 +32357,7 @@ function exportGridPdf(devices, label, unit, period, customerName, options) {
|
|
|
32297
32357
|
doc.setTextColor(...ACCENT2);
|
|
32298
32358
|
doc.setFont("helvetica", "bold");
|
|
32299
32359
|
doc.setFontSize(12);
|
|
32300
|
-
doc.text(chart.title || "Participa\xE7\xE3o por Dispositivo", MARGIN, titleY);
|
|
32360
|
+
doc.text(pdfSafe(chart.title || "Participa\xE7\xE3o por Dispositivo"), MARGIN, titleY);
|
|
32301
32361
|
const imgTop = titleY + 4;
|
|
32302
32362
|
const availW = TABLE_W;
|
|
32303
32363
|
const availH = MAX_Y - imgTop;
|
|
@@ -34471,7 +34531,7 @@ var DeviceReportModal = class {
|
|
|
34471
34531
|
// Mesmo rótulo da coluna da tela (antes saía "Consumo (°C)" em temperatura)
|
|
34472
34532
|
valueLabel: this.domainConfig.label,
|
|
34473
34533
|
countLabel: this.granularity === "1h" ? "hora(s)" : "dia(s)",
|
|
34474
|
-
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura" } : {}
|
|
34534
|
+
...isTemp ? { hidePerc: true, emptyValueText: "Sem leitura", valueDecimals: 2 } : {}
|
|
34475
34535
|
};
|
|
34476
34536
|
}
|
|
34477
34537
|
// Gráfico da página final do PDF = painel da direita da tela
|
|
@@ -37509,7 +37569,7 @@ var AllReportModal = class {
|
|
|
37509
37569
|
// Header row only
|
|
37510
37570
|
["Identificador", "Nome", `Consumo (${this.domainConfig.unit})`],
|
|
37511
37571
|
// Data rows
|
|
37512
|
-
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2)])
|
|
37572
|
+
...sortedData.map((row) => [row.identifier, row.name, row.consumption.toFixed(2).replace(".", ",")])
|
|
37513
37573
|
];
|
|
37514
37574
|
const csvContent = toCsv(csvData);
|
|
37515
37575
|
this.downloadCSV(csvContent, `relatorio-geral-lojas-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`);
|
|
@@ -37521,7 +37581,7 @@ var AllReportModal = class {
|
|
|
37521
37581
|
const showId = this.showIdentifierColumn(rows);
|
|
37522
37582
|
const idCol = (r) => showId ? [r.identifier] : [];
|
|
37523
37583
|
const idHead = showId ? ["Identificador"] : [];
|
|
37524
|
-
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2);
|
|
37584
|
+
const n2 = (v) => v === null || v === void 0 || !Number.isFinite(v) ? "" : v.toFixed(2).replace(".", ",");
|
|
37525
37585
|
const date = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
37526
37586
|
const gran = this.granularity;
|
|
37527
37587
|
const fmtStamp = (ts) => {
|
|
@@ -37567,7 +37627,7 @@ var AllReportModal = class {
|
|
|
37567
37627
|
for (const r of rows) {
|
|
37568
37628
|
const raw = r.id && this.temperatureStats.get(r.id)?.series || [];
|
|
37569
37629
|
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
|
|
37630
|
+
for (const p2 of pts) series.push([...idCol(r), r.name, fmtTs(p2.timestamp), n2(p2.value)]);
|
|
37571
37631
|
}
|
|
37572
37632
|
const csvContent = toCsv([...meta, ...summary, [], ...series]);
|
|
37573
37633
|
this.downloadCSV(csvContent, `relatorio-temperatura-${gran}-${date}.csv`);
|
|
@@ -37594,7 +37654,7 @@ var AllReportModal = class {
|
|
|
37594
37654
|
for (const row of sortedData) {
|
|
37595
37655
|
const points = row.id && series.get(row.id) || [];
|
|
37596
37656
|
for (const p of points) {
|
|
37597
|
-
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2)]);
|
|
37657
|
+
csvData.push([row.identifier, row.name, fmtTs(p.timestamp), p.value.toFixed(2).replace(".", ",")]);
|
|
37598
37658
|
}
|
|
37599
37659
|
}
|
|
37600
37660
|
if (csvData.length === 1) {
|
|
@@ -37724,7 +37784,9 @@ var AllReportModal = class {
|
|
|
37724
37784
|
{ label: "M\xE1x (\xB0C)", pdfW: 35 }
|
|
37725
37785
|
],
|
|
37726
37786
|
emptyValueText: "Sem leitura",
|
|
37727
|
-
countLabel: "sensor(es)"
|
|
37787
|
+
countLabel: "sensor(es)",
|
|
37788
|
+
valueDecimals: 2
|
|
37789
|
+
// "30,00" como na tela (não "30")
|
|
37728
37790
|
};
|
|
37729
37791
|
}
|
|
37730
37792
|
// Accent hex da paleta do dashboard (tema efetivo) para o PDF/XLS — cai no
|