From 60ccb1a54b2720134e0dd0a719688cf5110ad5a7 Mon Sep 17 00:00:00 2001 From: weskubo-cgi <80127167+weskubo-cgi@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:58:52 -0800 Subject: [PATCH] OFMCC-5947 - Message screenshots (#424) * OFMCC-5947 initial commit. * Removed unused import. * Refined code. Removed images that can't be replaced. Removed hyperlinks to CRM attachments. * Minor update. --------- Co-authored-by: weskubo-cgi --- backend/src/app.js | 2 ++ backend/src/components/files.js | 22 ++++++++++++ backend/src/routes/files.js | 28 +++++++++++++++ .../messages/RequestConversations.vue | 36 ++++++++++++++++--- frontend/src/services/fileService.js | 15 ++++++++ frontend/src/utils/constants.js | 1 + frontend/src/utils/file.js | 20 ++++++++++- 7 files changed, 119 insertions(+), 5 deletions(-) create mode 100644 backend/src/components/files.js create mode 100644 backend/src/routes/files.js create mode 100644 frontend/src/services/fileService.js diff --git a/backend/src/app.js b/backend/src/app.js index 106aa6fb..74c1d300 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -28,6 +28,7 @@ const authRouter = require('./routes/auth') const userRouter = require('./routes/user') const configRouter = require('./routes/config') const documentsRouter = require('./routes/documents') +const filesRouter = require('./routes/files') const healthCheckRouter = require('./routes/healthCheck') const messageRouter = require('./routes/message') const notificationRouter = require('./routes/notification') @@ -263,6 +264,7 @@ apiRouter.use('/auth', authRouter) apiRouter.use('/config', configRouter) apiRouter.use('/documents', documentsRouter) apiRouter.use('/facilities', facilitiesRouter) +apiRouter.use('/files', filesRouter) apiRouter.use('/funding-agreements', fundingAgreementsRouter) apiRouter.use('/health', healthCheckRouter) apiRouter.use('/irregular', irregularApplicationsRouter) diff --git a/backend/src/components/files.js b/backend/src/components/files.js new file mode 100644 index 00000000..fdba983b --- /dev/null +++ b/backend/src/components/files.js @@ -0,0 +1,22 @@ +'use strict' +const { getOperation, handleError } = require('./utils') +const HttpStatus = require('http-status-codes') + +async function getFile(req, res) { + try { + let operation = `msdyn_richtextfiles(${req.params.fileId})/` + if (req.query.image) { + operation += 'msdyn_imageblob/$value?size=full' + } else { + operation += 'msdyn_fileblob' + } + const response = await getOperation(operation) + return res.status(HttpStatus.OK).json(response?.value) + } catch (e) { + handleError(res, e) + } +} + +module.exports = { + getFile, +} diff --git a/backend/src/routes/files.js b/backend/src/routes/files.js new file mode 100644 index 00000000..28c9dc13 --- /dev/null +++ b/backend/src/routes/files.js @@ -0,0 +1,28 @@ +const express = require('express') +const passport = require('passport') +const router = express.Router() +const auth = require('../components/auth') +const isValidBackendToken = auth.isValidBackendToken() +const { getFile } = require('../components/files') +const { param, query, validationResult } = require('express-validator') +const validatePermission = require('../middlewares/validatePermission.js') +const { PERMISSIONS } = require('../util/constants') + +module.exports = router + +/** + * Get the file by id + */ +router.get( + '/:fileId', + passport.authenticate('jwt', { session: false }), + isValidBackendToken, + [param('fileId', 'URL param: [fileId] is required').notEmpty().isUUID()], + query('image').optional().isBoolean(), + validatePermission(PERMISSIONS.MANAGE_NOTIFICATIONS), + (req, res) => { + validationResult(req).throw() + return getFile(req, res) + }, +) +module.exports = router diff --git a/frontend/src/components/messages/RequestConversations.vue b/frontend/src/components/messages/RequestConversations.vue index 4b70af20..8067152b 100644 --- a/frontend/src/components/messages/RequestConversations.vue +++ b/frontend/src/components/messages/RequestConversations.vue @@ -87,14 +87,18 @@ diff --git a/frontend/src/services/fileService.js b/frontend/src/services/fileService.js new file mode 100644 index 00000000..ed5f83fe --- /dev/null +++ b/frontend/src/services/fileService.js @@ -0,0 +1,15 @@ +import ApiService from '@/common/apiService' +import { ApiRoutes } from '@/utils/constants' + +export default { + async getFile(fileId, image = false) { + try { + if (!fileId) return null + const response = await ApiService.apiAxios.get(`${ApiRoutes.FILES}/${fileId}?image=${image}`) + return response.data + } catch (error) { + console.log(`Failed to get file - ${error}`) + throw error + } + }, +} diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js index 0a749829..b4c0de95 100644 --- a/frontend/src/utils/constants.js +++ b/frontend/src/utils/constants.js @@ -16,6 +16,7 @@ export const ApiRoutes = Object.freeze({ FACILITIES: baseRoot + '/facilities', FACILITIES_CONTACTS: baseRoot + '/facilities/:facilityId/contacts', FACILITIES_LICENCES: baseRoot + '/facilities/:facilityId/licences', + FILES: baseRoot + '/files', FUNDING_AGREEMENTS: baseRoot + '/funding-agreements', LICENCES: baseRoot + '/licences', LOOKUP: baseRoot + '/config/lookup', diff --git a/frontend/src/utils/file.js b/frontend/src/utils/file.js index ddb5f2ad..0eb0060e 100644 --- a/frontend/src/utils/file.js +++ b/frontend/src/utils/file.js @@ -3,7 +3,6 @@ * @param {*} bytes * @param {*} decimals */ - export function humanFileSize(bytes, decimals = 2) { if (bytes === 0) return '0 Bytes' const k = 1024 @@ -40,3 +39,22 @@ export function updateHeicFileNameToJpg(filename) { const regex = /\.heic(?![\s\S]*\.heic)/i //looks for last occurrence of .heic case-insensitive return filename?.replace(regex, '.jpg') } + +/** + * Quick and dirty way to determine image type based on base64 encoding. + * @param image The base64 encoded image + */ +export function deriveImageType(image) { + switch (image.charAt(0)) { + case '/': + return 'jpg' + case 'i': + return 'png' + case 'R': + return 'gif' + case 'U': + return 'webp' + default: + return '*' + } +}