mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[PUI] Mantine tree (#7357)
* Refactor part category tree - New "NavigationTree" using native mantine components - Make it generic, too * Replace existing <StockLocationTree /> component * Adjust API filtering for location tree endpoint * Added playwright tests * Update api filter classes * Fix for DetailsImage - Update to @mantine/core had changed the <AspectRatio> component * fix for identifierString function * Adjust playwright tests
This commit is contained in:
parent
c90ee43808
commit
f3223c6d7f
@ -166,3 +166,5 @@ SEARCH_ORDER_FILTER_ALIAS = [
|
||||
]
|
||||
|
||||
ORDER_FILTER = [rest_filters.DjangoFilterBackend, filters.OrderingFilter]
|
||||
|
||||
ORDER_FILTER_ALIAS = [rest_filters.DjangoFilterBackend, InvenTreeOrderingFilter]
|
||||
|
@ -26,6 +26,7 @@ from InvenTree.api import (
|
||||
)
|
||||
from InvenTree.filters import (
|
||||
ORDER_FILTER,
|
||||
ORDER_FILTER_ALIAS,
|
||||
SEARCH_ORDER_FILTER,
|
||||
SEARCH_ORDER_FILTER_ALIAS,
|
||||
InvenTreeDateFilter,
|
||||
@ -303,10 +304,12 @@ class CategoryTree(ListAPI):
|
||||
queryset = PartCategory.objects.all()
|
||||
serializer_class = part_serializers.CategoryTree
|
||||
|
||||
filter_backends = ORDER_FILTER
|
||||
filter_backends = ORDER_FILTER_ALIAS
|
||||
|
||||
ordering_fields = ['level', 'name', 'subcategories']
|
||||
|
||||
ordering_field_aliases = {'level': ['level', 'name'], 'name': ['name', 'level']}
|
||||
|
||||
# Order by tree level (top levels first) and then name
|
||||
ordering = ['level', 'name']
|
||||
|
||||
|
@ -35,7 +35,7 @@ from InvenTree.api import (
|
||||
MetadataView,
|
||||
)
|
||||
from InvenTree.filters import (
|
||||
ORDER_FILTER,
|
||||
ORDER_FILTER_ALIAS,
|
||||
SEARCH_ORDER_FILTER,
|
||||
SEARCH_ORDER_FILTER_ALIAS,
|
||||
InvenTreeDateFilter,
|
||||
@ -429,13 +429,15 @@ class StockLocationTree(ListAPI):
|
||||
queryset = StockLocation.objects.all()
|
||||
serializer_class = StockSerializers.LocationTreeSerializer
|
||||
|
||||
filter_backends = ORDER_FILTER
|
||||
filter_backends = ORDER_FILTER_ALIAS
|
||||
|
||||
ordering_fields = ['level', 'name', 'sublocations']
|
||||
|
||||
# Order by tree level (top levels first) and then name
|
||||
ordering = ['level', 'name']
|
||||
|
||||
ordering_field_aliases = {'level': ['level', 'name'], 'name': ['name', 'level']}
|
||||
|
||||
def get_queryset(self, *args, **kwargs):
|
||||
"""Return annotated queryset for the StockLocationTree endpoint."""
|
||||
queryset = super().get_queryset(*args, **kwargs)
|
||||
|
@ -27,7 +27,7 @@
|
||||
"@lingui/core": "^4.10.0",
|
||||
"@lingui/react": "^4.10.0",
|
||||
"@mantine/carousel": "^7.8.0",
|
||||
"@mantine/core": "^7.8.0",
|
||||
"@mantine/core": "^7.10.0",
|
||||
"@mantine/dates": "^7.8.0",
|
||||
"@mantine/dropzone": "^7.8.0",
|
||||
"@mantine/form": "^7.8.0",
|
||||
@ -36,7 +36,6 @@
|
||||
"@mantine/notifications": "^7.8.0",
|
||||
"@mantine/spotlight": "^7.8.0",
|
||||
"@mantine/vanilla-extract": "^7.8.0",
|
||||
"@naisutech/react-tree": "^3.1.0",
|
||||
"@sentry/react": "^7.110.0",
|
||||
"@tabler/icons-react": "^3.2.0",
|
||||
"@tanstack/react-query": "^5.29.2",
|
||||
@ -60,7 +59,7 @@
|
||||
"react-router-dom": "^6.22.3",
|
||||
"react-select": "^5.8.0",
|
||||
"react-simplemde-editor": "^5.2.0",
|
||||
"recharts": "^2.12.4",
|
||||
"recharts": "2",
|
||||
"styled-components": "^6.1.8",
|
||||
"zustand": "^4.5.2"
|
||||
},
|
||||
|
@ -355,7 +355,7 @@ export function DetailsImage(props: Readonly<DetailImageProps>) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<AspectRatio ref={ref} maw={IMAGE_DIMENSION} ratio={1}>
|
||||
<AspectRatio ref={ref} maw={IMAGE_DIMENSION} ratio={1} pos="relative">
|
||||
<>
|
||||
<ApiImage
|
||||
src={img}
|
||||
|
@ -10,6 +10,7 @@ import { IconMenu2 } from '@tabler/icons-react';
|
||||
import { useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { identifierString } from '../../functions/conversion';
|
||||
import { navigateToLink } from '../../functions/navigation';
|
||||
|
||||
export type Breadcrumb = {
|
||||
@ -47,7 +48,8 @@ export function BreadcrumbList({
|
||||
<Group gap="xs">
|
||||
{navCallback && (
|
||||
<ActionIcon
|
||||
key="nav-action"
|
||||
key="nav-breadcrumb-action"
|
||||
aria-label="nav-breadcrumb-action"
|
||||
onClick={navCallback}
|
||||
variant="transparent"
|
||||
>
|
||||
@ -59,6 +61,9 @@ export function BreadcrumbList({
|
||||
return (
|
||||
<Anchor
|
||||
key={index}
|
||||
aria-label={`breadcrumb-${index}-${identifierString(
|
||||
breadcrumb.name
|
||||
)}`}
|
||||
onClick={(event: any) =>
|
||||
breadcrumb.url &&
|
||||
navigateToLink(breadcrumb.url, navigate, event)
|
||||
|
205
src/frontend/src/components/nav/NavigationTree.tsx
Normal file
205
src/frontend/src/components/nav/NavigationTree.tsx
Normal file
@ -0,0 +1,205 @@
|
||||
import {
|
||||
ActionIcon,
|
||||
Anchor,
|
||||
Divider,
|
||||
Drawer,
|
||||
Group,
|
||||
LoadingOverlay,
|
||||
RenderTreeNodePayload,
|
||||
Space,
|
||||
Stack,
|
||||
Tree,
|
||||
TreeNodeData,
|
||||
useTree
|
||||
} from '@mantine/core';
|
||||
import {
|
||||
IconChevronDown,
|
||||
IconChevronRight,
|
||||
IconPoint,
|
||||
IconSitemap
|
||||
} from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { navigateToLink } from '../../functions/navigation';
|
||||
import { getDetailUrl } from '../../functions/urls';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
|
||||
/*
|
||||
* A generic navigation tree component.
|
||||
*/
|
||||
export default function NavigationTree({
|
||||
title,
|
||||
opened,
|
||||
onClose,
|
||||
selectedId,
|
||||
modelType,
|
||||
endpoint
|
||||
}: {
|
||||
title: string;
|
||||
opened: boolean;
|
||||
onClose: () => void;
|
||||
selectedId?: number | null;
|
||||
modelType: ModelType;
|
||||
endpoint: ApiEndpoints;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const treeState = useTree();
|
||||
|
||||
// Data query to fetch the tree data from server
|
||||
const query = useQuery({
|
||||
enabled: opened,
|
||||
queryKey: [modelType, opened],
|
||||
queryFn: async () =>
|
||||
api
|
||||
.get(apiUrl(endpoint), {
|
||||
data: {
|
||||
ordering: 'level'
|
||||
}
|
||||
})
|
||||
.then((response) => response.data ?? [])
|
||||
.catch((error) => {
|
||||
console.error(`Error fetching ${modelType} tree`);
|
||||
return [];
|
||||
})
|
||||
});
|
||||
|
||||
const follow = useCallback(
|
||||
(node: TreeNodeData, event?: any) => {
|
||||
const url = getDetailUrl(modelType, node.value);
|
||||
if (event?.shiftKey || event?.ctrlKey) {
|
||||
navigateToLink(url, navigate, event);
|
||||
} else {
|
||||
onClose();
|
||||
navigate(url);
|
||||
}
|
||||
},
|
||||
[modelType, navigate]
|
||||
);
|
||||
|
||||
// Map returned query to a "tree" structure
|
||||
const data: TreeNodeData[] = useMemo(() => {
|
||||
/*
|
||||
* Reconstruct the navigation tree from the provided data.
|
||||
* It is required (and assumed) that the data is first sorted by level.
|
||||
*/
|
||||
|
||||
let nodes: Record<number, any> = {};
|
||||
let tree: TreeNodeData[] = [];
|
||||
|
||||
if (!query?.data?.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
for (let ii = 0; ii < query.data.length; ii++) {
|
||||
let node = {
|
||||
...query.data[ii],
|
||||
children: [],
|
||||
label: query.data[ii].name,
|
||||
value: query.data[ii].pk.toString(),
|
||||
selected: query.data[ii].pk === selectedId
|
||||
};
|
||||
|
||||
const pk: number = node.pk;
|
||||
const parent: number | null = node.parent;
|
||||
|
||||
if (!parent) {
|
||||
// This is a top level node
|
||||
tree.push(node);
|
||||
} else {
|
||||
// This is *not* a top level node, so the parent *must* already exist
|
||||
nodes[parent]?.children.push(node);
|
||||
}
|
||||
|
||||
// Finally, add this node
|
||||
nodes[pk] = node;
|
||||
|
||||
if (pk === selectedId) {
|
||||
// Expand all parents
|
||||
let parent = nodes[node.parent];
|
||||
while (parent) {
|
||||
parent.expanded = true;
|
||||
parent = nodes[parent.parent];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tree;
|
||||
}, [selectedId, query.data]);
|
||||
|
||||
const renderNode = useCallback(
|
||||
(payload: RenderTreeNodePayload) => {
|
||||
return (
|
||||
<Group
|
||||
justify="left"
|
||||
key={payload.node.value}
|
||||
wrap="nowrap"
|
||||
onClick={() => {
|
||||
if (payload.hasChildren) {
|
||||
treeState.toggleExpanded(payload.node.value);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Space w={5 * payload.level} />
|
||||
<ActionIcon
|
||||
size="sm"
|
||||
variant="transparent"
|
||||
aria-label={`nav-tree-toggle-${payload.node.value}}`}
|
||||
>
|
||||
{payload.hasChildren ? (
|
||||
payload.expanded ? (
|
||||
<IconChevronDown />
|
||||
) : (
|
||||
<IconChevronRight />
|
||||
)
|
||||
) : (
|
||||
<IconPoint />
|
||||
)}
|
||||
</ActionIcon>
|
||||
<Anchor
|
||||
onClick={(event: any) => follow(payload.node, event)}
|
||||
aria-label={`nav-tree-item-${payload.node.value}`}
|
||||
>
|
||||
{payload.node.label}
|
||||
</Anchor>
|
||||
</Group>
|
||||
);
|
||||
},
|
||||
[treeState]
|
||||
);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
opened={opened}
|
||||
size="md"
|
||||
position="left"
|
||||
onClose={onClose}
|
||||
withCloseButton={true}
|
||||
styles={{
|
||||
header: {
|
||||
width: '100%'
|
||||
},
|
||||
title: {
|
||||
width: '100%'
|
||||
}
|
||||
}}
|
||||
title={
|
||||
<Group justify="left" p="ms" gap="md" wrap="nowrap">
|
||||
<IconSitemap />
|
||||
<StylishText size="lg">{title}</StylishText>
|
||||
</Group>
|
||||
}
|
||||
>
|
||||
<Stack gap="xs">
|
||||
<Divider />
|
||||
<LoadingOverlay visible={query.isFetching || query.isLoading} />
|
||||
<Tree data={data} tree={treeState} renderNode={renderNode} />
|
||||
</Stack>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
@ -20,6 +20,7 @@ import {
|
||||
useParams
|
||||
} from 'react-router-dom';
|
||||
|
||||
import { identifierString } from '../../functions/conversion';
|
||||
import { navigateToLink } from '../../functions/navigation';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
import { Boundary } from '../Boundary';
|
||||
@ -172,6 +173,9 @@ function BasePanelGroup({
|
||||
<Tabs.Panel
|
||||
key={panel.name}
|
||||
value={panel.name}
|
||||
aria-label={`nav-panel-${identifierString(
|
||||
`${pageKey}-${panel.name}`
|
||||
)}`}
|
||||
p="sm"
|
||||
style={{
|
||||
overflowX: 'scroll',
|
||||
|
@ -1,176 +0,0 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import {
|
||||
Drawer,
|
||||
Group,
|
||||
LoadingOverlay,
|
||||
Stack,
|
||||
Text,
|
||||
useMantineColorScheme
|
||||
} from '@mantine/core';
|
||||
import { ReactTree, ThemeSettings } from '@naisutech/react-tree';
|
||||
import {
|
||||
IconChevronDown,
|
||||
IconChevronRight,
|
||||
IconSitemap
|
||||
} from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useMemo } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { theme, vars } from '../../theme';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
|
||||
export function PartCategoryTree({
|
||||
opened,
|
||||
onClose,
|
||||
selectedCategory
|
||||
}: {
|
||||
opened: boolean;
|
||||
onClose: () => void;
|
||||
selectedCategory?: number | null;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const treeQuery = useQuery({
|
||||
enabled: opened,
|
||||
queryKey: ['part_category_tree', opened],
|
||||
queryFn: async () =>
|
||||
api
|
||||
.get(apiUrl(ApiEndpoints.category_tree), {})
|
||||
.then((response) =>
|
||||
response.data.map((category: any) => {
|
||||
return {
|
||||
id: category.pk,
|
||||
label: category.name,
|
||||
parentId: category.parent,
|
||||
children: category.subcategories
|
||||
};
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
console.error('Error fetching part category tree:', error);
|
||||
return [];
|
||||
}),
|
||||
refetchOnMount: true
|
||||
});
|
||||
|
||||
function renderNode({ node }: { node: any }) {
|
||||
return (
|
||||
<Group
|
||||
justify="space-between"
|
||||
key={node.id}
|
||||
wrap="nowrap"
|
||||
onClick={() => {
|
||||
onClose();
|
||||
navigate(`/part/category/${node.id}`);
|
||||
}}
|
||||
>
|
||||
<Text>{node.label}</Text>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
function renderIcon({ node, open }: { node: any; open?: boolean }) {
|
||||
if (node.children == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return open ? <IconChevronDown /> : <IconChevronRight />;
|
||||
}
|
||||
|
||||
const { colorScheme } = useMantineColorScheme();
|
||||
|
||||
const themes: ThemeSettings = useMemo(() => {
|
||||
const currentTheme =
|
||||
colorScheme === 'dark'
|
||||
? vars.colors.defaultColor
|
||||
: vars.colors.primaryColors;
|
||||
|
||||
return {
|
||||
dark: {
|
||||
text: {
|
||||
fontFamily: vars.fontFamily,
|
||||
//fontSize: vars.fontSizes.md,
|
||||
color: vars.colors.text
|
||||
},
|
||||
nodes: {
|
||||
height: '2.5rem',
|
||||
folder: {
|
||||
selectedBgColor: currentTheme[4],
|
||||
hoverBgColor: currentTheme[6]
|
||||
},
|
||||
leaf: {
|
||||
selectedBgColor: currentTheme[4],
|
||||
hoverBgColor: currentTheme[6]
|
||||
},
|
||||
icons: {
|
||||
folderColor: currentTheme[3],
|
||||
leafColor: currentTheme[3]
|
||||
}
|
||||
}
|
||||
},
|
||||
light: {
|
||||
text: {
|
||||
fontFamily: vars.fontFamily,
|
||||
//fontSize: vars.fontSizes.md,
|
||||
color: vars.colors.text
|
||||
},
|
||||
nodes: {
|
||||
height: '2.5rem',
|
||||
folder: {
|
||||
selectedBgColor: currentTheme[4],
|
||||
hoverBgColor: currentTheme[2]
|
||||
},
|
||||
leaf: {
|
||||
selectedBgColor: currentTheme[4],
|
||||
hoverBgColor: currentTheme[2]
|
||||
},
|
||||
icons: {
|
||||
folderColor: currentTheme[8],
|
||||
leafColor: currentTheme[6]
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}, [theme]);
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
opened={opened}
|
||||
size="md"
|
||||
position="left"
|
||||
onClose={onClose}
|
||||
withCloseButton={true}
|
||||
styles={{
|
||||
header: {
|
||||
width: '100%'
|
||||
},
|
||||
title: {
|
||||
width: '100%'
|
||||
}
|
||||
}}
|
||||
title={
|
||||
<Group justify="left" p="ms" gap="md" wrap="nowrap">
|
||||
<IconSitemap />
|
||||
<StylishText size="lg">{t`Part Categories`}</StylishText>
|
||||
</Group>
|
||||
}
|
||||
>
|
||||
<Stack gap="xs">
|
||||
<LoadingOverlay visible={treeQuery.isFetching} />
|
||||
<ReactTree
|
||||
nodes={treeQuery.data ?? []}
|
||||
RenderNode={renderNode}
|
||||
RenderIcon={renderIcon}
|
||||
defaultSelectedNodes={selectedCategory ? [selectedCategory] : []}
|
||||
showEmptyItems={false}
|
||||
theme={colorScheme}
|
||||
themes={themes}
|
||||
/>
|
||||
</Stack>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import { Drawer, Group, LoadingOverlay, Stack, Text } from '@mantine/core';
|
||||
import { ReactTree } from '@naisutech/react-tree';
|
||||
import {
|
||||
IconChevronDown,
|
||||
IconChevronRight,
|
||||
IconSitemap
|
||||
} from '@tabler/icons-react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { api } from '../../App';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { apiUrl } from '../../states/ApiState';
|
||||
import { StylishText } from '../items/StylishText';
|
||||
|
||||
export function StockLocationTree({
|
||||
opened,
|
||||
onClose,
|
||||
selectedLocation
|
||||
}: {
|
||||
opened: boolean;
|
||||
onClose: () => void;
|
||||
selectedLocation?: number | null;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const treeQuery = useQuery({
|
||||
enabled: opened,
|
||||
queryKey: ['stock_location_tree', opened],
|
||||
queryFn: async () =>
|
||||
api
|
||||
.get(apiUrl(ApiEndpoints.stock_location_tree), {})
|
||||
.then((response) =>
|
||||
response.data.map((location: any) => {
|
||||
return {
|
||||
id: location.pk,
|
||||
label: location.name,
|
||||
parentId: location.parent,
|
||||
children: location.sublocations
|
||||
};
|
||||
})
|
||||
)
|
||||
.catch((error) => {
|
||||
console.error('Error fetching stock location tree:', error);
|
||||
return [];
|
||||
}),
|
||||
refetchOnMount: true
|
||||
});
|
||||
|
||||
function renderNode({ node }: { node: any }) {
|
||||
return (
|
||||
<Group
|
||||
justify="space-between"
|
||||
key={node.id}
|
||||
wrap="nowrap"
|
||||
onClick={() => {
|
||||
onClose();
|
||||
navigate(`/stock/location/${node.id}`);
|
||||
}}
|
||||
>
|
||||
<Text>{node.label}</Text>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
function renderIcon({ node, open }: { node: any; open?: boolean }) {
|
||||
if (node.children == 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return open ? <IconChevronDown /> : <IconChevronRight />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
opened={opened}
|
||||
size="md"
|
||||
position="left"
|
||||
onClose={onClose}
|
||||
withCloseButton={true}
|
||||
styles={{
|
||||
header: {
|
||||
width: '100%'
|
||||
},
|
||||
title: {
|
||||
width: '100%'
|
||||
}
|
||||
}}
|
||||
title={
|
||||
<Group justify="left" wrap="nowrap" gap="md" p="md">
|
||||
<IconSitemap />
|
||||
<StylishText size="lg">{t`Stock Locations`}</StylishText>
|
||||
</Group>
|
||||
}
|
||||
>
|
||||
<Stack gap="xs">
|
||||
<LoadingOverlay visible={treeQuery.isFetching} />
|
||||
<ReactTree
|
||||
nodes={treeQuery.data ?? []}
|
||||
showEmptyItems={false}
|
||||
RenderNode={renderNode}
|
||||
RenderIcon={renderIcon}
|
||||
defaultSelectedNodes={selectedLocation ? [selectedLocation] : []}
|
||||
/>
|
||||
</Stack>
|
||||
</Drawer>
|
||||
);
|
||||
}
|
@ -35,5 +35,8 @@ export function resolveItem(obj: any, path: string): any {
|
||||
|
||||
export function identifierString(value: string): string {
|
||||
// Convert an input string e.g. "Hello World" into a string that can be used as an identifier, e.g. "hello-world"
|
||||
|
||||
value = value || '-';
|
||||
|
||||
return value.toLowerCase().replace(/[^a-z0-9]/g, '-');
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ import {
|
||||
DeleteItemAction,
|
||||
EditItemAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import NavigationTree from '../../components/nav/NavigationTree';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { UserRoles } from '../../enums/Roles';
|
||||
@ -277,12 +277,15 @@ export default function CategoryDetail({}: {}) {
|
||||
{deleteCategory.modal}
|
||||
<Stack gap="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PartCategoryTree
|
||||
<NavigationTree
|
||||
modelType={ModelType.partcategory}
|
||||
title={t`Part Categories`}
|
||||
endpoint={ApiEndpoints.category_tree}
|
||||
opened={treeOpen}
|
||||
onClose={() => {
|
||||
setTreeOpen(false);
|
||||
}}
|
||||
selectedCategory={category?.pk}
|
||||
selectedId={category?.pk}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Part Category`}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { t } from '@lingui/macro';
|
||||
import {
|
||||
Alert,
|
||||
Divider,
|
||||
Grid,
|
||||
LoadingOverlay,
|
||||
Skeleton,
|
||||
@ -51,9 +52,9 @@ import {
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import NavigationTree from '../../components/nav/NavigationTree';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { PartCategoryTree } from '../../components/nav/PartCategoryTree';
|
||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||
import { formatPriceRange } from '../../defaults/formatters';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
@ -817,12 +818,15 @@ export default function PartDetail() {
|
||||
{deletePart.modal}
|
||||
<Stack gap="xs">
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<PartCategoryTree
|
||||
<NavigationTree
|
||||
title={t`Part Categories`}
|
||||
modelType={ModelType.partcategory}
|
||||
endpoint={ApiEndpoints.category_tree}
|
||||
opened={treeOpen}
|
||||
onClose={() => {
|
||||
setTreeOpen(false);
|
||||
}}
|
||||
selectedCategory={part?.category}
|
||||
selectedId={part?.category}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Part` + ': ' + part.full_name}
|
||||
|
@ -23,9 +23,9 @@ import {
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import NavigationTree from '../../components/nav/NavigationTree';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
import { ModelType } from '../../enums/ModelType';
|
||||
import { UserRoles } from '../../enums/Roles';
|
||||
@ -357,10 +357,13 @@ export default function Stock() {
|
||||
{deleteLocation.modal}
|
||||
<Stack>
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<StockLocationTree
|
||||
<NavigationTree
|
||||
title={t`Stock Locations`}
|
||||
modelType={ModelType.stocklocation}
|
||||
endpoint={ApiEndpoints.stock_location_tree}
|
||||
opened={treeOpen}
|
||||
onClose={() => setTreeOpen(false)}
|
||||
selectedLocation={location?.pk}
|
||||
selectedId={location?.pk}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Stock Items`}
|
||||
|
@ -31,9 +31,9 @@ import {
|
||||
UnlinkBarcodeAction,
|
||||
ViewBarcodeAction
|
||||
} from '../../components/items/ActionDropdown';
|
||||
import NavigationTree from '../../components/nav/NavigationTree';
|
||||
import { PageDetail } from '../../components/nav/PageDetail';
|
||||
import { PanelGroup, PanelType } from '../../components/nav/PanelGroup';
|
||||
import { StockLocationTree } from '../../components/nav/StockLocationTree';
|
||||
import { StatusRenderer } from '../../components/render/StatusRenderer';
|
||||
import { NotesEditor } from '../../components/widgets/MarkdownEditor';
|
||||
import { ApiEndpoints } from '../../enums/ApiEndpoints';
|
||||
@ -539,10 +539,13 @@ export default function StockDetail() {
|
||||
return (
|
||||
<Stack>
|
||||
<LoadingOverlay visible={instanceQuery.isFetching} />
|
||||
<StockLocationTree
|
||||
<NavigationTree
|
||||
title={t`Stock Locations`}
|
||||
modelType={ModelType.stocklocation}
|
||||
endpoint={ApiEndpoints.stock_location_tree}
|
||||
opened={treeOpen}
|
||||
onClose={() => setTreeOpen(false)}
|
||||
selectedLocation={stockitem?.location}
|
||||
selectedId={stockitem?.location}
|
||||
/>
|
||||
<PageDetail
|
||||
title={t`Stock Item`}
|
||||
|
@ -199,7 +199,7 @@ test('PUI - Language / Color', async ({ page }) => {
|
||||
await page.getByRole('menuitem', { name: 'Logout' }).click();
|
||||
await page.getByRole('button', { name: 'Send me an email' }).click();
|
||||
await page.getByRole('button').nth(3).click();
|
||||
await page.getByLabel('Select language').click();
|
||||
await page.getByLabel('Select language').first().click();
|
||||
await page.getByRole('option', { name: 'German' }).click();
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
|
@ -95,3 +95,20 @@ test('PUI - Purchasing', async ({ page }) => {
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
await page.getByRole('tab', { name: 'Details' }).waitFor();
|
||||
});
|
||||
|
||||
test('PUI - Stock Location Tree', async ({ page }) => {
|
||||
await doQuickLogin(page);
|
||||
|
||||
await page.goto(`${baseUrl}/stock/location/index/`);
|
||||
await page.waitForURL('**/platform/stock/location/**');
|
||||
await page.getByRole('tab', { name: 'Location Details' }).click();
|
||||
|
||||
await page.getByLabel('nav-breadcrumb-action').click();
|
||||
await page.getByLabel('nav-tree-toggle-1}').click();
|
||||
await page.getByLabel('nav-tree-item-2').click();
|
||||
|
||||
await page.getByLabel('breadcrumb-2-storage-room-a').waitFor();
|
||||
await page.getByLabel('breadcrumb-1-factory').click();
|
||||
|
||||
await page.getByRole('cell', { name: 'Factory' }).first().waitFor();
|
||||
});
|
||||
|
@ -316,13 +316,20 @@
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.24.1"
|
||||
"@babel/plugin-transform-typescript" "^7.24.1"
|
||||
|
||||
"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.13", "@babel/runtime@^7.21.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
|
||||
"@babel/runtime@^7.12.0", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.6", "@babel/runtime@^7.21.0":
|
||||
version "7.24.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd"
|
||||
integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/runtime@^7.20.13", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
|
||||
version "7.24.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e"
|
||||
integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
|
||||
"@babel/template@^7.22.15", "@babel/template@^7.24.0":
|
||||
version "7.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
|
||||
@ -524,13 +531,6 @@
|
||||
dependencies:
|
||||
"@emotion/memoize" "^0.8.1"
|
||||
|
||||
"@emotion/is-prop-valid@^1.2.0":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz#d4175076679c6a26faa92b03bb786f9e52612337"
|
||||
integrity sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==
|
||||
dependencies:
|
||||
"@emotion/memoize" "^0.8.1"
|
||||
|
||||
"@emotion/memoize@^0.8.1":
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
|
||||
@ -932,13 +932,21 @@
|
||||
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
|
||||
|
||||
"@floating-ui/core@^1.0.0":
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1"
|
||||
integrity sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.2.tgz#d37f3e0ac1f1c756c7de45db13303a266226851a"
|
||||
integrity sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg==
|
||||
dependencies:
|
||||
"@floating-ui/utils" "^0.2.1"
|
||||
"@floating-ui/utils" "^0.2.0"
|
||||
|
||||
"@floating-ui/dom@^1.0.1", "@floating-ui/dom@^1.6.1":
|
||||
"@floating-ui/dom@^1.0.0":
|
||||
version "1.6.5"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9"
|
||||
integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw==
|
||||
dependencies:
|
||||
"@floating-ui/core" "^1.0.0"
|
||||
"@floating-ui/utils" "^0.2.0"
|
||||
|
||||
"@floating-ui/dom@^1.0.1":
|
||||
version "1.6.3"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.3.tgz#954e46c1dd3ad48e49db9ada7218b0985cee75ef"
|
||||
integrity sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==
|
||||
@ -946,26 +954,26 @@
|
||||
"@floating-ui/core" "^1.0.0"
|
||||
"@floating-ui/utils" "^0.2.0"
|
||||
|
||||
"@floating-ui/react-dom@^2.0.0":
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.8.tgz#afc24f9756d1b433e1fe0d047c24bd4d9cefaa5d"
|
||||
integrity sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==
|
||||
"@floating-ui/react-dom@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.0.tgz#4f0e5e9920137874b2405f7d6c862873baf4beff"
|
||||
integrity sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA==
|
||||
dependencies:
|
||||
"@floating-ui/dom" "^1.6.1"
|
||||
"@floating-ui/dom" "^1.0.0"
|
||||
|
||||
"@floating-ui/react@^0.26.9":
|
||||
version "0.26.12"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.12.tgz#6908f774d8e3167d89b37fd83be975c7e5d8be99"
|
||||
integrity sha512-D09o62HrWdIkstF2kGekIKAC0/N/Dl6wo3CQsnLcOmO3LkW6Ik8uIb3kw8JYkwxNCcg+uJ2bpWUiIijTBep05w==
|
||||
version "0.26.16"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.16.tgz#3415a087f452165161c2d313d1d57e8142894679"
|
||||
integrity sha512-HEf43zxZNAI/E781QIVpYSF3K2VH4TTYZpqecjdsFkjsaU1EbaWcM++kw0HXFffj7gDUcBFevX8s0rQGQpxkow==
|
||||
dependencies:
|
||||
"@floating-ui/react-dom" "^2.0.0"
|
||||
"@floating-ui/react-dom" "^2.1.0"
|
||||
"@floating-ui/utils" "^0.2.0"
|
||||
tabbable "^6.0.0"
|
||||
|
||||
"@floating-ui/utils@^0.2.0", "@floating-ui/utils@^0.2.1":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2"
|
||||
integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==
|
||||
"@floating-ui/utils@^0.2.0":
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5"
|
||||
integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==
|
||||
|
||||
"@fortawesome/fontawesome-common-types@6.5.2":
|
||||
version "6.5.2"
|
||||
@ -1216,56 +1224,56 @@
|
||||
resolved "https://registry.yarnpkg.com/@mantine/carousel/-/carousel-7.8.0.tgz#d49b3a57cebfc9c774467bd4c46df1005eb765f4"
|
||||
integrity sha512-nxuLtZ4N4KJaayab5KuaffYhiVi4UaIjywkgQiNfTxABlgFdERNfo5if9sSMyisL0r3RUPJBfLkyi8A4fEC8GQ==
|
||||
|
||||
"@mantine/core@^7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/core/-/core-7.8.0.tgz#b4bbd82ea2f1a25f5fb3d11ae5583cf80ecd8383"
|
||||
integrity sha512-19RKuNdJ/s8pZjy2w2rvTsl4ybi/XM6vf+Kc0WY7kpLFCvdG+/UxNi1MuJF8t2Zs0QSFeb/H5yZQNe0XPbegHw==
|
||||
"@mantine/core@^7.10.0":
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/core/-/core-7.10.0.tgz#bfaafc92cf2346e5a6cbb49289f577ce3f7c05f7"
|
||||
integrity sha512-hNqhdn/+4x8+FDWzR5fu1eMgnG1Mw4fZHw4WjIYjKrSv0NeKHY263RiesZz8RwcUQ8r7LlD95/2tUOMnKVTV5Q==
|
||||
dependencies:
|
||||
"@floating-ui/react" "^0.26.9"
|
||||
clsx "2.1.0"
|
||||
clsx "^2.1.1"
|
||||
react-number-format "^5.3.1"
|
||||
react-remove-scroll "^2.5.7"
|
||||
react-textarea-autosize "8.5.3"
|
||||
type-fest "^4.12.0"
|
||||
|
||||
"@mantine/dates@^7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/dates/-/dates-7.8.0.tgz#a8785030000487158e1bd23655ea26245bbf299a"
|
||||
integrity sha512-9jjiYMwP3jQOpOLKkjhp9uf2BGhtEbOnOzyAlpLOS0CJJlYtB0tO6dJ3JaogrOZ/Yfee7ZUBgouCG5EkR4/qtQ==
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/dates/-/dates-7.10.0.tgz#0c2a02883d5fb4a36b40a578b26ef5a697c333e5"
|
||||
integrity sha512-LBBh1U/RzxFQKGA6sSYxbCwYEMoM5lNIhwofY6g8zOTAZuRQqo5FIWItmB9I9ltT+M2o75SADeP6ZBLi4ec8ZA==
|
||||
dependencies:
|
||||
clsx "2.1.0"
|
||||
clsx "^2.1.1"
|
||||
|
||||
"@mantine/dropzone@^7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/dropzone/-/dropzone-7.8.0.tgz#f962c72adb585ddc7706dca680102728a52b2de7"
|
||||
integrity sha512-rpNTR3NASvI3BnqhY5wg3BDhxkABT9UoZEGRrOGnS3YU7SYXg5rT9ch5Cm4iPwMNdwsyAIU6K2ii4wWk40dRpg==
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/dropzone/-/dropzone-7.10.0.tgz#54283a22d1e848619a1659e38dd29852bff135e7"
|
||||
integrity sha512-LFJjYvz0pSfKCSiVGLgAS94AazF2npK/ZYrr+Ax9/tdd1HgbxSd3B8SaPdGm1wOwZbpp8w0auyl3fZfqnDBG8w==
|
||||
dependencies:
|
||||
react-dropzone-esm "15.0.1"
|
||||
|
||||
"@mantine/form@^7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/form/-/form-7.8.0.tgz#3f16b2e0124c65286892ed50181d192ae03d988b"
|
||||
integrity sha512-Qn3/69zGt/p3wyMwGz2V0+FbmvqC2/PvXaeyO0a4CnwhROeE7ObyCKXDcBmgapOSBHr/7wFvMeTDMaTMfe3DXw==
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/form/-/form-7.10.0.tgz#3e8e3fb836948becb13b89412c74016b50bac3d3"
|
||||
integrity sha512-ChAtqdQCAZrnH6iiCivumyMuMsev+tFWIgsCCgAmbP2sOyMtjbNtypKrcwBwI/PzAH9N4jSJlsmJsnRdXNeEkQ==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.3"
|
||||
klona "^2.0.6"
|
||||
|
||||
"@mantine/hooks@^7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/hooks/-/hooks-7.8.0.tgz#fc32e07746689459c4b049dc581d1dbda5545686"
|
||||
integrity sha512-+70fkgjhVJeJ+nJqnburIM3UAsfvxat1Low9HMPobLbv64FIdB4Nzu5ct3qojNQ58r5sK01tg5UoFIJYslaVrg==
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/hooks/-/hooks-7.10.0.tgz#10a259e204a8af29df6aeeb24090c1e2c6debca0"
|
||||
integrity sha512-fnalwYS2WQEFS4wmhmAetDZ/VdJPLNeUXPX9t+S21o3p/dRTX1xhU2mS7yWaQUKM0hPD1TcujqXGlP2M2g/A9A==
|
||||
|
||||
"@mantine/modals@^7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/modals/-/modals-7.8.0.tgz#1960f34a7d0c45490465d61acf5da9a0c65610ca"
|
||||
integrity sha512-/Kxquz8U7xau9PoqPi5Pjysfnq8b48VRAMp62B+SsPWNTH47R0F7dYRYpLQ2/0VU+OWGY0lOshxpgA61sZ3IPA==
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/modals/-/modals-7.10.0.tgz#c08789491bfbfb1d432818e0fc4b2eac71fd480e"
|
||||
integrity sha512-UVtmRpTBWDqcJjdv97IUYLduYcZBrqteyDwnspHT453iFZlvCglHUXYR+LvN5ExE+kxUe2IUXL/pEaIRTjwtKQ==
|
||||
|
||||
"@mantine/notifications@^7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/notifications/-/notifications-7.8.0.tgz#90b97ca3191951bffea5da6a6ce9e607daf37bf5"
|
||||
integrity sha512-O7BnaCcwVg38fh+gSZ6GEsTFPPgJAiOTrRkOMXG+7pNqJT9YNa9KDZhiPZzn3WV4wexncjyK32a8gGSVtf+kdg==
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/notifications/-/notifications-7.10.0.tgz#aa638b8bb6c3d6bfb34d518a49ef8a8b6ab499e4"
|
||||
integrity sha512-3a0mmM9Kr3nPP+8VHsIuly507nda6ciu2aB/xSxb7gFIKHw3GqSu77pxXa+5l4Y6AQKKvP9360K4KjH6+rOBWw==
|
||||
dependencies:
|
||||
"@mantine/store" "7.8.0"
|
||||
"@mantine/store" "7.10.0"
|
||||
react-transition-group "4.4.5"
|
||||
|
||||
"@mantine/spotlight@^7.8.0":
|
||||
@ -1275,6 +1283,11 @@
|
||||
dependencies:
|
||||
"@mantine/store" "7.8.0"
|
||||
|
||||
"@mantine/store@7.10.0":
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/store/-/store-7.10.0.tgz#68368c6ca5b75cfb331220e06a3235be753df055"
|
||||
integrity sha512-B6AyUX0cA97/hI9v0att7eJJnQTcUG7zBlTdWhOsptBV5UoDNrzdv3DDWIFxrA8h+nhNKGBh6Dif5HWh1+QLeA==
|
||||
|
||||
"@mantine/store@7.8.0":
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/store/-/store-7.8.0.tgz#d3ac70a96b71cbc0a4ef506bf751d8e290666d28"
|
||||
@ -1292,15 +1305,6 @@
|
||||
dependencies:
|
||||
moo "^0.5.1"
|
||||
|
||||
"@naisutech/react-tree@^3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@naisutech/react-tree/-/react-tree-3.1.0.tgz#a83820425b53a1ec7a39804ff8bd9024f0a953f4"
|
||||
integrity sha512-6p1l3ZIaTmbgiAf/mpFELvqwl51LDhr+09f7L+C27DBLWjtleezCMoUuiSLhrJgpixCPNL13PuI3q2yn+0AGvA==
|
||||
dependencies:
|
||||
"@emotion/is-prop-valid" "^1.2.0"
|
||||
nanoid "^4.0.0"
|
||||
react-draggable "^4.4.5"
|
||||
|
||||
"@playwright/test@^1.43.1":
|
||||
version "1.43.1"
|
||||
resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.43.1.tgz#16728a59eb8ce0f60472f98d8886d6cab0fa3e42"
|
||||
@ -2114,16 +2118,21 @@ clone@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||
integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
|
||||
|
||||
clsx@2.1.0, clsx@^2.0.0, clsx@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb"
|
||||
integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==
|
||||
|
||||
clsx@^1.1.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
|
||||
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
|
||||
|
||||
clsx@^2.0.0, clsx@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.0.tgz#e851283bcb5c80ee7608db18487433f7b23f77cb"
|
||||
integrity sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==
|
||||
|
||||
clsx@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
|
||||
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
|
||||
|
||||
codemirror-spell-checker@1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz#1c660f9089483ccb5113b9ba9ca19c3f4993371e"
|
||||
@ -2361,9 +2370,9 @@ date-fns@^3.6.0:
|
||||
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
|
||||
|
||||
dayjs@^1.11.10:
|
||||
version "1.11.10"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.10.tgz#68acea85317a6e164457d6d6947564029a6a16a0"
|
||||
integrity sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==
|
||||
version "1.11.11"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e"
|
||||
integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==
|
||||
|
||||
debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
@ -3315,11 +3324,6 @@ nanoid@^3.3.6, nanoid@^3.3.7:
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
nanoid@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e"
|
||||
integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==
|
||||
|
||||
node-preload@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301"
|
||||
@ -3721,9 +3725,9 @@ react-remove-scroll-bar@^2.3.6:
|
||||
tslib "^2.0.0"
|
||||
|
||||
react-remove-scroll@^2.5.7:
|
||||
version "2.5.9"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.9.tgz#6a38e7d46043abc2c6b0fb39db650b9f2e38be3e"
|
||||
integrity sha512-bvHCLBrFfM2OgcrpPY2YW84sPdS2o2HKWJUf1xGyGLnSoEnOTOBpahIarjRuYtN0ryahCeP242yf+5TrBX/pZA==
|
||||
version "2.5.10"
|
||||
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.10.tgz#5fae456a23962af6d3c38ca1978bcfe0806c4061"
|
||||
integrity sha512-m3zvBRANPBw3qxVVjEIPEQinkcwlFZ4qyomuWVpNJdv4c6MvHfXV0C3L9Jx5rr3HeBHKNRX+1jreB5QloDIJjA==
|
||||
dependencies:
|
||||
react-remove-scroll-bar "^2.3.6"
|
||||
react-style-singleton "^2.2.1"
|
||||
@ -3843,10 +3847,10 @@ recharts-scale@^0.4.4:
|
||||
dependencies:
|
||||
decimal.js-light "^2.4.1"
|
||||
|
||||
recharts@^2.12.4:
|
||||
version "2.12.5"
|
||||
resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.12.5.tgz#b335eb66173317dccb3e126fce1d7ac5b3cee1e9"
|
||||
integrity sha512-Cy+BkqrFIYTHJCyKHJEPvbHE2kVQEP6PKbOHJ8ztRGTAhvHuUnCwDaKVb13OwRFZ0QNUk1QvGTDdgWSMbuMtKw==
|
||||
recharts@2:
|
||||
version "2.12.7"
|
||||
resolved "https://registry.yarnpkg.com/recharts/-/recharts-2.12.7.tgz#c7f42f473a257ff88b43d88a92530930b5f9e773"
|
||||
integrity sha512-hlLJMhPQfv4/3NBSAyq3gzGg4h2v69RJh6KU7b3pXYNNAELs9kEoXOjbkxdXpALqKBoVmVptGfLpxdaVYqjmXQ==
|
||||
dependencies:
|
||||
clsx "^2.0.0"
|
||||
eventemitter3 "^4.0.1"
|
||||
@ -4276,9 +4280,9 @@ type-fest@^0.8.0:
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
||||
type-fest@^4.12.0:
|
||||
version "4.15.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.15.0.tgz#21da206b89c15774cc718c4f2d693e13a1a14a43"
|
||||
integrity sha512-tB9lu0pQpX5KJq54g+oHOLumOx+pMep4RaM6liXh2PKmVRFF+/vAtUP0ZaJ0kOySfVNjF6doBWPHhBhISKdlIA==
|
||||
version "4.18.3"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.18.3.tgz#5249f96e7c2c3f0f1561625f54050e343f1c8f68"
|
||||
integrity sha512-Q08/0IrpvM+NMY9PA2rti9Jb+JejTddwmwmVQGskAlhtcrw1wsRzoR6ode6mR+OAabNa75w/dxedSUY2mlphaQ==
|
||||
|
||||
typedarray-to-buffer@^3.1.5:
|
||||
version "3.1.5"
|
||||
|
Loading…
Reference in New Issue
Block a user