mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
parent
374ee51d85
commit
58f4ef21cb
15
src/frontend/src/components/buttons/SpotlightButton.tsx
Normal file
15
src/frontend/src/components/buttons/SpotlightButton.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import { ActionIcon } from '@mantine/core';
|
||||||
|
import { spotlight } from '@mantine/spotlight';
|
||||||
|
import { IconCommand } from '@tabler/icons-react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A button which opens the quick command modal
|
||||||
|
*/
|
||||||
|
export function SpotlightButton() {
|
||||||
|
return (
|
||||||
|
<ActionIcon onClick={() => spotlight.open()} title={t`Open spotlight`}>
|
||||||
|
<IconCommand />
|
||||||
|
</ActionIcon>
|
||||||
|
);
|
||||||
|
}
|
@ -16,6 +16,10 @@ export interface MenuLinkItem {
|
|||||||
docchildren?: React.ReactNode;
|
docchildren?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type menuItemsCollection = {
|
||||||
|
[key: string]: MenuLinkItem;
|
||||||
|
};
|
||||||
|
|
||||||
function ConditionalDocTooltip({
|
function ConditionalDocTooltip({
|
||||||
item,
|
item,
|
||||||
children
|
children
|
||||||
|
@ -10,6 +10,7 @@ import { navTabs as mainNavTabs } from '../../defaults/links';
|
|||||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||||
import { InvenTreeStyle } from '../../globalStyle';
|
import { InvenTreeStyle } from '../../globalStyle';
|
||||||
import { apiUrl } from '../../states/ApiState';
|
import { apiUrl } from '../../states/ApiState';
|
||||||
|
import { SpotlightButton } from '../buttons/SpotlightButton';
|
||||||
import { ScanButton } from '../items/ScanButton';
|
import { ScanButton } from '../items/ScanButton';
|
||||||
import { MainMenu } from './MainMenu';
|
import { MainMenu } from './MainMenu';
|
||||||
import { NavHoverMenu } from './NavHoverMenu';
|
import { NavHoverMenu } from './NavHoverMenu';
|
||||||
@ -80,6 +81,7 @@ export function Header() {
|
|||||||
<ActionIcon onClick={openSearchDrawer}>
|
<ActionIcon onClick={openSearchDrawer}>
|
||||||
<IconSearch />
|
<IconSearch />
|
||||||
</ActionIcon>
|
</ActionIcon>
|
||||||
|
<SpotlightButton />
|
||||||
<ScanButton />
|
<ScanButton />
|
||||||
<ActionIcon onClick={openNotificationDrawer}>
|
<ActionIcon onClick={openNotificationDrawer}>
|
||||||
<Indicator
|
<Indicator
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
import { Container, Flex, Space } from '@mantine/core';
|
import { Container, Flex, Space } from '@mantine/core';
|
||||||
import { Navigate, Outlet, useLocation } from 'react-router-dom';
|
import { SpotlightProvider } from '@mantine/spotlight';
|
||||||
|
import { IconSearch } from '@tabler/icons-react';
|
||||||
|
import { Navigate, Outlet, useLocation, useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { getActions } from '../../defaults/actions';
|
||||||
import { InvenTreeStyle } from '../../globalStyle';
|
import { InvenTreeStyle } from '../../globalStyle';
|
||||||
import { useSessionState } from '../../states/SessionState';
|
import { useSessionState } from '../../states/SessionState';
|
||||||
import { Footer } from './Footer';
|
import { Footer } from './Footer';
|
||||||
@ -22,17 +26,27 @@ export const ProtectedRoute = ({ children }: { children: JSX.Element }) => {
|
|||||||
|
|
||||||
export default function LayoutComponent() {
|
export default function LayoutComponent() {
|
||||||
const { classes } = InvenTreeStyle();
|
const { classes } = InvenTreeStyle();
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const actions = getActions(navigate);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<Flex direction="column" mih="100vh">
|
<SpotlightProvider
|
||||||
<Header />
|
actions={actions}
|
||||||
<Container className={classes.layoutContent} size="100%">
|
searchIcon={<IconSearch size="1.2rem" />}
|
||||||
<Outlet />
|
searchPlaceholder={t`Search...`}
|
||||||
</Container>
|
shortcut={['mod + K', '/']}
|
||||||
<Space h="xl" />
|
nothingFoundMessage={t`Nothing found...`}
|
||||||
<Footer />
|
>
|
||||||
</Flex>
|
<Flex direction="column" mih="100vh">
|
||||||
|
<Header />
|
||||||
|
<Container className={classes.layoutContent} size="100%">
|
||||||
|
<Outlet />
|
||||||
|
</Container>
|
||||||
|
<Space h="xl" />
|
||||||
|
<Footer />
|
||||||
|
</Flex>
|
||||||
|
</SpotlightProvider>
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,8 @@ import { useLocalState } from '../../states/LocalState';
|
|||||||
import { InvenTreeLogo } from '../items/InvenTreeLogo';
|
import { InvenTreeLogo } from '../items/InvenTreeLogo';
|
||||||
import { MenuLinks } from '../items/MenuLinks';
|
import { MenuLinks } from '../items/MenuLinks';
|
||||||
|
|
||||||
|
const onlyItems = Object.values(menuItems);
|
||||||
|
|
||||||
export function NavHoverMenu({
|
export function NavHoverMenu({
|
||||||
openDrawer: openDrawer
|
openDrawer: openDrawer
|
||||||
}: {
|
}: {
|
||||||
@ -85,7 +87,7 @@ export function NavHoverMenu({
|
|||||||
mx="-md"
|
mx="-md"
|
||||||
color={theme.colorScheme === 'dark' ? 'dark.5' : 'gray.1'}
|
color={theme.colorScheme === 'dark' ? 'dark.5' : 'gray.1'}
|
||||||
/>
|
/>
|
||||||
<MenuLinks links={menuItems} highlighted={true} />
|
<MenuLinks links={onlyItems} highlighted={true} />
|
||||||
<div className={classes.headerDropdownFooter}>
|
<div className={classes.headerDropdownFooter}>
|
||||||
<Group position="apart">
|
<Group position="apart">
|
||||||
<div>
|
<div>
|
||||||
|
@ -18,6 +18,7 @@ import { MenuLinkItem, MenuLinks } from '../items/MenuLinks';
|
|||||||
|
|
||||||
// TODO @matmair #1: implement plugin loading and menu item generation see #5269
|
// TODO @matmair #1: implement plugin loading and menu item generation see #5269
|
||||||
const plugins: MenuLinkItem[] = [];
|
const plugins: MenuLinkItem[] = [];
|
||||||
|
const onlyItems = Object.values(menuItems);
|
||||||
|
|
||||||
export function NavigationDrawer({
|
export function NavigationDrawer({
|
||||||
opened,
|
opened,
|
||||||
@ -60,7 +61,7 @@ function DrawerContent() {
|
|||||||
<Container className={classes.layoutContent} p={0}>
|
<Container className={classes.layoutContent} p={0}>
|
||||||
<ScrollArea h={scrollHeight} type="always" offsetScrollbars>
|
<ScrollArea h={scrollHeight} type="always" offsetScrollbars>
|
||||||
<Title order={5}>{t`Pages`}</Title>
|
<Title order={5}>{t`Pages`}</Title>
|
||||||
<MenuLinks links={menuItems} />
|
<MenuLinks links={onlyItems} />
|
||||||
<Space h="md" />
|
<Space h="md" />
|
||||||
{plugins.length > 0 ? (
|
{plugins.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
|
40
src/frontend/src/defaults/actions.tsx
Normal file
40
src/frontend/src/defaults/actions.tsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { t } from '@lingui/macro';
|
||||||
|
import type { SpotlightAction } from '@mantine/spotlight';
|
||||||
|
import { IconFileText, IconHome, IconInfoCircle } from '@tabler/icons-react';
|
||||||
|
import { NavigateFunction } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { menuItems } from './menuItems';
|
||||||
|
|
||||||
|
export function getActions(navigate: NavigateFunction) {
|
||||||
|
/**
|
||||||
|
* Default actions for the spotlight
|
||||||
|
*/
|
||||||
|
const actions: SpotlightAction[] = [
|
||||||
|
{
|
||||||
|
title: t`Home`,
|
||||||
|
description: `Go to the home page`,
|
||||||
|
onTrigger: (action) => navigate(menuItems.home.link),
|
||||||
|
icon: <IconHome size="1.2rem" />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t`Dashboard`,
|
||||||
|
description: t`Go to the InvenTree dashboard`,
|
||||||
|
onTrigger: () => navigate(menuItems.dashboard.link),
|
||||||
|
icon: <IconHome size="1.2rem" />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t`Documentation`,
|
||||||
|
description: t`Visit documentation to learn more about InvenTree`,
|
||||||
|
onTrigger: () => console.log('Documentation'),
|
||||||
|
icon: <IconFileText size="1.2rem" />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t`About InvenTree`,
|
||||||
|
description: t`About the InvenTree org`,
|
||||||
|
onTrigger: () => navigate(menuItems.about.link),
|
||||||
|
icon: <IconInfoCircle size="1.2rem" />
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return actions;
|
||||||
|
}
|
@ -1,75 +1,75 @@
|
|||||||
import { Trans } from '@lingui/macro';
|
import { Trans } from '@lingui/macro';
|
||||||
|
|
||||||
import { MenuLinkItem } from '../components/items/MenuLinks';
|
import { menuItemsCollection } from '../components/items/MenuLinks';
|
||||||
import { IS_DEV_OR_DEMO } from '../main';
|
import { IS_DEV_OR_DEMO } from '../main';
|
||||||
|
|
||||||
export const menuItems: MenuLinkItem[] = [
|
export const menuItems: menuItemsCollection = {
|
||||||
{
|
home: {
|
||||||
id: 'home',
|
id: 'home',
|
||||||
text: <Trans>Home</Trans>,
|
text: <Trans>Home</Trans>,
|
||||||
link: '/',
|
link: '/',
|
||||||
highlight: true
|
highlight: true
|
||||||
},
|
},
|
||||||
{
|
profile: {
|
||||||
id: 'profile',
|
id: 'profile',
|
||||||
text: <Trans>Account settings</Trans>,
|
text: <Trans>Account settings</Trans>,
|
||||||
link: '/settings/user',
|
link: '/settings/user',
|
||||||
doctext: <Trans>User attributes and design settings.</Trans>
|
doctext: <Trans>User attributes and design settings.</Trans>
|
||||||
},
|
},
|
||||||
{
|
scan: {
|
||||||
id: 'scan',
|
id: 'scan',
|
||||||
text: <Trans>Scanning</Trans>,
|
text: <Trans>Scanning</Trans>,
|
||||||
link: '/scan',
|
link: '/scan',
|
||||||
doctext: <Trans>View for interactive scanning and multiple actions.</Trans>,
|
doctext: <Trans>View for interactive scanning and multiple actions.</Trans>,
|
||||||
highlight: true
|
highlight: true
|
||||||
},
|
},
|
||||||
{
|
dashboard: {
|
||||||
id: 'dashboard',
|
id: 'dashboard',
|
||||||
text: <Trans>Dashboard</Trans>,
|
text: <Trans>Dashboard</Trans>,
|
||||||
link: '/dashboard'
|
link: '/dashboard'
|
||||||
},
|
},
|
||||||
{
|
parts: {
|
||||||
id: 'parts',
|
id: 'parts',
|
||||||
text: <Trans>Parts</Trans>,
|
text: <Trans>Parts</Trans>,
|
||||||
link: '/part/'
|
link: '/part/'
|
||||||
},
|
},
|
||||||
{
|
stock: {
|
||||||
id: 'stock',
|
id: 'stock',
|
||||||
text: <Trans>Stock</Trans>,
|
text: <Trans>Stock</Trans>,
|
||||||
link: '/stock'
|
link: '/stock'
|
||||||
},
|
},
|
||||||
{
|
build: {
|
||||||
id: 'build',
|
id: 'build',
|
||||||
text: <Trans>Build</Trans>,
|
text: <Trans>Build</Trans>,
|
||||||
link: '/build/'
|
link: '/build/'
|
||||||
},
|
},
|
||||||
{
|
purchasing: {
|
||||||
id: 'purchasing',
|
id: 'purchasing',
|
||||||
text: <Trans>Purchasing</Trans>,
|
text: <Trans>Purchasing</Trans>,
|
||||||
link: '/purchasing/'
|
link: '/purchasing/'
|
||||||
},
|
},
|
||||||
{
|
sales: {
|
||||||
id: 'sales',
|
id: 'sales',
|
||||||
text: <Trans>Sales</Trans>,
|
text: <Trans>Sales</Trans>,
|
||||||
link: '/sales/'
|
link: '/sales/'
|
||||||
},
|
},
|
||||||
{
|
'settings-system': {
|
||||||
id: 'settings-system',
|
id: 'settings-system',
|
||||||
text: <Trans>System Settings</Trans>,
|
text: <Trans>System Settings</Trans>,
|
||||||
link: '/settings/system'
|
link: '/settings/system'
|
||||||
},
|
},
|
||||||
{
|
'settings-admin': {
|
||||||
id: 'settings-admin',
|
id: 'settings-admin',
|
||||||
text: <Trans>Admin Center</Trans>,
|
text: <Trans>Admin Center</Trans>,
|
||||||
link: '/settings/admin'
|
link: '/settings/admin'
|
||||||
}
|
}
|
||||||
];
|
};
|
||||||
|
|
||||||
if (IS_DEV_OR_DEMO) {
|
if (IS_DEV_OR_DEMO) {
|
||||||
menuItems.push({
|
menuItems['playground'] = {
|
||||||
id: 'playground',
|
id: 'playground',
|
||||||
text: <Trans>Playground</Trans>,
|
text: <Trans>Playground</Trans>,
|
||||||
link: '/playground',
|
link: '/playground',
|
||||||
highlight: true
|
highlight: true
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user