feat(EE): resolve comments (#1420)

* feat: resolve comment (EE)

* Add resolve to comment mark in editor (EE)

* comment ui permissions

* sticky comment state tabs (EE)

* cleanup

* feat: add space_id to comments and allow space admins to delete any comment

- Add space_id column to comments table with data migration from pages
- Add last_edited_by_id, resolved_by_id, and updated_at columns to comments
- Update comment deletion permissions to allow space admins to delete any comment
- Backfill space_id on old comments

* fix foreign keys
This commit is contained in:
Philip Okugbe
2025-07-29 21:36:48 +01:00
committed by GitHub
parent ec12e80423
commit ca9558b246
23 changed files with 927 additions and 341 deletions

View File

@ -1,15 +1,28 @@
import { ActionIcon, Menu } from "@mantine/core";
import { IconDots, IconEdit, IconTrash } from "@tabler/icons-react";
import { ActionIcon, Menu, Tooltip } from "@mantine/core";
import { IconDots, IconEdit, IconTrash, IconCircleCheck, IconCircleCheckFilled } from "@tabler/icons-react";
import { modals } from "@mantine/modals";
import { useTranslation } from "react-i18next";
import { useIsCloudEE } from "@/hooks/use-is-cloud-ee";
type CommentMenuProps = {
onEditComment: () => void;
onDeleteComment: () => void;
onResolveComment?: () => void;
canEdit?: boolean;
isResolved?: boolean;
isParentComment?: boolean;
};
function CommentMenu({ onEditComment, onDeleteComment }: CommentMenuProps) {
function CommentMenu({
onEditComment,
onDeleteComment,
onResolveComment,
canEdit = true,
isResolved = false,
isParentComment = false
}: CommentMenuProps) {
const { t } = useTranslation();
const isCloudEE = useIsCloudEE();
//@ts-ignore
const openDeleteModal = () =>
@ -30,9 +43,34 @@ function CommentMenu({ onEditComment, onDeleteComment }: CommentMenuProps) {
</Menu.Target>
<Menu.Dropdown>
<Menu.Item onClick={onEditComment} leftSection={<IconEdit size={14} />}>
{t("Edit comment")}
</Menu.Item>
{canEdit && (
<Menu.Item onClick={onEditComment} leftSection={<IconEdit size={14} />}>
{t("Edit comment")}
</Menu.Item>
)}
{isParentComment && (
isCloudEE ? (
<Menu.Item
onClick={onResolveComment}
leftSection={
isResolved ?
<IconCircleCheckFilled size={14} /> :
<IconCircleCheck size={14} />
}
>
{isResolved ? t("Re-open comment") : t("Resolve comment")}
</Menu.Item>
) : (
<Tooltip label={t("Available in enterprise edition")} position="left">
<Menu.Item
disabled
leftSection={<IconCircleCheck size={14} />}
>
{t("Resolve comment")}
</Menu.Item>
</Tooltip>
)
)}
<Menu.Item
leftSection={<IconTrash size={14} />}
onClick={openDeleteModal}