2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 03:26:45 +00:00

[UI] Icons in navbar (#9346)

* Add Icons to main header

* Add user configurability
This commit is contained in:
Oliver 2025-03-20 10:19:50 +11:00 committed by GitHub
parent bdc5f9e84e
commit cb240e4e0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 90 additions and 21 deletions

View File

@ -183,6 +183,12 @@ USER_SETTINGS: dict[str, InvenTreeSettingsKeyType] = {
'default': False,
'validator': bool,
},
'ICONS_IN_NAVBAR': {
'name': _('Navigation Icons'),
'description': _('Display icons in the navigation bar'),
'default': False,
'validator': bool,
},
'DATE_DISPLAY_FORMAT': {
'name': _('Date Format'),
'description': _('Preferred format for displaying dates'),

View File

@ -13,13 +13,16 @@ import { type ReactNode, useEffect, useMemo, useState } from 'react';
import { useMatch, useNavigate } from 'react-router-dom';
import { api } from '../../App';
import { navTabs as mainNavTabs } from '../../defaults/links';
import { getNavTabs } from '../../defaults/links';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import { navigateToLink } from '../../functions/navigation';
import * as classes from '../../main.css';
import { apiUrl, useServerApiState } from '../../states/ApiState';
import { useLocalState } from '../../states/LocalState';
import { useGlobalSettingsState } from '../../states/SettingsState';
import {
useGlobalSettingsState,
useUserSettingsState
} from '../../states/SettingsState';
import { useUserState } from '../../states/UserState';
import { ScanButton } from '../buttons/ScanButton';
import { SpotlightButton } from '../buttons/SpotlightButton';
@ -160,30 +163,45 @@ function NavTabs() {
const navigate = useNavigate();
const match = useMatch(':tabName/*');
const tabValue = match?.params.tabName;
const navTabs = getNavTabs(user);
const userSettings = useUserSettingsState();
const withIcons: boolean = useMemo(
() => userSettings.isSet('ICONS_IN_NAVBAR', false),
[userSettings]
);
const tabs: ReactNode[] = useMemo(() => {
const _tabs: ReactNode[] = [];
mainNavTabs.forEach((tab) => {
navTabs.forEach((tab) => {
if (tab.role && !user.hasViewRole(tab.role)) {
return;
}
// TODO: Hide icons if user does not wish to display them!
_tabs.push(
<Tabs.Tab
value={tab.name}
key={tab.name}
leftSection={
withIcons &&
tab.icon && (
<ActionIcon variant='transparent'>{tab.icon}</ActionIcon>
)
}
onClick={(event: any) =>
navigateToLink(`/${tab.name}`, navigate, event)
}
>
{tab.text}
{tab.title}
</Tabs.Tab>
);
});
return _tabs;
}, [mainNavTabs, user]);
}, [navTabs, user, withIcons]);
return (
<Tabs

View File

@ -1,28 +1,72 @@
import { Trans, t } from '@lingui/macro';
import { openContextModal } from '@mantine/modals';
import {
IconBox,
IconBuildingFactory2,
IconDashboard,
IconPackages,
IconShoppingCart,
IconTruckDelivery
} from '@tabler/icons-react';
import type { ReactNode } from 'react';
import type { MenuLinkItem } from '../components/items/MenuLinks';
import { StylishText } from '../components/items/StylishText';
import { UserRoles } from '../enums/Roles';
import type { SettingsStateProps } from '../states/SettingsState';
import type { UserStateProps } from '../states/UserState';
export const navTabs = [
{ text: <Trans>Dashboard</Trans>, name: 'home' },
{ text: <Trans>Parts</Trans>, name: 'part', role: UserRoles.part },
{ text: <Trans>Stock</Trans>, name: 'stock', role: UserRoles.stock },
{
text: <Trans>Manufacturing</Trans>,
name: 'manufacturing',
role: UserRoles.build
},
{
text: <Trans>Purchasing</Trans>,
name: 'purchasing',
role: UserRoles.purchase_order
},
{ text: <Trans>Sales</Trans>, name: 'sales', role: UserRoles.sales_order }
];
type NavTab = {
name: string;
title: string;
icon: ReactNode;
role?: UserRoles;
};
export function getNavTabs(user: UserStateProps): NavTab[] {
const navTabs: NavTab[] = [
{
name: 'home',
title: t`Dashboard`,
icon: <IconDashboard />
},
{
name: 'part',
title: t`Parts`,
icon: <IconBox />,
role: UserRoles.part
},
{
name: 'stock',
title: t`Stock`,
icon: <IconPackages />,
role: UserRoles.stock
},
{
name: 'manufacturing',
title: t`Manufacturing`,
icon: <IconBuildingFactory2 />,
role: UserRoles.build
},
{
name: 'purchasing',
title: t`Purchasing`,
icon: <IconShoppingCart />,
role: UserRoles.purchase_order
},
{
name: 'sales',
title: t`Sales`,
icon: <IconTruckDelivery />,
role: UserRoles.sales_order
}
];
return navTabs.filter((tab) => {
if (!tab.role) return true;
return user.hasViewRole(tab.role);
});
}
export const docLinks = {
app: 'https://docs.inventree.org/app/',

View File

@ -49,6 +49,7 @@ export default function UserSettings() {
content: (
<UserSettingList
keys={[
'ICONS_IN_NAVBAR',
'STICKY_HEADER',
'DATE_DISPLAY_FORMAT',
'FORMS_CLOSE_USING_ESCAPE',