mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-12 10:53:51 +00:00
refactor: download project file
This commit is contained in:
committed by
Carlos Valente
parent
6f80de58ca
commit
00f04fb78c
@@ -11,15 +11,15 @@ const dbPath = `${apiEntryUrl}/db`;
|
||||
/**
|
||||
* HTTP request to the current DB
|
||||
*/
|
||||
async function getDb(): Promise<AxiosResponse<DatabaseModel>> {
|
||||
return axios.get(`${dbPath}/download`);
|
||||
async function getDb(fileName?: string): Promise<AxiosResponse<DatabaseModel>> {
|
||||
return axios.post(`${dbPath}/download/`, { fileName });
|
||||
}
|
||||
|
||||
/**
|
||||
* Request download of the current project file
|
||||
* @param fileName
|
||||
*/
|
||||
export async function downloadProject(fileName: string = 'ontime-project') {
|
||||
export async function downloadProject(fileName: string) {
|
||||
try {
|
||||
const { data, name } = await fileDownload(fileName);
|
||||
|
||||
@@ -152,7 +152,7 @@ export async function getInfo(): Promise<GetInfo> {
|
||||
* @returns
|
||||
*/
|
||||
async function fileDownload(fileName: string): Promise<{ data: DatabaseModel; name: string }> {
|
||||
const response = await getDb();
|
||||
const response = await getDb(fileName);
|
||||
|
||||
const headerLine = response.headers['Content-Disposition'];
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ function ActionMenu({
|
||||
<MenuItem onClick={handleRename}>Rename</MenuItem>
|
||||
<MenuItem onClick={handleDuplicate}>Duplicate</MenuItem>
|
||||
<MenuItem onClick={handleDownload}>Download</MenuItem>
|
||||
{current && <MenuItem onClick={handleExportCSV}>Export CSV Rundown</MenuItem>}
|
||||
<MenuItem onClick={handleExportCSV}>Export CSV Rundown</MenuItem>
|
||||
<MenuItem isDisabled={current} onClick={handleDelete}>
|
||||
Delete
|
||||
</MenuItem>
|
||||
|
||||
@@ -10,9 +10,8 @@
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"express-static-gzip": "^2.1.7",
|
||||
"express-validator": "^6.14.2",
|
||||
"express-validator": "^7.0.1",
|
||||
"fast-equals": "^5.0.1",
|
||||
"google-auth-library": "^9.4.2",
|
||||
"got": "^14.0.0",
|
||||
|
||||
@@ -6,17 +6,19 @@ import {
|
||||
ProjectData,
|
||||
ProjectFileListResponse,
|
||||
} from 'ontime-types';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
|
||||
import { join } from 'path';
|
||||
import { existsSync } from 'fs';
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import { failEmptyObjects } from '../../utils/routerUtils.js';
|
||||
import { resolveDbPath, resolveProjectsDirectory } from '../../setup/index.js';
|
||||
import { resolveDbDirectory, resolveProjectsDirectory } from '../../setup/index.js';
|
||||
|
||||
import * as projectService from '../../services/project-service/ProjectService.js';
|
||||
import { ensureJsonExtension } from '../../utils/fileManagement.js';
|
||||
import { generateUniqueFileName } from '../../utils/generateUniqueFilename.js';
|
||||
import { appStateService } from '../../services/app-state-service/AppStateService.js';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
|
||||
export async function patchPartialProjectFile(req: Request, res: Response<DatabaseModel | ErrorResponse>) {
|
||||
// all fields are optional in validation
|
||||
@@ -76,9 +78,30 @@ export async function createProjectFile(req: Request, res: Response<{ filename:
|
||||
}
|
||||
}
|
||||
|
||||
export async function projectDownload(_req: Request, res: Response) {
|
||||
const fileTitle = projectService.getProjectTitle();
|
||||
res.download(resolveDbPath, `${fileTitle}.json`, (error) => {
|
||||
/**
|
||||
* Utility function finds the correct project file to download
|
||||
*/
|
||||
function selectProjectFile(fileName?: string) {
|
||||
const projectsDirectory = resolveDbDirectory;
|
||||
const fileToDownload = fileName ? ensureJsonExtension(fileName) : projectService.getProjectTitle();
|
||||
const pathToFile = join(projectsDirectory, fileToDownload);
|
||||
|
||||
return { pathToFile, name: fileToDownload };
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows downloading of a optionally given project files
|
||||
* If no {filename} is provided, loaded file will be served
|
||||
*/
|
||||
export async function projectDownload(req: Request, res: Response) {
|
||||
const { pathToFile, name } = selectProjectFile(req.body?.fileName);
|
||||
|
||||
// Check if the file exists before attempting to download
|
||||
if (!existsSync(pathToFile)) {
|
||||
return res.status(404).send({ message: `Project ${name} not found.` });
|
||||
}
|
||||
|
||||
res.download(pathToFile, name, (error) => {
|
||||
if (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
|
||||
@@ -16,6 +16,7 @@ import { uploadProjectFile } from './db.middleware.js';
|
||||
import {
|
||||
projectSanitiser,
|
||||
sanitizeProjectFilename,
|
||||
validateDownloadProject,
|
||||
validateLoadProjectFile,
|
||||
validatePatchProjectFile,
|
||||
validateProjectDuplicate,
|
||||
@@ -24,7 +25,7 @@ import {
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/download', projectDownload);
|
||||
router.post('/download', validateDownloadProject, projectDownload);
|
||||
router.post('/upload', uploadProjectFile, postProjectFile);
|
||||
|
||||
router.patch('/', validatePatchProjectFile, patchPartialProjectFile);
|
||||
|
||||
@@ -104,3 +104,19 @@ export const validateProjectRename = [
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @description Validates a download request which can include an optional project name.
|
||||
*/
|
||||
export const validateDownloadProject = [
|
||||
body('fileName').isString().optional(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
if (!errors.isEmpty()) {
|
||||
return res.status(422).json({ errors: errors.array() });
|
||||
}
|
||||
|
||||
next();
|
||||
},
|
||||
];
|
||||
|
||||
@@ -20,9 +20,7 @@ export function ensureDirectory(directory: string): void {
|
||||
* Ensures that a filename ends with .json extension
|
||||
*/
|
||||
export function ensureJsonExtension(filename: string): string {
|
||||
if (!filename) return filename;
|
||||
|
||||
return filename.includes('.json') ? filename : `${filename}.json`;
|
||||
return filename.endsWith('.json') ? filename : `${filename}.json`;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user