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

Add resolveAllComments and resolveOwnComments permissions

GitOrigin-RevId: 1fca9391dc3ff6e890532054582c49f11731e987
This commit is contained in:
Eric Mc Sween
2025-02-19 07:34:33 -05:00
committed by Copybot
parent ae491f910b
commit 483c97a484
6 changed files with 44 additions and 16 deletions
@@ -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,
@@ -1,6 +1,8 @@
export type Permissions = {
read: boolean
comment: boolean
resolveOwnComments: boolean
resolveAllComments: boolean
trackedWrite: boolean
write: boolean
admin: boolean
@@ -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,
]
)
@@ -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), [])
@@ -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">
@@ -28,6 +28,8 @@ const PermissionsProvider: FC = ({ children }) => (
value={{
read: true,
comment: true,
resolveOwnComments: false,
resolveAllComments: false,
trackedWrite: false,
write: false,
admin: false,