import { exportFile, QTableColumn, useQuasar } from 'quasar'; import { storeToRefs } from 'pinia'; import { unparse } from 'papaparse'; import { useI18n } from 'vue-i18n'; import { api } from 'src/services'; import { useDashboardStore } from 'src/stores/main'; /** * TABLE EXPORT (CSV / JSON). * * Server-mode tables — every table whose rows live in wp_vtables_source — * never ship their rows to the browser * (fetch_table blanks source.rows and sends only first_page), so exporting from * memory produced an empty file. Those go through the streaming export endpoint * instead. Only legacy tables, whose rows really are in source.rows, keep the * client-side path. * * Either way the export is the full table. */ export type ExportFormat = 'csv' | 'json' | 'xlsx'; export function useTableExport() { const { selectedTable } = storeToRefs(useDashboardStore()); const { t } = useI18n(); const $q = useQuasar(); function download(type: ExportFormat) { const table = selectedTable.value; if (!table) { return; } // xlsx is always built server-side — there is no client-side writer, and // the endpoint handles legacy tables too via its source-blob fallback. if (type === 'xlsx' || table.server_mode) { // A plain navigation, not XHR: the response is an attachment, so the // browser hands it straight to the download manager and never buffers // the whole dataset in JS. window.location.href = api.exportRowsUrl(table.id, type); return; } const { title, source: { columns, rows }, } = table; const name = `${title}.${type}`; let content = ''; if (type === 'csv') { // Build the matrix explicitly instead of patching a header line into // unparse(rows) output: that assumed the object key order matched the // column order, and injected the labels unquoted, so any label holding a // comma corrupted the header row. const cols: QTableColumn[] = Array.isArray(columns) ? columns : []; content = cols.length ? unparse({ fields: cols.map((col) => col.label ?? col.name), data: (rows ?? []).map((row: Record) => cols.map((col) => row[col.name] ?? '') ), }) : unparse(rows ?? []); } else { content = JSON.stringify(rows ?? []); } const status = exportFile(name, content); if (!status) { $q.notify({ type: 'negative', message: t('failed'), }); } } return { download }; }