You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
7.5 KiB
257 lines
7.5 KiB
// task.js
|
|
// Copyright (C) 2024 DTP Technologies, LLC
|
|
// All Rights Reserved
|
|
|
|
'use strict';
|
|
|
|
import express from 'express';
|
|
|
|
import { SiteController, SiteError } from '../../lib/site-lib.js';
|
|
import { populateTaskId, populateSessionId } from './lib/populators.js';
|
|
|
|
export default class TaskController extends SiteController {
|
|
|
|
static get name ( ) { return 'TaskController'; }
|
|
static get slug ( ) { return 'task'; }
|
|
|
|
constructor (dtp) {
|
|
super(dtp, TaskController);
|
|
}
|
|
|
|
async start ( ) {
|
|
const { dtp } = this;
|
|
|
|
const {
|
|
limiter: limiterService,
|
|
session: sessionService,
|
|
} = dtp.services;
|
|
const limiterConfig = limiterService.config.task;
|
|
|
|
const multer = this.createMulter(TaskController.slug, {
|
|
limits: {
|
|
fileSize: 1024 * 1000 * 5,
|
|
},
|
|
});
|
|
|
|
const authCheck = sessionService.authCheckMiddleware({ requireLogin: true });
|
|
|
|
const router = express.Router();
|
|
dtp.app.use('/task', authCheck, router);
|
|
|
|
router.use(async (req, res, next) => {
|
|
res.locals.currentView = TaskController.name;
|
|
return next();
|
|
});
|
|
|
|
async function checkTaskOwnership (req, res, next) {
|
|
if (Array.isArray(res.locals.task.project.managers) && (res.locals.task.project.managers.length > 0)) {
|
|
res.locals.manager = res.locals.task.project.managers.find((manager) => manager._id.equals(req.user._id));
|
|
}
|
|
if (!res.locals.manager && !res.locals.task.user._id.equals(req.user._id)) {
|
|
return next(new SiteError(401, 'This is not your task'));
|
|
}
|
|
return next();
|
|
}
|
|
|
|
async function checkSessionOwnership (req, res, next) {
|
|
if (Array.isArray(res.locals.task.project.managers) && (res.locals.task.project.managers.length > 0)) {
|
|
res.locals.manager = res.locals.task.project.managers.find((manager) => manager._id.equals(req.user._id));
|
|
}
|
|
if (!res.locals.manager && !res.locals.session.user._id.equals(req.user._id)) {
|
|
throw new SiteError(401, 'This is not your session');
|
|
}
|
|
return next();
|
|
}
|
|
|
|
router.param('taskId', populateTaskId(this));
|
|
router.param('sessionId', populateSessionId(this));
|
|
|
|
router.post(
|
|
'/:taskId/session/start',
|
|
limiterService.create(limiterConfig.postStartTaskSession),
|
|
this.postStartTaskSession.bind(this),
|
|
);
|
|
|
|
router.post(
|
|
'/:taskId/session/:sessionId/screenshot',
|
|
checkSessionOwnership,
|
|
limiterService.create(limiterConfig.postTaskSessionScreenshot),
|
|
multer.single('image'),
|
|
this.postTaskSessionScreenshot.bind(this),
|
|
);
|
|
|
|
router.post(
|
|
'/:taskId/session/:sessionId/status',
|
|
limiterService.create(limiterConfig.postTaskSessionStatus),
|
|
checkSessionOwnership,
|
|
this.postTaskSessionStatus.bind(this),
|
|
);
|
|
|
|
router.post(
|
|
'/:taskId/session/:sessionId/close',
|
|
limiterService.create(limiterConfig.postCloseTaskSession),
|
|
checkSessionOwnership,
|
|
this.postCloseTaskSession.bind(this),
|
|
);
|
|
|
|
router.post(
|
|
'/:taskId/start',
|
|
limiterService.create(limiterConfig.postStartTask),
|
|
checkTaskOwnership,
|
|
this.postStartTask.bind(this),
|
|
);
|
|
router.post(
|
|
'/:taskId/close',
|
|
limiterService.create(limiterConfig.postCloseTask),
|
|
checkTaskOwnership,
|
|
this.postCloseTask.bind(this),
|
|
);
|
|
|
|
router.post(
|
|
'/',
|
|
limiterService.create(limiterConfig.postCreateTask),
|
|
this.postCreateTask.bind(this),
|
|
);
|
|
|
|
router.get(
|
|
'/:taskId/session/:sessionId',
|
|
limiterService.create(limiterConfig.getTaskSessionView),
|
|
checkSessionOwnership,
|
|
this.getTaskSessionView.bind(this),
|
|
);
|
|
|
|
router.get(
|
|
'/:taskId',
|
|
limiterService.create(limiterConfig.getTaskView),
|
|
checkTaskOwnership,
|
|
this.getTaskView.bind(this),
|
|
);
|
|
}
|
|
|
|
async postStartTaskSession (req, res) {
|
|
const { task: taskService } = this.dtp.services;
|
|
try {
|
|
res.locals.session = await taskService.createTaskSession(res.locals.task);
|
|
res.status(200).json({
|
|
success: true,
|
|
session: res.locals.session,
|
|
});
|
|
} catch (error) {
|
|
this.log.error('failed to create task session', { error });
|
|
res.status(error.statusCode || 500).json({
|
|
success: false,
|
|
message: error.message,
|
|
});
|
|
}
|
|
}
|
|
|
|
async postTaskSessionScreenshot (req, res) {
|
|
const { task: taskService } = this.dtp.services;
|
|
try {
|
|
await taskService.addTaskSessionScreenshot(res.locals.session, req.file);
|
|
res.status(200).json({ success: true });
|
|
} catch (error) {
|
|
this.log.error('failed to add task session screenshot', { error });
|
|
res.status(error.statusCode || 500).json({
|
|
success: false,
|
|
message: error.message,
|
|
});
|
|
}
|
|
}
|
|
|
|
async postTaskSessionStatus (req, res) {
|
|
const { task: taskService } = this.dtp.services;
|
|
try {
|
|
this.log.debug('updating task session status', {
|
|
sessionId: res.locals.session._id,
|
|
params: req.body,
|
|
});
|
|
await taskService.setTaskSessionStatus(res.locals.session, req.body.status);
|
|
|
|
const displayList = this.createDisplayList('set-session-status');
|
|
displayList.showNotification(
|
|
'Session status updated',
|
|
'success',
|
|
'bottom-center',
|
|
5000,
|
|
);
|
|
|
|
res.status(200).json({ success: true, displayList });
|
|
} catch (error) {
|
|
this.log.error('failed to update task session status', { error });
|
|
res.status(error.statusCode || 500).json({
|
|
success: false,
|
|
message: error.message,
|
|
});
|
|
}
|
|
}
|
|
|
|
async postCloseTaskSession (req, res) {
|
|
const { task: taskService } = this.dtp.services;
|
|
try {
|
|
await taskService.closeTaskSession(res.locals.session);
|
|
res.status(200).json({ success: true });
|
|
} catch (error) {
|
|
this.log.error('failed to close task session', { error });
|
|
res.status(error.statusCode || 500).json({
|
|
success: false,
|
|
message: error.message,
|
|
});
|
|
}
|
|
}
|
|
|
|
async postStartTask (req, res, next) {
|
|
const { task: taskService } = this.dtp.services;
|
|
try {
|
|
await taskService.startTask(res.locals.task);
|
|
res.redirect(`/task/${res.locals.task._id}`);
|
|
} catch (error) {
|
|
this.log.error('failed to close task session', { error });
|
|
return next(error);
|
|
}
|
|
}
|
|
|
|
async postCloseTask (req, res, next) {
|
|
const { task: taskService } = this.dtp.services;
|
|
try {
|
|
await taskService.closeTask(res.locals.task);
|
|
res.redirect('/');
|
|
} catch (error) {
|
|
this.log.error('failed to close task', { error });
|
|
return next(error);
|
|
}
|
|
}
|
|
|
|
async postCreateTask (req, res, next) {
|
|
const { task: taskService } = this.dtp.services;
|
|
try {
|
|
res.locals.task = await taskService.createTask(req.user, req.body);
|
|
res.redirect(`/task/${res.locals.task._id}`);
|
|
} catch (error) {
|
|
this.log.error('failed to create new task', { error });
|
|
return next(error);
|
|
}
|
|
}
|
|
|
|
async getTaskSessionView (req, res) {
|
|
res.render('task/session/view');
|
|
}
|
|
|
|
async getTaskView (req, res, next) {
|
|
const { report: reportService, task: taskService } = this.dtp.services;
|
|
try {
|
|
res.locals.pagination = this.getPaginationParameters(req, 50);
|
|
res.locals.sessions = await taskService.getSessionsForTask(
|
|
res.locals.task,
|
|
res.locals.pagination,
|
|
);
|
|
|
|
res.locals.weekStartDate = reportService.startOfWeek();
|
|
|
|
res.render('task/view');
|
|
} catch (error) {
|
|
this.log.error('failed to present the Task view', { error });
|
|
return next(error);
|
|
}
|
|
}
|
|
}
|