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

Merge pull request #23691 from overleaf/em-resolve-comments-permissions

Add resolveAllComments and resolveOwnComments permissions

GitOrigin-RevId: 1fca9391dc3ff6e890532054582c49f11731e987
Eric Mc Sween 1 год назад
Родитель
Сommit
483c97a484

+ 8 - 0
services/web/frontend/js/features/ide-react/context/permissions-context.tsx

@@ -18,6 +18,8 @@ const permissionsMap: DeepReadonly<Record<PermissionsLevel, Permissions>> = {
   readOnly: {
     read: true,
     comment: true,
+    resolveOwnComments: false,
+    resolveAllComments: false,
     trackedWrite: false,
     write: false,
     admin: false,
@@ -26,6 +28,8 @@ const permissionsMap: DeepReadonly<Record<PermissionsLevel, Permissions>> = {
   review: {
     read: true,
     comment: true,
+    resolveOwnComments: true,
+    resolveAllComments: false,
     trackedWrite: true,
     write: false,
     admin: false,
@@ -34,6 +38,8 @@ const permissionsMap: DeepReadonly<Record<PermissionsLevel, Permissions>> = {
   readAndWrite: {
     read: true,
     comment: true,
+    resolveOwnComments: true,
+    resolveAllComments: true,
     trackedWrite: true,
     write: true,
     admin: false,
@@ -42,6 +48,8 @@ const permissionsMap: DeepReadonly<Record<PermissionsLevel, Permissions>> = {
   owner: {
     read: true,
     comment: true,
+    resolveOwnComments: true,
+    resolveAllComments: true,
     trackedWrite: true,
     write: true,
     admin: true,

+ 2 - 0
services/web/frontend/js/features/ide-react/types/permissions.ts

@@ -1,6 +1,8 @@
 export type Permissions = {
   read: boolean
   comment: boolean
+  resolveOwnComments: boolean
+  resolveAllComments: boolean
   trackedWrite: boolean
   write: boolean
   admin: boolean

+ 4 - 3
services/web/frontend/js/features/review-panel-new/components/review-panel-comment.tsx

@@ -77,10 +77,10 @@ export const ReviewPanelComment = memo<{
     async (commentId: CommentId) => {
       setProcessing(true)
       try {
-        if (permissions.write) {
+        if (permissions.resolveAllComments) {
           // Owners and editors can delete any message
           await deleteMessage(comment.op.t, commentId)
-        } else {
+        } else if (permissions.resolveOwnComments) {
           // Reviewers can only delete their own messages
           await deleteOwnMessage(comment.op.t, commentId)
         }
@@ -100,7 +100,8 @@ export const ReviewPanelComment = memo<{
       deleteOwnMessage,
       showGenericMessageModal,
       t,
-      permissions.write,
+      permissions.resolveOwnComments,
+      permissions.resolveAllComments,
     ]
   )
 

+ 5 - 3
services/web/frontend/js/features/review-panel-new/components/review-panel-message.tsx

@@ -37,12 +37,14 @@ export const ReviewPanelMessage: FC<{
   const [deleting, setDeleting] = useState(false)
   const [content, setContent] = useState(message.content)
   const user = useUserContext()
-  const { write, trackedWrite } = usePermissionsContext()
+  const permissions = usePermissionsContext()
 
   const isCommentAuthor = user.id === message.user.id
   const canEdit = isCommentAuthor
-  const canResolve = write || (trackedWrite && isCommentAuthor)
-  const canDelete = write || (trackedWrite && isCommentAuthor)
+  const canResolve =
+    permissions.resolveAllComments ||
+    (permissions.resolveOwnComments && isCommentAuthor)
+  const canDelete = canResolve
 
   const handleEditOption = useCallback(() => setEditing(true), [])
   const showDeleteModal = useCallback(() => setDeleting(true), [])

+ 23 - 10
services/web/frontend/js/features/review-panel-new/components/review-panel-resolved-thread.tsx

@@ -10,6 +10,8 @@ import { Change, CommentOperation } from '../../../../../types/change'
 import classNames from 'classnames'
 import { debugConsole } from '@/utils/debugging'
 import { useModalsContext } from '@/features/ide-react/context/modals-context'
+import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
+import { useUserContext } from '@/shared/context/user-context'
 
 export const ReviewPanelResolvedThread: FC<{
   id: ThreadId
@@ -20,6 +22,12 @@ export const ReviewPanelResolvedThread: FC<{
   const { reopenThread, deleteThread } = useThreadsActionsContext()
   const [processing, setProcessing] = useState(false)
   const { showGenericMessageModal } = useModalsContext()
+  const permissions = usePermissionsContext()
+  const user = useUserContext()
+  const isCommentAuthor = user.id === comment.metadata?.user_id
+  const canDelete =
+    permissions.resolveAllComments ||
+    (permissions.resolveOwnComments && isCommentAuthor)
 
   const handleReopenThread = useCallback(async () => {
     setProcessing(true)
@@ -81,16 +89,21 @@ export const ReviewPanelResolvedThread: FC<{
               <MaterialIcon type="refresh" accessibilityLabel={t('reopen')} />
             </button>
           </OLTooltip>
-
-          <OLTooltip
-            id="delete-thread"
-            overlayProps={{ placement: 'bottom' }}
-            description={t('delete')}
-          >
-            <button type="button" className="btn" onClick={handleDeleteThread}>
-              <MaterialIcon type="delete" accessibilityLabel={t('delete')} />
-            </button>
-          </OLTooltip>
+          {canDelete && (
+            <OLTooltip
+              id="delete-thread"
+              overlayProps={{ placement: 'bottom' }}
+              description={t('delete')}
+            >
+              <button
+                type="button"
+                className="btn"
+                onClick={handleDeleteThread}
+              >
+                <MaterialIcon type="delete" accessibilityLabel={t('delete')} />
+              </button>
+            </OLTooltip>
+          )}
         </div>
       </div>
       <div className="review-panel-resolved-comment-quoted-text">

+ 2 - 0
services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-readonly.spec.tsx

@@ -28,6 +28,8 @@ const PermissionsProvider: FC = ({ children }) => (
     value={{
       read: true,
       comment: true,
+      resolveOwnComments: false,
+      resolveAllComments: false,
       trackedWrite: false,
       write: false,
       admin: false,