myio-js-library 0.1.35 → 0.1.37
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 +63 -26
- package/dist/index.d.cts +2 -0
- package/dist/index.js +63 -26
- package/dist/myio-js-library.umd.js +63 -26
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5809,6 +5809,7 @@ var DeviceReportModal = class {
|
|
|
5809
5809
|
isLoading = false;
|
|
5810
5810
|
eventHandlers = {};
|
|
5811
5811
|
dateRangePicker = null;
|
|
5812
|
+
sortState = { key: null, direction: "asc" };
|
|
5812
5813
|
show() {
|
|
5813
5814
|
this.modal = createModal({
|
|
5814
5815
|
title: `Relat\xF3rio - ${this.params.identifier || "SEM IDENTIFICADOR"} - ${this.params.label || "SEM ETIQUETA"}`,
|
|
@@ -5963,6 +5964,12 @@ var DeviceReportModal = class {
|
|
|
5963
5964
|
const container = document.getElementById("table-container");
|
|
5964
5965
|
if (!container) return;
|
|
5965
5966
|
const total = this.calculateTotal();
|
|
5967
|
+
const getSortIndicator = (columnKey) => {
|
|
5968
|
+
if (this.sortState.key === columnKey) {
|
|
5969
|
+
return this.sortState.direction === "asc" ? "\u2191" : "\u2193";
|
|
5970
|
+
}
|
|
5971
|
+
return "\u2195";
|
|
5972
|
+
};
|
|
5966
5973
|
container.innerHTML = `
|
|
5967
5974
|
<div style="margin-bottom: 16px; padding: 12px; background: var(--myio-bg); border-radius: 6px;">
|
|
5968
5975
|
<strong>Total: ${fmtPt(total)} kWh</strong>
|
|
@@ -5974,11 +5981,11 @@ var DeviceReportModal = class {
|
|
|
5974
5981
|
<tr>
|
|
5975
5982
|
<th style="cursor: pointer;" data-sort="date">
|
|
5976
5983
|
Data
|
|
5977
|
-
<span style="margin-left: 4px; opacity: 0.5;"
|
|
5984
|
+
<span style="margin-left: 4px; opacity: ${this.sortState.key === "date" ? "1" : "0.5"};">${getSortIndicator("date")}</span>
|
|
5978
5985
|
</th>
|
|
5979
5986
|
<th style="cursor: pointer; text-align: right;" data-sort="consumption">
|
|
5980
5987
|
Consumo (kWh)
|
|
5981
|
-
<span style="margin-left: 4px; opacity: 0.5;"
|
|
5988
|
+
<span style="margin-left: 4px; opacity: ${this.sortState.key === "consumption" ? "1" : "0.5"};">${getSortIndicator("consumption")}</span>
|
|
5982
5989
|
</th>
|
|
5983
5990
|
</tr>
|
|
5984
5991
|
</thead>
|
|
@@ -6006,12 +6013,20 @@ var DeviceReportModal = class {
|
|
|
6006
6013
|
});
|
|
6007
6014
|
}
|
|
6008
6015
|
sortData(key) {
|
|
6016
|
+
if (this.sortState.key === key) {
|
|
6017
|
+
this.sortState.direction = this.sortState.direction === "asc" ? "desc" : "asc";
|
|
6018
|
+
} else {
|
|
6019
|
+
this.sortState.key = key;
|
|
6020
|
+
this.sortState.direction = "asc";
|
|
6021
|
+
}
|
|
6009
6022
|
this.data.sort((a, b) => {
|
|
6023
|
+
let comparison = 0;
|
|
6010
6024
|
if (key === "date") {
|
|
6011
|
-
|
|
6025
|
+
comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
|
|
6012
6026
|
} else {
|
|
6013
|
-
|
|
6027
|
+
comparison = a.consumption - b.consumption;
|
|
6014
6028
|
}
|
|
6029
|
+
return this.sortState.direction === "desc" ? -comparison : comparison;
|
|
6015
6030
|
});
|
|
6016
6031
|
}
|
|
6017
6032
|
calculateTotal() {
|
|
@@ -7166,15 +7181,15 @@ var AllReportModal = class {
|
|
|
7166
7181
|
<tr>
|
|
7167
7182
|
<th style="cursor: pointer; width: 25%;" data-sort="identifier">
|
|
7168
7183
|
Identifier
|
|
7169
|
-
<span style="margin-left: 4px; opacity:
|
|
7184
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("identifier")};">${this.getSortIcon("identifier")}</span>
|
|
7170
7185
|
</th>
|
|
7171
7186
|
<th style="cursor: pointer; width: 45%;" data-sort="name">
|
|
7172
7187
|
Name
|
|
7173
|
-
<span style="margin-left: 4px; opacity:
|
|
7188
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("name")};">${this.getSortIcon("name")}</span>
|
|
7174
7189
|
</th>
|
|
7175
7190
|
<th style="cursor: pointer; text-align: right; width: 30%;" data-sort="consumption">
|
|
7176
7191
|
Consumption (kWh)
|
|
7177
|
-
<span style="margin-left: 4px; opacity:
|
|
7192
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("consumption")};">${this.getSortIcon("consumption")}</span>
|
|
7178
7193
|
</th>
|
|
7179
7194
|
</tr>
|
|
7180
7195
|
</thead>
|
|
@@ -7196,6 +7211,9 @@ var AllReportModal = class {
|
|
|
7196
7211
|
if (this.sortField !== field) return "\u2195";
|
|
7197
7212
|
return this.sortDirection === "asc" ? "\u2191" : "\u2193";
|
|
7198
7213
|
}
|
|
7214
|
+
getSortOpacity(field) {
|
|
7215
|
+
return this.sortField === field ? "1" : "0.5";
|
|
7216
|
+
}
|
|
7199
7217
|
setupTableSorting() {
|
|
7200
7218
|
const headers = document.querySelectorAll("[data-sort]");
|
|
7201
7219
|
headers.forEach((header) => {
|
|
@@ -7377,14 +7395,23 @@ var AllReportModal = class {
|
|
|
7377
7395
|
}
|
|
7378
7396
|
const data = await response.json();
|
|
7379
7397
|
console.log("[AllReportModal] Customer totals response:", data);
|
|
7380
|
-
return
|
|
7398
|
+
return data;
|
|
7381
7399
|
}
|
|
7382
|
-
mapCustomerTotalsResponse(
|
|
7383
|
-
|
|
7384
|
-
|
|
7400
|
+
mapCustomerTotalsResponse(apiResponse) {
|
|
7401
|
+
let dataArray = [];
|
|
7402
|
+
if (apiResponse && apiResponse.data && Array.isArray(apiResponse.data)) {
|
|
7403
|
+
dataArray = apiResponse.data;
|
|
7404
|
+
} else if (Array.isArray(apiResponse)) {
|
|
7405
|
+
dataArray = apiResponse;
|
|
7406
|
+
} else {
|
|
7407
|
+
console.warn("[AllReportModal] Invalid API response structure:", apiResponse);
|
|
7408
|
+
return [];
|
|
7409
|
+
}
|
|
7410
|
+
if (dataArray.length === 0) {
|
|
7411
|
+
console.warn("[AllReportModal] Empty data array in API response");
|
|
7385
7412
|
return [];
|
|
7386
7413
|
}
|
|
7387
|
-
const mappedData =
|
|
7414
|
+
const mappedData = dataArray.map((item) => {
|
|
7388
7415
|
const identifier = item.identifier || item.deviceId || item.id || "N/A";
|
|
7389
7416
|
const name = item.deviceLabel || item.name || item.label || identifier;
|
|
7390
7417
|
const consumption = this.parseConsumptionValue(item);
|
|
@@ -7394,11 +7421,11 @@ var AllReportModal = class {
|
|
|
7394
7421
|
consumption
|
|
7395
7422
|
};
|
|
7396
7423
|
}).filter((store) => {
|
|
7397
|
-
return !this.shouldExcludeStore(store.name);
|
|
7424
|
+
return !this.shouldExcludeStore(store.name, store.identifier);
|
|
7398
7425
|
}).filter((store) => {
|
|
7399
7426
|
return !isNaN(store.consumption) && store.consumption >= 0;
|
|
7400
7427
|
});
|
|
7401
|
-
console.log("[AllReportModal] Mapped customer totals:", mappedData.length, "stores");
|
|
7428
|
+
console.log("[AllReportModal] Mapped customer totals:", mappedData.length, "stores from", dataArray.length, "total devices");
|
|
7402
7429
|
return mappedData;
|
|
7403
7430
|
}
|
|
7404
7431
|
parseConsumptionValue(item) {
|
|
@@ -7422,14 +7449,24 @@ var AllReportModal = class {
|
|
|
7422
7449
|
console.warn("[AllReportModal] No valid consumption value found in item:", item);
|
|
7423
7450
|
return 0;
|
|
7424
7451
|
}
|
|
7425
|
-
shouldExcludeStore(storeName) {
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7452
|
+
shouldExcludeStore(storeName, storeId) {
|
|
7453
|
+
const filters = this.params.filters;
|
|
7454
|
+
if (!filters) return false;
|
|
7455
|
+
if (filters.forceOnlyIds && Array.isArray(filters.forceOnlyIds) && filters.forceOnlyIds.length > 0) {
|
|
7456
|
+
return !filters.forceOnlyIds.includes(storeId);
|
|
7457
|
+
}
|
|
7458
|
+
if (filters.excludeIds && Array.isArray(filters.excludeIds) && filters.excludeIds.length > 0) {
|
|
7459
|
+
return filters.excludeIds.includes(storeId);
|
|
7460
|
+
}
|
|
7461
|
+
if (filters.excludeLabels && Array.isArray(filters.excludeLabels) && filters.excludeLabels.length > 0) {
|
|
7462
|
+
return filters.excludeLabels.some((filter) => {
|
|
7463
|
+
if (filter instanceof RegExp) {
|
|
7464
|
+
return filter.test(storeName);
|
|
7465
|
+
}
|
|
7466
|
+
return storeName.toLowerCase().includes(filter.toLowerCase());
|
|
7467
|
+
});
|
|
7468
|
+
}
|
|
7469
|
+
return false;
|
|
7433
7470
|
}
|
|
7434
7471
|
downloadCSV(content, filename) {
|
|
7435
7472
|
const BOM = "\uFEFF";
|
|
@@ -8057,16 +8094,16 @@ var DefaultSettingsPersister = class {
|
|
|
8057
8094
|
throw this.createHttpError(getRes.status, await getRes.text().catch(() => ""));
|
|
8058
8095
|
}
|
|
8059
8096
|
const device = await getRes.json();
|
|
8060
|
-
const
|
|
8061
|
-
method: "
|
|
8097
|
+
const postRes = await fetch(`${this.tbBaseUrl}/api/device`, {
|
|
8098
|
+
method: "POST",
|
|
8062
8099
|
headers: {
|
|
8063
8100
|
"X-Authorization": `Bearer ${this.jwtToken}`,
|
|
8064
8101
|
"Content-Type": "application/json"
|
|
8065
8102
|
},
|
|
8066
8103
|
body: JSON.stringify({ ...device, label: this.sanitizeLabel(label) })
|
|
8067
8104
|
});
|
|
8068
|
-
if (!
|
|
8069
|
-
throw this.createHttpError(
|
|
8105
|
+
if (!postRes.ok) {
|
|
8106
|
+
throw this.createHttpError(postRes.status, await postRes.text().catch(() => ""));
|
|
8070
8107
|
}
|
|
8071
8108
|
return { ok: true };
|
|
8072
8109
|
} catch (error) {
|
package/dist/index.d.cts
CHANGED
package/dist/index.js
CHANGED
|
@@ -5742,6 +5742,7 @@ var DeviceReportModal = class {
|
|
|
5742
5742
|
isLoading = false;
|
|
5743
5743
|
eventHandlers = {};
|
|
5744
5744
|
dateRangePicker = null;
|
|
5745
|
+
sortState = { key: null, direction: "asc" };
|
|
5745
5746
|
show() {
|
|
5746
5747
|
this.modal = createModal({
|
|
5747
5748
|
title: `Relat\xF3rio - ${this.params.identifier || "SEM IDENTIFICADOR"} - ${this.params.label || "SEM ETIQUETA"}`,
|
|
@@ -5896,6 +5897,12 @@ var DeviceReportModal = class {
|
|
|
5896
5897
|
const container = document.getElementById("table-container");
|
|
5897
5898
|
if (!container) return;
|
|
5898
5899
|
const total = this.calculateTotal();
|
|
5900
|
+
const getSortIndicator = (columnKey) => {
|
|
5901
|
+
if (this.sortState.key === columnKey) {
|
|
5902
|
+
return this.sortState.direction === "asc" ? "\u2191" : "\u2193";
|
|
5903
|
+
}
|
|
5904
|
+
return "\u2195";
|
|
5905
|
+
};
|
|
5899
5906
|
container.innerHTML = `
|
|
5900
5907
|
<div style="margin-bottom: 16px; padding: 12px; background: var(--myio-bg); border-radius: 6px;">
|
|
5901
5908
|
<strong>Total: ${fmtPt(total)} kWh</strong>
|
|
@@ -5907,11 +5914,11 @@ var DeviceReportModal = class {
|
|
|
5907
5914
|
<tr>
|
|
5908
5915
|
<th style="cursor: pointer;" data-sort="date">
|
|
5909
5916
|
Data
|
|
5910
|
-
<span style="margin-left: 4px; opacity: 0.5;"
|
|
5917
|
+
<span style="margin-left: 4px; opacity: ${this.sortState.key === "date" ? "1" : "0.5"};">${getSortIndicator("date")}</span>
|
|
5911
5918
|
</th>
|
|
5912
5919
|
<th style="cursor: pointer; text-align: right;" data-sort="consumption">
|
|
5913
5920
|
Consumo (kWh)
|
|
5914
|
-
<span style="margin-left: 4px; opacity: 0.5;"
|
|
5921
|
+
<span style="margin-left: 4px; opacity: ${this.sortState.key === "consumption" ? "1" : "0.5"};">${getSortIndicator("consumption")}</span>
|
|
5915
5922
|
</th>
|
|
5916
5923
|
</tr>
|
|
5917
5924
|
</thead>
|
|
@@ -5939,12 +5946,20 @@ var DeviceReportModal = class {
|
|
|
5939
5946
|
});
|
|
5940
5947
|
}
|
|
5941
5948
|
sortData(key) {
|
|
5949
|
+
if (this.sortState.key === key) {
|
|
5950
|
+
this.sortState.direction = this.sortState.direction === "asc" ? "desc" : "asc";
|
|
5951
|
+
} else {
|
|
5952
|
+
this.sortState.key = key;
|
|
5953
|
+
this.sortState.direction = "asc";
|
|
5954
|
+
}
|
|
5942
5955
|
this.data.sort((a, b) => {
|
|
5956
|
+
let comparison = 0;
|
|
5943
5957
|
if (key === "date") {
|
|
5944
|
-
|
|
5958
|
+
comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
|
|
5945
5959
|
} else {
|
|
5946
|
-
|
|
5960
|
+
comparison = a.consumption - b.consumption;
|
|
5947
5961
|
}
|
|
5962
|
+
return this.sortState.direction === "desc" ? -comparison : comparison;
|
|
5948
5963
|
});
|
|
5949
5964
|
}
|
|
5950
5965
|
calculateTotal() {
|
|
@@ -7099,15 +7114,15 @@ var AllReportModal = class {
|
|
|
7099
7114
|
<tr>
|
|
7100
7115
|
<th style="cursor: pointer; width: 25%;" data-sort="identifier">
|
|
7101
7116
|
Identifier
|
|
7102
|
-
<span style="margin-left: 4px; opacity:
|
|
7117
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("identifier")};">${this.getSortIcon("identifier")}</span>
|
|
7103
7118
|
</th>
|
|
7104
7119
|
<th style="cursor: pointer; width: 45%;" data-sort="name">
|
|
7105
7120
|
Name
|
|
7106
|
-
<span style="margin-left: 4px; opacity:
|
|
7121
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("name")};">${this.getSortIcon("name")}</span>
|
|
7107
7122
|
</th>
|
|
7108
7123
|
<th style="cursor: pointer; text-align: right; width: 30%;" data-sort="consumption">
|
|
7109
7124
|
Consumption (kWh)
|
|
7110
|
-
<span style="margin-left: 4px; opacity:
|
|
7125
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("consumption")};">${this.getSortIcon("consumption")}</span>
|
|
7111
7126
|
</th>
|
|
7112
7127
|
</tr>
|
|
7113
7128
|
</thead>
|
|
@@ -7129,6 +7144,9 @@ var AllReportModal = class {
|
|
|
7129
7144
|
if (this.sortField !== field) return "\u2195";
|
|
7130
7145
|
return this.sortDirection === "asc" ? "\u2191" : "\u2193";
|
|
7131
7146
|
}
|
|
7147
|
+
getSortOpacity(field) {
|
|
7148
|
+
return this.sortField === field ? "1" : "0.5";
|
|
7149
|
+
}
|
|
7132
7150
|
setupTableSorting() {
|
|
7133
7151
|
const headers = document.querySelectorAll("[data-sort]");
|
|
7134
7152
|
headers.forEach((header) => {
|
|
@@ -7310,14 +7328,23 @@ var AllReportModal = class {
|
|
|
7310
7328
|
}
|
|
7311
7329
|
const data = await response.json();
|
|
7312
7330
|
console.log("[AllReportModal] Customer totals response:", data);
|
|
7313
|
-
return
|
|
7331
|
+
return data;
|
|
7314
7332
|
}
|
|
7315
|
-
mapCustomerTotalsResponse(
|
|
7316
|
-
|
|
7317
|
-
|
|
7333
|
+
mapCustomerTotalsResponse(apiResponse) {
|
|
7334
|
+
let dataArray = [];
|
|
7335
|
+
if (apiResponse && apiResponse.data && Array.isArray(apiResponse.data)) {
|
|
7336
|
+
dataArray = apiResponse.data;
|
|
7337
|
+
} else if (Array.isArray(apiResponse)) {
|
|
7338
|
+
dataArray = apiResponse;
|
|
7339
|
+
} else {
|
|
7340
|
+
console.warn("[AllReportModal] Invalid API response structure:", apiResponse);
|
|
7341
|
+
return [];
|
|
7342
|
+
}
|
|
7343
|
+
if (dataArray.length === 0) {
|
|
7344
|
+
console.warn("[AllReportModal] Empty data array in API response");
|
|
7318
7345
|
return [];
|
|
7319
7346
|
}
|
|
7320
|
-
const mappedData =
|
|
7347
|
+
const mappedData = dataArray.map((item) => {
|
|
7321
7348
|
const identifier = item.identifier || item.deviceId || item.id || "N/A";
|
|
7322
7349
|
const name = item.deviceLabel || item.name || item.label || identifier;
|
|
7323
7350
|
const consumption = this.parseConsumptionValue(item);
|
|
@@ -7327,11 +7354,11 @@ var AllReportModal = class {
|
|
|
7327
7354
|
consumption
|
|
7328
7355
|
};
|
|
7329
7356
|
}).filter((store) => {
|
|
7330
|
-
return !this.shouldExcludeStore(store.name);
|
|
7357
|
+
return !this.shouldExcludeStore(store.name, store.identifier);
|
|
7331
7358
|
}).filter((store) => {
|
|
7332
7359
|
return !isNaN(store.consumption) && store.consumption >= 0;
|
|
7333
7360
|
});
|
|
7334
|
-
console.log("[AllReportModal] Mapped customer totals:", mappedData.length, "stores");
|
|
7361
|
+
console.log("[AllReportModal] Mapped customer totals:", mappedData.length, "stores from", dataArray.length, "total devices");
|
|
7335
7362
|
return mappedData;
|
|
7336
7363
|
}
|
|
7337
7364
|
parseConsumptionValue(item) {
|
|
@@ -7355,14 +7382,24 @@ var AllReportModal = class {
|
|
|
7355
7382
|
console.warn("[AllReportModal] No valid consumption value found in item:", item);
|
|
7356
7383
|
return 0;
|
|
7357
7384
|
}
|
|
7358
|
-
shouldExcludeStore(storeName) {
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7385
|
+
shouldExcludeStore(storeName, storeId) {
|
|
7386
|
+
const filters = this.params.filters;
|
|
7387
|
+
if (!filters) return false;
|
|
7388
|
+
if (filters.forceOnlyIds && Array.isArray(filters.forceOnlyIds) && filters.forceOnlyIds.length > 0) {
|
|
7389
|
+
return !filters.forceOnlyIds.includes(storeId);
|
|
7390
|
+
}
|
|
7391
|
+
if (filters.excludeIds && Array.isArray(filters.excludeIds) && filters.excludeIds.length > 0) {
|
|
7392
|
+
return filters.excludeIds.includes(storeId);
|
|
7393
|
+
}
|
|
7394
|
+
if (filters.excludeLabels && Array.isArray(filters.excludeLabels) && filters.excludeLabels.length > 0) {
|
|
7395
|
+
return filters.excludeLabels.some((filter) => {
|
|
7396
|
+
if (filter instanceof RegExp) {
|
|
7397
|
+
return filter.test(storeName);
|
|
7398
|
+
}
|
|
7399
|
+
return storeName.toLowerCase().includes(filter.toLowerCase());
|
|
7400
|
+
});
|
|
7401
|
+
}
|
|
7402
|
+
return false;
|
|
7366
7403
|
}
|
|
7367
7404
|
downloadCSV(content, filename) {
|
|
7368
7405
|
const BOM = "\uFEFF";
|
|
@@ -7990,16 +8027,16 @@ var DefaultSettingsPersister = class {
|
|
|
7990
8027
|
throw this.createHttpError(getRes.status, await getRes.text().catch(() => ""));
|
|
7991
8028
|
}
|
|
7992
8029
|
const device = await getRes.json();
|
|
7993
|
-
const
|
|
7994
|
-
method: "
|
|
8030
|
+
const postRes = await fetch(`${this.tbBaseUrl}/api/device`, {
|
|
8031
|
+
method: "POST",
|
|
7995
8032
|
headers: {
|
|
7996
8033
|
"X-Authorization": `Bearer ${this.jwtToken}`,
|
|
7997
8034
|
"Content-Type": "application/json"
|
|
7998
8035
|
},
|
|
7999
8036
|
body: JSON.stringify({ ...device, label: this.sanitizeLabel(label) })
|
|
8000
8037
|
});
|
|
8001
|
-
if (!
|
|
8002
|
-
throw this.createHttpError(
|
|
8038
|
+
if (!postRes.ok) {
|
|
8039
|
+
throw this.createHttpError(postRes.status, await postRes.text().catch(() => ""));
|
|
8003
8040
|
}
|
|
8004
8041
|
return { ok: true };
|
|
8005
8042
|
} catch (error) {
|
|
@@ -5731,6 +5731,7 @@
|
|
|
5731
5731
|
isLoading = false;
|
|
5732
5732
|
eventHandlers = {};
|
|
5733
5733
|
dateRangePicker = null;
|
|
5734
|
+
sortState = { key: null, direction: "asc" };
|
|
5734
5735
|
show() {
|
|
5735
5736
|
this.modal = createModal({
|
|
5736
5737
|
title: `Relat\xF3rio - ${this.params.identifier || "SEM IDENTIFICADOR"} - ${this.params.label || "SEM ETIQUETA"}`,
|
|
@@ -5885,6 +5886,12 @@
|
|
|
5885
5886
|
const container = document.getElementById("table-container");
|
|
5886
5887
|
if (!container) return;
|
|
5887
5888
|
const total = this.calculateTotal();
|
|
5889
|
+
const getSortIndicator = (columnKey) => {
|
|
5890
|
+
if (this.sortState.key === columnKey) {
|
|
5891
|
+
return this.sortState.direction === "asc" ? "\u2191" : "\u2193";
|
|
5892
|
+
}
|
|
5893
|
+
return "\u2195";
|
|
5894
|
+
};
|
|
5888
5895
|
container.innerHTML = `
|
|
5889
5896
|
<div style="margin-bottom: 16px; padding: 12px; background: var(--myio-bg); border-radius: 6px;">
|
|
5890
5897
|
<strong>Total: ${fmtPt(total)} kWh</strong>
|
|
@@ -5896,11 +5903,11 @@
|
|
|
5896
5903
|
<tr>
|
|
5897
5904
|
<th style="cursor: pointer;" data-sort="date">
|
|
5898
5905
|
Data
|
|
5899
|
-
<span style="margin-left: 4px; opacity: 0.5;"
|
|
5906
|
+
<span style="margin-left: 4px; opacity: ${this.sortState.key === "date" ? "1" : "0.5"};">${getSortIndicator("date")}</span>
|
|
5900
5907
|
</th>
|
|
5901
5908
|
<th style="cursor: pointer; text-align: right;" data-sort="consumption">
|
|
5902
5909
|
Consumo (kWh)
|
|
5903
|
-
<span style="margin-left: 4px; opacity: 0.5;"
|
|
5910
|
+
<span style="margin-left: 4px; opacity: ${this.sortState.key === "consumption" ? "1" : "0.5"};">${getSortIndicator("consumption")}</span>
|
|
5904
5911
|
</th>
|
|
5905
5912
|
</tr>
|
|
5906
5913
|
</thead>
|
|
@@ -5928,12 +5935,20 @@
|
|
|
5928
5935
|
});
|
|
5929
5936
|
}
|
|
5930
5937
|
sortData(key) {
|
|
5938
|
+
if (this.sortState.key === key) {
|
|
5939
|
+
this.sortState.direction = this.sortState.direction === "asc" ? "desc" : "asc";
|
|
5940
|
+
} else {
|
|
5941
|
+
this.sortState.key = key;
|
|
5942
|
+
this.sortState.direction = "asc";
|
|
5943
|
+
}
|
|
5931
5944
|
this.data.sort((a, b) => {
|
|
5945
|
+
let comparison = 0;
|
|
5932
5946
|
if (key === "date") {
|
|
5933
|
-
|
|
5947
|
+
comparison = new Date(a.date).getTime() - new Date(b.date).getTime();
|
|
5934
5948
|
} else {
|
|
5935
|
-
|
|
5949
|
+
comparison = a.consumption - b.consumption;
|
|
5936
5950
|
}
|
|
5951
|
+
return this.sortState.direction === "desc" ? -comparison : comparison;
|
|
5937
5952
|
});
|
|
5938
5953
|
}
|
|
5939
5954
|
calculateTotal() {
|
|
@@ -7088,15 +7103,15 @@
|
|
|
7088
7103
|
<tr>
|
|
7089
7104
|
<th style="cursor: pointer; width: 25%;" data-sort="identifier">
|
|
7090
7105
|
Identifier
|
|
7091
|
-
<span style="margin-left: 4px; opacity:
|
|
7106
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("identifier")};">${this.getSortIcon("identifier")}</span>
|
|
7092
7107
|
</th>
|
|
7093
7108
|
<th style="cursor: pointer; width: 45%;" data-sort="name">
|
|
7094
7109
|
Name
|
|
7095
|
-
<span style="margin-left: 4px; opacity:
|
|
7110
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("name")};">${this.getSortIcon("name")}</span>
|
|
7096
7111
|
</th>
|
|
7097
7112
|
<th style="cursor: pointer; text-align: right; width: 30%;" data-sort="consumption">
|
|
7098
7113
|
Consumption (kWh)
|
|
7099
|
-
<span style="margin-left: 4px; opacity:
|
|
7114
|
+
<span style="margin-left: 4px; opacity: ${this.getSortOpacity("consumption")};">${this.getSortIcon("consumption")}</span>
|
|
7100
7115
|
</th>
|
|
7101
7116
|
</tr>
|
|
7102
7117
|
</thead>
|
|
@@ -7118,6 +7133,9 @@
|
|
|
7118
7133
|
if (this.sortField !== field) return "\u2195";
|
|
7119
7134
|
return this.sortDirection === "asc" ? "\u2191" : "\u2193";
|
|
7120
7135
|
}
|
|
7136
|
+
getSortOpacity(field) {
|
|
7137
|
+
return this.sortField === field ? "1" : "0.5";
|
|
7138
|
+
}
|
|
7121
7139
|
setupTableSorting() {
|
|
7122
7140
|
const headers = document.querySelectorAll("[data-sort]");
|
|
7123
7141
|
headers.forEach((header) => {
|
|
@@ -7299,14 +7317,23 @@
|
|
|
7299
7317
|
}
|
|
7300
7318
|
const data = await response.json();
|
|
7301
7319
|
console.log("[AllReportModal] Customer totals response:", data);
|
|
7302
|
-
return
|
|
7320
|
+
return data;
|
|
7303
7321
|
}
|
|
7304
|
-
mapCustomerTotalsResponse(
|
|
7305
|
-
|
|
7306
|
-
|
|
7322
|
+
mapCustomerTotalsResponse(apiResponse) {
|
|
7323
|
+
let dataArray = [];
|
|
7324
|
+
if (apiResponse && apiResponse.data && Array.isArray(apiResponse.data)) {
|
|
7325
|
+
dataArray = apiResponse.data;
|
|
7326
|
+
} else if (Array.isArray(apiResponse)) {
|
|
7327
|
+
dataArray = apiResponse;
|
|
7328
|
+
} else {
|
|
7329
|
+
console.warn("[AllReportModal] Invalid API response structure:", apiResponse);
|
|
7330
|
+
return [];
|
|
7331
|
+
}
|
|
7332
|
+
if (dataArray.length === 0) {
|
|
7333
|
+
console.warn("[AllReportModal] Empty data array in API response");
|
|
7307
7334
|
return [];
|
|
7308
7335
|
}
|
|
7309
|
-
const mappedData =
|
|
7336
|
+
const mappedData = dataArray.map((item) => {
|
|
7310
7337
|
const identifier = item.identifier || item.deviceId || item.id || "N/A";
|
|
7311
7338
|
const name = item.deviceLabel || item.name || item.label || identifier;
|
|
7312
7339
|
const consumption = this.parseConsumptionValue(item);
|
|
@@ -7316,11 +7343,11 @@
|
|
|
7316
7343
|
consumption
|
|
7317
7344
|
};
|
|
7318
7345
|
}).filter((store) => {
|
|
7319
|
-
return !this.shouldExcludeStore(store.name);
|
|
7346
|
+
return !this.shouldExcludeStore(store.name, store.identifier);
|
|
7320
7347
|
}).filter((store) => {
|
|
7321
7348
|
return !isNaN(store.consumption) && store.consumption >= 0;
|
|
7322
7349
|
});
|
|
7323
|
-
console.log("[AllReportModal] Mapped customer totals:", mappedData.length, "stores");
|
|
7350
|
+
console.log("[AllReportModal] Mapped customer totals:", mappedData.length, "stores from", dataArray.length, "total devices");
|
|
7324
7351
|
return mappedData;
|
|
7325
7352
|
}
|
|
7326
7353
|
parseConsumptionValue(item) {
|
|
@@ -7344,14 +7371,24 @@
|
|
|
7344
7371
|
console.warn("[AllReportModal] No valid consumption value found in item:", item);
|
|
7345
7372
|
return 0;
|
|
7346
7373
|
}
|
|
7347
|
-
shouldExcludeStore(storeName) {
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7374
|
+
shouldExcludeStore(storeName, storeId) {
|
|
7375
|
+
const filters = this.params.filters;
|
|
7376
|
+
if (!filters) return false;
|
|
7377
|
+
if (filters.forceOnlyIds && Array.isArray(filters.forceOnlyIds) && filters.forceOnlyIds.length > 0) {
|
|
7378
|
+
return !filters.forceOnlyIds.includes(storeId);
|
|
7379
|
+
}
|
|
7380
|
+
if (filters.excludeIds && Array.isArray(filters.excludeIds) && filters.excludeIds.length > 0) {
|
|
7381
|
+
return filters.excludeIds.includes(storeId);
|
|
7382
|
+
}
|
|
7383
|
+
if (filters.excludeLabels && Array.isArray(filters.excludeLabels) && filters.excludeLabels.length > 0) {
|
|
7384
|
+
return filters.excludeLabels.some((filter) => {
|
|
7385
|
+
if (filter instanceof RegExp) {
|
|
7386
|
+
return filter.test(storeName);
|
|
7387
|
+
}
|
|
7388
|
+
return storeName.toLowerCase().includes(filter.toLowerCase());
|
|
7389
|
+
});
|
|
7390
|
+
}
|
|
7391
|
+
return false;
|
|
7355
7392
|
}
|
|
7356
7393
|
downloadCSV(content, filename) {
|
|
7357
7394
|
const BOM = "\uFEFF";
|
|
@@ -7979,16 +8016,16 @@
|
|
|
7979
8016
|
throw this.createHttpError(getRes.status, await getRes.text().catch(() => ""));
|
|
7980
8017
|
}
|
|
7981
8018
|
const device = await getRes.json();
|
|
7982
|
-
const
|
|
7983
|
-
method: "
|
|
8019
|
+
const postRes = await fetch(`${this.tbBaseUrl}/api/device`, {
|
|
8020
|
+
method: "POST",
|
|
7984
8021
|
headers: {
|
|
7985
8022
|
"X-Authorization": `Bearer ${this.jwtToken}`,
|
|
7986
8023
|
"Content-Type": "application/json"
|
|
7987
8024
|
},
|
|
7988
8025
|
body: JSON.stringify({ ...device, label: this.sanitizeLabel(label) })
|
|
7989
8026
|
});
|
|
7990
|
-
if (!
|
|
7991
|
-
throw this.createHttpError(
|
|
8027
|
+
if (!postRes.ok) {
|
|
8028
|
+
throw this.createHttpError(postRes.status, await postRes.text().catch(() => ""));
|
|
7992
8029
|
}
|
|
7993
8030
|
return { ok: true };
|
|
7994
8031
|
} catch (error) {
|