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 (