mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 05:05:42 +00:00 
			
		
		
		
	[UI] More actions (#10719)
* Add more spotlight actions: - Open user settings - Open system settings * Add some actions * Multiple attempts in test code
This commit is contained in:
		| @@ -56,7 +56,7 @@ export default function LayoutComponent() { | |||||||
|       setActions(defaultActions); |       setActions(defaultActions); | ||||||
|       setCustomActions(false); |       setCustomActions(false); | ||||||
|     } |     } | ||||||
|   }, [location]); |   }, [customActions, defaultActions, location]); | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <ProtectedRoute> |     <ProtectedRoute> | ||||||
|   | |||||||
| @@ -1,11 +1,22 @@ | |||||||
| import { t } from '@lingui/core/macro'; | import { t } from '@lingui/core/macro'; | ||||||
| import type { SpotlightActionData } from '@mantine/spotlight'; | import type { SpotlightActionData } from '@mantine/spotlight'; | ||||||
| import { IconBarcode, IconLink, IconPointer } from '@tabler/icons-react'; | import { | ||||||
|  |   IconBarcode, | ||||||
|  |   IconLink, | ||||||
|  |   IconPointer, | ||||||
|  |   IconSettings, | ||||||
|  |   IconUserBolt, | ||||||
|  |   IconUserCog | ||||||
|  | } from '@tabler/icons-react'; | ||||||
| import type { NavigateFunction } from 'react-router-dom'; | import type { NavigateFunction } from 'react-router-dom'; | ||||||
|  |  | ||||||
|  | import { ModelInformationDict } from '@lib/enums/ModelInformation'; | ||||||
|  | import { UserRoles } from '@lib/index'; | ||||||
| import { openContextModal } from '@mantine/modals'; | import { openContextModal } from '@mantine/modals'; | ||||||
|  | import { useMemo } from 'react'; | ||||||
| import { useShallow } from 'zustand/react/shallow'; | import { useShallow } from 'zustand/react/shallow'; | ||||||
| import { useLocalState } from '../states/LocalState'; | import { useLocalState } from '../states/LocalState'; | ||||||
|  | import { useGlobalSettingsState } from '../states/SettingsStates'; | ||||||
| import { useUserState } from '../states/UserState'; | import { useUserState } from '../states/UserState'; | ||||||
| import { aboutInvenTree, docLinks, licenseInfo, serverInfo } from './links'; | import { aboutInvenTree, docLinks, licenseInfo, serverInfo } from './links'; | ||||||
|  |  | ||||||
| @@ -20,71 +31,133 @@ export function getActions(navigate: NavigateFunction) { | |||||||
|   const setNavigationOpen = useLocalState( |   const setNavigationOpen = useLocalState( | ||||||
|     useShallow((state) => state.setNavigationOpen) |     useShallow((state) => state.setNavigationOpen) | ||||||
|   ); |   ); | ||||||
|   const { user } = useUserState(); |   const globalSettings = useGlobalSettingsState(); | ||||||
|  |   const user = useUserState(); | ||||||
|  |  | ||||||
|   const actions: SpotlightActionData[] = [ |   const actions: SpotlightActionData[] = useMemo(() => { | ||||||
|     { |     const _actions: SpotlightActionData[] = [ | ||||||
|       id: 'dashboard', |       { | ||||||
|       label: t`Dashboard`, |         id: 'dashboard', | ||||||
|       description: t`Go to the InvenTree dashboard`, |         label: t`Dashboard`, | ||||||
|       onClick: () => navigate('/'), |         description: t`Go to the InvenTree dashboard`, | ||||||
|       leftSection: <IconLink size='1.2rem' /> |         onClick: () => navigate('/'), | ||||||
|     }, |         leftSection: <IconLink size='1.2rem' /> | ||||||
|     { |  | ||||||
|       id: 'documentation', |  | ||||||
|       label: t`Documentation`, |  | ||||||
|       description: t`Visit the documentation to learn more about InvenTree`, |  | ||||||
|       onClick: () => { |  | ||||||
|         window.location.href = docLinks.faq; |  | ||||||
|       }, |       }, | ||||||
|       leftSection: <IconLink size='1.2rem' /> |       { | ||||||
|     }, |         id: 'documentation', | ||||||
|     { |         label: t`Documentation`, | ||||||
|       id: 'about', |         description: t`Visit the documentation to learn more about InvenTree`, | ||||||
|       label: t`About InvenTree`, |         onClick: () => { | ||||||
|       description: t`About the InvenTree org`, |           window.location.href = docLinks.faq; | ||||||
|       onClick: () => aboutInvenTree(), |         }, | ||||||
|       leftSection: <IconLink size='1.2rem' /> |         leftSection: <IconLink size='1.2rem' /> | ||||||
|     }, |       }, | ||||||
|     { |       { | ||||||
|       id: 'server-info', |         id: 'about', | ||||||
|       label: t`Server Information`, |         label: t`About InvenTree`, | ||||||
|       description: t`About this InvenTree instance`, |         description: t`About the InvenTree org`, | ||||||
|       onClick: () => serverInfo(), |         onClick: () => aboutInvenTree(), | ||||||
|       leftSection: <IconLink size='1.2rem' /> |         leftSection: <IconLink size='1.2rem' /> | ||||||
|     }, |       }, | ||||||
|     { |       { | ||||||
|       id: 'license-info', |         id: 'server-info', | ||||||
|       label: t`License Information`, |         label: t`Server Information`, | ||||||
|       description: t`Licenses for dependencies of the service`, |         description: t`About this InvenTree instance`, | ||||||
|       onClick: () => licenseInfo(), |         onClick: () => serverInfo(), | ||||||
|       leftSection: <IconLink size='1.2rem' /> |         leftSection: <IconLink size='1.2rem' /> | ||||||
|     }, |       }, | ||||||
|     { |       { | ||||||
|       id: 'navigation', |         id: 'license-info', | ||||||
|       label: t`Open Navigation`, |         label: t`License Information`, | ||||||
|       description: t`Open the main navigation menu`, |         description: t`Licenses for dependencies of the service`, | ||||||
|       onClick: () => setNavigationOpen(true), |         onClick: () => licenseInfo(), | ||||||
|       leftSection: <IconPointer size='1.2rem' /> |         leftSection: <IconLink size='1.2rem' /> | ||||||
|     }, |       }, | ||||||
|     { |       { | ||||||
|       id: 'scan', |         id: 'navigation', | ||||||
|       label: t`Scan`, |         label: t`Open Navigation`, | ||||||
|       description: t`Scan a barcode or QR code`, |         description: t`Open the main navigation menu`, | ||||||
|       onClick: () => openQrModal(navigate), |         onClick: () => setNavigationOpen(true), | ||||||
|       leftSection: <IconBarcode size='1.2rem' /> |         leftSection: <IconPointer size='1.2rem' /> | ||||||
|     } |       }, | ||||||
|   ]; |       { | ||||||
|  |         id: 'scan', | ||||||
|  |         label: t`Scan`, | ||||||
|  |         description: t`Scan a barcode or QR code`, | ||||||
|  |         onClick: () => openQrModal(navigate), | ||||||
|  |         leftSection: <IconBarcode size='1.2rem' /> | ||||||
|  |       }, | ||||||
|  |       { | ||||||
|  |         id: 'user-settings', | ||||||
|  |         label: t`User Settings`, | ||||||
|  |  | ||||||
|   // Staff actions |         description: t`Go to your user settings`, | ||||||
|   user?.is_staff && |         onClick: () => navigate('/settings/user'), | ||||||
|     actions.push({ |         leftSection: <IconUserCog size='1.2rem' /> | ||||||
|       id: 'admin-center', |       } | ||||||
|       label: t`Admin Center`, |     ]; | ||||||
|       description: t`Go to the Admin Center`, |  | ||||||
|       onClick: () => {}, /// navigate(menuItems['settings-admin'].link),} |     // Page Actions | ||||||
|       leftSection: <IconLink size='1.2rem' /> |     user?.hasViewRole(UserRoles.purchase_order) && | ||||||
|     }); |       _actions.push({ | ||||||
|  |         id: 'purchase-orders', | ||||||
|  |         label: t`Purchase Orders`, | ||||||
|  |         description: t`Go to Purchase Orders`, | ||||||
|  |         onClick: () => | ||||||
|  |           navigate(ModelInformationDict['purchaseorder'].url_overview!), | ||||||
|  |         leftSection: <IconLink size='1.2rem' /> | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |     user?.hasViewRole(UserRoles.sales_order) && | ||||||
|  |       _actions.push({ | ||||||
|  |         id: 'sales-orders', | ||||||
|  |         label: t`Sales Orders`, | ||||||
|  |         description: t`Go to Sales Orders`, | ||||||
|  |         onClick: () => | ||||||
|  |           navigate(ModelInformationDict['salesorder'].url_overview!), | ||||||
|  |         leftSection: <IconLink size='1.2rem' /> | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |     globalSettings.isSet('RETURNORDER_ENABLED') && | ||||||
|  |       user?.hasViewRole(UserRoles.return_order) && | ||||||
|  |       _actions.push({ | ||||||
|  |         id: 'return-orders', | ||||||
|  |         label: t`Return Orders`, | ||||||
|  |         description: t`Go to Return Orders`, | ||||||
|  |         onClick: () => | ||||||
|  |           navigate(ModelInformationDict['returnorder'].url_overview!), | ||||||
|  |         leftSection: <IconLink size='1.2rem' /> | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |     user?.hasViewRole(UserRoles.build) && | ||||||
|  |       _actions.push({ | ||||||
|  |         id: 'builds', | ||||||
|  |         label: t`Build Orders`, | ||||||
|  |         description: t`Go to Build Orders`, | ||||||
|  |         onClick: () => navigate(ModelInformationDict['build'].url_overview!), | ||||||
|  |         leftSection: <IconLink size='1.2rem' /> | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |     user?.isStaff() && | ||||||
|  |       _actions.push({ | ||||||
|  |         id: 'system-settings', | ||||||
|  |         label: t`System Settings`, | ||||||
|  |         description: t`Go to System Settings`, | ||||||
|  |         onClick: () => navigate('/settings/system'), | ||||||
|  |         leftSection: <IconSettings size='1.2rem' /> | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |     user?.isStaff() && | ||||||
|  |       _actions.push({ | ||||||
|  |         id: 'admin-center', | ||||||
|  |         label: t`Admin Center`, | ||||||
|  |         description: t`Go to the Admin Center`, | ||||||
|  |         onClick: () => {}, /// navigate(menuItems['settings-admin'].link),} | ||||||
|  |         leftSection: <IconUserBolt size='1.2rem' /> | ||||||
|  |       }); | ||||||
|  |  | ||||||
|  |     return _actions; | ||||||
|  |   }, [navigate, setNavigationOpen, globalSettings, user]); | ||||||
|  |  | ||||||
|   return actions; |   return actions; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -336,12 +336,29 @@ test('Settings - Admin - Barcode History', async ({ browser }) => { | |||||||
|  |  | ||||||
|   for (let i = 0; i < barcodes.length; i++) { |   for (let i = 0; i < barcodes.length; i++) { | ||||||
|     const barcode = barcodes[i]; |     const barcode = barcodes[i]; | ||||||
|     await api.post('barcode/', { |  | ||||||
|       data: { |     let attempts = 5; | ||||||
|         barcode: barcode |  | ||||||
|       }, |     while (attempts > 0) { | ||||||
|       timeout: 5000 |       let result = false; | ||||||
|     }); |  | ||||||
|  |       await api | ||||||
|  |         .post('barcode/', { | ||||||
|  |           data: { | ||||||
|  |             barcode: barcode | ||||||
|  |           }, | ||||||
|  |           timeout: 5000 | ||||||
|  |         }) | ||||||
|  |         .then(() => { | ||||||
|  |           result = true; | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |       if (result) { | ||||||
|  |         break; | ||||||
|  |       } else { | ||||||
|  |         attempts -= 1; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   await page.getByRole('button', { name: 'admin' }).click(); |   await page.getByRole('button', { name: 'admin' }).click(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user