mirror of
https://github.com/directus/directus.git
synced 2026-01-27 12:58:03 -05:00
Add new export experience (#12201)
* Use script setup * Start on export dialog * Use new system field interface, replace limit with numeric input * Set placeholder * Add sort config * Use folder picker, correct layoutQuery use * Add local download button * Allow writing exports to file * Add notification after export * Fix sort config, use new export endpoint * Setup notification hints * Add information notice * Fix local limit, cancel button * Add (basic) docs for export functionality * Fix json export file format * Implement xml batch stitching * Resolve review points
This commit is contained in:
@@ -1,14 +1,13 @@
|
||||
import { RequestHandler } from 'express';
|
||||
import { Transform, transforms } from 'json2csv';
|
||||
import ms from 'ms';
|
||||
import { PassThrough } from 'stream';
|
||||
import { getCache } from '../cache';
|
||||
import env from '../env';
|
||||
import asyncHandler from '../utils/async-handler';
|
||||
import { getCacheKey } from '../utils/get-cache-key';
|
||||
import { parse as toXML } from 'js2xmlparser';
|
||||
import { getCacheControlHeader } from '../utils/get-cache-headers';
|
||||
import logger from '../logger';
|
||||
import { ExportService } from '../services';
|
||||
import { getDateFormatted } from '../utils/get-date-formatted';
|
||||
|
||||
export const respond: RequestHandler = asyncHandler(async (req, res) => {
|
||||
const { cache } = getCache();
|
||||
@@ -38,6 +37,8 @@ export const respond: RequestHandler = asyncHandler(async (req, res) => {
|
||||
}
|
||||
|
||||
if (req.sanitizedQuery.export) {
|
||||
const exportService = new ExportService({ accountability: req.accountability, schema: req.schema });
|
||||
|
||||
let filename = '';
|
||||
|
||||
if (req.collection) {
|
||||
@@ -51,30 +52,19 @@ export const respond: RequestHandler = asyncHandler(async (req, res) => {
|
||||
if (req.sanitizedQuery.export === 'json') {
|
||||
res.attachment(`${filename}.json`);
|
||||
res.set('Content-Type', 'application/json');
|
||||
return res.status(200).send(JSON.stringify(res.locals.payload?.data || null, null, '\t'));
|
||||
return res.status(200).send(exportService.transform(res.locals.payload?.data, 'json'));
|
||||
}
|
||||
|
||||
if (req.sanitizedQuery.export === 'xml') {
|
||||
res.attachment(`${filename}.xml`);
|
||||
res.set('Content-Type', 'text/xml');
|
||||
return res.status(200).send(toXML('data', res.locals.payload?.data));
|
||||
return res.status(200).send(exportService.transform(res.locals.payload?.data, 'xml'));
|
||||
}
|
||||
|
||||
if (req.sanitizedQuery.export === 'csv') {
|
||||
res.attachment(`${filename}.csv`);
|
||||
res.set('Content-Type', 'text/csv');
|
||||
const stream = new PassThrough();
|
||||
|
||||
if (!res.locals.payload?.data || res.locals.payload.data.length === 0) {
|
||||
stream.end(Buffer.from(''));
|
||||
return stream.pipe(res);
|
||||
} else {
|
||||
stream.end(Buffer.from(JSON.stringify(res.locals.payload.data), 'utf-8'));
|
||||
const json2csv = new Transform({
|
||||
transforms: [transforms.flatten({ separator: '.' })],
|
||||
});
|
||||
return stream.pipe(json2csv).pipe(res);
|
||||
}
|
||||
return res.status(200).send(exportService.transform(res.locals.payload?.data, 'csv'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,15 +76,3 @@ export const respond: RequestHandler = asyncHandler(async (req, res) => {
|
||||
return res.status(204).end();
|
||||
}
|
||||
});
|
||||
|
||||
function getDateFormatted() {
|
||||
const date = new Date();
|
||||
|
||||
let month = String(date.getMonth() + 1);
|
||||
if (month.length === 1) month = '0' + month;
|
||||
|
||||
let day = String(date.getDate());
|
||||
if (day.length === 1) day = '0' + day;
|
||||
|
||||
return `${date.getFullYear()}-${month}-${day} at ${date.getHours()}.${date.getMinutes()}.${date.getSeconds()}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user