diff --git a/web/components/issues/issue-layouts/empty-states/project.tsx b/web/components/issues/issue-layouts/empty-states/project.tsx
index 458f02c53..27c11dbbf 100644
--- a/web/components/issues/issue-layouts/empty-states/project.tsx
+++ b/web/components/issues/issue-layouts/empty-states/project.tsx
@@ -4,6 +4,8 @@ import { PlusIcon } from "lucide-react";
import { useMobxStore } from "lib/mobx/store-provider";
// components
import { NewEmptyState } from "components/common/new-empty-state";
+// constants
+import { EUserWorkspaceRoles } from "constants/workspace";
// assets
import emptyIssue from "public/empty-state/empty_issues.webp";
import { EProjectStore } from "store/command-palette.store";
@@ -12,8 +14,11 @@ export const ProjectEmptyState: React.FC = observer(() => {
const {
commandPalette: commandPaletteStore,
trackEvent: { setTrackElement },
+ user: { currentProjectRole },
} = useMobxStore();
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
return (
{
commandPaletteStore.toggleCreateIssueModal(true, EProjectStore.PROJECT);
},
}}
+ disabled={!isEditingAllowed}
/>
);
diff --git a/web/components/modules/modules-list-view.tsx b/web/components/modules/modules-list-view.tsx
index 3e4f42ccd..9b8c51236 100644
--- a/web/components/modules/modules-list-view.tsx
+++ b/web/components/modules/modules-list-view.tsx
@@ -9,6 +9,8 @@ import useLocalStorage from "hooks/use-local-storage";
import { ModuleCardItem, ModuleListItem, ModulePeekOverview, ModulesListGanttChartView } from "components/modules";
// ui
import { Loader } from "@plane/ui";
+// constants
+import { EUserWorkspaceRoles } from "constants/workspace";
// assets
import emptyModule from "public/empty-state/empty_modules.webp";
import { NewEmptyState } from "components/common/new-empty-state";
@@ -17,12 +19,18 @@ export const ModulesListView: React.FC = observer(() => {
const router = useRouter();
const { workspaceSlug, projectId, peekModule } = router.query;
- const { module: moduleStore, commandPalette: commandPaletteStore } = useMobxStore();
+ const {
+ module: moduleStore,
+ commandPalette: commandPaletteStore,
+ user: { currentProjectRole },
+ } = useMobxStore();
const { storedValue: modulesView } = useLocalStorage("modules_view", "grid");
const modulesList = moduleStore.projectModules;
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
if (!modulesList)
return (
@@ -93,6 +101,7 @@ export const ModulesListView: React.FC = observer(() => {
text: "Build your first module",
onClick: () => commandPaletteStore.toggleCreateModuleModal(true),
}}
+ disabled={!isEditingAllowed}
/>
)}
>
diff --git a/web/components/page-views/workspace-dashboard.tsx b/web/components/page-views/workspace-dashboard.tsx
index c276e6278..2f300c990 100644
--- a/web/components/page-views/workspace-dashboard.tsx
+++ b/web/components/page-views/workspace-dashboard.tsx
@@ -8,6 +8,8 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { TourRoot } from "components/onboarding";
import { UserGreetingsView } from "components/user";
import { CompletedIssuesGraph, IssuesList, IssuesPieChart, IssuesStats } from "components/workspace";
+// constants
+import { EUserWorkspaceRoles } from "constants/workspace";
// images
import { NewEmptyState } from "components/common/new-empty-state";
import emptyProject from "public/empty-state/dashboard_empty_project.webp";
@@ -36,6 +38,8 @@ export const WorkspaceDashboardView = observer(() => {
workspaceSlug ? () => userStore.fetchUserDashboardInfo(workspaceSlug.toString(), month) : null
);
+ const isEditingAllowed = !!userStore.currentProjectRole && userStore.currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
const handleTourCompleted = () => {
userStore
.updateTourCompleted()
@@ -96,6 +100,7 @@ export const WorkspaceDashboardView = observer(() => {
commandPaletteStore.toggleCreateProjectModal(true);
},
}}
+ disabled={!isEditingAllowed}
/>
)
) : null}
diff --git a/web/components/pages/pages-list/list-view.tsx b/web/components/pages/pages-list/list-view.tsx
index 769bed1bd..9f94a6671 100644
--- a/web/components/pages/pages-list/list-view.tsx
+++ b/web/components/pages/pages-list/list-view.tsx
@@ -30,18 +30,7 @@ export const PagesListView: FC = observer(({ pages }) => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
- const canUserCreatePage =
- currentProjectRole && [EUserWorkspaceRoles.ADMIN, EUserWorkspaceRoles.MEMBER].includes(currentProjectRole);
-
- const emptyStatePrimaryButton = canUserCreatePage
- ? {
- primaryButton: {
- icon: ,
- text: "Create your first page",
- onClick: () => toggleCreatePageModal(true),
- },
- }
- : {};
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
return (
<>
@@ -69,7 +58,12 @@ export const PagesListView: FC = observer(({ pages }) => {
"We wrote Parth and Meera’s love story. You could write your project’s mission, goals, and eventual vision.",
direction: "right",
}}
- {...emptyStatePrimaryButton}
+ primaryButton={{
+ icon: ,
+ text: "Create your first page",
+ onClick: () => toggleCreatePageModal(true),
+ }}
+ disabled={!isEditingAllowed}
/>
)}
diff --git a/web/components/pages/pages-list/recent-pages-list.tsx b/web/components/pages/pages-list/recent-pages-list.tsx
index 68d3056ff..21fb8277f 100644
--- a/web/components/pages/pages-list/recent-pages-list.tsx
+++ b/web/components/pages/pages-list/recent-pages-list.tsx
@@ -12,16 +12,21 @@ import { Loader } from "@plane/ui";
import emptyPage from "public/empty-state/empty_page.png";
// helpers
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
+// constants
+import { EUserWorkspaceRoles } from "constants/workspace";
export const RecentPagesList: FC = observer(() => {
// store
const {
commandPalette: commandPaletteStore,
page: { recentProjectPages },
+ user: { currentProjectRole },
} = useMobxStore();
const isEmpty = recentProjectPages && Object.values(recentProjectPages).every((value) => value.length === 0);
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
if (!recentProjectPages) {
return (
@@ -66,6 +71,7 @@ export const RecentPagesList: FC = observer(() => {
text: "Create your first page",
onClick: () => commandPaletteStore.toggleCreatePageModal(true),
}}
+ disabled={!isEditingAllowed}
/>
>
)}
diff --git a/web/components/project/card-list.tsx b/web/components/project/card-list.tsx
index 6b3e1ebab..979ade4ec 100644
--- a/web/components/project/card-list.tsx
+++ b/web/components/project/card-list.tsx
@@ -9,6 +9,8 @@ import { Loader } from "@plane/ui";
import emptyProject from "public/empty-state/empty_project.webp";
// icons
import { NewEmptyState } from "components/common/new-empty-state";
+// constants
+import { EUserWorkspaceRoles } from "constants/workspace";
export interface IProjectCardList {
workspaceSlug: string;
@@ -21,10 +23,13 @@ export const ProjectCardList: FC = observer((props) => {
project: projectStore,
commandPalette: commandPaletteStore,
trackEvent: { setTrackElement },
+ user: { currentProjectRole },
} = useMobxStore();
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : null;
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
if (!projects) {
return (
@@ -69,6 +74,7 @@ export const ProjectCardList: FC = observer((props) => {
commandPaletteStore.toggleCreateProjectModal(true);
},
}}
+ disabled={!isEditingAllowed}
/>
)}
>
diff --git a/web/components/views/views-list.tsx b/web/components/views/views-list.tsx
index e6d9b2544..d293bbe73 100644
--- a/web/components/views/views-list.tsx
+++ b/web/components/views/views-list.tsx
@@ -13,6 +13,8 @@ import { Input, Loader } from "@plane/ui";
import emptyView from "public/empty-state/empty_view.webp";
// icons
import { Plus, Search } from "lucide-react";
+// constants
+import { EUserWorkspaceRoles } from "constants/workspace";
export const ProjectViewsList = observer(() => {
const [query, setQuery] = useState("");
@@ -20,10 +22,16 @@ export const ProjectViewsList = observer(() => {
const router = useRouter();
const { projectId } = router.query;
- const { projectViews: projectViewsStore, commandPalette: commandPaletteStore } = useMobxStore();
+ const {
+ projectViews: projectViewsStore,
+ commandPalette: commandPaletteStore,
+ user: { currentProjectRole },
+ } = useMobxStore();
const viewsList = projectId ? projectViewsStore.viewsList[projectId.toString()] : undefined;
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
if (!viewsList)
return (
@@ -73,6 +81,7 @@ export const ProjectViewsList = observer(() => {
text: "Build your first view",
onClick: () => commandPaletteStore.toggleCreateViewModal(true),
}}
+ disabled={!isEditingAllowed}
/>
)}
>
diff --git a/web/pages/[workspaceSlug]/analytics.tsx b/web/pages/[workspaceSlug]/analytics.tsx
index c396842d8..b76d07647 100644
--- a/web/pages/[workspaceSlug]/analytics.tsx
+++ b/web/pages/[workspaceSlug]/analytics.tsx
@@ -15,6 +15,7 @@ import { Plus } from "lucide-react";
import emptyAnalytics from "public/empty-state/empty_analytics.webp";
// constants
import { ANALYTICS_TABS } from "constants/analytics";
+import { EUserWorkspaceRoles } from "constants/workspace";
// type
import { NextPageWithLayout } from "types/app";
@@ -24,8 +25,11 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
project: { workspaceProjects },
commandPalette: { toggleCreateProjectModal },
trackEvent: { setTrackElement },
+ user: { currentProjectRole },
} = useMobxStore();
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
return (
<>
{workspaceProjects && workspaceProjects.length > 0 ? (
@@ -77,6 +81,7 @@ const AnalyticsPage: NextPageWithLayout = observer(() => {
toggleCreateProjectModal(true);
},
}}
+ disabled={!isEditingAllowed}
/>
>
)}
diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
index 982dbf27d..c987408b0 100644
--- a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
+++ b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx
@@ -19,6 +19,7 @@ import { TCycleView, TCycleLayout } from "types";
import { NextPageWithLayout } from "types/app";
// constants
import { CYCLE_TAB_LIST, CYCLE_VIEW_LAYOUTS } from "constants/cycle";
+import { EUserWorkspaceRoles } from "constants/workspace";
// lib cookie
import { setLocalStorage, getLocalStorage } from "lib/local-storage";
import { NewEmptyState } from "components/common/new-empty-state";
@@ -27,7 +28,10 @@ import { NewEmptyState } from "components/common/new-empty-state";
const ProjectCyclesPage: NextPageWithLayout = observer(() => {
const [createModal, setCreateModal] = useState(false);
// store
- const { cycle: cycleStore } = useMobxStore();
+ const {
+ cycle: cycleStore,
+ user: { currentProjectRole },
+ } = useMobxStore();
const { projectCycles } = cycleStore;
// router
const router = useRouter();
@@ -75,6 +79,8 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
const cycleLayout = cycleStore?.cycleLayout;
const totalCycles = projectCycles?.length ?? 0;
+ const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
+
if (!workspaceSlug || !projectId) return null;
return (
@@ -104,6 +110,7 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => {
setCreateModal(true);
},
}}
+ disabled={!isEditingAllowed}
/>
) : (