forked from github/plane
fix: incomplete cycle issues auth (#4299)
This commit is contained in:
parent
6ac3cb9b31
commit
0e3d5cc4eb
@ -416,7 +416,7 @@ export const CycleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
to: "End date",
|
to: "End date",
|
||||||
}}
|
}}
|
||||||
required={cycleDetails.status !== "draft"}
|
required={cycleDetails.status !== "draft"}
|
||||||
disabled={isArchived}
|
disabled={!isEditingAllowed || isArchived}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { PlusIcon } from "lucide-react";
|
import { PlusIcon } from "lucide-react";
|
||||||
// hooks
|
|
||||||
import { EmptyState } from "@/components/common";
|
|
||||||
import { EIssuesStoreType } from "@/constants/issue";
|
|
||||||
import { useApplication, useEventTracker } from "@/hooks/store";
|
|
||||||
// components
|
// components
|
||||||
|
import { EmptyState } from "@/components/common";
|
||||||
|
// constants
|
||||||
|
import { EIssuesStoreType } from "@/constants/issue";
|
||||||
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
|
// hooks
|
||||||
|
import { useApplication, useEventTracker, useUser } from "@/hooks/store";
|
||||||
// assets
|
// assets
|
||||||
import emptyIssue from "public/empty-state/issue.svg";
|
import emptyIssue from "public/empty-state/issue.svg";
|
||||||
|
|
||||||
@ -12,6 +14,11 @@ export const ProjectViewEmptyState: React.FC = observer(() => {
|
|||||||
// store hooks
|
// store hooks
|
||||||
const { commandPalette: commandPaletteStore } = useApplication();
|
const { commandPalette: commandPaletteStore } = useApplication();
|
||||||
const { setTrackElement } = useEventTracker();
|
const { setTrackElement } = useEventTracker();
|
||||||
|
const {
|
||||||
|
membership: { currentProjectRole },
|
||||||
|
} = useUser();
|
||||||
|
// auth
|
||||||
|
const isCreatingIssueAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid h-full w-full place-items-center">
|
<div className="grid h-full w-full place-items-center">
|
||||||
@ -19,14 +26,18 @@ export const ProjectViewEmptyState: React.FC = observer(() => {
|
|||||||
title="View issues will appear here"
|
title="View issues will appear here"
|
||||||
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
|
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
|
||||||
image={emptyIssue}
|
image={emptyIssue}
|
||||||
primaryButton={{
|
primaryButton={
|
||||||
text: "New issue",
|
isCreatingIssueAllowed
|
||||||
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
|
? {
|
||||||
onClick: () => {
|
text: "New issue",
|
||||||
setTrackElement("View issue empty state");
|
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
|
||||||
commandPaletteStore.toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW);
|
onClick: () => {
|
||||||
},
|
setTrackElement("View issue empty state");
|
||||||
}}
|
commandPaletteStore.toggleCreateIssueModal(true, EIssuesStoreType.PROJECT_VIEW);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// hooks
|
// components
|
||||||
import { CycleIssueQuickActions } from "@/components/issues";
|
import { CycleIssueQuickActions } from "@/components/issues";
|
||||||
|
// constants
|
||||||
import { EIssuesStoreType } from "@/constants/issue";
|
import { EIssuesStoreType } from "@/constants/issue";
|
||||||
import { useCycle, useIssues } from "@/hooks/store";
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
// ui
|
// hooks
|
||||||
// types
|
import { useCycle, useIssues, useUser } from "@/hooks/store";
|
||||||
// components
|
// components
|
||||||
import { BaseKanBanRoot } from "../base-kanban-root";
|
import { BaseKanBanRoot } from "../base-kanban-root";
|
||||||
|
|
||||||
@ -19,11 +20,18 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
|||||||
// store
|
// store
|
||||||
const { issues } = useIssues(EIssuesStoreType.CYCLE);
|
const { issues } = useIssues(EIssuesStoreType.CYCLE);
|
||||||
const { currentProjectCompletedCycleIds } = useCycle();
|
const { currentProjectCompletedCycleIds } = useCycle();
|
||||||
|
const {
|
||||||
|
membership: { currentProjectRole },
|
||||||
|
} = useUser();
|
||||||
|
|
||||||
const isCompletedCycle =
|
const isCompletedCycle =
|
||||||
cycleId && currentProjectCompletedCycleIds ? currentProjectCompletedCycleIds.includes(cycleId.toString()) : false;
|
cycleId && currentProjectCompletedCycleIds ? currentProjectCompletedCycleIds.includes(cycleId.toString()) : false;
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||||
|
|
||||||
const canEditIssueProperties = useCallback(() => !isCompletedCycle, [isCompletedCycle]);
|
const canEditIssueProperties = useCallback(
|
||||||
|
() => !isCompletedCycle && isEditingAllowed,
|
||||||
|
[isCompletedCycle, isEditingAllowed]
|
||||||
|
);
|
||||||
|
|
||||||
const addIssuesToView = useCallback(
|
const addIssuesToView = useCallback(
|
||||||
(issueIds: string[]) => {
|
(issueIds: string[]) => {
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// hooks
|
|
||||||
import { CycleIssueQuickActions } from "@/components/issues";
|
|
||||||
import { EIssuesStoreType } from "@/constants/issue";
|
|
||||||
import { useCycle, useIssues } from "@/hooks/store";
|
|
||||||
// components
|
// components
|
||||||
// types
|
import { CycleIssueQuickActions } from "@/components/issues";
|
||||||
// constants
|
// constants
|
||||||
|
import { EIssuesStoreType } from "@/constants/issue";
|
||||||
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
|
// hooks
|
||||||
|
import { useCycle, useIssues, useUser } from "@/hooks/store";
|
||||||
|
// types
|
||||||
import { BaseListRoot } from "../base-list-root";
|
import { BaseListRoot } from "../base-list-root";
|
||||||
|
|
||||||
export interface ICycleListLayout {}
|
export interface ICycleListLayout {}
|
||||||
@ -17,12 +18,19 @@ export const CycleListLayout: React.FC = observer(() => {
|
|||||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||||
// store
|
// store
|
||||||
const { issues } = useIssues(EIssuesStoreType.CYCLE);
|
const { issues } = useIssues(EIssuesStoreType.CYCLE);
|
||||||
const { currentProjectCompletedCycleIds } = useCycle();
|
const { currentProjectCompletedCycleIds } = useCycle(); // mobx store
|
||||||
|
const {
|
||||||
|
membership: { currentProjectRole },
|
||||||
|
} = useUser();
|
||||||
|
|
||||||
const isCompletedCycle =
|
const isCompletedCycle =
|
||||||
cycleId && currentProjectCompletedCycleIds ? currentProjectCompletedCycleIds.includes(cycleId.toString()) : false;
|
cycleId && currentProjectCompletedCycleIds ? currentProjectCompletedCycleIds.includes(cycleId.toString()) : false;
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||||
|
|
||||||
const canEditIssueProperties = useCallback(() => !isCompletedCycle, [isCompletedCycle]);
|
const canEditIssueProperties = useCallback(
|
||||||
|
() => !isCompletedCycle && isEditingAllowed,
|
||||||
|
[isCompletedCycle, isEditingAllowed]
|
||||||
|
);
|
||||||
|
|
||||||
const addIssuesToView = useCallback(
|
const addIssuesToView = useCallback(
|
||||||
(issueIds: string[]) => {
|
(issueIds: string[]) => {
|
||||||
|
@ -1,22 +1,33 @@
|
|||||||
import React, { useCallback } from "react";
|
import React, { useCallback } from "react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// mobx store
|
// constants
|
||||||
import { EIssuesStoreType } from "@/constants/issue";
|
import { EIssuesStoreType } from "@/constants/issue";
|
||||||
import { useCycle } from "@/hooks/store";
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
|
// hooks
|
||||||
|
import { useCycle, useUser } from "@/hooks/store";
|
||||||
// components
|
// components
|
||||||
import { CycleIssueQuickActions } from "../../quick-action-dropdowns";
|
import { CycleIssueQuickActions } from "../../quick-action-dropdowns";
|
||||||
import { BaseSpreadsheetRoot } from "../base-spreadsheet-root";
|
import { BaseSpreadsheetRoot } from "../base-spreadsheet-root";
|
||||||
|
|
||||||
export const CycleSpreadsheetLayout: React.FC = observer(() => {
|
export const CycleSpreadsheetLayout: React.FC = observer(() => {
|
||||||
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { cycleId } = router.query;
|
const { cycleId } = router.query;
|
||||||
|
// store hooks
|
||||||
const { currentProjectCompletedCycleIds } = useCycle();
|
const { currentProjectCompletedCycleIds } = useCycle();
|
||||||
|
const {
|
||||||
|
membership: { currentProjectRole },
|
||||||
|
} = useUser();
|
||||||
|
// auth
|
||||||
const isCompletedCycle =
|
const isCompletedCycle =
|
||||||
cycleId && currentProjectCompletedCycleIds ? currentProjectCompletedCycleIds.includes(cycleId.toString()) : false;
|
cycleId && currentProjectCompletedCycleIds ? currentProjectCompletedCycleIds.includes(cycleId.toString()) : false;
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||||
|
|
||||||
const canEditIssueProperties = useCallback(() => !isCompletedCycle, [isCompletedCycle]);
|
const canEditIssueProperties = useCallback(
|
||||||
|
() => !isCompletedCycle && isEditingAllowed,
|
||||||
|
[isCompletedCycle, isEditingAllowed]
|
||||||
|
);
|
||||||
|
|
||||||
if (!cycleId) return null;
|
if (!cycleId) return null;
|
||||||
|
|
||||||
|
@ -480,7 +480,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
from: "Start date",
|
from: "Start date",
|
||||||
to: "Target date",
|
to: "Target date",
|
||||||
}}
|
}}
|
||||||
disabled={isArchived}
|
disabled={!isEditingAllowed || isArchived}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
@ -510,7 +510,7 @@ export const ModuleDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
multiple={false}
|
multiple={false}
|
||||||
buttonVariant="background-with-text"
|
buttonVariant="background-with-text"
|
||||||
placeholder="Lead"
|
placeholder="Lead"
|
||||||
disabled={isArchived}
|
disabled={!isEditingAllowed || isArchived}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -4,10 +4,13 @@ import { ArchiveRestoreIcon, Clipboard, Copy, Link, Lock, LockOpen } from "lucid
|
|||||||
import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/document-editor";
|
import { EditorReadOnlyRefApi, EditorRefApi } from "@plane/document-editor";
|
||||||
// ui
|
// ui
|
||||||
import { ArchiveIcon, CustomMenu, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui";
|
import { ArchiveIcon, CustomMenu, TOAST_TYPE, ToggleSwitch, setToast } from "@plane/ui";
|
||||||
|
// constants
|
||||||
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
// helpers
|
// helpers
|
||||||
|
import { cn } from "@/helpers/common.helper";
|
||||||
import { copyTextToClipboard, copyUrlToClipboard } from "@/helpers/string.helper";
|
import { copyTextToClipboard, copyUrlToClipboard } from "@/helpers/string.helper";
|
||||||
// hooks
|
// hooks
|
||||||
import { useApplication } from "@/hooks/store";
|
import { useApplication, useUser } from "@/hooks/store";
|
||||||
// store
|
// store
|
||||||
import { IPageStore } from "@/store/pages/page.store";
|
import { IPageStore } from "@/store/pages/page.store";
|
||||||
|
|
||||||
@ -38,6 +41,11 @@ export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
|
|||||||
const {
|
const {
|
||||||
router: { workspaceSlug, projectId },
|
router: { workspaceSlug, projectId },
|
||||||
} = useApplication();
|
} = useApplication();
|
||||||
|
const {
|
||||||
|
membership: { currentProjectRole },
|
||||||
|
} = useUser();
|
||||||
|
// auth
|
||||||
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||||
|
|
||||||
const handleArchivePage = async () =>
|
const handleArchivePage = async () =>
|
||||||
await archive().catch(() =>
|
await archive().catch(() =>
|
||||||
@ -146,9 +154,17 @@ export const PageOptionsDropdown: React.FC<Props> = observer((props) => {
|
|||||||
full_width: !view_props?.full_width,
|
full_width: !view_props?.full_width,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
disabled={!isEditingAllowed}
|
||||||
>
|
>
|
||||||
Full width
|
Full width
|
||||||
<ToggleSwitch value={!!view_props?.full_width} onChange={() => {}} />
|
<ToggleSwitch
|
||||||
|
value={!!view_props?.full_width}
|
||||||
|
onChange={() => {}}
|
||||||
|
className={cn({
|
||||||
|
"opacity-40": !isEditingAllowed,
|
||||||
|
})}
|
||||||
|
disabled={!isEditingAllowed}
|
||||||
|
/>
|
||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
{MENU_ITEMS.map((item) => {
|
{MENU_ITEMS.map((item) => {
|
||||||
if (!item.shouldRender) return null;
|
if (!item.shouldRender) return null;
|
||||||
|
Loading…
Reference in New Issue
Block a user