From 184db0156cf0292856e5c95306b2cfa6bb86650a Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Mon, 18 Dec 2023 13:25:03 +0530 Subject: [PATCH] User role validation across workspace and projects. (#3167) * chore: remove `add link` button for guests & viewer in modules sidebar. * chore: remove `+` (add view) icon for guests & viewer in `All Issues`. * chore: remove `Start Project` button from Dashboard & Projects empty state for guests & viewers. * chore: project level user role validation for empty states. --- web/components/common/new-empty-state.tsx | 2 +- .../issue-layouts/empty-states/project.tsx | 20 ++++++++------ web/components/modules/modules-list-view.tsx | 14 ++++++---- web/components/modules/sidebar.tsx | 16 ++++++----- .../page-views/workspace-dashboard.tsx | 18 ++++++++----- web/components/pages/pages-list/list-view.tsx | 14 ++++++---- .../pages/pages-list/recent-pages-list.tsx | 14 ++++++---- web/components/project/card-list.tsx | 18 ++++++++----- web/components/views/views-list.tsx | 14 ++++++---- web/components/workspace/views/header.tsx | 27 ++++++++++++------- .../projects/[projectId]/cycles/index.tsx | 18 ++++++++----- 11 files changed, 108 insertions(+), 67 deletions(-) diff --git a/web/components/common/new-empty-state.tsx b/web/components/common/new-empty-state.tsx index 058a3988f..508d2e5da 100644 --- a/web/components/common/new-empty-state.tsx +++ b/web/components/common/new-empty-state.tsx @@ -19,7 +19,7 @@ type Props = { icon?: any; text: string; onClick: () => void; - }; + } | null; disabled?: boolean; }; diff --git a/web/components/issues/issue-layouts/empty-states/project.tsx b/web/components/issues/issue-layouts/empty-states/project.tsx index 27c11dbbf..7db04b36a 100644 --- a/web/components/issues/issue-layouts/empty-states/project.tsx +++ b/web/components/issues/issue-layouts/empty-states/project.tsx @@ -31,14 +31,18 @@ export const ProjectEmptyState: React.FC = observer(() => { description: "Redesign the Plane UI, Rebrand the company, or Launch the new fuel injection system are examples of issues that likely have sub-issues.", }} - primaryButton={{ - text: "Create your first issue", - icon: , - onClick: () => { - setTrackElement("PROJECT_EMPTY_STATE"); - commandPaletteStore.toggleCreateIssueModal(true, EProjectStore.PROJECT); - }, - }} + primaryButton={ + isEditingAllowed + ? { + text: "Create your first issue", + icon: , + onClick: () => { + setTrackElement("PROJECT_EMPTY_STATE"); + commandPaletteStore.toggleCreateIssueModal(true, EProjectStore.PROJECT); + }, + } + : null + } disabled={!isEditingAllowed} /> diff --git a/web/components/modules/modules-list-view.tsx b/web/components/modules/modules-list-view.tsx index 9b8c51236..a6621dbc8 100644 --- a/web/components/modules/modules-list-view.tsx +++ b/web/components/modules/modules-list-view.tsx @@ -96,11 +96,15 @@ export const ModulesListView: React.FC = observer(() => { description: "A cart module, a chassis module, and a warehouse module are all good example of this grouping.", }} - primaryButton={{ - icon: , - text: "Build your first module", - onClick: () => commandPaletteStore.toggleCreateModuleModal(true), - }} + primaryButton={ + isEditingAllowed + ? { + icon: , + text: "Build your first module", + onClick: () => commandPaletteStore.toggleCreateModuleModal(true), + } + : null + } disabled={!isEditingAllowed} /> )} diff --git a/web/components/modules/sidebar.tsx b/web/components/modules/sidebar.tsx index 35bf88567..3c9552465 100644 --- a/web/components/modules/sidebar.tsx +++ b/web/components/modules/sidebar.tsx @@ -626,13 +626,15 @@ export const ModuleDetailsSidebar: React.FC = observer((props) => { No links added yet - + {isEditingAllowed && ( + + )} )} diff --git a/web/components/page-views/workspace-dashboard.tsx b/web/components/page-views/workspace-dashboard.tsx index 2f300c990..ff378e23d 100644 --- a/web/components/page-views/workspace-dashboard.tsx +++ b/web/components/page-views/workspace-dashboard.tsx @@ -93,13 +93,17 @@ export const WorkspaceDashboardView = observer(() => { direction: "right", description: "A project could be a product’s roadmap, a marketing campaign, or launching a new car.", }} - primaryButton={{ - text: "Build your first project", - onClick: () => { - setTrackElement("DASHBOARD_PAGE"); - commandPaletteStore.toggleCreateProjectModal(true); - }, - }} + primaryButton={ + isEditingAllowed + ? { + text: "Build your first project", + onClick: () => { + setTrackElement("DASHBOARD_PAGE"); + commandPaletteStore.toggleCreateProjectModal(true); + }, + } + : null + } disabled={!isEditingAllowed} /> ) diff --git a/web/components/pages/pages-list/list-view.tsx b/web/components/pages/pages-list/list-view.tsx index 9f94a6671..bb35edfa0 100644 --- a/web/components/pages/pages-list/list-view.tsx +++ b/web/components/pages/pages-list/list-view.tsx @@ -58,11 +58,15 @@ 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", }} - primaryButton={{ - icon: , - text: "Create your first page", - onClick: () => toggleCreatePageModal(true), - }} + primaryButton={ + isEditingAllowed + ? { + icon: , + text: "Create your first page", + onClick: () => toggleCreatePageModal(true), + } + : null + } 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 21fb8277f..4648ec1e4 100644 --- a/web/components/pages/pages-list/recent-pages-list.tsx +++ b/web/components/pages/pages-list/recent-pages-list.tsx @@ -66,11 +66,15 @@ export const RecentPagesList: FC = observer(() => { "We wrote Parth and Meera’s love story. You could write your project’s mission, goals, and eventual vision.", direction: "right", }} - primaryButton={{ - icon: , - text: "Create your first page", - onClick: () => commandPaletteStore.toggleCreatePageModal(true), - }} + primaryButton={ + isEditingAllowed + ? { + icon: , + text: "Create your first page", + onClick: () => commandPaletteStore.toggleCreatePageModal(true), + } + : null + } disabled={!isEditingAllowed} /> diff --git a/web/components/project/card-list.tsx b/web/components/project/card-list.tsx index 979ade4ec..76f3112b6 100644 --- a/web/components/project/card-list.tsx +++ b/web/components/project/card-list.tsx @@ -67,13 +67,17 @@ export const ProjectCardList: FC = observer((props) => { direction: "right", description: "A project could be a product’s roadmap, a marketing campaign, or launching a new car.", }} - primaryButton={{ - text: "Start your first project", - onClick: () => { - setTrackElement("PROJECTS_EMPTY_STATE"); - commandPaletteStore.toggleCreateProjectModal(true); - }, - }} + primaryButton={ + isEditingAllowed + ? { + text: "Start your first project", + onClick: () => { + setTrackElement("PROJECTS_EMPTY_STATE"); + commandPaletteStore.toggleCreateProjectModal(true); + }, + } + : null + } disabled={!isEditingAllowed} /> )} diff --git a/web/components/views/views-list.tsx b/web/components/views/views-list.tsx index d293bbe73..d08ec2c04 100644 --- a/web/components/views/views-list.tsx +++ b/web/components/views/views-list.tsx @@ -76,11 +76,15 @@ export const ProjectViewsList = observer(() => { description: "You can create a view from here with as many properties as filters as you see fit.", direction: "right", }} - primaryButton={{ - icon: , - text: "Build your first view", - onClick: () => commandPaletteStore.toggleCreateViewModal(true), - }} + primaryButton={ + isEditingAllowed + ? { + icon: , + text: "Build your first view", + onClick: () => commandPaletteStore.toggleCreateViewModal(true), + } + : null + } disabled={!isEditingAllowed} /> )} diff --git a/web/components/workspace/views/header.tsx b/web/components/workspace/views/header.tsx index b0b67cc22..f0636d80a 100644 --- a/web/components/workspace/views/header.tsx +++ b/web/components/workspace/views/header.tsx @@ -9,7 +9,7 @@ import { CreateUpdateWorkspaceViewModal } from "components/workspace"; // icon import { Plus } from "lucide-react"; // constants -import { DEFAULT_GLOBAL_VIEWS_LIST } from "constants/workspace"; +import { DEFAULT_GLOBAL_VIEWS_LIST, EUserWorkspaceRoles } from "constants/workspace"; export const GlobalViewsHeader: React.FC = observer(() => { const [createViewModal, setCreateViewModal] = useState(false); @@ -17,7 +17,10 @@ export const GlobalViewsHeader: React.FC = observer(() => { const router = useRouter(); const { workspaceSlug, globalViewId } = router.query; - const { globalViews: globalViewsStore } = useMobxStore(); + const { + globalViews: globalViewsStore, + user: { currentWorkspaceRole }, + } = useMobxStore(); // bring the active view to the centre of the header useEffect(() => { @@ -28,11 +31,13 @@ export const GlobalViewsHeader: React.FC = observer(() => { if (activeTabElement) activeTabElement.scrollIntoView({ behavior: "smooth", inline: "center" }); }, [globalViewId]); + const isAuthorizedUser = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER; + const isTabSelected = (tabKey: string) => router.pathname.includes(tabKey); return ( <> setCreateViewModal(false)} /> -
+
{DEFAULT_GLOBAL_VIEWS_LIST.map((tab) => ( { ))} - + {isAuthorizedUser && ( + + )}
); diff --git a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx index c987408b0..2a98c75e4 100644 --- a/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx +++ b/web/pages/[workspaceSlug]/projects/[projectId]/cycles/index.tsx @@ -103,13 +103,17 @@ const ProjectCyclesPage: NextPageWithLayout = observer(() => { description: "A sprint, an iteration, and or any other term you use for weekly or fortnightly tracking of work is a cycle.", }} - primaryButton={{ - icon: , - text: "Set your first cycle", - onClick: () => { - setCreateModal(true); - }, - }} + primaryButton={ + isEditingAllowed + ? { + icon: , + text: "Set your first cycle", + onClick: () => { + setCreateModal(true); + }, + } + : null + } disabled={!isEditingAllowed} />