mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: user permission related fix (#3066)
* chore: page action user permission validation * chore: cycle & module action user permission validation * chore: issue quick action user permission validation * chore: spreadsheet layout improvement
This commit is contained in:
parent
73b58e91ee
commit
f38278f465
@ -23,6 +23,7 @@ import { ICycle } from "types";
|
|||||||
import { useMobxStore } from "lib/mobx/store-provider";
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// constants
|
// constants
|
||||||
import { CYCLE_STATUS } from "constants/cycle";
|
import { CYCLE_STATUS } from "constants/cycle";
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
export interface ICyclesBoardCard {
|
export interface ICyclesBoardCard {
|
||||||
workspaceSlug: string;
|
workspaceSlug: string;
|
||||||
@ -36,6 +37,7 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
|||||||
const {
|
const {
|
||||||
cycle: cycleStore,
|
cycle: cycleStore,
|
||||||
trackEvent: { setTrackElement },
|
trackEvent: { setTrackElement },
|
||||||
|
user: userStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
// toast
|
// toast
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
@ -49,6 +51,9 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
|||||||
const startDate = new Date(cycle.start_date ?? "");
|
const startDate = new Date(cycle.start_date ?? "");
|
||||||
const isDateValid = cycle.start_date || cycle.end_date;
|
const isDateValid = cycle.start_date || cycle.end_date;
|
||||||
|
|
||||||
|
const { currentProjectRole } = userStore;
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const currentCycle = CYCLE_STATUS.find((status) => status.value === cycleStatus);
|
const currentCycle = CYCLE_STATUS.find((status) => status.value === cycleStatus);
|
||||||
@ -68,8 +73,8 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
|||||||
? cycleTotalIssues === 0
|
? cycleTotalIssues === 0
|
||||||
? "0 Issue"
|
? "0 Issue"
|
||||||
: cycleTotalIssues === cycle.completed_issues
|
: cycleTotalIssues === cycle.completed_issues
|
||||||
? `${cycleTotalIssues} Issue${cycleTotalIssues > 1 ? "s" : ""}`
|
? `${cycleTotalIssues} Issue${cycleTotalIssues > 1 ? "s" : ""}`
|
||||||
: `${cycle.completed_issues}/${cycleTotalIssues} Issues`
|
: `${cycle.completed_issues}/${cycleTotalIssues} Issues`
|
||||||
: "0 Issue";
|
: "0 Issue";
|
||||||
|
|
||||||
const handleCopyText = (e: MouseEvent<HTMLButtonElement>) => {
|
const handleCopyText = (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
@ -235,17 +240,18 @@ export const CyclesBoardCard: FC<ICyclesBoardCard> = (props) => {
|
|||||||
<span className="text-xs text-custom-text-400">No due date</span>
|
<span className="text-xs text-custom-text-400">No due date</span>
|
||||||
)}
|
)}
|
||||||
<div className="z-10 flex items-center gap-1.5">
|
<div className="z-10 flex items-center gap-1.5">
|
||||||
{cycle.is_favorite ? (
|
{isEditingAllowed &&
|
||||||
<button type="button" onClick={handleRemoveFromFavorites}>
|
(cycle.is_favorite ? (
|
||||||
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
<button type="button" onClick={handleRemoveFromFavorites}>
|
||||||
</button>
|
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
||||||
) : (
|
</button>
|
||||||
<button type="button" onClick={handleAddToFavorites}>
|
) : (
|
||||||
<Star className="h-3.5 w-3.5 text-custom-text-200" />
|
<button type="button" onClick={handleAddToFavorites}>
|
||||||
</button>
|
<Star className="h-3.5 w-3.5 text-custom-text-200" />
|
||||||
)}
|
</button>
|
||||||
|
))}
|
||||||
<CustomMenu width="auto" ellipsis className="z-10">
|
<CustomMenu width="auto" ellipsis className="z-10">
|
||||||
{!isCompleted && (
|
{!isCompleted && isEditingAllowed && (
|
||||||
<>
|
<>
|
||||||
<CustomMenu.MenuItem onClick={handleEditCycle}>
|
<CustomMenu.MenuItem onClick={handleEditCycle}>
|
||||||
<span className="flex items-center justify-start gap-2">
|
<span className="flex items-center justify-start gap-2">
|
||||||
|
@ -24,6 +24,7 @@ import { copyTextToClipboard } from "helpers/string.helper";
|
|||||||
import { ICycle } from "types";
|
import { ICycle } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { CYCLE_STATUS } from "constants/cycle";
|
import { CYCLE_STATUS } from "constants/cycle";
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
type TCyclesListItem = {
|
type TCyclesListItem = {
|
||||||
cycle: ICycle;
|
cycle: ICycle;
|
||||||
@ -41,6 +42,7 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
|
|||||||
const {
|
const {
|
||||||
cycle: cycleStore,
|
cycle: cycleStore,
|
||||||
trackEvent: { setTrackElement },
|
trackEvent: { setTrackElement },
|
||||||
|
user: userStore,
|
||||||
} = useMobxStore();
|
} = useMobxStore();
|
||||||
// toast
|
// toast
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
@ -53,6 +55,9 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
|
|||||||
const endDate = new Date(cycle.end_date ?? "");
|
const endDate = new Date(cycle.end_date ?? "");
|
||||||
const startDate = new Date(cycle.start_date ?? "");
|
const startDate = new Date(cycle.start_date ?? "");
|
||||||
|
|
||||||
|
const { currentProjectRole } = userStore;
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const cycleTotalIssues =
|
const cycleTotalIssues =
|
||||||
@ -226,19 +231,19 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
{isEditingAllowed &&
|
||||||
{cycle.is_favorite ? (
|
(cycle.is_favorite ? (
|
||||||
<button type="button" onClick={handleRemoveFromFavorites}>
|
<button type="button" onClick={handleRemoveFromFavorites}>
|
||||||
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button type="button" onClick={handleAddToFavorites}>
|
<button type="button" onClick={handleAddToFavorites}>
|
||||||
<Star className="h-3.5 w-3.5 text-custom-text-200" />
|
<Star className="h-3.5 w-3.5 text-custom-text-200" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
))}
|
||||||
|
|
||||||
<CustomMenu width="auto" ellipsis>
|
<CustomMenu width="auto" ellipsis>
|
||||||
{!isCompleted && (
|
{!isCompleted && isEditingAllowed && (
|
||||||
<>
|
<>
|
||||||
<CustomMenu.MenuItem onClick={handleEditCycle}>
|
<CustomMenu.MenuItem onClick={handleEditCycle}>
|
||||||
<span className="flex items-center justify-start gap-2">
|
<span className="flex items-center justify-start gap-2">
|
||||||
|
@ -94,7 +94,7 @@ export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props
|
|||||||
|
|
||||||
const label = (
|
const label = (
|
||||||
<Tooltip tooltipHeading="State" tooltipContent={selectedOption?.name ?? ""} position="top">
|
<Tooltip tooltipHeading="State" tooltipContent={selectedOption?.name ?? ""} position="top">
|
||||||
<div className="flex w-full cursor-pointer items-center gap-2 text-custom-text-200">
|
<div className="flex w-full items-center gap-2 text-custom-text-200">
|
||||||
{selectedOption && <StateGroupIcon stateGroup={selectedOption?.group as any} color={selectedOption?.color} />}
|
{selectedOption && <StateGroupIcon stateGroup={selectedOption?.group as any} color={selectedOption?.color} />}
|
||||||
<span className="line-clamp-1 inline-block truncate">{selectedOption?.name ?? "State"}</span>
|
<span className="line-clamp-1 inline-block truncate">{selectedOption?.name ?? "State"}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,8 @@ import { useState } from "react";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { CustomMenu } from "@plane/ui";
|
import { CustomMenu } from "@plane/ui";
|
||||||
import { Copy, Link, Pencil, Trash2 } from "lucide-react";
|
import { Copy, Link, Pencil, Trash2 } from "lucide-react";
|
||||||
|
// mobx store
|
||||||
|
import { useMobxStore } from "lib/mobx/store-provider";
|
||||||
// hooks
|
// hooks
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// components
|
// components
|
||||||
@ -12,6 +14,8 @@ import { copyUrlToClipboard } from "helpers/string.helper";
|
|||||||
import { IIssue } from "types";
|
import { IIssue } from "types";
|
||||||
import { IQuickActionProps } from "../list/list-view-types";
|
import { IQuickActionProps } from "../list/list-view-types";
|
||||||
import { EProjectStore } from "store/command-palette.store";
|
import { EProjectStore } from "store/command-palette.store";
|
||||||
|
// constant
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) => {
|
export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) => {
|
||||||
const { issue, handleDelete, handleUpdate, customActionButton } = props;
|
const { issue, handleDelete, handleUpdate, customActionButton } = props;
|
||||||
@ -24,6 +28,12 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) =>
|
|||||||
const [issueToEdit, setIssueToEdit] = useState<IIssue | null>(null);
|
const [issueToEdit, setIssueToEdit] = useState<IIssue | null>(null);
|
||||||
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
|
||||||
|
|
||||||
|
const { user: userStore } = useMobxStore();
|
||||||
|
|
||||||
|
const { currentProjectRole } = userStore;
|
||||||
|
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const handleCopyIssueLink = () => {
|
const handleCopyIssueLink = () => {
|
||||||
@ -71,43 +81,47 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = (props) =>
|
|||||||
Copy link
|
Copy link
|
||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
<CustomMenu.MenuItem
|
{isEditingAllowed && (
|
||||||
onClick={(e) => {
|
<>
|
||||||
e.preventDefault();
|
<CustomMenu.MenuItem
|
||||||
e.stopPropagation();
|
onClick={(e) => {
|
||||||
setIssueToEdit(issue);
|
e.preventDefault();
|
||||||
setCreateUpdateIssueModal(true);
|
e.stopPropagation();
|
||||||
}}
|
setIssueToEdit(issue);
|
||||||
>
|
setCreateUpdateIssueModal(true);
|
||||||
<div className="flex items-center gap-2">
|
}}
|
||||||
<Pencil className="h-3 w-3" />
|
>
|
||||||
Edit issue
|
<div className="flex items-center gap-2">
|
||||||
</div>
|
<Pencil className="h-3 w-3" />
|
||||||
</CustomMenu.MenuItem>
|
Edit issue
|
||||||
<CustomMenu.MenuItem
|
</div>
|
||||||
onClick={(e) => {
|
</CustomMenu.MenuItem>
|
||||||
e.preventDefault();
|
<CustomMenu.MenuItem
|
||||||
e.stopPropagation();
|
onClick={(e) => {
|
||||||
setCreateUpdateIssueModal(true);
|
e.preventDefault();
|
||||||
}}
|
e.stopPropagation();
|
||||||
>
|
setCreateUpdateIssueModal(true);
|
||||||
<div className="flex items-center gap-2">
|
}}
|
||||||
<Copy className="h-3 w-3" />
|
>
|
||||||
Make a copy
|
<div className="flex items-center gap-2">
|
||||||
</div>
|
<Copy className="h-3 w-3" />
|
||||||
</CustomMenu.MenuItem>
|
Make a copy
|
||||||
<CustomMenu.MenuItem
|
</div>
|
||||||
onClick={(e) => {
|
</CustomMenu.MenuItem>
|
||||||
e.preventDefault();
|
<CustomMenu.MenuItem
|
||||||
e.stopPropagation();
|
onClick={(e) => {
|
||||||
setDeleteIssueModal(true);
|
e.preventDefault();
|
||||||
}}
|
e.stopPropagation();
|
||||||
>
|
setDeleteIssueModal(true);
|
||||||
<div className="flex items-center gap-2">
|
}}
|
||||||
<Trash2 className="h-3 w-3" />
|
>
|
||||||
Delete issue
|
<div className="flex items-center gap-2">
|
||||||
</div>
|
<Trash2 className="h-3 w-3" />
|
||||||
</CustomMenu.MenuItem>
|
Delete issue
|
||||||
|
</div>
|
||||||
|
</CustomMenu.MenuItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</CustomMenu>
|
</CustomMenu>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -19,6 +19,7 @@ import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper"
|
|||||||
import { IModule } from "types";
|
import { IModule } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { MODULE_STATUS } from "constants/module";
|
import { MODULE_STATUS } from "constants/module";
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
module: IModule;
|
module: IModule;
|
||||||
@ -35,7 +36,11 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const { module: moduleStore } = useMobxStore();
|
const { module: moduleStore, user: userStore } = useMobxStore();
|
||||||
|
|
||||||
|
const { currentProjectRole } = userStore;
|
||||||
|
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
const moduleTotalIssues =
|
const moduleTotalIssues =
|
||||||
module.backlog_issues +
|
module.backlog_issues +
|
||||||
@ -59,8 +64,8 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
|
|||||||
? !moduleTotalIssues || moduleTotalIssues === 0
|
? !moduleTotalIssues || moduleTotalIssues === 0
|
||||||
? "0 Issue"
|
? "0 Issue"
|
||||||
: moduleTotalIssues === module.completed_issues
|
: moduleTotalIssues === module.completed_issues
|
||||||
? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}`
|
? `${moduleTotalIssues} Issue${moduleTotalIssues > 1 ? "s" : ""}`
|
||||||
: `${module.completed_issues}/${moduleTotalIssues} Issues`
|
: `${module.completed_issues}/${moduleTotalIssues} Issues`
|
||||||
: "0 Issue";
|
: "0 Issue";
|
||||||
|
|
||||||
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
|
const handleAddToFavorites = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
@ -217,28 +222,34 @@ export const ModuleCardItem: React.FC<Props> = observer((props) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="z-10 flex items-center gap-1.5">
|
<div className="z-10 flex items-center gap-1.5">
|
||||||
{module.is_favorite ? (
|
{isEditingAllowed &&
|
||||||
<button type="button" onClick={handleRemoveFromFavorites}>
|
(module.is_favorite ? (
|
||||||
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
<button type="button" onClick={handleRemoveFromFavorites}>
|
||||||
</button>
|
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
||||||
) : (
|
</button>
|
||||||
<button type="button" onClick={handleAddToFavorites}>
|
) : (
|
||||||
<Star className="h-3.5 w-3.5 text-custom-text-200" />
|
<button type="button" onClick={handleAddToFavorites}>
|
||||||
</button>
|
<Star className="h-3.5 w-3.5 text-custom-text-200" />
|
||||||
)}
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
<CustomMenu width="auto" ellipsis className="z-10">
|
<CustomMenu width="auto" ellipsis className="z-10">
|
||||||
<CustomMenu.MenuItem onClick={handleEditModule}>
|
{isEditingAllowed && (
|
||||||
<span className="flex items-center justify-start gap-2">
|
<>
|
||||||
<Pencil className="h-3 w-3" />
|
<CustomMenu.MenuItem onClick={handleEditModule}>
|
||||||
<span>Edit module</span>
|
<span className="flex items-center justify-start gap-2">
|
||||||
</span>
|
<Pencil className="h-3 w-3" />
|
||||||
</CustomMenu.MenuItem>
|
<span>Edit module</span>
|
||||||
<CustomMenu.MenuItem onClick={handleDeleteModule}>
|
</span>
|
||||||
<span className="flex items-center justify-start gap-2">
|
</CustomMenu.MenuItem>
|
||||||
<Trash2 className="h-3 w-3" />
|
<CustomMenu.MenuItem onClick={handleDeleteModule}>
|
||||||
<span>Delete module</span>
|
<span className="flex items-center justify-start gap-2">
|
||||||
</span>
|
<Trash2 className="h-3 w-3" />
|
||||||
</CustomMenu.MenuItem>
|
<span>Delete module</span>
|
||||||
|
</span>
|
||||||
|
</CustomMenu.MenuItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<CustomMenu.MenuItem onClick={handleCopyText}>
|
<CustomMenu.MenuItem onClick={handleCopyText}>
|
||||||
<span className="flex items-center justify-start gap-2">
|
<span className="flex items-center justify-start gap-2">
|
||||||
<LinkIcon className="h-3 w-3" />
|
<LinkIcon className="h-3 w-3" />
|
||||||
|
@ -19,6 +19,7 @@ import { renderShortDate, renderShortMonthDate } from "helpers/date-time.helper"
|
|||||||
import { IModule } from "types";
|
import { IModule } from "types";
|
||||||
// constants
|
// constants
|
||||||
import { MODULE_STATUS } from "constants/module";
|
import { MODULE_STATUS } from "constants/module";
|
||||||
|
import { EUserWorkspaceRoles } from "constants/workspace";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
module: IModule;
|
module: IModule;
|
||||||
@ -35,7 +36,11 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
|
|||||||
|
|
||||||
const { setToastAlert } = useToast();
|
const { setToastAlert } = useToast();
|
||||||
|
|
||||||
const { module: moduleStore } = useMobxStore();
|
const { module: moduleStore, user: userStore } = useMobxStore();
|
||||||
|
|
||||||
|
const { currentProjectRole } = userStore;
|
||||||
|
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
const completionPercentage = ((module.completed_issues + module.cancelled_issues) / module.total_issues) * 100;
|
const completionPercentage = ((module.completed_issues + module.cancelled_issues) / module.total_issues) * 100;
|
||||||
|
|
||||||
@ -194,29 +199,34 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
{module.is_favorite ? (
|
{isEditingAllowed &&
|
||||||
<button type="button" onClick={handleRemoveFromFavorites} className="z-[1]">
|
(module.is_favorite ? (
|
||||||
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
<button type="button" onClick={handleRemoveFromFavorites} className="z-[1]">
|
||||||
</button>
|
<Star className="h-3.5 w-3.5 fill-current text-amber-500" />
|
||||||
) : (
|
</button>
|
||||||
<button type="button" onClick={handleAddToFavorites} className="z-[1]">
|
) : (
|
||||||
<Star className="h-3.5 w-3.5 text-custom-text-300" />
|
<button type="button" onClick={handleAddToFavorites} className="z-[1]">
|
||||||
</button>
|
<Star className="h-3.5 w-3.5 text-custom-text-300" />
|
||||||
)}
|
</button>
|
||||||
|
))}
|
||||||
|
|
||||||
<CustomMenu width="auto" verticalEllipsis buttonClassName="z-[1]">
|
<CustomMenu width="auto" verticalEllipsis buttonClassName="z-[1]">
|
||||||
<CustomMenu.MenuItem onClick={handleEditModule}>
|
{isEditingAllowed && (
|
||||||
<span className="flex items-center justify-start gap-2">
|
<>
|
||||||
<Pencil className="h-3 w-3" />
|
<CustomMenu.MenuItem onClick={handleEditModule}>
|
||||||
<span>Edit module</span>
|
<span className="flex items-center justify-start gap-2">
|
||||||
</span>
|
<Pencil className="h-3 w-3" />
|
||||||
</CustomMenu.MenuItem>
|
<span>Edit module</span>
|
||||||
<CustomMenu.MenuItem onClick={handleDeleteModule}>
|
</span>
|
||||||
<span className="flex items-center justify-start gap-2">
|
</CustomMenu.MenuItem>
|
||||||
<Trash2 className="h-3 w-3" />
|
<CustomMenu.MenuItem onClick={handleDeleteModule}>
|
||||||
<span>Delete module</span>
|
<span className="flex items-center justify-start gap-2">
|
||||||
</span>
|
<Trash2 className="h-3 w-3" />
|
||||||
</CustomMenu.MenuItem>
|
<span>Delete module</span>
|
||||||
|
</span>
|
||||||
|
</CustomMenu.MenuItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<CustomMenu.MenuItem onClick={handleCopyText}>
|
<CustomMenu.MenuItem onClick={handleCopyText}>
|
||||||
<span className="flex items-center justify-start gap-2">
|
<span className="flex items-center justify-start gap-2">
|
||||||
<LinkIcon className="h-3 w-3" />
|
<LinkIcon className="h-3 w-3" />
|
||||||
|
@ -154,6 +154,7 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
|
|||||||
const userCanChangeAccess = isCurrentUserOwner;
|
const userCanChangeAccess = isCurrentUserOwner;
|
||||||
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
const userCanArchive = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||||
const userCanDelete = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
const userCanDelete = isCurrentUserOwner || currentProjectRole === EUserWorkspaceRoles.ADMIN;
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -208,17 +209,19 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
|
|||||||
<p className="text-sm text-custom-text-200">{render24HourFormatTime(page.updated_at)}</p>
|
<p className="text-sm text-custom-text-200">{render24HourFormatTime(page.updated_at)}</p>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<Tooltip tooltipContent={`${page.is_favorite ? "Remove from favorites" : "Mark as favorite"}`}>
|
{isEditingAllowed && (
|
||||||
{page.is_favorite ? (
|
<Tooltip tooltipContent={`${page.is_favorite ? "Remove from favorites" : "Mark as favorite"}`}>
|
||||||
<button type="button" onClick={handleRemoveFromFavorites}>
|
{page.is_favorite ? (
|
||||||
<Star className="h-3.5 w-3.5 fill-orange-400 text-orange-400" />
|
<button type="button" onClick={handleRemoveFromFavorites}>
|
||||||
</button>
|
<Star className="h-3.5 w-3.5 fill-orange-400 text-orange-400" />
|
||||||
) : (
|
</button>
|
||||||
<button type="button" onClick={handleAddToFavorites}>
|
) : (
|
||||||
<Star className="h-3.5 w-3.5" />
|
<button type="button" onClick={handleAddToFavorites}>
|
||||||
</button>
|
<Star className="h-3.5 w-3.5" />
|
||||||
)}
|
</button>
|
||||||
</Tooltip>
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
{userCanChangeAccess && (
|
{userCanChangeAccess && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
tooltipContent={`${
|
tooltipContent={`${
|
||||||
@ -255,7 +258,7 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
)}
|
)}
|
||||||
{userCanDelete && (
|
{userCanDelete && isEditingAllowed && (
|
||||||
<CustomMenu.MenuItem onClick={handleDeletePage}>
|
<CustomMenu.MenuItem onClick={handleDeletePage}>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Trash2 className="h-3 w-3" />
|
<Trash2 className="h-3 w-3" />
|
||||||
@ -266,7 +269,7 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
|
|||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{userCanEdit && (
|
{userCanEdit && isEditingAllowed && (
|
||||||
<CustomMenu.MenuItem onClick={handleEditPage}>
|
<CustomMenu.MenuItem onClick={handleEditPage}>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Pencil className="h-3 w-3" />
|
<Pencil className="h-3 w-3" />
|
||||||
@ -274,7 +277,7 @@ export const PagesListItem: FC<IPagesListItem> = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
)}
|
)}
|
||||||
{userCanArchive && (
|
{userCanArchive && isEditingAllowed && (
|
||||||
<CustomMenu.MenuItem onClick={handleArchivePage}>
|
<CustomMenu.MenuItem onClick={handleArchivePage}>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Archive className="h-3 w-3" />
|
<Archive className="h-3 w-3" />
|
||||||
|
Loading…
Reference in New Issue
Block a user