diff --git a/packages/superdoc/src/components/CommentsLayer/CommentDialog.vue b/packages/superdoc/src/components/CommentsLayer/CommentDialog.vue index 9e8505d1ba..690df3dc79 100644 --- a/packages/superdoc/src/components/CommentsLayer/CommentDialog.vue +++ b/packages/superdoc/src/components/CommentsLayer/CommentDialog.vue @@ -101,28 +101,6 @@ const isInternalDropdownDisabled = computed(() => { return getConfig.value.readOnly; }); -const overflowOptions = [ - { label: 'Edit', key: 'edit' }, - { label: 'Delete', key: 'delete' }, -]; - -const showOverflow = computed(() => (comment) => { - if (!!props.comment.resolvedTime) return []; - if (getConfig.value.readOnly) return []; - if (!getConfig.value.overflow) return []; - if (comment.trackedChange) return []; - - const isOwnComment = comment.creatorEmail === superdocStore.user.email; - if (isOwnComment) return isAllowed(PERMISSIONS.COMMENTS_OVERFLOW_OWN, role, isInternal); - return isAllowed(PERMISSIONS.COMMENTS_OVERFLOW_OTHER, role, isInternal); -}); - -const getOverflowOptions = (comment) => { - const isOwnComment = comment.creatorEmail === superdocStore.user.email; - if (!isOwnComment) return overflowOptions.filter((o) => o.key !== 'delete'); - return overflowOptions; -}; - const isEditingThisComment = computed(() => (comment) => { return isEditing.value === comment.commentId; }); @@ -308,12 +286,10 @@ onMounted(() => {
{ if (!props.comment) return false; if (props.comment.resolvedTime) return false; if (commentsStore.pendingComment) return false; - if (props.comment.parentCommentId) return false; if (props.isPendingInput) return false; return true; }); @@ -69,8 +69,8 @@ const allowReject = computed(() => { const allowOverflow = computed(() => { if (!generallyAllowed.value) return false; if (props.comment.trackedChange) return false; - if (!props.overflowOptions || !props.overflowOptions.length) return false; if (props.isPendingInput) return false; + if (getOverflowOptions.value.length === 0) return false; return true; }); @@ -78,10 +78,24 @@ const allowOverflow = computed(() => { const getOverflowOptions = computed(() => { if (!generallyAllowed.value) return false; - if (!props.comment.creatorEmail !== proxy.$superdoc.config.user.email) { - return props.overflowOptions.filter((option) => option.key !== 'edit'); - } - return props.overflowOptions; + const allowedOptions = []; + const options = new Set(); + + // Only the comment creator can edit + if (props.comment.creatorEmail === proxy.$superdoc.config.user.email) { + options.add('edit'); + }; + + const isOwnComment = props.comment.creatorEmail === proxy.$superdoc.config.user.email; + + if (isOwnComment && isAllowed(PERMISSIONS.COMMENTS_DELETE_OWN, role, isInternal)) { + options.add('delete'); + } else if (!isOwnComment && isAllowed(PERMISSIONS.COMMENTS_DELETE_OTHER, role, isInternal)) { + options.add('delete'); + }; + + options.forEach((option) => allowedOptions.push(OVERFLOW_OPTIONS[option])); + return allowedOptions; }); const handleResolve = () => emit('resolve'); diff --git a/packages/superdoc/src/core/collaboration/helpers.js b/packages/superdoc/src/core/collaboration/helpers.js index f4895bccc1..a711f704e0 100644 --- a/packages/superdoc/src/core/collaboration/helpers.js +++ b/packages/superdoc/src/core/collaboration/helpers.js @@ -27,9 +27,20 @@ export const initCollaborationComments = (superdoc) => { if (currentUser.name === user.name && currentUser.email === user.email) return; + if (__IS_DEBUG__) console.debug('[initCollaborationComments] commentsArray.observe', commentsArray.toJSON()); + // Update conversations const comments = commentsArray.toJSON(); - superdoc.commentsStore.commentsList = comments.map((c) => useComment(c)); + + const seen = new Set(); + const filtered = []; + comments.forEach((c) =>{ + if (!seen.has(c.commentId)) { + seen.add(c.commentId); + filtered.push(c); + }; + }); + superdoc.commentsStore.commentsList = filtered.map((c) => useComment(c)); }); }; diff --git a/packages/superdoc/src/core/collaboration/permissions.js b/packages/superdoc/src/core/collaboration/permissions.js index 4a3db24395..d541103d7b 100644 --- a/packages/superdoc/src/core/collaboration/permissions.js +++ b/packages/superdoc/src/core/collaboration/permissions.js @@ -5,6 +5,8 @@ export const PERMISSIONS = Object.freeze({ REJECT_OTHER: 'REJECT_OTHER', COMMENTS_OVERFLOW_OWN: 'COMMENTS_OVERFLOW', COMMENTS_OVERFLOW_OTHER: 'COMMENTS_OVERFLOW_OTHER', + COMMENTS_DELETE_OWN: 'COMMENTS_DELETE_OWN', + COMMENTS_DELETE_OTHER: 'COMMENTS_DELETE_OTHER', UPLOAD_VERSION: 'UPLOAD_VERSION', VERSION_HISTORY: 'VERSION_HISTORY', }); @@ -17,8 +19,8 @@ const ROLES = Object.freeze({ const permissions = Object.freeze({ [PERMISSIONS.RESOLVE_OWN]: { - internal: [ROLES.EDITOR, ROLES.SUGGESTER], - external: [ROLES.EDITOR, ROLES.SUGGESTER], + internal: [ROLES.EDITOR], + external: [ROLES.EDITOR], }, [PERMISSIONS.RESOLVE_OTHER]: { internal: [ROLES.EDITOR], @@ -40,6 +42,14 @@ const permissions = Object.freeze({ internal: [ROLES.EDITOR], external: [], }, + [PERMISSIONS.COMMENTS_DELETE_OWN]: { + internal: [ROLES.EDITOR, ROLES.SUGGESTER], + external: [ROLES.EDITOR, ROLES.SUGGESTER], + }, + [PERMISSIONS.COMMENTS_DELETE_OTHER]: { + internal: [ROLES.EDITOR], + external: [], + }, [PERMISSIONS.UPLOAD_VERSION]: { internal: [ROLES.EDITOR], external: [], diff --git a/packages/superdoc/src/stores/comments-store.js b/packages/superdoc/src/stores/comments-store.js index a9e3e8b859..b113ba36f2 100644 --- a/packages/superdoc/src/stores/comments-store.js +++ b/packages/superdoc/src/stores/comments-store.js @@ -423,6 +423,7 @@ export const useCommentsStore = defineStore('comments', () => { }; if (__IS_DEBUG__) console.debug('[deleteComment] emitting...', event); + superdoc.emit('comments-update', event); syncCommentsToClients(superdoc, event); } @@ -449,6 +450,8 @@ export const useCommentsStore = defineStore('comments', () => { const processLoadedDocxComments = ({ superdoc, comments, documentId }) => { const document = superdocStore.getDocument(documentId); + if (__IS_DEBUG__) console.debug('[processLoadedDocxComments] processing comments...', comments); + comments.forEach((comment) => { const importedName = `${comment.creatorName.replace('(imported)', '')} (imported)` const newComment = useComment({