mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-22 07:29:08 +00:00
refactor: download files from interface (#831)
This commit is contained in:
@@ -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 };
|
||||||
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user