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} /> ) : (