Merge pull request #2150 from overleaf/cmg-archiving-frontend

Frontend for new archiving and trashing

GitOrigin-RevId: be8676ab6c2fea7f8fb23655772a008d067b2a78
This commit is contained in:
Chrystal Maria Griffiths
2019-11-25 15:59:10 +00:00
committed by sharelatex
parent 1a456da017
commit 0abe99d98f
13 changed files with 954 additions and 579 deletions
@@ -34,7 +34,6 @@ const Features = require('../../infrastructure/Features')
const BrandVariationsHandler = require('../BrandVariations/BrandVariationsHandler')
const { getUserAffiliations } = require('../Institutions/InstitutionsAPI')
const V1Handler = require('../V1/V1Handler')
const { Project } = require('../../models/Project')
const ProjectController = {
_isInPercentageRollout(rolloutName, objectId, percentage) {
@@ -145,11 +144,10 @@ const ProjectController = {
archiveProject(req, res, next) {
const projectId = req.params.Project_id
const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ projectId }, 'received request to archive project')
const user = AuthenticationController.getSessionUser(req)
ProjectDeleter.archiveProject(projectId, user._id, function(err) {
ProjectDeleter.archiveProject(projectId, userId, function(err) {
if (err != null) {
return next(err)
} else {
@@ -160,11 +158,38 @@ const ProjectController = {
unarchiveProject(req, res, next) {
const projectId = req.params.Project_id
const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ projectId }, 'received request to unarchive project')
const user = AuthenticationController.getSessionUser(req)
ProjectDeleter.unarchiveProject(projectId, userId, function(err) {
if (err != null) {
return next(err)
} else {
return res.sendStatus(200)
}
})
},
ProjectDeleter.unarchiveProject(projectId, user._id, function(err) {
trashProject(req, res, next) {
const projectId = req.params.project_id
const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ projectId }, 'received request to trash project')
ProjectDeleter.trashProject(projectId, userId, function(err) {
if (err != null) {
return next(err)
} else {
return res.sendStatus(200)
}
})
},
untrashProject(req, res, next) {
const projectId = req.params.project_id
const userId = AuthenticationController.getLoggedInUserId(req)
logger.log({ projectId }, 'received request to untrash project')
ProjectDeleter.untrashProject(projectId, userId, function(err) {
if (err != null) {
return next(err)
} else {
@@ -210,38 +235,6 @@ const ProjectController = {
})
},
trashProject(req, res, next) {
const projectId = req.params.project_id
const userId = AuthenticationController.getLoggedInUserId(req)
Project.update(
{ _id: projectId },
{ $addToSet: { trashed: userId } },
error => {
if (error) {
return next(error)
}
res.sendStatus(200)
}
)
},
untrashProject(req, res, next) {
const projectId = req.params.project_id
const userId = AuthenticationController.getLoggedInUserId(req)
Project.update(
{ _id: projectId },
{ $pull: { trashed: userId } },
error => {
if (error) {
return next(error)
}
res.sendStatus(200)
}
)
},
cloneProject(req, res, next) {
res.setTimeout(5 * 60 * 1000) // allow extra time for the copy to complete
metrics.inc('cloned-project')
@@ -376,7 +369,7 @@ const ProjectController = {
projects(cb) {
ProjectGetter.findAllUsersProjects(
userId,
'name lastUpdated lastUpdatedBy publicAccesLevel archived owner_ref tokens',
'name lastUpdated lastUpdatedBy publicAccesLevel archived trashed owner_ref tokens',
cb
)
},
@@ -925,6 +918,10 @@ const ProjectController = {
},
_buildProjectViewModel(project, accessLevel, source, userId) {
const archived = ProjectHelper.isArchived(project, userId)
// If a project is simultaneously trashed and archived, we will consider it archived but not trashed.
const trashed = ProjectHelper.isTrashed(project, userId) && !archived
TokenAccessHandler.protectTokens(project, accessLevel)
const model = {
id: project._id,
@@ -934,7 +931,8 @@ const ProjectController = {
publicAccessLevel: project.publicAccesLevel,
accessLevel,
source,
archived: ProjectHelper.isArchived(project, userId),
archived,
trashed,
owner_ref: project.owner_ref,
tokens: project.tokens,
isV1Project: false
@@ -947,11 +945,16 @@ const ProjectController = {
},
_buildV1ProjectViewModel(project) {
const archived = project.archived
// If a project is simultaneously trashed and archived, we will consider it archived but not trashed.
const trashed = project.removed && !archived
const projectViewModel = {
id: project.id,
name: project.title,
lastUpdated: new Date(project.updated_at * 1000), // Convert from epoch
archived: project.removed || project.archived,
archived: archived,
trashed: trashed,
isV1Project: true
}
if (
@@ -11,7 +11,7 @@
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const { db } = require('../../infrastructure/mongojs')
const { db, ObjectId } = require('../../infrastructure/mongojs')
const { promisify, callbackify } = require('util')
const { Project } = require('../../models/Project')
const { DeletedProject } = require('../../models/DeletedProject')
@@ -160,11 +160,11 @@ const ProjectDeleter = {
// Async methods
async function archiveProject(project_id, userId) {
logger.log({ project_id }, 'archiving project from user request')
async function archiveProject(projectId, userId) {
logger.log({ projectId }, 'archiving project from user request')
try {
let project = await Project.findOne({ _id: project_id }).exec()
let project = await Project.findOne({ _id: projectId }).exec()
if (!project) {
throw new Errors.NotFoundError('project not found')
}
@@ -174,18 +174,21 @@ async function archiveProject(project_id, userId) {
'ARCHIVE'
)
await Project.update({ _id: project_id }, { $set: { archived: archived } })
await Project.update(
{ _id: projectId },
{ $set: { archived: archived }, $pull: { trashed: ObjectId(userId) } }
)
} catch (err) {
logger.warn({ err }, 'problem archiving project')
throw err
}
}
async function unarchiveProject(project_id, userId) {
logger.log({ project_id }, 'unarchiving project from user request')
async function unarchiveProject(projectId, userId) {
logger.log({ projectId }, 'unarchiving project from user request')
try {
let project = await Project.findOne({ _id: project_id }).exec()
let project = await Project.findOne({ _id: projectId }).exec()
if (!project) {
throw new Errors.NotFoundError('project not found')
}
@@ -196,13 +199,54 @@ async function unarchiveProject(project_id, userId) {
'UNARCHIVE'
)
await Project.update({ _id: project_id }, { $set: { archived: archived } })
await Project.update({ _id: projectId }, { $set: { archived: archived } })
} catch (err) {
logger.warn({ err }, 'problem unarchiving project')
throw err
}
}
async function trashProject(projectId, userId) {
logger.log({ projectId }, 'trashing project from user request')
try {
let project = await Project.findOne({ _id: projectId }).exec()
if (!project) {
throw new Errors.NotFoundError('project not found')
}
await Project.update(
{ _id: projectId },
{
$addToSet: { trashed: ObjectId(userId) },
$pull: { archived: ObjectId(userId) }
}
)
} catch (err) {
logger.warn({ err }, 'problem trashing project')
throw err
}
}
async function untrashProject(projectId, userId) {
logger.log({ projectId }, 'untrashing project from user request')
try {
let project = await Project.findOne({ _id: projectId }).exec()
if (!project) {
throw new Errors.NotFoundError('project not found')
}
await Project.update(
{ _id: projectId },
{ $pull: { trashed: ObjectId(userId) } }
)
} catch (err) {
logger.warn({ err }, 'problem untrashing project')
throw err
}
}
async function deleteProject(project_id, options = {}) {
logger.log({ project_id }, 'deleting project')
@@ -350,6 +394,8 @@ async function expireDeletedProject(projectId) {
const promises = {
archiveProject: archiveProject,
unarchiveProject: unarchiveProject,
trashProject: trashProject,
untrashProject: untrashProject,
deleteProject: deleteProject,
undeleteProject: undeleteProject,
expireDeletedProject: expireDeletedProject,
@@ -359,6 +405,8 @@ const promises = {
ProjectDeleter.promises = promises
ProjectDeleter.archiveProject = callbackify(archiveProject)
ProjectDeleter.unarchiveProject = callbackify(unarchiveProject)
ProjectDeleter.trashProject = callbackify(trashProject)
ProjectDeleter.untrashProject = callbackify(untrashProject)
ProjectDeleter.deleteProject = callbackify(deleteProject)
ProjectDeleter.undeleteProject = callbackify(undeleteProject)
ProjectDeleter.expireDeletedProject = callbackify(expireDeletedProject)