101 lines
2.9 KiB
JavaScript
101 lines
2.9 KiB
JavaScript
/*
|
|
* CSV and attachment export module (F2). Generates a CSV file from the current
|
|
* report's answers and allows downloading individual attachments. XLSX and ZIP
|
|
* export can be added by integrating SheetJS and JSZip libraries.
|
|
*/
|
|
|
|
import { state, getCurrentReport, getTemplateRecord } from './state.js';
|
|
import { dbGetAllByIndex } from './db.js';
|
|
import { STORE_ATTACHMENTS } from './constants.js';
|
|
|
|
/*
|
|
* Exports the active report as a CSV file. Columns are derived from the template
|
|
* definition so field labels appear as headers and field values as the row.
|
|
*/
|
|
export async function exportReportCSV() {
|
|
const report = getCurrentReport();
|
|
|
|
if (!report) {
|
|
throw new Error('No report to export');
|
|
}
|
|
|
|
const template = getTemplateRecord(report.templateCode, report.templateVersion);
|
|
|
|
if (!template) {
|
|
throw new Error('Template definition needed for export');
|
|
}
|
|
|
|
const headers = [];
|
|
const values = [];
|
|
|
|
/* Meta columns. */
|
|
headers.push('Report Number', 'Template', 'Version', 'Status', 'Created', 'Updated');
|
|
values.push(
|
|
report.reportNumber,
|
|
report.templateCode,
|
|
String(report.templateVersion),
|
|
report.status,
|
|
report.createdAt,
|
|
report.updatedAt
|
|
);
|
|
|
|
/* Dynamic field columns derived from the template definition. */
|
|
for (const section of template.definition.sections || []) {
|
|
for (const field of section.fields || []) {
|
|
if (field.type === 'attachment') {
|
|
continue;
|
|
}
|
|
|
|
headers.push(field.label);
|
|
const raw = report.answers[field.id];
|
|
values.push(raw === undefined || raw === null ? '' : String(raw));
|
|
}
|
|
}
|
|
|
|
const csvContent = [
|
|
headers.map(csvEscape).join(','),
|
|
values.map(csvEscape).join(',')
|
|
].join('\r\n');
|
|
|
|
downloadBlob(
|
|
new Blob([csvContent], { type: 'text/csv;charset=utf-8' }),
|
|
`${report.reportNumber || 'report'}.csv`
|
|
);
|
|
}
|
|
|
|
/*
|
|
* Exports all attachments for the active report as individual file downloads.
|
|
* A future iteration could bundle these into a ZIP archive using JSZip.
|
|
*/
|
|
export async function exportReportAttachments() {
|
|
const report = getCurrentReport();
|
|
|
|
if (!report) {
|
|
throw new Error('No report to export');
|
|
}
|
|
|
|
const attachments = await dbGetAllByIndex(STORE_ATTACHMENTS, 'byReportId', report.id);
|
|
|
|
for (const attachment of attachments) {
|
|
downloadBlob(attachment.blob, attachment.generatedFilename);
|
|
}
|
|
}
|
|
|
|
/* ── Helpers ────────────────────────────────────────────────────────────── */
|
|
|
|
function csvEscape(value) {
|
|
const str = String(value).replace(/"/g, '""');
|
|
return /[",\r\n]/.test(str) ? `"${str}"` : str;
|
|
}
|
|
|
|
function downloadBlob(blob, filename) {
|
|
const url = URL.createObjectURL(blob);
|
|
const anchor = document.createElement('a');
|
|
anchor.href = url;
|
|
anchor.download = filename;
|
|
document.body.appendChild(anchor);
|
|
anchor.click();
|
|
anchor.remove();
|
|
URL.revokeObjectURL(url);
|
|
}
|