refactor: download files from interface (#831)

This commit is contained in:
Carlos Valente
2024-03-18 20:27:58 +01:00
committed by GitHub
parent a91a8a6358
commit 4b21745fc7
5 changed files with 75 additions and 66 deletions
+59 -11
View File
@@ -10,27 +10,54 @@ import {
} from 'ontime-types'; } from 'ontime-types';
import { ImportMap } from 'ontime-utils'; import { ImportMap } from 'ontime-utils';
import { makeCSV, makeTable } from '../../features/cuesheet/cuesheetUtils';
import { apiEntryUrl } from './constants'; import { apiEntryUrl } from './constants';
import fileDownload from './utils'; import { createBlob, downloadBlob } from './utils';
const dbPath = `${apiEntryUrl}/db`; const dbPath = `${apiEntryUrl}/db`;
/** /**
* HTTP request to download db in JSON format * HTTP request to the current DB
*/ */
export async function downloadRundown(fileName?: string) { async function getDb(): Promise<AxiosResponse<DatabaseModel>> {
return fileDownload( return axios.get(`${dbPath}/download`);
dbPath,
{ name: fileName ?? 'rundown', type: 'json' },
{ type: 'application/json;charset=utf-8;' },
);
} }
/** /**
* HTTP request to download db in CSV format * Request download of the current project file
* @param fileName
*/ */
export async function downloadCSV(fileName?: string) { export async function downloadProject(fileName: string = 'ontime-project') {
return fileDownload(dbPath, { name: fileName ?? 'rundown', type: 'csv' }, { type: 'text/csv;charset=utf-8;' }); try {
const { data, name } = await fileDownload(fileName);
const fileContent = JSON.stringify(data, null, 2);
const blob = createBlob(fileContent, 'application/json;charset=utf-8;');
downloadBlob(blob, `${name}.json`);
} catch (error) {
console.error(error);
}
}
/**
* Request download of the current rundown as a CSV file
* @param fileName
*/
export async function downloadCSV(fileName: string = 'rundown') {
try {
const { data, name } = await fileDownload(fileName);
const { project, rundown, customFields } = data;
const sheetData = makeTable(project, rundown, customFields);
const fileContent = makeCSV(sheetData);
const blob = createBlob(fileContent, 'text/csv;charset=utf-8;');
downloadBlob(blob, `${name}.csv`);
} catch (error) {
console.error(error);
}
} }
/** /**
@@ -153,3 +180,24 @@ export async function importSpreadsheetPreview(file: File, options: ImportMap):
return response.data; return response.data;
} }
/**
* Utility function gets project from db
* @param fileName
* @returns
*/
async function fileDownload(fileName: string): Promise<{ data: DatabaseModel; name: string }> {
const response = await getDb();
const headerLine = response.headers['Content-Disposition'];
// try and get the filename from the response
let name = fileName;
if (headerLine != null) {
const startFileNameIndex = headerLine.indexOf('"') + 1;
const endFileNameIndex = headerLine.lastIndexOf('"');
name = headerLine.substring(startFileNameIndex, endFileNameIndex);
}
return { data: response.data, name };
}
+13 -48
View File
@@ -2,7 +2,6 @@ import axios, { AxiosError } from 'axios';
import { LogLevel } from 'ontime-types'; import { LogLevel } from 'ontime-types';
import { generateId, millisToString } from 'ontime-utils'; import { generateId, millisToString } from 'ontime-utils';
import { makeCSV, makeTable } from '../../features/cuesheet/cuesheetUtils';
import { ontimeQueryClient } from '../queryClient'; import { ontimeQueryClient } from '../queryClient';
import { addLog } from '../stores/logger'; import { addLog } from '../stores/logger';
import { nowInMillis } from '../utils/time'; import { nowInMillis } from '../utils/time';
@@ -56,63 +55,29 @@ export async function invalidateAllCaches() {
await ontimeQueryClient.invalidateQueries(); await ontimeQueryClient.invalidateQueries();
} }
type FileOptions = {
name: string;
type: string;
};
type BlobOptions = {
type: string;
};
/** /**
* Gets DB from backend and prepares a file to be downloaded * Creates blob from content
* @param url * @param fileContent
* @param fileOptions * @param type
* @param blobOptions
* @returns * @returns
*/ */
export default async function fileDownload(url: string, fileOptions: FileOptions, blobOptions: BlobOptions) { export function createBlob(fileContent: string, type: string): Blob {
const response = await axios({ return new Blob([fileContent], { type });
url: `${url}/db`, }
method: 'GET',
});
const headerLine = response.headers['Content-Disposition']; /**
let { name: fileName } = fileOptions; * downloads a blob
const { type: fileType } = fileOptions; * @param downloadUrl
const { project, rundown, customFields } = response.data; * @param fileName
*/
// try and get the filename from the response export function downloadBlob(blob: Blob, fileName: string) {
if (headerLine != null) {
const startFileNameIndex = headerLine.indexOf('"') + 1;
const endFileNameIndex = headerLine.lastIndexOf('"');
fileName = headerLine.substring(startFileNameIndex, endFileNameIndex);
}
let fileContent = '';
if (fileType === 'json') {
fileContent = JSON.stringify(response.data);
fileName += '.json';
}
if (fileType === 'csv') {
const sheetData = makeTable(project, rundown, customFields);
fileContent = makeCSV(sheetData);
fileName += '.csv';
}
const blob = new Blob([fileContent], { type: blobOptions.type });
const downloadUrl = URL.createObjectURL(blob); const downloadUrl = URL.createObjectURL(blob);
const link = document.createElement('a'); const link = document.createElement('a');
link.setAttribute('href', downloadUrl); link.setAttribute('href', downloadUrl);
link.setAttribute('download', fileName); link.setAttribute('download', fileName);
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
// Clean up the URL.createObjectURL to release resources // Clean up the URL.createObjectURL to release resources
URL.revokeObjectURL(downloadUrl); URL.revokeObjectURL(downloadUrl);
return;
} }
@@ -75,10 +75,6 @@ $inner-padding: 1rem;
box-shadow: 0 1px $white-10; box-shadow: 0 1px $white-10;
} }
tr {
padding: 1rem 0;
}
th { th {
font-weight: 400; font-weight: 400;
color: $gray-400; color: $gray-400;
@@ -5,7 +5,7 @@ import { IoEllipsisHorizontal } from '@react-icons/all-files/io5/IoEllipsisHoriz
import { import {
deleteProject, deleteProject,
downloadCSV, downloadCSV,
downloadRundown, downloadProject,
duplicateProject, duplicateProject,
loadProject, loadProject,
renameProject, renameProject,
@@ -148,7 +148,7 @@ function ActionMenu({
}; };
const handleDownload = async () => { const handleDownload = async () => {
await downloadRundown(filename); await downloadProject(filename);
}; };
const handleExportCSV = async () => { const handleExportCSV = async () => {
@@ -1,5 +1,5 @@
.current { .current {
background-color: $blue-900; background-color: $blue-1100;
} }
.actionButton { .actionButton {