Improve csv format and align with report

This commit is contained in:
Simon Stürz 2025-12-11 14:43:01 +01:00
parent bcb7b41976
commit cd1c30223f

View File

@ -1042,37 +1042,96 @@ class DashboardApp {
if (!Array.isArray(sessions) || !sessions.length) if (!Array.isArray(sessions) || !sessions.length)
return ''; return '';
const headers = this.collectSessionColumns(sessions); const columns = [
if (!headers.length) { label: 'Session ID', key: 'sessionId' },
return ''; { label: 'Charger name', key: 'chargerName' },
{ label: 'Charger serial number', key: 'chargerSerialNumber' },
{ label: 'Car', key: 'carName' },
{ label: 'Start', key: 'startTimestamp', formatter: value => this.formatCsvTimestamp(value) },
{ label: 'End', key: 'endTimestamp', formatter: value => this.formatCsvTimestamp(value) },
{ label: 'Energy [kWh]', key: 'sessionEnergy' },
{ label: 'Meter start [kWh]', key: 'energyStart' },
{ label: 'Meter end [kWh]', key: 'energyEnd' }
];
const lines = []; const lines = [];
lines.push(headers.join(';')); lines.push(columns.map(column => column.label).join(';'));
sessions.forEach(session => { sessions.forEach(session => {
const row = headers.map(header => this.escapeCsvValue(session ? session[header] : '')); const row = columns.map(column => {
const raw = session ? session[column.key] : '';
const formatted = typeof column.formatter === 'function'
? column.formatter(raw)
: this.formatCsvPrimitive(raw);
return this.escapeCsvValue(formatted);
});
lines.push(row.join(';')); lines.push(row.join(';'));
}); });
return lines.join('\n'); return lines.join('\n');
} }
collectSessionColumns(sessions) { formatCsvPrimitive(value) {
const headers = []; if (value === null || value === undefined)
sessions.forEach(session => { return '';
if (!session)
return; if (typeof value === 'number')
Object.keys(session).forEach(key => { return Number.isFinite(value) ? String(value) : '';
if (!headers.includes(key))
headers.push(key); if (typeof value === 'string') {
}); const trimmed = value.trim();
}); return trimmed.length ? trimmed : '';
return headers; }
if (Array.isArray(value)) {
if (!value.length)
return '';
try {
return JSON.stringify(value);
} catch (error) {
return '';
}
}
if (typeof value === 'object') {
if (!Object.keys(value).length)
return '';
try {
return JSON.stringify(value);
} catch (error) {
return '';
}
}
return String(value);
}
formatCsvTimestamp(value) {
const numeric = typeof value === 'string' ? Number.parseFloat(value) : value;
if (!Number.isFinite(numeric))
return '';
const ms = numeric > 1e12 ? numeric : numeric * 1000;
const date = new Date(ms);
if (Number.isNaN(date.getTime()))
return '';
const pad = part => String(part).padStart(2, '0');
const day = pad(date.getDate());
const month = pad(date.getMonth() + 1);
const year = date.getFullYear();
const hours = pad(date.getHours());
const minutes = pad(date.getMinutes());
return `${day}.${month}.${year} ${hours}:${minutes}`;
} }
escapeCsvValue(value) { escapeCsvValue(value) {
if (value === null || value === undefined) if (value === null || value === undefined)
return ''; return '';
if (typeof value === 'number' && !Number.isFinite(value))
return '';
if (typeof value === 'object') { if (typeof value === 'object') {
try { try {
value = JSON.stringify(value); value = JSON.stringify(value);