From cb240e4e0f9fc1412e50061b7eb20afcbb0c113a Mon Sep 17 00:00:00 2001 From: Oliver Date: Thu, 20 Mar 2025 10:19:50 +1100 Subject: [PATCH] [UI] Icons in navbar (#9346) * Add Icons to main header * Add user configurability --- src/backend/InvenTree/common/setting/user.py | 6 ++ src/frontend/src/components/nav/Header.tsx | 28 +++++-- src/frontend/src/defaults/links.tsx | 76 +++++++++++++++---- .../src/pages/Index/Settings/UserSettings.tsx | 1 + 4 files changed, 90 insertions(+), 21 deletions(-) diff --git a/src/backend/InvenTree/common/setting/user.py b/src/backend/InvenTree/common/setting/user.py index 7f648fe514..99eb41bfbb 100644 --- a/src/backend/InvenTree/common/setting/user.py +++ b/src/backend/InvenTree/common/setting/user.py @@ -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'), diff --git a/src/frontend/src/components/nav/Header.tsx b/src/frontend/src/components/nav/Header.tsx index 90b0441956..cfb830eb49 100644 --- a/src/frontend/src/components/nav/Header.tsx +++ b/src/frontend/src/components/nav/Header.tsx @@ -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( {tab.icon} + ) + } onClick={(event: any) => navigateToLink(`/${tab.name}`, navigate, event) } > - {tab.text} + {tab.title} ); }); return _tabs; - }, [mainNavTabs, user]); + }, [navTabs, user, withIcons]); return ( Dashboard, name: 'home' }, - { text: Parts, name: 'part', role: UserRoles.part }, - { text: Stock, name: 'stock', role: UserRoles.stock }, - { - text: Manufacturing, - name: 'manufacturing', - role: UserRoles.build - }, - { - text: Purchasing, - name: 'purchasing', - role: UserRoles.purchase_order - }, - { text: Sales, 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: + }, + { + name: 'part', + title: t`Parts`, + icon: , + role: UserRoles.part + }, + { + name: 'stock', + title: t`Stock`, + icon: , + role: UserRoles.stock + }, + { + name: 'manufacturing', + title: t`Manufacturing`, + icon: , + role: UserRoles.build + }, + { + name: 'purchasing', + title: t`Purchasing`, + icon: , + role: UserRoles.purchase_order + }, + { + name: 'sales', + title: t`Sales`, + icon: , + 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/', diff --git a/src/frontend/src/pages/Index/Settings/UserSettings.tsx b/src/frontend/src/pages/Index/Settings/UserSettings.tsx index 60a6a43805..42e1b3b508 100644 --- a/src/frontend/src/pages/Index/Settings/UserSettings.tsx +++ b/src/frontend/src/pages/Index/Settings/UserSettings.tsx @@ -49,6 +49,7 @@ export default function UserSettings() { content: (