mirror of
https://github.com/docmost/docmost.git
synced 2026-05-07 06:23:06 +08:00
ui permissions
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
import { useSpaceAbility } from "@/features/space/permissions/use-space-ability";
|
||||||
|
import {
|
||||||
|
SpaceCaslAction,
|
||||||
|
SpaceCaslSubject,
|
||||||
|
} from "@/features/space/permissions/permissions.type";
|
||||||
|
import { usePageRestrictionInfoQuery } from "@/ee/page-permission/queries/page-permission-query";
|
||||||
|
|
||||||
|
export function usePagePermission(pageId: string, spaceRules: any) {
|
||||||
|
const spaceAbility = useSpaceAbility(spaceRules);
|
||||||
|
const { data: restrictionInfo, isLoading } =
|
||||||
|
usePageRestrictionInfoQuery(pageId);
|
||||||
|
|
||||||
|
if (isLoading || !restrictionInfo) {
|
||||||
|
return { canEdit: false, restrictionInfo: undefined };
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasRestriction =
|
||||||
|
restrictionInfo.hasDirectRestriction ||
|
||||||
|
restrictionInfo.hasInheritedRestriction;
|
||||||
|
|
||||||
|
const canEdit = hasRestriction
|
||||||
|
? (restrictionInfo.userAccess?.canEdit ?? false)
|
||||||
|
: spaceAbility.can(SpaceCaslAction.Manage, SpaceCaslSubject.Page);
|
||||||
|
|
||||||
|
return { canEdit, restrictionInfo };
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ export * from "./components/publish-tab";
|
|||||||
export * from "./components/page-permission-list";
|
export * from "./components/page-permission-list";
|
||||||
export * from "./components/page-permission-item";
|
export * from "./components/page-permission-item";
|
||||||
export * from "./components/general-access-select";
|
export * from "./components/general-access-select";
|
||||||
|
export * from "./hooks/use-page-permission";
|
||||||
export * from "./queries/page-permission-query";
|
export * from "./queries/page-permission-query";
|
||||||
export * from "./services/page-permission-service";
|
export * from "./services/page-permission-service";
|
||||||
export * from "./types/page-permission.types";
|
export * from "./types/page-permission.types";
|
||||||
|
|||||||
@@ -17,11 +17,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useQueryEmit } from "@/features/websocket/use-query-emit";
|
import { useQueryEmit } from "@/features/websocket/use-query-emit";
|
||||||
import { useIsCloudEE } from "@/hooks/use-is-cloud-ee";
|
import { useIsCloudEE } from "@/hooks/use-is-cloud-ee";
|
||||||
import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts";
|
import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts";
|
||||||
import { useSpaceAbility } from "@/features/space/permissions/use-space-ability.ts";
|
import { usePagePermission } from "@/ee/page-permission";
|
||||||
import {
|
|
||||||
SpaceCaslAction,
|
|
||||||
SpaceCaslSubject,
|
|
||||||
} from "@/features/space/permissions/permissions.type.ts";
|
|
||||||
|
|
||||||
function CommentListWithTabs() {
|
function CommentListWithTabs() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -38,13 +34,9 @@ function CommentListWithTabs() {
|
|||||||
const isCloudEE = useIsCloudEE();
|
const isCloudEE = useIsCloudEE();
|
||||||
const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug);
|
const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug);
|
||||||
|
|
||||||
const spaceRules = space?.membership?.permissions;
|
const { canEdit: canComment } = usePagePermission(
|
||||||
const spaceAbility = useSpaceAbility(spaceRules);
|
page?.id,
|
||||||
|
space?.membership?.permissions,
|
||||||
|
|
||||||
const canComment: boolean = spaceAbility.can(
|
|
||||||
SpaceCaslAction.Manage,
|
|
||||||
SpaceCaslSubject.Page
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Separate active and resolved comments
|
// Separate active and resolved comments
|
||||||
@@ -54,14 +46,14 @@ function CommentListWithTabs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const parentComments = comments.items.filter(
|
const parentComments = comments.items.filter(
|
||||||
(comment: IComment) => comment.parentCommentId === null
|
(comment: IComment) => comment.parentCommentId === null,
|
||||||
);
|
);
|
||||||
|
|
||||||
const active = parentComments.filter(
|
const active = parentComments.filter(
|
||||||
(comment: IComment) => !comment.resolvedAt
|
(comment: IComment) => !comment.resolvedAt,
|
||||||
);
|
);
|
||||||
const resolved = parentComments.filter(
|
const resolved = parentComments.filter(
|
||||||
(comment: IComment) => comment.resolvedAt
|
(comment: IComment) => comment.resolvedAt,
|
||||||
);
|
);
|
||||||
|
|
||||||
return { activeComments: active, resolvedComments: resolved };
|
return { activeComments: active, resolvedComments: resolved };
|
||||||
@@ -89,7 +81,7 @@ function CommentListWithTabs() {
|
|||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[createCommentMutation, page?.id]
|
[createCommentMutation, page?.id],
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderComments = useCallback(
|
const renderComments = useCallback(
|
||||||
@@ -131,7 +123,7 @@ function CommentListWithTabs() {
|
|||||||
)}
|
)}
|
||||||
</Paper>
|
</Paper>
|
||||||
),
|
),
|
||||||
[comments, handleAddReply, isLoading, space?.membership?.role]
|
[comments, handleAddReply, isLoading, space?.membership?.role],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isCommentsLoading) {
|
if (isCommentsLoading) {
|
||||||
@@ -199,7 +191,14 @@ function CommentListWithTabs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ height: "85vh", display: "flex", flexDirection: "column", marginTop: '-15px' }}>
|
<div
|
||||||
|
style={{
|
||||||
|
height: "85vh",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
marginTop: "-15px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Tabs defaultValue="open" variant="default" style={{ flex: "0 0 auto" }}>
|
<Tabs defaultValue="open" variant="default" style={{ flex: "0 0 auto" }}>
|
||||||
<Tabs.List justify="center">
|
<Tabs.List justify="center">
|
||||||
<Tabs.Tab
|
<Tabs.Tab
|
||||||
@@ -273,9 +272,9 @@ const ChildComments = ({
|
|||||||
const getChildComments = useCallback(
|
const getChildComments = useCallback(
|
||||||
(parentId: string) =>
|
(parentId: string) =>
|
||||||
comments.items.filter(
|
comments.items.filter(
|
||||||
(comment: IComment) => comment.parentCommentId === parentId
|
(comment: IComment) => comment.parentCommentId === parentId,
|
||||||
),
|
),
|
||||||
[comments.items]
|
[comments.items],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -171,11 +171,14 @@ export function TitleEditor({
|
|||||||
}, [pageId]);
|
}, [pageId]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// honor user default page edit mode preference
|
if (titleEditor) {
|
||||||
if (userPageEditMode && titleEditor && editable) {
|
if (userPageEditMode && editable) {
|
||||||
if (userPageEditMode === PageEditMode.Edit) {
|
if (userPageEditMode === PageEditMode.Edit) {
|
||||||
titleEditor.setEditable(true);
|
titleEditor.setEditable(true);
|
||||||
} else if (userPageEditMode === PageEditMode.Read) {
|
} else if (userPageEditMode === PageEditMode.Read) {
|
||||||
|
titleEditor.setEditable(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
titleEditor.setEditable(false);
|
titleEditor.setEditable(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,9 @@ import { Helmet } from "react-helmet-async";
|
|||||||
import PageHeader from "@/features/page/components/header/page-header.tsx";
|
import PageHeader from "@/features/page/components/header/page-header.tsx";
|
||||||
import { extractPageSlugId } from "@/lib";
|
import { extractPageSlugId } from "@/lib";
|
||||||
import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts";
|
import { useGetSpaceBySlugQuery } from "@/features/space/queries/space-query.ts";
|
||||||
import { useSpaceAbility } from "@/features/space/permissions/use-space-ability.ts";
|
|
||||||
import {
|
|
||||||
SpaceCaslAction,
|
|
||||||
SpaceCaslSubject,
|
|
||||||
} from "@/features/space/permissions/permissions.type.ts";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { usePagePermission } from "@/ee/page-permission";
|
||||||
|
|
||||||
const MemoizedFullEditor = React.memo(FullEditor);
|
const MemoizedFullEditor = React.memo(FullEditor);
|
||||||
const MemoizedPageHeader = React.memo(PageHeader);
|
const MemoizedPageHeader = React.memo(PageHeader);
|
||||||
@@ -30,8 +26,7 @@ export default function Page() {
|
|||||||
} = usePageQuery({ pageId: extractPageSlugId(pageSlug) });
|
} = usePageQuery({ pageId: extractPageSlugId(pageSlug) });
|
||||||
const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug);
|
const { data: space } = useGetSpaceBySlugQuery(page?.space?.slug);
|
||||||
|
|
||||||
const spaceRules = space?.membership?.permissions;
|
const { canEdit } = usePagePermission(page?.id, space?.membership?.permissions);
|
||||||
const spaceAbility = useSpaceAbility(spaceRules);
|
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return <></>;
|
return <></>;
|
||||||
@@ -55,12 +50,7 @@ export default function Page() {
|
|||||||
<title>{`${page?.icon || ""} ${page?.title || t("untitled")}`}</title>
|
<title>{`${page?.icon || ""} ${page?.title || t("untitled")}`}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<MemoizedPageHeader
|
<MemoizedPageHeader readOnly={!canEdit} />
|
||||||
readOnly={spaceAbility.cannot(
|
|
||||||
SpaceCaslAction.Manage,
|
|
||||||
SpaceCaslSubject.Page,
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<MemoizedFullEditor
|
<MemoizedFullEditor
|
||||||
key={page.id}
|
key={page.id}
|
||||||
@@ -69,10 +59,7 @@ export default function Page() {
|
|||||||
content={page.content}
|
content={page.content}
|
||||||
slugId={page.slugId}
|
slugId={page.slugId}
|
||||||
spaceSlug={page?.space?.slug}
|
spaceSlug={page?.space?.slug}
|
||||||
editable={spaceAbility.can(
|
editable={canEdit}
|
||||||
SpaceCaslAction.Manage,
|
|
||||||
SpaceCaslSubject.Page,
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
<MemoizedHistoryModal pageId={page.id} />
|
<MemoizedHistoryModal pageId={page.id} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user