mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-10 01:43:43 +00:00
Upload corporate logo (#1314)
* feat: upload logo to project data --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me>
This commit is contained in:
@@ -1,9 +1,19 @@
|
||||
import { DatabaseModel, ErrorResponse, MessageResponse, ProjectFileListResponse } from 'ontime-types';
|
||||
import {
|
||||
DatabaseModel,
|
||||
ErrorResponse,
|
||||
MessageResponse,
|
||||
ProjectFileListResponse,
|
||||
ProjectLogoResponse,
|
||||
} from 'ontime-types';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
|
||||
import { doesProjectExist, handleUploaded } from '../../services/project-service/projectServiceUtils.js';
|
||||
import {
|
||||
doesProjectExist,
|
||||
handleImageUpload,
|
||||
handleUploaded,
|
||||
} from '../../services/project-service/projectServiceUtils.js';
|
||||
import * as projectService from '../../services/project-service/ProjectService.js';
|
||||
|
||||
export async function patchPartialProjectFile(req: Request, res: Response<DatabaseModel | ErrorResponse>) {
|
||||
@@ -39,6 +49,7 @@ export async function createProjectFile(req: Request, res: Response<{ filename:
|
||||
publicInfo: req.body?.publicInfo ?? '',
|
||||
backstageUrl: req.body?.backstageUrl ?? '',
|
||||
backstageInfo: req.body?.backstageInfo ?? '',
|
||||
projectLogo: req.body?.projectLogo ?? null,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -124,6 +135,30 @@ export async function postProjectFile(req: Request, res: Response<MessageRespons
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uploads an image file to be used as a project logo.
|
||||
* The image file is saved in the logo directory.
|
||||
*/
|
||||
export async function postProjectLogo(req: Request, res: Response<ProjectLogoResponse | ErrorResponse>) {
|
||||
if (!req.file) {
|
||||
res.status(400).send({ message: 'File not found' });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const { filename, path } = req.file;
|
||||
|
||||
const logoFilename = await handleImageUpload(path, filename);
|
||||
|
||||
res.status(201).send({
|
||||
logoFilename,
|
||||
});
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
res.status(500).send({ message });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and lists all project files from the uploads directory.
|
||||
*/
|
||||
|
||||
@@ -12,8 +12,22 @@ const filterProjectFile = (_req: Request, file: Express.Multer.File, cb: FileFil
|
||||
}
|
||||
};
|
||||
|
||||
const filterImageFile = (_req: Request, file: Express.Multer.File, cb: FileFilterCallback) => {
|
||||
if (file.mimetype.includes('image')) {
|
||||
cb(null, true);
|
||||
} else {
|
||||
cb(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Build multer uploader for a single file
|
||||
export const uploadProjectFile = multer({
|
||||
storage,
|
||||
fileFilter: filterProjectFile,
|
||||
}).single('project');
|
||||
|
||||
// Build multer uploader for a single image file
|
||||
export const uploadImageFile = multer({
|
||||
storage,
|
||||
fileFilter: filterImageFile,
|
||||
}).single('image');
|
||||
|
||||
@@ -13,6 +13,7 @@ export const validateNewProject = [
|
||||
body('publicInfo').optional().isString().trim(),
|
||||
body('backstageUrl').optional().isString().trim(),
|
||||
body('backstageInfo').optional().isString().trim(),
|
||||
body('projectLogo').optional().isString().trim(),
|
||||
body('endMessage').optional().isString().trim(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
|
||||
@@ -2,12 +2,14 @@ import { ErrorResponse, ProjectData } from 'ontime-types';
|
||||
import { getErrorMessage } from 'ontime-utils';
|
||||
|
||||
import type { Request, Response } from 'express';
|
||||
import { join } from 'path';
|
||||
|
||||
import { removeUndefined } from '../../utils/parserUtils.js';
|
||||
import { deleteFile, removeUndefined } from '../../utils/parserUtils.js';
|
||||
import { failEmptyObjects } from '../../utils/routerUtils.js';
|
||||
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||
import { publicDir } from '../../setup/index.js';
|
||||
|
||||
export async function getProjectData(_req: Request, res: Response<ProjectData>) {
|
||||
export function getProjectData(_req: Request, res: Response<ProjectData>) {
|
||||
res.json(getDataProvider().getProjectData());
|
||||
}
|
||||
|
||||
@@ -17,6 +19,8 @@ export async function postProjectData(req: Request, res: Response<ProjectData |
|
||||
}
|
||||
|
||||
try {
|
||||
const currentProjectData = getDataProvider().getProjectData();
|
||||
|
||||
const newEvent: Partial<ProjectData> = removeUndefined({
|
||||
title: req.body?.title,
|
||||
description: req.body?.description,
|
||||
@@ -25,8 +29,20 @@ export async function postProjectData(req: Request, res: Response<ProjectData |
|
||||
backstageUrl: req.body?.backstageUrl,
|
||||
backstageInfo: req.body?.backstageInfo,
|
||||
endMessage: req.body?.endMessage,
|
||||
projectLogo: req.body?.projectLogo,
|
||||
});
|
||||
|
||||
const newData = await getDataProvider().setProjectData(newEvent);
|
||||
|
||||
// Delete the old logo if the new logo is empty
|
||||
if (!newData.projectLogo && currentProjectData.projectLogo) {
|
||||
const filePath = join(publicDir.logoDir, currentProjectData.projectLogo);
|
||||
|
||||
deleteFile(filePath).catch((_error) => {
|
||||
/** we do not handle this error */
|
||||
});
|
||||
}
|
||||
|
||||
res.status(200).send(newData);
|
||||
} catch (error) {
|
||||
const message = getErrorMessage(error);
|
||||
|
||||
@@ -2,8 +2,11 @@ import express from 'express';
|
||||
|
||||
import { getProjectData, postProjectData } from './project.controller.js';
|
||||
import { projectSanitiser } from './project.validation.js';
|
||||
import { uploadImageFile } from '../db/db.middleware.js';
|
||||
import { postProjectLogo } from '../db/db.controller.js';
|
||||
|
||||
export const router = express.Router();
|
||||
|
||||
router.get('/', getProjectData);
|
||||
router.post('/', projectSanitiser, postProjectData);
|
||||
router.post('/upload', uploadImageFile, postProjectLogo);
|
||||
|
||||
@@ -9,6 +9,7 @@ export const projectSanitiser = [
|
||||
body('backstageUrl').optional().isString().trim(),
|
||||
body('backstageInfo').optional().isString().trim(),
|
||||
body('endMessage').optional().isString().trim(),
|
||||
body('projectLogo').optional({ nullable: true }).isString().trim(),
|
||||
|
||||
(req: Request, res: Response, next: NextFunction) => {
|
||||
const errors = validationResult(req);
|
||||
|
||||
Reference in New Issue
Block a user