diff --git a/src/frontend/src/components/nav/Header.tsx b/src/frontend/src/components/nav/Header.tsx index 49426d599b..7ba9ef6f8b 100644 --- a/src/frontend/src/components/nav/Header.tsx +++ b/src/frontend/src/components/nav/Header.tsx @@ -2,7 +2,7 @@ import { ActionIcon, Container, Group, Indicator, Tabs } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { IconBell, IconSearch } from '@tabler/icons-react'; import { useQuery } from '@tanstack/react-query'; -import { useEffect, useState } from 'react'; +import { ReactNode, useEffect, useMemo, useState } from 'react'; import { useMatch, useNavigate } from 'react-router-dom'; import { api } from '../../App'; @@ -132,10 +132,35 @@ export function Header() { } function NavTabs() { + const user = useUserState(); const navigate = useNavigate(); const match = useMatch(':tabName/*'); const tabValue = match?.params.tabName; + const tabs: ReactNode[] = useMemo(() => { + let _tabs: ReactNode[] = []; + + mainNavTabs.forEach((tab) => { + if (tab.role && !user.hasViewRole(tab.role)) { + return; + } + + _tabs.push( + + navigateToLink(`/${tab.name}`, navigate, event) + } + > + {tab.text} + + ); + }); + + return _tabs; + }, [mainNavTabs, user]); + return ( - - {mainNavTabs.map((tab) => ( - - navigateToLink(`/${tab.name}`, navigate, event) - } - > - {tab.text} - - ))} - + {tabs.map((tab) => tab)} ); } diff --git a/src/frontend/src/defaults/links.tsx b/src/frontend/src/defaults/links.tsx index bc836c52ec..1646bab73e 100644 --- a/src/frontend/src/defaults/links.tsx +++ b/src/frontend/src/defaults/links.tsx @@ -3,6 +3,7 @@ import { openContextModal } from '@mantine/modals'; import { DocumentationLinkItem } from '../components/items/DocumentationLinks'; import { StylishText } from '../components/items/StylishText'; +import { UserRoles } from '../enums/Roles'; import { IS_DEV_OR_DEMO } from '../main'; export const footerLinks = [ @@ -25,12 +26,17 @@ export const footerLinks = [ export const navTabs = [ { text: Home, name: 'home' }, { text: Dashboard, name: 'dashboard' }, - { text: Parts, name: 'part' }, - { text: Stock, name: 'stock' }, - { text: Build, name: 'build' }, - { text: Purchasing, name: 'purchasing' }, - { text: Sales, name: 'sales' } + { text: Parts, name: 'part', role: UserRoles.part }, + { text: Stock, name: 'stock', role: UserRoles.stock }, + { text: Build, name: 'build', role: UserRoles.build }, + { + text: Purchasing, + name: 'purchasing', + role: UserRoles.purchase_order + }, + { text: Sales, name: 'sales', role: UserRoles.sales_order } ]; + if (IS_DEV_OR_DEMO) { navTabs.push({ text: Playground, name: 'playground' }); } diff --git a/src/frontend/src/pages/build/BuildIndex.tsx b/src/frontend/src/pages/build/BuildIndex.tsx index a20c45a5b0..aae18ff115 100644 --- a/src/frontend/src/pages/build/BuildIndex.tsx +++ b/src/frontend/src/pages/build/BuildIndex.tsx @@ -1,13 +1,22 @@ import { t } from '@lingui/macro'; import { Stack } from '@mantine/core'; +import PermissionDenied from '../../components/errors/PermissionDenied'; import { PageDetail } from '../../components/nav/PageDetail'; +import { UserRoles } from '../../enums/Roles'; +import { useUserState } from '../../states/UserState'; import { BuildOrderTable } from '../../tables/build/BuildOrderTable'; /** * Build Order index page */ export default function BuildIndex() { + const user = useUserState(); + + if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.build)) { + return ; + } + return ( diff --git a/src/frontend/src/pages/purchasing/PurchasingIndex.tsx b/src/frontend/src/pages/purchasing/PurchasingIndex.tsx index 408cf40a0a..13c91771b7 100644 --- a/src/frontend/src/pages/purchasing/PurchasingIndex.tsx +++ b/src/frontend/src/pages/purchasing/PurchasingIndex.tsx @@ -7,12 +7,17 @@ import { } from '@tabler/icons-react'; import { useMemo } from 'react'; +import PermissionDenied from '../../components/errors/PermissionDenied'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup } from '../../components/nav/PanelGroup'; +import { UserRoles } from '../../enums/Roles'; +import { useUserState } from '../../states/UserState'; import { CompanyTable } from '../../tables/company/CompanyTable'; import { PurchaseOrderTable } from '../../tables/purchasing/PurchaseOrderTable'; export default function PurchasingIndex() { + const user = useUserState(); + const panels = useMemo(() => { return [ { @@ -46,6 +51,10 @@ export default function PurchasingIndex() { ]; }, []); + if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.purchase_order)) { + return ; + } + return ( diff --git a/src/frontend/src/pages/sales/SalesIndex.tsx b/src/frontend/src/pages/sales/SalesIndex.tsx index 3de329ea7c..16a94174e5 100644 --- a/src/frontend/src/pages/sales/SalesIndex.tsx +++ b/src/frontend/src/pages/sales/SalesIndex.tsx @@ -7,13 +7,18 @@ import { } from '@tabler/icons-react'; import { useMemo } from 'react'; +import PermissionDenied from '../../components/errors/PermissionDenied'; import { PageDetail } from '../../components/nav/PageDetail'; import { PanelGroup } from '../../components/nav/PanelGroup'; +import { UserRoles } from '../../enums/Roles'; +import { useUserState } from '../../states/UserState'; import { CompanyTable } from '../../tables/company/CompanyTable'; import { ReturnOrderTable } from '../../tables/sales/ReturnOrderTable'; import { SalesOrderTable } from '../../tables/sales/SalesOrderTable'; export default function PurchasingIndex() { + const user = useUserState(); + const panels = useMemo(() => { return [ { @@ -39,6 +44,10 @@ export default function PurchasingIndex() { ]; }, []); + if (!user.isLoggedIn() || !user.hasViewRole(UserRoles.sales_order)) { + return ; + } + return (