[PUI] Tab permissions (#7692)

* [PUI] Hide main nav tabs based on user roles

* Add permission checks on top-level pages

* Specify return type
This commit is contained in:
Oliver 2024-07-19 16:54:55 +10:00 committed by GitHub
parent 0a2817dbf3
commit d4cd7d4a72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 65 additions and 19 deletions

View File

@ -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(
<Tabs.Tab
value={tab.name}
key={tab.name}
onClick={(event: any) =>
navigateToLink(`/${tab.name}`, navigate, event)
}
>
{tab.text}
</Tabs.Tab>
);
});
return _tabs;
}, [mainNavTabs, user]);
return (
<Tabs
defaultValue="home"
@ -146,19 +171,7 @@ function NavTabs() {
}}
value={tabValue}
>
<Tabs.List>
{mainNavTabs.map((tab) => (
<Tabs.Tab
value={tab.name}
key={tab.name}
onClick={(event: any) =>
navigateToLink(`/${tab.name}`, navigate, event)
}
>
{tab.text}
</Tabs.Tab>
))}
</Tabs.List>
<Tabs.List>{tabs.map((tab) => tab)}</Tabs.List>
</Tabs>
);
}

View File

@ -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: <Trans>Home</Trans>, name: 'home' },
{ text: <Trans>Dashboard</Trans>, name: 'dashboard' },
{ text: <Trans>Parts</Trans>, name: 'part' },
{ text: <Trans>Stock</Trans>, name: 'stock' },
{ text: <Trans>Build</Trans>, name: 'build' },
{ text: <Trans>Purchasing</Trans>, name: 'purchasing' },
{ text: <Trans>Sales</Trans>, name: 'sales' }
{ text: <Trans>Parts</Trans>, name: 'part', role: UserRoles.part },
{ text: <Trans>Stock</Trans>, name: 'stock', role: UserRoles.stock },
{ text: <Trans>Build</Trans>, name: 'build', role: UserRoles.build },
{
text: <Trans>Purchasing</Trans>,
name: 'purchasing',
role: UserRoles.purchase_order
},
{ text: <Trans>Sales</Trans>, name: 'sales', role: UserRoles.sales_order }
];
if (IS_DEV_OR_DEMO) {
navTabs.push({ text: <Trans>Playground</Trans>, name: 'playground' });
}

View File

@ -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 <PermissionDenied />;
}
return (
<Stack>
<PageDetail title={t`Build Orders`} actions={[]} />

View File

@ -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 <PermissionDenied />;
}
return (
<Stack>
<PageDetail title={t`Purchasing`} />

View File

@ -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 <PermissionDenied />;
}
return (
<Stack>
<PageDetail title={t`Sales`} />