Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XiaoW Hotfix of Project refactor and white screen issue fix #980

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
267 changes: 154 additions & 113 deletions src/controllers/projectController.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,47 @@
/* eslint-disable quotes */
/* eslint-disable arrow-parens */
const mongoose = require("mongoose");
const timeentry = require("../models/timeentry");
const userProfile = require("../models/userProfile");
const userProject = require("../helpers/helperModels/userProjects");
const { hasPermission } = require("../utilities/permissions");
const escapeRegex = require("../utilities/escapeRegex");
const cache = require("../utilities/nodeCache")();
const mongoose = require('mongoose');
const timeentry = require('../models/timeentry');
const task = require('../models/task');
const wbs = require('../models/wbs');
const userProfile = require('../models/userProfile');
const { hasPermission } = require('../utilities/permissions');
const escapeRegex = require('../utilities/escapeRegex');
const logger = require('../startup/logger');
const cache = require('../utilities/nodeCache')();

const projectController = function (Project) {
const getAllProjects = function (req, res) {
Project.find({}, "projectName isActive category modifiedDatetime")
.sort({ modifiedDatetime: -1 })
.then((results) => {
res.status(200).send(results);
})
.catch((error) => res.status(404).send(error));
const getAllProjects = async function (req, res) {
try {
const projects = await Project.find(
{ isArchived: { $ne: true } },
'projectName isActive category modifiedDatetime',
).sort({ modifiedDatetime: -1 });
res.status(200).send(projects);
} catch (error) {
logger.logException(error);
res.status(404).send('Error fetching projects. Please try again.');
}
};

const deleteProject = async function (req, res) {
if (!(await hasPermission(req.body.requestor, "deleteProject"))) {
res
.status(403)
.send({ error: "You are not authorized to delete projects." });
if (!(await hasPermission(req.body.requestor, 'deleteProject'))) {
res.status(403).send({ error: 'You are not authorized to delete projects.' });
return;
}
const { projectId } = req.params;
Project.findById(projectId, (error, record) => {
if (error || !record || record === null || record.length === 0) {
res.status(400).send({ error: "No valid records found" });
res.status(400).send({ error: 'No valid records found' });
return;
}

// find if project has any time entries associated with it

timeentry.find({ projectId: record._id }, "_id").then((timeentries) => {
timeentry.find({ projectId: record._id }, '_id').then((timeentries) => {
if (timeentries.length > 0) {
res.status(400).send({
error:
"This project has associated time entries and cannot be deleted. Consider inactivaing it instead.",
'This project has associated time entries and cannot be deleted. Consider inactivaing it instead.',
});
} else {
const removeprojectfromprofile = userProfile
Expand All @@ -49,9 +52,8 @@ const projectController = function (Project) {
Promise.all([removeprojectfromprofile, removeproject])
.then(
res.status(200).send({
message:
"Project successfully deleted and user profiles updated.",
})
message: 'Project successfully deleted and user profiles updated.',
}),
)
.catch((errors) => {
res.status(400).send(errors);
Expand All @@ -64,117 +66,164 @@ const projectController = function (Project) {
};

const postProject = async function (req, res) {
if (!(await hasPermission(req.body.requestor, "postProject"))) {
res
.status(403)
.send({ error: "You are not authorized to create new projects." });
return;
if (!(await hasPermission(req.body.requestor, 'postProject'))) {
return res.status(401).send('You are not authorized to create new projects.');
}

if (!req.body.projectName || !req.body.isActive) {
res.status(400).send({
error: "Project Name and active status are mandatory fields.",
});
return;
if (!req.body.projectName) {
return res.status(400).send('Project Name is mandatory fields.');
}

Project.find({
projectName: { $regex: escapeRegex(req.body.projectName), $options: "i" },
}).then((result) => {
if (result.length > 0) {
res.status(400).send({
error: `Project Name must be unique. Another project with name ${result.projectName} already exists. Please note that project names are case insensitive.`,
});
try {
const projectWithRepeatedName = await Project.find({
projectName: {
$regex: escapeRegex(req.body.projectName),
$options: 'i',
},
});
if (projectWithRepeatedName.length > 0) {
res
.status(400)
.send(
`Project Name must be unique. Another project with name ${req.body.projectName} already exists. Please note that project names are case insensitive.`,
);
return;
}
const _project = new Project();
const now = new Date();
_project.projectName = req.body.projectName;
_project.category = req.body.projectCategory || "Unspecified";
_project.isActive = req.body.isActive;
_project.createdDatetime = Date.now();
_project.modifiedDatetime = Date.now();

_project
.save()
.then((results) => res.status(201).send(results))
.catch((error) => res.status(500).send({ error }));
});
_project.category = req.body.projectCategory;
_project.isActive = true;
_project.createdDatetime = now;
_project.modifiedDatetime = now;
const savedProject = await _project.save();
return res.status(200).send(savedProject);
} catch (error) {
logger.logException(error);
res.status(400).send('Error creating project. Please try again.');
}
};

const putProject = async function (req, res) {
if (!(await hasPermission(req.body.requestor, "putProject"))) {
res
.status(403)
.send("You are not authorized to make changes in the projects.");
if (!(await hasPermission(req.body.requestor, 'putProject'))) {
res.status(403).send('You are not authorized to make changes in the projects.');
return;
}

const { projectId } = req.params;
Project.findById(projectId, (error, record) => {
if (error || record === null) {
res.status(400).send("No valid records found");
const { projectName, category, isActive, _id: projectId, isArchived } = req.body;
const sameNameProejct = await Project.find({
projectName,
_id: { $ne: projectId },
});
if (sameNameProejct.length > 0) {
res.status(400).send('This project name is already taken');
return;
}
const session = await mongoose.startSession();
session.startTransaction();
try {
const targetProject = await Project.findById(projectId);
if (!targetProject) {
res.status(400).send('No valid records found');
return;
}

record.projectName = req.body.projectName;
record.category = req.body.category;
record.isActive = req.body.isActive;
record.modifiedDatetime = Date.now();

record
.save()
.then((results) => res.status(201).send(results._id))
.catch((errors) => res.status(400).send(errors));
});
targetProject.projectName = projectName;
targetProject.category = category;
targetProject.isActive = isActive;
targetProject.modifiedDatetime = Date.now();
if (isArchived) {
targetProject.isArchived = isArchived;
// deactivate wbs within target project
await wbs.updateMany({ projectId }, { isActive: false }, { session });
// deactivate tasks within affected wbs
const deactivatedwbsIds = await wbs.find({ projectId }, '_id');
await task.updateMany(
{ wbsId: { $in: deactivatedwbsIds } },
{ isActive: false },
{ session },
);
// remove project from userprofiles.projects array
await userProfile.updateMany(
{ projects: projectId },
{ $pull: { projects: projectId } },
{ session },
);
// deactivate timeentry for affected tasks
await timeentry.updateMany({ projectId }, { isActive: false }, { session });
}
await targetProject.save({ session });
await session.commitTransaction();
res.status(200).send(targetProject);
} catch (error) {
await session.abortTransaction();
logger.logException(error);
res.status(400).send('Error updating project. Please try again.');
} finally {
session.endSession();
}
};

const getProjectById = function (req, res) {
const { projectId } = req.params;

Project.findById(projectId, "-__v -createdDatetime -modifiedDatetime")
Project.findById(projectId, '-__v -createdDatetime -modifiedDatetime')
.then((results) => res.status(200).send(results))
.catch((error) => res.status(404).send(error));
.catch((err) => {
logger.logException(err);
res.status(404).send('Error fetching project. Please try again.');
});
};

const getUserProjects = function (req, res) {
const { userId } = req.params;

userProject
.findById(userId)
.then((results) => {
res.status(200).send(results.projects);
})
.catch((error) => {
res.status(400).send(error);
});
const getUserProjects = async function (req, res) {
try {
const { userId } = req.params;
const user = await userProfile.findById(userId, 'projects');
if (!user) {
res.status(400).send('Invalid user');
return;
}
const { projects } = user;
const projectList = await Project.find(
{ _id: { $in: projects }, isActive: { $ne: false } },
'_id projectName category',
);
const result = projectList
.map((p) => {
p = p.toObject();
p.projectId = p._id;
delete p._id;
return p;
})
.sort((p1, p2) => {
if (p1.projectName.toLowerCase() < p2.projectName.toLowerCase()) return -1;
if (p1.projectName.toLowerCase() > p2.projectName.toLowerCase()) return 1;
return 0;
});
res.status(200).send(result);
} catch (error) {
logger.logException(error);
res.status(400).send('Error fetching projects. Please try again.');
}
};

const assignProjectToUsers = async function (req, res) {
// verify requestor is administrator, projectId is passed in request params and is valid mongoose objectid, and request body contains an array of users

if (!(await hasPermission(req.body.requestor, "assignProjectToUsers"))) {
res
.status(403)
.send({ error: "You are not authorized to perform this operation" });
if (!(await hasPermission(req.body.requestor, 'assignProjectToUsers'))) {
res.status(403).send('You are not authorized to perform this operation');
return;
}

if (
!req.params.projectId ||
!mongoose.Types.ObjectId.isValid(req.params.projectId) ||
!req.body.users ||
req.body.users.length === 0
) {
res.status(400).send({ error: "Invalid request" });
res.status(400).send('Invalid request');
return;
}

// verify project exists

Project.findById(req.params.projectId)
.then((project) => {
if (!project || project.length === 0) {
res.status(400).send({ error: "Invalid project" });
res.status(400).send('Invalid project');
return;
}
const { users } = req.body;
Expand All @@ -186,50 +235,42 @@ const projectController = function (Project) {
if (cache.hasCache(`user-${userId}`)) {
cache.removeCache(`user-${userId}`);
}
if (operation === "Assign") {
if (operation === 'Assign') {
assignlist.push(userId);
} else {
unassignlist.push(userId);
}
});

const assignPromise = userProfile
.updateMany(
{ _id: { $in: assignlist } },
{ $addToSet: { projects: project._id } }
)
.updateMany({ _id: { $in: assignlist } }, { $addToSet: { projects: project._id } })
.exec();
const unassignPromise = userProfile
.updateMany(
{ _id: { $in: unassignlist } },
{ $pull: { projects: project._id } }
)
.updateMany({ _id: { $in: unassignlist } }, { $pull: { projects: project._id } })
.exec();

Promise.all([assignPromise, unassignPromise])
.then(() => {
res.status(200).send({ result: "Done" });
res.status(200).send({ result: 'Done' });
})
.catch((error) => {
res.status(500).send({ error });
});
})
.catch((error) => {
res.status(500).send({ error });
.catch((err) => {
logger.logException(err);
res.status(500).send('Error fetching project. Please try again.');
});
};

const getprojectMembership = function (req, res) {
const { projectId } = req.params;
if (!mongoose.Types.ObjectId.isValid(projectId)) {
res.status(400).send({ error: "Invalid request" });
res.status(400).send('Invalid request');
return;
}
userProfile
.find(
{ projects: projectId },
"_id firstName lastName isActive profilePic"
)
.find({ projects: projectId }, '_id firstName lastName isActive profilePic')
.sort({ firstName: 1, lastName: 1 })
.then((results) => {
res.status(200).send(results);
Expand Down
Loading
Loading