Просмотр исходного кода

Ensure track changes is enabled for reviewers when switching roles (#22645)

* Ensure track changes is enabled for reviewers when switching roles

* update track_changes.${userId} if track_changes is an object

GitOrigin-RevId: 3e803f4d475dbb67ff85b30095307ea58a07b2bc
Domagoj Kriskovic 1 год назад
Родитель
Сommit
2d57e347aa

+ 62 - 24
services/web/app/src/Features/Collaborators/CollaboratorsHandler.js

@@ -149,32 +149,12 @@ async function addUserIdToProject(
   }
 
   if (privilegeLevel === PrivilegeLevels.REVIEW) {
-    const trackChanges =
-      typeof project.track_changes === 'object' ? project.track_changes : {}
-
+    const trackChanges = await convertTrackChangesToExplicitFormat(
+      projectId,
+      project.track_changes
+    )
     trackChanges[userId] = true
 
-    if (project.track_changes === true) {
-      // track changes are enabled for all
-      // we need to convert it to explicit format
-      const members =
-        await CollaboratorsGetter.promises.getMemberIdsWithPrivilegeLevels(
-          project
-        )
-
-      for (const { id, privilegeLevel } of members) {
-        if (
-          [
-            PrivilegeLevels.OWNER,
-            PrivilegeLevels.READ_AND_WRITE,
-            PrivilegeLevels.REVIEW,
-          ].includes(privilegeLevel)
-        ) {
-          trackChanges[id] = true
-        }
-      }
-    }
-
     await Project.updateOne(
       { _id: projectId },
       { track_changes: trackChanges, $addToSet: level }
@@ -312,6 +292,22 @@ async function setCollaboratorPrivilegeLevel(
         },
         $addToSet: { reviewer_refs: userId },
       }
+
+      const project = await ProjectGetter.promises.getProject(projectId, {
+        track_changes: true,
+      })
+      const newTrackChangesState = await convertTrackChangesToExplicitFormat(
+        projectId,
+        project.track_changes
+      )
+      if (newTrackChangesState[userId] !== true) {
+        newTrackChangesState[userId] = true
+      }
+      if (typeof project.track_changes === 'object') {
+        update.$set = { [`track_changes.${userId}`]: true }
+      } else {
+        update.$set = { track_changes: newTrackChangesState }
+      }
       break
     }
     case PrivilegeLevels.READ_ONLY: {
@@ -334,6 +330,14 @@ async function setCollaboratorPrivilegeLevel(
   if (mongoResponse.matchedCount === 0) {
     throw new Errors.NotFoundError('project or collaborator not found')
   }
+
+  if (update.$set?.track_changes) {
+    EditorRealTimeController.emitToRoom(
+      projectId,
+      'toggle-track-changes',
+      update.$set.track_changes
+    )
+  }
 }
 
 async function userIsTokenMember(userId, projectId) {
@@ -367,3 +371,37 @@ async function _flushProjects(projectIds) {
     await TpdsProjectFlusher.promises.flushProjectToTpds(projectId)
   }
 }
+
+async function convertTrackChangesToExplicitFormat(
+  projectId,
+  trackChangesState
+) {
+  if (typeof trackChangesState === 'object') {
+    return { ...trackChangesState }
+  }
+
+  if (trackChangesState === true) {
+    // track changes are enabled for all
+    const members =
+      await CollaboratorsGetter.promises.getMemberIdsWithPrivilegeLevels(
+        projectId
+      )
+
+    const newTrackChangesState = {}
+    for (const { id, privilegeLevel } of members) {
+      if (
+        [
+          PrivilegeLevels.OWNER,
+          PrivilegeLevels.READ_AND_WRITE,
+          PrivilegeLevels.REVIEW,
+        ].includes(privilegeLevel)
+      ) {
+        newTrackChangesState[id] = true
+      }
+    }
+
+    return newTrackChangesState
+  }
+
+  return {}
+}

+ 77 - 24
services/web/test/unit/src/Collaborators/CollaboratorsHandlerTests.js

@@ -640,33 +640,86 @@ describe('CollaboratorsHandler', function () {
       )
     })
 
-    it('sets a collaborator to reviewer', async function () {
-      this.ProjectMock.expects('updateOne')
-        .withArgs(
-          {
-            _id: this.projectId,
-            $or: [
-              { collaberator_refs: this.userId },
-              { readOnly_refs: this.userId },
-              { reviewer_refs: this.userId },
-            ],
+    describe('sets a collaborator to reviewer when track changes is enabled for everyone', function () {
+      beforeEach(function () {
+        this.ProjectGetter.promises.getProject = sinon.stub().resolves({
+          _id: new ObjectId(),
+          owner_ref: this.addingUserId,
+          name: 'Foo',
+          track_changes: true,
+        })
+      })
+      it('should correctly update the project', async function () {
+        this.ProjectMock.expects('updateOne')
+          .withArgs(
+            {
+              _id: this.projectId,
+              $or: [
+                { collaberator_refs: this.userId },
+                { readOnly_refs: this.userId },
+                { reviewer_refs: this.userId },
+              ],
+            },
+            {
+              $addToSet: { reviewer_refs: this.userId },
+              $set: { track_changes: { [this.userId]: true } },
+              $pull: {
+                readOnly_refs: this.userId,
+                collaberator_refs: this.userId,
+                pendingEditor_refs: this.userId,
+              },
+            }
+          )
+          .chain('exec')
+          .resolves({ matchedCount: 1 })
+        await this.CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel(
+          this.projectId,
+          this.userId,
+          'review'
+        )
+      })
+    })
+
+    describe('sets a collaborator to reviewer when track changes is not enabled for everyone', function () {
+      beforeEach(function () {
+        this.ProjectGetter.promises.getProject = sinon.stub().resolves({
+          _id: new ObjectId(),
+          owner_ref: this.addingUserId,
+          name: 'Foo',
+          track_changes: {
+            [this.userId]: true,
           },
-          {
-            $addToSet: { reviewer_refs: this.userId },
-            $pull: {
-              readOnly_refs: this.userId,
-              collaberator_refs: this.userId,
-              pendingEditor_refs: this.userId,
+        })
+      })
+      it('should correctly update the project', async function () {
+        this.ProjectMock.expects('updateOne')
+          .withArgs(
+            {
+              _id: this.projectId,
+              $or: [
+                { collaberator_refs: this.userId },
+                { readOnly_refs: this.userId },
+                { reviewer_refs: this.userId },
+              ],
             },
-          }
+            {
+              $addToSet: { reviewer_refs: this.userId },
+              $set: { [`track_changes.${this.userId}`]: true },
+              $pull: {
+                readOnly_refs: this.userId,
+                collaberator_refs: this.userId,
+                pendingEditor_refs: this.userId,
+              },
+            }
+          )
+          .chain('exec')
+          .resolves({ matchedCount: 1 })
+        await this.CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel(
+          this.projectId,
+          this.userId,
+          'review'
         )
-        .chain('exec')
-        .resolves({ matchedCount: 1 })
-      await this.CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel(
-        this.projectId,
-        this.userId,
-        'review'
-      )
+      })
     })
 
     it('sets a collaborator to read-only as a pendingEditor', async function () {