2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-01 19:20:55 +00:00

feat(PUI): Make header tabs links to simpilfy new tab behaviour (#8779)

* add anchor element to tabs to enable opening in new tab

* simplify

* use unstyled button instead

* also enable linking on nav panels

* make sure metakey also works (reduces duplication)

* remove headers changes

* move check for modified key to lib

* render nav items as link

---------

Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
Matthias Mair
2025-06-25 17:07:32 +02:00
committed by GitHub
parent be99b645ad
commit 83b6653d78
6 changed files with 47 additions and 14 deletions

View File

@ -72,7 +72,7 @@ export const navigateToLink = (
const base = `/${getBaseUrl()}`;
if (event?.ctrlKey || event?.shiftKey) {
if (eventModified(event)) {
// Open the link in a new tab
let url = link;
if (link.startsWith('/') && !link.startsWith(base)) {
@ -91,3 +91,14 @@ export const navigateToLink = (
navigate(url);
}
};
/**
* Check if the event is modified (e.g. ctrl, shift, or meta key pressed)
* @param event - The event to check
* @returns true if the event was modified
*/
export const eventModified = (
event: React.MouseEvent<HTMLButtonElement | HTMLAnchorElement>
) => {
return event?.ctrlKey || event?.shiftKey || event?.metaKey;
};

View File

@ -4,6 +4,7 @@ import { useCallback, useMemo } from 'react';
import { ModelInformationDict } from '@lib/enums/ModelInformation';
import type { ModelType } from '@lib/enums/ModelType';
import { eventModified } from '@lib/functions/Navigation';
import { generateUrl } from '../../functions/urls';
import { useServerApiState } from '../../states/ApiState';
import { useUserState } from '../../states/UserState';
@ -66,7 +67,7 @@ export default function AdminButton(props: Readonly<AdminButtonProps>) {
`${server.server.django_admin}${modelDef.admin_url}${props.id}/`
);
if (event?.ctrlKey || event?.shiftKey) {
if (eventModified(event)) {
// Open the link in a new tab
window.open(url, '_blank');
} else {

View File

@ -5,7 +5,8 @@ import {
Indicator,
Tabs,
Text,
Tooltip
Tooltip,
UnstyledButton
} from '@mantine/core';
import { useDisclosure, useDocumentVisibility } from '@mantine/hooks';
import { IconBell, IconSearch } from '@tabler/icons-react';
@ -15,12 +16,14 @@ import { useMatch, useNavigate } from 'react-router-dom';
import { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import { apiUrl } from '@lib/functions/Api';
import { getBaseUrl } from '@lib/functions/Navigation';
import { navigateToLink } from '@lib/functions/Navigation';
import { t } from '@lingui/core/macro';
import { useShallow } from 'zustand/react/shallow';
import { api } from '../../App';
import type { NavigationUIFeature } from '../../components/plugins/PluginUIFeatureTypes';
import { getNavTabs } from '../../defaults/links';
import { generateUrl } from '../../functions/urls';
import { usePluginUIFeature } from '../../hooks/UsePluginUIFeature';
import * as classes from '../../main.css';
import { useServerApiState } from '../../states/ApiState';
@ -215,7 +218,12 @@ function NavTabs() {
navigateToLink(`/${tab.name}`, navigate, event)
}
>
{tab.title}
<UnstyledButton
component={'a'}
href={generateUrl(`/${getBaseUrl()}/${tab.name}`)}
>
{tab.title}
</UnstyledButton>
</Tabs.Tab>
);
});

View File

@ -24,8 +24,11 @@ import { useNavigate } from 'react-router-dom';
import type { ApiEndpoints } from '@lib/enums/ApiEndpoints';
import type { ModelType } from '@lib/enums/ModelType';
import { apiUrl } from '@lib/functions/Api';
import { getDetailUrl } from '@lib/functions/Navigation';
import { navigateToLink } from '@lib/functions/Navigation';
import {
eventModified,
getDetailUrl,
navigateToLink
} from '@lib/functions/Navigation';
import { useApi } from '../../contexts/ApiContext';
import { ApiIcon } from '../items/ApiIcon';
import { StylishText } from '../items/StylishText';
@ -73,7 +76,7 @@ export default function NavigationTree({
const follow = useCallback(
(node: TreeNodeData, event?: any) => {
const url = getDetailUrl(modelType, node.value);
if (event?.shiftKey || event?.ctrlKey) {
if (eventModified(event)) {
navigateToLink(url, navigate, event);
} else {
onClose();

View File

@ -38,7 +38,7 @@ import { ModelType } from '@lib/enums/ModelType';
import { UserRoles } from '@lib/enums/Roles';
import { apiUrl } from '@lib/functions/Api';
import { cancelEvent } from '@lib/functions/Events';
import { navigateToLink } from '@lib/functions/Navigation';
import { eventModified, navigateToLink } from '@lib/functions/Navigation';
import { showNotification } from '@mantine/notifications';
import { api } from '../../App';
import { useUserSettingsState } from '../../states/SettingsState';
@ -96,7 +96,7 @@ function QueryResultGroup({
const url = `${overviewUrl}?search=${searchText}`;
// Close drawer if opening in the same tab
if (!(event?.ctrlKey || event?.shiftKey)) {
if (!eventModified(event)) {
onClose();
}
@ -456,7 +456,7 @@ export function SearchDrawer({
return;
}
if (event?.ctrlKey || event?.shiftKey) {
if (eventModified(event)) {
// Keep the drawer open in this condition
} else {
closeDrawer();

View File

@ -8,7 +8,8 @@ import {
Stack,
Tabs,
Text,
Tooltip
Tooltip,
UnstyledButton
} from '@mantine/core';
import {
IconLayoutSidebarLeftCollapse,
@ -32,10 +33,12 @@ import {
import type { ModelType } from '@lib/enums/ModelType';
import { cancelEvent } from '@lib/functions/Events';
import { eventModified, getBaseUrl } from '@lib/functions/Navigation';
import { navigateToLink } from '@lib/functions/Navigation';
import { t } from '@lingui/core/macro';
import { useShallow } from 'zustand/react/shallow';
import { identifierString } from '../../functions/conversion';
import { generateUrl } from '../../functions/urls';
import { usePluginPanels } from '../../hooks/UsePluginPanels';
import { useLocalState } from '../../states/LocalState';
import { vars } from '../../theme';
@ -170,9 +173,9 @@ function BasePanelGroup({
// Callback when the active panel changes
const handlePanelChange = useCallback(
(targetPanel: string, event?: any) => {
if (event && (event?.ctrlKey || event?.shiftKey)) {
cancelEvent(event);
if (event && eventModified(event)) {
const url = `${location.pathname}/../${targetPanel}`;
cancelEvent(event);
navigateToLink(url, navigate, event);
} else {
navigate(`../${targetPanel}`);
@ -252,7 +255,14 @@ function BasePanelGroup({
handlePanelChange(panel.name, event)
}
>
{expanded && panel.label}
<UnstyledButton
component={'a'}
href={generateUrl(
`/${getBaseUrl()}${location.pathname}/${panel.name}`
)}
>
{expanded && panel.label}
</UnstyledButton>
</Tabs.Tab>
</Tooltip>
)