Skip to content

Commit

Permalink
Merge pull request #28 from bcgov/ofmcc-251-view-notifications
Browse files Browse the repository at this point in the history
Update for OFMCC-251 - View Notifications
  • Loading branch information
jgstorey authored Nov 2, 2023
2 parents 8d748a2 + f17391e commit d54f22b
Show file tree
Hide file tree
Showing 19 changed files with 1,180 additions and 365 deletions.
5 changes: 4 additions & 1 deletion backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ const apiRouter = express.Router()
const authRouter = require('./routes/auth')
const userRouter = require('./routes/user')
const configRouter = require('./routes/config')

const messageRouter = require('./routes/message')
const notificationRouter = require('./routes/notification')
const organizationRouter = require('./routes/organization')

const connectRedis = require('connect-redis')
Expand Down Expand Up @@ -186,6 +187,8 @@ app.use(/(\/api)?/, apiRouter)
apiRouter.use('/auth', authRouter)
apiRouter.use('/user', userRouter)
apiRouter.use('/config', configRouter)
apiRouter.use('/messages', messageRouter)
apiRouter.use('/notifications', notificationRouter)

//TODO: Router from MyCCS only here for 1st backend iteration example. To be removed ...
apiRouter.use('/organization', organizationRouter)
Expand Down
83 changes: 42 additions & 41 deletions backend/src/components/message.js
Original file line number Diff line number Diff line change
@@ -1,61 +1,62 @@
'use strict';
const { getOperation, patchOperationWithObjectId } = require('./utils');
const { MappableObjectForFront } = require('../util/mapping/MappableObject');
const { MessageMappings } = require('../util/mapping/Mappings');
const HttpStatus = require('http-status-codes');
const moment = require('moment');
const log = require('./logger');
'use strict'
const { getOperation, patchOperationWithObjectId } = require('./utils')
const { MappableObjectForFront } = require('../util/mapping/MappableObject')
const { MessageMappings } = require('../util/mapping/Mappings')
const HttpStatus = require('http-status-codes')
const moment = require('moment')
const log = require('./logger')
const { join } = require('path')

function mapMessageObjectForFront(data) {
if (data.createdon) {
data.createdon = new moment(data.createdon).format('YYYY/MM/DD');
data.createdon = new moment(data.createdon).format('YYYY/MM/DD')
}
return new MappableObjectForFront(data, MessageMappings).toJSON();
return new MappableObjectForFront(data, MessageMappings).toJSON()
}

function sortByPropertyDesc(property){
return function(a,b){
if(a[property] < b[property])
return 1;
else if(a[property] > b[property])
return -1;
return 0;
};
function sortByPropertyDesc(property) {
return function (a, b) {
if (a[property] < b[property]) return 1
else if (a[property] > b[property]) return -1
return 0
}
}

async function getAllMessages(req, res) {
async function getMessages(req, res) {
try {
let operation = 'emails?$select=activityid,createdon,description,lastopenedtime ,_regardingobjectid_value,subject&$expand=regardingobjectid_account_email($select=accountid,accountnumber,name)&$filter=(regardingobjectid_account_email/accountid eq ' + req.params.organizationId + ' and statecode eq 1)';
log.info('operation: ', operation);
let operationResponse = await getOperation(operation);
operationResponse.value.sort(sortByPropertyDesc('createdon'));
let allMessages = [];
operationResponse.value.forEach(item => {
let message = mapMessageObjectForFront(item);
if (message.lastOpenedTime)
message['isRead'] = true;
else
message['isRead'] = false;
allMessages.push(message);
});
return res.status(HttpStatus.OK).json(allMessages);
let operation =
'emails?$select=description,lastopenedtime,subject,createdon&$expand=email_activity_parties($filter=(_partyid_value eq ' +
req.params.contactId +
'))&$filter=(email_activity_parties/any(o1:(o1/_partyid_value eq ' +
req.params.contactId +
')))'
log.info('operation: ', operation)
let operationResponse = await getOperation(operation)
operationResponse.value.sort(sortByPropertyDesc('createdon'))
let messages = []
for (const item of operationResponse.value) {
let message = mapMessageObjectForFront(item)
if (message.lastOpenedTime) message['isRead'] = true
else message['isRead'] = false
messages.push(message)
}
return res.status(HttpStatus.OK).json(messages)
} catch (e) {
log.error('failed with error', e);
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(e.data? e.data : e?.status );
log.error('failed with error', e)
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(e.data ? e.data : e?.status)
}
}

async function updateMessageLastOpenedTime(req, res) {
try {
let response = await patchOperationWithObjectId('emails', req.params.messageId, req.body);
return res.status(HttpStatus.OK).json(response);
let response = await patchOperationWithObjectId('emails', req.params.messageId, req.body)
return res.status(HttpStatus.OK).json(response)
} catch (e) {
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(e.data? e.data : e?.status );
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(e.data ? e.data : e?.status)
}
}

module.exports = {
getAllMessages,
updateMessageLastOpenedTime
};

getMessages,
updateMessageLastOpenedTime,
}
62 changes: 62 additions & 0 deletions backend/src/components/notification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
'use strict'
const { getOperation, patchOperationWithObjectId } = require('./utils')
const { MappableObjectForFront } = require('../util/mapping/MappableObject')
const { NotificationMappings } = require('../util/mapping/Mappings')
const HttpStatus = require('http-status-codes')
const moment = require('moment')
const log = require('./logger')
const { join } = require('path')

function mapNotificationObjectForFront(data) {
if (data.createdon) {
data.createdon = new moment(data.createdon).format('YYYY/MM/DD')
}
return new MappableObjectForFront(data, NotificationMappings).toJSON()
}

function sortByPropertyDesc(property) {
return function (a, b) {
if (a[property] < b[property]) return 1
else if (a[property] > b[property]) return -1
return 0
}
}

async function getNotifications(req, res) {
try {
let operation =
'emails?$select=description,lastopenedtime,subject,createdon&$expand=email_activity_parties($filter=(_partyid_value eq ' +
req.params.contactId +
'))&$filter=(email_activity_parties/any(o1:(o1/_partyid_value eq ' +
req.params.contactId +
')))'
log.info('operation: ', operation)
let operationResponse = await getOperation(operation)
operationResponse.value.sort(sortByPropertyDesc('createdon'))
let notifications = []
for (const item of operationResponse.value) {
let notification = mapNotificationObjectForFront(item)
if (notification.lastOpenedTime) notification['isRead'] = true
else notification['isRead'] = false
notifications.push(notification)
}
return res.status(HttpStatus.OK).json(notifications)
} catch (e) {
log.error('failed with error', e)
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(e.data ? e.data : e?.status)
}
}

async function updateNotificationLastOpenedTime(req, res) {
try {
let response = await patchOperationWithObjectId('emails', req.params.notificationId, req.body)
return res.status(HttpStatus.OK).json(response)
} catch (e) {
return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json(e.data ? e.data : e?.status)
}
}

module.exports = {
getNotifications,
updateNotificationLastOpenedTime,
}
38 changes: 18 additions & 20 deletions backend/src/routes/message.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
const express = require('express');
const passport = require('passport');
const router = express.Router();
const auth = require('../components/auth');
const isValidBackendToken= auth.isValidBackendToken();
const { getAllMessages, updateMessageLastOpenedTime } = require('../components/message');
const { param, validationResult } = require('express-validator');
const express = require('express')
const passport = require('passport')
const router = express.Router()
const auth = require('../components/auth')
const isValidBackendToken = auth.isValidBackendToken()
const { getMessages, updateMessageLastOpenedTime } = require('../components/message')
const { param, validationResult } = require('express-validator')

module.exports = router;
module.exports = router

/**
* Get ALL messages of an organization
* Get messages filtered by contactid
*/
router.get('/organization/:organizationId', passport.authenticate('jwt', {session: false}),isValidBackendToken,
[param('organizationId', 'URL param: [organizationId] is required').not().isEmpty()], (req, res) => {
validationResult(req).throw();
return getAllMessages(req, res);
});
router.get('/contact/:contactId', passport.authenticate('jwt', { session: false }), isValidBackendToken, [param('contactId', 'URL param: [contactId] is required').not().isEmpty()], (req, res) => {
validationResult(req).throw()
return getMessages(req, res)
})

/**
* Update Last Opened Time of an existing Message
*/
router.put('/:messageId', passport.authenticate('jwt', {session: false}),isValidBackendToken, [
param('messageId', 'URL param: [messageId] is required').not().isEmpty()], (req, res) => {
validationResult(req).throw();
return updateMessageLastOpenedTime(req, res);
});
router.put('/:messageId', passport.authenticate('jwt', { session: false }), isValidBackendToken, [param('messageId', 'URL param: [messageId] is required').not().isEmpty()], (req, res) => {
validationResult(req).throw()
return updateMessageLastOpenedTime(req, res)
})

module.exports = router;
module.exports = router
27 changes: 27 additions & 0 deletions backend/src/routes/notification.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const express = require('express')
const passport = require('passport')
const router = express.Router()
const auth = require('../components/auth')
const isValidBackendToken = auth.isValidBackendToken()
const { getNotifications, updateNotificationLastOpenedTime } = require('../components/notification')
const { param, validationResult } = require('express-validator')

module.exports = router

/**
* Get notifications filtered by contactid
*/
router.get('/contact/:contactId', passport.authenticate('jwt', { session: false }), isValidBackendToken, [param('contactId', 'URL param: [contactId] is required').not().isEmpty()], (req, res) => {
validationResult(req).throw()
return getNotifications(req, res)
})

/**
* Update Last Opened Time of an existing Notification
*/
router.put('/:notificationId', passport.authenticate('jwt', { session: false }), isValidBackendToken, [param('notificationId', 'URL param: [notificationId] is required').not().isEmpty()], (req, res) => {
validationResult(req).throw()
return updateNotificationLastOpenedTime(req, res)
})

module.exports = router
9 changes: 9 additions & 0 deletions backend/src/util/mapping/Mappings.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,16 @@ const UserProfileFacilityMappings = [
{ back: 'statuscode', front: 'facilityStatusCode' },
]

const NotificationMappings = [
{ back: 'activityid', front: 'notificationId' },
{ back: 'subject', front: 'subject' },
{ back: 'createdon', front: 'dateReceived' },
{ back: 'description', front: 'notificationContent' },
{ back: 'lastopenedtime', front: 'lastOpenedTime' },
]

module.exports = {
NotificationMappings,
UserProfileMappings,
UserProfileOrganizationMappings,
UserProfileFacilityPermissionMappings,
Expand Down
Loading

0 comments on commit d54f22b

Please sign in to comment.