Copy tags when cloning a project (#14987)

GitOrigin-RevId: 4cdca0ef2f26bf6bba02b675b0ef02ba8da881e2
This commit is contained in:
Alf Eaton
2023-09-29 08:04:14 +00:00
committed by Copybot
parent 04900349e6
commit 15475cdb3c
21 changed files with 315 additions and 21 deletions
@@ -37,6 +37,7 @@ const { hasAdminAccess } = require('../Helpers/AdminAuthorizationHelper')
const InstitutionsFeatures = require('../Institutions/InstitutionsFeatures')
const ProjectAuditLogHandler = require('./ProjectAuditLogHandler')
const PublicAccessLevels = require('../Authorization/PublicAccessLevels')
const TagsHandler = require('../Tags/TagsHandler')
/**
* @typedef {import("./types").GetProjectsRequest} GetProjectsRequest
@@ -253,7 +254,7 @@ const ProjectController = {
res.setTimeout(5 * 60 * 1000) // allow extra time for the copy to complete
metrics.inc('cloned-project')
const projectId = req.params.Project_id
const { projectName } = req.body
const { projectName, tags } = req.body
logger.debug({ projectId, projectName }, 'cloning project')
if (!SessionManager.isUserLoggedIn(req.session)) {
return res.json({ redir: '/register' })
@@ -264,6 +265,7 @@ const ProjectController = {
currentUser,
projectId,
projectName,
tags,
(err, project) => {
if (err != null) {
OError.tag(err, 'error cloning project', {
@@ -739,6 +741,12 @@ const ProjectController = {
}
)
},
projectTags(cb) {
if (!userId) {
return cb(null, [])
}
TagsHandler.getTagsForProject(userId, projectId, cb)
},
},
(
err,
@@ -757,6 +765,7 @@ const ProjectController = {
sourceEditorToolbarAssigment,
historyViewAssignment,
reviewPanelAssignment,
projectTags,
}
) => {
if (err != null) {
@@ -944,6 +953,7 @@ const ProjectController = {
isReviewPanelReact: reviewPanelAssignment.variant === 'react',
showPersonalAccessToken,
hasTrackChangesFeature: Features.hasFeature('track-changes'),
projectTags,
})
timer.done()
}
@@ -17,6 +17,7 @@ const ProjectOptionsHandler = require('./ProjectOptionsHandler')
const SafePath = require('./SafePath')
const TpdsProjectFlusher = require('../ThirdPartyDataStore/TpdsProjectFlusher')
const _ = require('lodash')
const TagsHandler = require('../Tags/TagsHandler')
module.exports = {
duplicate: callbackify(duplicate),
@@ -25,7 +26,7 @@ module.exports = {
},
}
async function duplicate(owner, originalProjectId, newProjectName) {
async function duplicate(owner, originalProjectId, newProjectName, tags = []) {
await DocumentUpdaterHandler.promises.flushProjectToMongo(originalProjectId)
const originalProject = await ProjectGetter.promises.getProject(
originalProjectId,
@@ -50,6 +51,14 @@ async function duplicate(owner, originalProjectId, newProjectName) {
])
segmentation.duplicatedFromProject = originalProjectId
// count the number of tags before and after, for analytics
segmentation['original-tags'] =
await TagsHandler.promises.countTagsForProject(
owner._id,
originalProject._id
)
segmentation['updated-tags'] = tags.length
// remove any leading or trailing spaces
newProjectName = newProjectName.trim()
@@ -88,6 +97,14 @@ async function duplicate(owner, originalProjectId, newProjectName) {
newProject: { version: projectVersion },
})
await TpdsProjectFlusher.promises.flushProjectToTpds(newProject._id)
if (tags?.length > 0) {
await TagsHandler.promises.addProjectToTags(
owner._id,
tags.map(tag => tag.id),
newProject._id
)
}
} catch (err) {
// Clean up broken clone on error.
// Make sure we delete the new failed project, not the original one!
@@ -98,6 +115,7 @@ async function duplicate(owner, originalProjectId, newProjectName) {
newProjectId: newProject._id,
})
}
return newProject
}
@@ -7,6 +7,14 @@ async function getAllTags(userId) {
return Tag.find({ user_id: userId })
}
async function countTagsForProject(userId, projectId) {
return Tag.count({ user_id: userId, project_ids: projectId })
}
async function getTagsForProject(userId, projectId) {
return Tag.find({ user_id: userId, project_ids: projectId }, '-project_ids')
}
async function createTag(userId, name, color, options = {}) {
if (name.length > MAX_TAG_LENGTH) {
if (options.truncate) {
@@ -119,26 +127,38 @@ async function removeProjectFromAllTags(userId, projectId) {
await Tag.updateMany(searchOps, deleteOperation)
}
async function addProjectToTags(userId, tagIds, projectId) {
const searchOps = { user_id: userId, _id: { $in: tagIds } }
const insertOperation = { $addToSet: { project_ids: projectId } }
await Tag.updateMany(searchOps, insertOperation)
}
module.exports = {
getAllTags: callbackify(getAllTags),
countTagsForProject: callbackify(countTagsForProject),
getTagsForProject: callbackify(getTagsForProject),
createTag: callbackify(createTag),
renameTag: callbackify(renameTag),
editTag: callbackify(editTag),
deleteTag: callbackify(deleteTag),
addProjectToTag: callbackify(addProjectToTag),
addProjectsToTag: callbackify(addProjectsToTag),
addProjectToTags: callbackify(addProjectToTags),
removeProjectFromTag: callbackify(removeProjectFromTag),
removeProjectsFromTag: callbackify(removeProjectsFromTag),
addProjectToTagName: callbackify(addProjectToTagName),
removeProjectFromAllTags: callbackify(removeProjectFromAllTags),
promises: {
getAllTags,
countTagsForProject,
getTagsForProject,
createTag,
renameTag,
editTag,
deleteTag,
addProjectToTag,
addProjectsToTag,
addProjectToTags,
removeProjectFromTag,
removeProjectsFromTag,
addProjectToTagName,