mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
[P-UI] Home page (#5344)
* Add new start page * [FR/P-UI] Home/Start page - widgets * load widgets dynamic * code cleanup * remove lodash * refactor and rename to WidgetLayout * Add CSS serving * removed unneeded complexity * clean up UI; switch to menu for controls * change signature * added hotkey * removed hover * removed dummy widget * Add translations * fix test * uses real data for getting started * adapted style for GettingStartedCard * added placeholder usage to GettingStartedCard
This commit is contained in:
parent
62362455b8
commit
ebbc27047b
@ -64,7 +64,7 @@ class AuthRequiredMiddleware(object):
|
||||
elif request.path_info.startswith('/accounts/'):
|
||||
authorized = True
|
||||
|
||||
elif request.path_info.startswith('/platform/') or request.path_info == '/platform':
|
||||
elif request.path_info.startswith('/platform/') or request.path_info.startswith('/assets/') or request.path_info == '/platform':
|
||||
authorized = True
|
||||
|
||||
elif 'Authorization' in request.headers.keys() or 'authorization' in request.headers.keys():
|
||||
|
@ -34,7 +34,6 @@ from report.api import report_api_urls
|
||||
from stock.api import stock_api_urls
|
||||
from stock.urls import stock_urls
|
||||
from users.api import user_urls
|
||||
from web.urls import spa_view
|
||||
from web.urls import urlpatterns as platform_urls
|
||||
|
||||
from .api import APISearchView, InfoView, NotFoundView
|
||||
@ -212,11 +211,7 @@ classic_frontendpatterns = [
|
||||
]
|
||||
|
||||
|
||||
new_frontendpatterns = [
|
||||
# Platform urls
|
||||
re_path(r'^platform/', include(platform_urls)),
|
||||
re_path(r'^platform', spa_view, name='platform'),
|
||||
]
|
||||
new_frontendpatterns = platform_urls
|
||||
|
||||
# Load patterns for frontend according to settings
|
||||
frontendpatterns = []
|
||||
|
@ -22,6 +22,7 @@ def spa_bundle():
|
||||
|
||||
manifest_data = json.load(manifest.open())
|
||||
index = manifest_data.get("index.html")
|
||||
css_index = manifest_data.get("index.css")
|
||||
|
||||
dynmanic_files = index.get("dynamicImports", [])
|
||||
imports_files = "".join(
|
||||
@ -32,5 +33,6 @@ def spa_bundle():
|
||||
)
|
||||
|
||||
return mark_safe(
|
||||
f"""<script type="module" src="{settings.STATIC_URL}web/{index['file']}"></script>{imports_files}"""
|
||||
f"""<link rel="stylesheet" href="{settings.STATIC_URL}web/{css_index['file']}" />
|
||||
<script type="module" src="{settings.STATIC_URL}web/{index['file']}"></script>{imports_files}"""
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
"""URLs for web app."""
|
||||
from django.conf import settings
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import path, re_path
|
||||
from django.urls import include, path, re_path
|
||||
from django.views.decorators.csrf import ensure_csrf_cookie
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
@ -20,8 +20,12 @@ spa_view = ensure_csrf_cookie(TemplateView.as_view(template_name="web/index.html
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('platform/', include([
|
||||
path("assets/<path:path>", RedirectAssetView.as_view()),
|
||||
re_path(r"^(?P<path>.*)/$", spa_view),
|
||||
path("set-password?uid=<uid>&token=<token>", spa_view, name="password_reset_confirm"),
|
||||
path("", spa_view),]
|
||||
)),
|
||||
re_path(r'^platform', spa_view, name='platform'),
|
||||
path("assets/<path:path>", RedirectAssetView.as_view()),
|
||||
re_path(r"^(?P<path>.*)/$", spa_view),
|
||||
path("set-password?uid=<uid>&token=<token>", spa_view, name="password_reset_confirm"),
|
||||
path("", spa_view),
|
||||
]
|
||||
|
@ -18,6 +18,7 @@
|
||||
"@fortawesome/react-fontawesome": "^0.2.0",
|
||||
"@lingui/core": "^4.3.0",
|
||||
"@lingui/react": "^4.3.0",
|
||||
"@mantine/carousel": "^6.0.17",
|
||||
"@mantine/core": "^6.0.17",
|
||||
"@mantine/dates": "^6.0.17",
|
||||
"@mantine/dropzone": "^6.0.17",
|
||||
@ -29,10 +30,12 @@
|
||||
"@tanstack/react-query": "^4.32.0",
|
||||
"axios": "^1.4.0",
|
||||
"dayjs": "^1.11.9",
|
||||
"embla-carousel-react": "^8.0.0-rc11",
|
||||
"html5-qrcode": "^2.3.8",
|
||||
"mantine-datatable": "^2.9.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-router-dom": "^6.14.2",
|
||||
"zustand": "^4.3.9"
|
||||
},
|
||||
@ -46,6 +49,7 @@
|
||||
"@types/node": "^20.4.4",
|
||||
"@types/react": "^18.2.15",
|
||||
"@types/react-dom": "^18.2.7",
|
||||
"@types/react-grid-layout": "^1.3.2",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@vitejs/plugin-react": "^4.0.3",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
|
92
src/frontend/src/components/items/GettingStartedCarousel.tsx
Normal file
92
src/frontend/src/components/items/GettingStartedCarousel.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { Carousel } from '@mantine/carousel';
|
||||
import {
|
||||
Anchor,
|
||||
Button,
|
||||
Paper,
|
||||
Text,
|
||||
Title,
|
||||
createStyles,
|
||||
rem
|
||||
} from '@mantine/core';
|
||||
|
||||
import { DocumentationLinkItem } from './DocumentationLinks';
|
||||
import { PlaceholderPill } from './Placeholder';
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
card: {
|
||||
height: rem(170),
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'flex-start',
|
||||
backgroundSize: 'cover',
|
||||
backgroundPosition: 'center'
|
||||
},
|
||||
|
||||
title: {
|
||||
fontWeight: 900,
|
||||
color:
|
||||
theme.colorScheme === 'dark' ? theme.colors.white : theme.colors.dark,
|
||||
lineHeight: 1.2,
|
||||
fontSize: rem(32),
|
||||
marginTop: 0
|
||||
},
|
||||
|
||||
category: {
|
||||
color:
|
||||
theme.colorScheme === 'dark' ? theme.colors.white : theme.colors.dark,
|
||||
opacity: 0.7,
|
||||
fontWeight: 700
|
||||
}
|
||||
}));
|
||||
|
||||
function StartedCard({
|
||||
title,
|
||||
description,
|
||||
link,
|
||||
placeholder
|
||||
}: DocumentationLinkItem) {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<Paper shadow="md" p="xl" radius="md" className={classes.card}>
|
||||
<div>
|
||||
<Title order={3} className={classes.title}>
|
||||
{title} {placeholder && <PlaceholderPill />}
|
||||
</Title>
|
||||
<Text size="sm" className={classes.category} lineClamp={2}>
|
||||
{description}
|
||||
</Text>
|
||||
</div>
|
||||
<Anchor href={link} target="_blank">
|
||||
<Button>
|
||||
<Trans>Read more</Trans>
|
||||
</Button>
|
||||
</Anchor>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export function GettingStartedCarousel({
|
||||
items
|
||||
}: {
|
||||
items: DocumentationLinkItem[];
|
||||
}) {
|
||||
const slides = items.map((item) => (
|
||||
<Carousel.Slide key={item.id}>
|
||||
<StartedCard {...item} />
|
||||
</Carousel.Slide>
|
||||
));
|
||||
|
||||
return (
|
||||
<Carousel
|
||||
slideSize="50%"
|
||||
breakpoints={[{ maxWidth: 'sm', slideSize: '100%', slideGap: rem(2) }]}
|
||||
slideGap="xl"
|
||||
align="start"
|
||||
>
|
||||
{slides}
|
||||
</Carousel>
|
||||
);
|
||||
}
|
29
src/frontend/src/components/widgets/DisplayWidget.tsx
Normal file
29
src/frontend/src/components/widgets/DisplayWidget.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { SimpleGrid, Title } from '@mantine/core';
|
||||
|
||||
import { ColorToggle } from '../items/ColorToggle';
|
||||
import { LanguageSelect } from '../items/LanguageSelect';
|
||||
|
||||
export default function DisplayWidget() {
|
||||
return (
|
||||
<span>
|
||||
<Title order={5}>
|
||||
<Trans>Display Settings</Trans>
|
||||
</Title>
|
||||
<SimpleGrid cols={2} spacing={0}>
|
||||
<div>
|
||||
<Trans>Color Mode</Trans>
|
||||
</div>
|
||||
<div>
|
||||
<ColorToggle />
|
||||
</div>
|
||||
<div>
|
||||
<Trans>Language</Trans>
|
||||
</div>
|
||||
<div>
|
||||
<LanguageSelect />
|
||||
</div>
|
||||
</SimpleGrid>
|
||||
</span>
|
||||
);
|
||||
}
|
35
src/frontend/src/components/widgets/FeedbackWidget.tsx
Normal file
35
src/frontend/src/components/widgets/FeedbackWidget.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { Button, Stack, Title } from '@mantine/core';
|
||||
import { IconExternalLink } from '@tabler/icons-react';
|
||||
|
||||
export default function FeedbackWidget() {
|
||||
return (
|
||||
<Stack
|
||||
sx={(theme) => ({
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.colors.gray[9]
|
||||
: theme.colors.gray[1],
|
||||
borderRadius: theme.radius.md
|
||||
})}
|
||||
p={15}
|
||||
>
|
||||
<Title order={5}>
|
||||
<Trans>Something is new: Platform UI</Trans>
|
||||
</Title>
|
||||
<Trans>
|
||||
We are building a new UI with a modern stack. What you currently see is
|
||||
not fixed and will be redesigned but demonstrates the UI/UX
|
||||
possibilities we will have going forward.
|
||||
</Trans>
|
||||
<Button
|
||||
component="a"
|
||||
href="https://github.com/inventree/InvenTree/discussions/5328"
|
||||
variant="outline"
|
||||
leftIcon={<IconExternalLink size="0.9rem" />}
|
||||
>
|
||||
<Trans>Provide Feedback</Trans>
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
}
|
16
src/frontend/src/components/widgets/GetStartedWidget.tsx
Normal file
16
src/frontend/src/components/widgets/GetStartedWidget.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { Title } from '@mantine/core';
|
||||
|
||||
import { navDocLinks } from '../../defaults/links';
|
||||
import { GettingStartedCarousel } from '../items/GettingStartedCarousel';
|
||||
|
||||
export default function GetStartedWidget() {
|
||||
return (
|
||||
<span>
|
||||
<Title order={5}>
|
||||
<Trans>Getting started</Trans>
|
||||
</Title>
|
||||
<GettingStartedCarousel items={navDocLinks} />
|
||||
</span>
|
||||
);
|
||||
}
|
246
src/frontend/src/components/widgets/WidgetLayout.tsx
Normal file
246
src/frontend/src/components/widgets/WidgetLayout.tsx
Normal file
@ -0,0 +1,246 @@
|
||||
import { Trans } from '@lingui/macro';
|
||||
import {
|
||||
ActionIcon,
|
||||
Container,
|
||||
Group,
|
||||
Indicator,
|
||||
createStyles
|
||||
} from '@mantine/core';
|
||||
import { Menu, Text } from '@mantine/core';
|
||||
import { useDisclosure, useHotkeys } from '@mantine/hooks';
|
||||
import {
|
||||
IconArrowBackUpDouble,
|
||||
IconDotsVertical,
|
||||
IconLayout2,
|
||||
IconSquare,
|
||||
IconSquareCheck
|
||||
} from '@tabler/icons-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Responsive, WidthProvider } from 'react-grid-layout';
|
||||
|
||||
const ReactGridLayout = WidthProvider(Responsive);
|
||||
|
||||
interface LayoutStorage {
|
||||
[key: string]: {};
|
||||
}
|
||||
|
||||
const compactType = 'vertical';
|
||||
|
||||
const useItemStyle = createStyles((theme) => ({
|
||||
backgroundItem: {
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.white,
|
||||
maxWidth: '100%',
|
||||
padding: '8px',
|
||||
boxShadow: theme.shadows.md
|
||||
},
|
||||
|
||||
baseItem: {
|
||||
maxWidth: '100%',
|
||||
padding: '8px'
|
||||
}
|
||||
}));
|
||||
|
||||
export interface LayoutItemType {
|
||||
i: number;
|
||||
val: string | JSX.Element | JSX.Element[] | (() => JSX.Element);
|
||||
w?: number;
|
||||
h?: number;
|
||||
x?: number;
|
||||
y?: number;
|
||||
minH?: number;
|
||||
}
|
||||
|
||||
export function WidgetLayout({
|
||||
items = [],
|
||||
className = 'layout',
|
||||
localstorageName = 'argl',
|
||||
rowHeight = 30
|
||||
}: {
|
||||
items: LayoutItemType[];
|
||||
className?: string;
|
||||
localstorageName?: string;
|
||||
rowHeight?: number;
|
||||
}) {
|
||||
const [layouts, setLayouts] = useState({});
|
||||
const [editable, setEditable] = useDisclosure(false);
|
||||
const [boxShown, setBoxShown] = useDisclosure(true);
|
||||
const { classes } = useItemStyle();
|
||||
|
||||
useEffect(() => {
|
||||
let layout = getFromLS('layouts') || [];
|
||||
const new_layout = JSON.parse(JSON.stringify(layout));
|
||||
setLayouts(new_layout);
|
||||
}, []);
|
||||
|
||||
function getFromLS(key: string) {
|
||||
let ls: LayoutStorage = {};
|
||||
if (localStorage) {
|
||||
try {
|
||||
ls = JSON.parse(localStorage.getItem(localstorageName) || '') || {};
|
||||
} catch (e) {
|
||||
/*Ignore*/
|
||||
}
|
||||
}
|
||||
return ls[key];
|
||||
}
|
||||
|
||||
function saveToLS(key: string, value: any) {
|
||||
if (localStorage) {
|
||||
localStorage.setItem(
|
||||
localstorageName,
|
||||
JSON.stringify({
|
||||
[key]: value
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function resetLayout() {
|
||||
setLayouts({});
|
||||
}
|
||||
|
||||
function onLayoutChange(layout: any, layouts: any) {
|
||||
saveToLS('layouts', layouts);
|
||||
setLayouts(layouts);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<WidgetControlBar
|
||||
editable={editable}
|
||||
editFnc={setEditable.toggle}
|
||||
resetLayout={resetLayout}
|
||||
boxShown={boxShown}
|
||||
boxFnc={setBoxShown.toggle}
|
||||
/>
|
||||
{layouts ? (
|
||||
<ReactGridLayout
|
||||
className={className}
|
||||
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
|
||||
rowHeight={rowHeight}
|
||||
layouts={layouts}
|
||||
onLayoutChange={(layout, layouts) => onLayoutChange(layout, layouts)}
|
||||
compactType={compactType}
|
||||
isDraggable={editable}
|
||||
isResizable={editable}
|
||||
>
|
||||
{items.map((item) => {
|
||||
return LayoutItem(item, boxShown, classes);
|
||||
})}
|
||||
</ReactGridLayout>
|
||||
) : (
|
||||
<div>
|
||||
<Trans>Loading</Trans>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function WidgetControlBar({
|
||||
editable,
|
||||
editFnc,
|
||||
resetLayout,
|
||||
boxShown,
|
||||
boxFnc
|
||||
}: {
|
||||
editable: boolean;
|
||||
editFnc: () => void;
|
||||
resetLayout: () => void;
|
||||
boxShown: boolean;
|
||||
boxFnc: () => void;
|
||||
}) {
|
||||
useHotkeys([['mod+E', () => editFnc()]]);
|
||||
|
||||
return (
|
||||
<Group position="right">
|
||||
<Menu
|
||||
shadow="md"
|
||||
width={200}
|
||||
openDelay={100}
|
||||
closeDelay={400}
|
||||
position="bottom-end"
|
||||
>
|
||||
<Menu.Target>
|
||||
<Indicator
|
||||
color="red"
|
||||
position="bottom-start"
|
||||
processing
|
||||
disabled={!editable}
|
||||
>
|
||||
<ActionIcon variant="transparent">
|
||||
<IconDotsVertical />
|
||||
</ActionIcon>
|
||||
</Indicator>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Menu.Label>
|
||||
<Trans>Layout</Trans>
|
||||
</Menu.Label>
|
||||
<Menu.Item
|
||||
icon={<IconArrowBackUpDouble size={14} />}
|
||||
onClick={resetLayout}
|
||||
>
|
||||
<Trans>Reset Layout</Trans>
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
icon={
|
||||
<IconLayout2 size={14} color={editable ? 'red' : undefined} />
|
||||
}
|
||||
onClick={editFnc}
|
||||
rightSection={
|
||||
<Text size="xs" color="dimmed">
|
||||
⌘E
|
||||
</Text>
|
||||
}
|
||||
>
|
||||
{editable ? <Trans>Stop Edit</Trans> : <Trans>Edit Layout</Trans>}
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Divider />
|
||||
|
||||
<Menu.Label>
|
||||
<Trans>Appearance</Trans>
|
||||
</Menu.Label>
|
||||
<Menu.Item
|
||||
icon={
|
||||
boxShown ? (
|
||||
<IconSquareCheck size={14} />
|
||||
) : (
|
||||
<IconSquare size={14} />
|
||||
)
|
||||
}
|
||||
onClick={boxFnc}
|
||||
>
|
||||
<Trans>Show Boxes</Trans>
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
function LayoutItem(
|
||||
item: any,
|
||||
backgroundColor: boolean,
|
||||
classes: { backgroundItem: string; baseItem: string }
|
||||
) {
|
||||
return (
|
||||
<Container
|
||||
key={item.i}
|
||||
data-grid={{
|
||||
w: item.w || 3,
|
||||
h: item.h || 3,
|
||||
x: item.x || 0,
|
||||
y: item.y || 0,
|
||||
minH: item.minH || undefined,
|
||||
minW: item.minW || undefined
|
||||
}}
|
||||
className={backgroundColor ? classes.backgroundItem : classes.baseItem}
|
||||
>
|
||||
{item.val}
|
||||
</Container>
|
||||
);
|
||||
}
|
@ -17,3 +17,8 @@ export const Loadable = (Component: any) => (props: JSX.IntrinsicAttributes) =>
|
||||
<Component {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
|
||||
export function LoadingItem({ item }: { item: any }): JSX.Element {
|
||||
const Itm = Loadable(item);
|
||||
return <Itm />;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import 'react-grid-layout/css/styles.css';
|
||||
import 'react-resizable/css/styles.css';
|
||||
|
||||
import App from './App';
|
||||
|
||||
|
@ -1,18 +1,63 @@
|
||||
import { Trans } from '@lingui/macro';
|
||||
import { Group } from '@mantine/core';
|
||||
import { Title } from '@mantine/core';
|
||||
import { lazy } from 'react';
|
||||
|
||||
import { PlaceholderPill } from '../../components/items/Placeholder';
|
||||
import { StylishText } from '../../components/items/StylishText';
|
||||
import {
|
||||
LayoutItemType,
|
||||
WidgetLayout
|
||||
} from '../../components/widgets/WidgetLayout';
|
||||
import { LoadingItem } from '../../functions/loading';
|
||||
import { useApiState } from '../../states/ApiState';
|
||||
|
||||
const vals: LayoutItemType[] = [
|
||||
{
|
||||
i: 1,
|
||||
val: (
|
||||
<LoadingItem
|
||||
item={lazy(() => import('../../components/widgets/GetStartedWidget'))}
|
||||
/>
|
||||
),
|
||||
w: 12,
|
||||
h: 6,
|
||||
x: 0,
|
||||
y: 0,
|
||||
minH: 6
|
||||
},
|
||||
{
|
||||
i: 2,
|
||||
val: (
|
||||
<LoadingItem
|
||||
item={lazy(() => import('../../components/widgets/DisplayWidget'))}
|
||||
/>
|
||||
),
|
||||
w: 3,
|
||||
h: 3,
|
||||
x: 0,
|
||||
y: 7,
|
||||
minH: 3
|
||||
},
|
||||
{
|
||||
i: 4,
|
||||
val: (
|
||||
<LoadingItem
|
||||
item={lazy(() => import('../../components/widgets/FeedbackWidget'))}
|
||||
/>
|
||||
),
|
||||
w: 4,
|
||||
h: 6,
|
||||
x: 0,
|
||||
y: 9
|
||||
}
|
||||
];
|
||||
|
||||
export default function Home() {
|
||||
const [username] = useApiState((state) => [state.user?.name]);
|
||||
return (
|
||||
<>
|
||||
<Group>
|
||||
<StylishText>
|
||||
<Trans>Home</Trans>
|
||||
</StylishText>
|
||||
<PlaceholderPill />
|
||||
</Group>
|
||||
<Title order={1}>
|
||||
<Trans>Welcome to your Dashboard{username && `, ${username}`}</Trans>
|
||||
</Title>
|
||||
<WidgetLayout items={vals} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -11,5 +11,9 @@ test('Basic Platform UI test', async ({ page }) => {
|
||||
await page.goto('./platform/');
|
||||
|
||||
await expect(page).toHaveTitle('InvenTree Demo Server');
|
||||
await expect(page.getByText('Home').nth(1)).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole('heading', {
|
||||
name: 'Welcome to your Dashboard, Ally Access'
|
||||
})
|
||||
).toBeVisible();
|
||||
});
|
||||
|
@ -877,6 +877,13 @@
|
||||
"@babel/runtime" "^7.20.13"
|
||||
"@lingui/core" "4.3.0"
|
||||
|
||||
"@mantine/carousel@^6.0.17":
|
||||
version "6.0.17"
|
||||
resolved "https://registry.yarnpkg.com/@mantine/carousel/-/carousel-6.0.17.tgz#d31fc9bc9ef14bd5ea3e9162d4a130b904cb478e"
|
||||
integrity sha512-cKX7zGmWVXdq/mPff5QYaHLR2X6bujbR4YZ3Hs3TD8KuySTZDOHipUD9IAVH1DtYJRE0+FIRb6OeZ7X9/N2Erg==
|
||||
dependencies:
|
||||
"@mantine/utils" "6.0.17"
|
||||
|
||||
"@mantine/core@^6.0.17":
|
||||
version "6.0.17"
|
||||
resolved "https://registry.npmjs.org/@mantine/core/-/core-6.0.17.tgz"
|
||||
@ -1167,6 +1174,13 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-grid-layout@^1.3.2":
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-1.3.2.tgz#9f195666a018a5ae2b773887e3b552cb4378d67f"
|
||||
integrity sha512-ZzpBEOC1JTQ7MGe1h1cPKSLP4jSWuxc+yvT4TsAlEW9+EFPzAf8nxQfFd7ea9gL17Em7PbwJZAsiwfQQBUklZQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-router-dom@^5.3.3":
|
||||
version "5.3.3"
|
||||
resolved "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz"
|
||||
@ -1442,6 +1456,11 @@ clsx@1.1.1:
|
||||
resolved "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz"
|
||||
integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==
|
||||
|
||||
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==
|
||||
|
||||
color-convert@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz"
|
||||
@ -1578,6 +1597,24 @@ electron-to-chromium@^1.4.431:
|
||||
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.468.tgz"
|
||||
integrity sha512-6M1qyhaJOt7rQtNti1lBA0GwclPH+oKCmsra/hkcWs5INLxfXXD/dtdnaKUYQu/pjOBP/8Osoe4mAcNvvzoFag==
|
||||
|
||||
embla-carousel-react@^8.0.0-rc11:
|
||||
version "8.0.0-rc11"
|
||||
resolved "https://registry.yarnpkg.com/embla-carousel-react/-/embla-carousel-react-8.0.0-rc11.tgz#0e2fde5cafa3cae9c30721e18aee648599527994"
|
||||
integrity sha512-hXOAUMOIa0GF5BtdTTqBuKcjgU+ipul6thTCXOZttqnu2c6VS3SIzUUT+onIIEw+AptzKJcPwGcoAByAGa9eJw==
|
||||
dependencies:
|
||||
embla-carousel "8.0.0-rc11"
|
||||
embla-carousel-reactive-utils "8.0.0-rc11"
|
||||
|
||||
embla-carousel-reactive-utils@8.0.0-rc11:
|
||||
version "8.0.0-rc11"
|
||||
resolved "https://registry.yarnpkg.com/embla-carousel-reactive-utils/-/embla-carousel-reactive-utils-8.0.0-rc11.tgz#d5493bd2bfeb68b1cbf65d4c836a4d36779a03de"
|
||||
integrity sha512-pDNVJNCn0dybLkHw93My+cMfkRQ5oLZff6ZCwgmrw+96aPiZUyo5ANywz8Lb70SWWgD/TNBRrtQCquvjHS31Sg==
|
||||
|
||||
embla-carousel@8.0.0-rc11:
|
||||
version "8.0.0-rc11"
|
||||
resolved "https://registry.yarnpkg.com/embla-carousel/-/embla-carousel-8.0.0-rc11.tgz#700ab6b3e4825ef9e6ac83238b81e3e1a316c3f4"
|
||||
integrity sha512-Toeaug98PGYzSY56p/xsa+u4zbQbAXgGymwEDUc2wqT+1XCnnUsH42MClglhABJQbobwDYxOabhJrfXyJKUMig==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
|
||||
@ -1987,6 +2024,11 @@ lodash.get@^4.4.2:
|
||||
resolved "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz"
|
||||
integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
|
||||
|
||||
lodash.isequal@^4.0.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||
|
||||
lodash.sortby@^4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz"
|
||||
@ -2231,7 +2273,7 @@ pretty-format@^29.6.1:
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^18.0.0"
|
||||
|
||||
prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
|
||||
prop-types@15.x, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
@ -2270,6 +2312,14 @@ react-dom@^18.2.0:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.0"
|
||||
|
||||
react-draggable@^4.0.0, react-draggable@^4.0.3:
|
||||
version "4.4.5"
|
||||
resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.5.tgz#9e37fe7ce1a4cf843030f521a0a4cc41886d7e7c"
|
||||
integrity sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==
|
||||
dependencies:
|
||||
clsx "^1.1.1"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
react-dropzone@14.2.3:
|
||||
version "14.2.3"
|
||||
resolved "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.2.3.tgz"
|
||||
@ -2279,6 +2329,17 @@ react-dropzone@14.2.3:
|
||||
file-selector "^0.6.0"
|
||||
prop-types "^15.8.1"
|
||||
|
||||
react-grid-layout@^1.3.4:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-1.3.4.tgz#4fa819be24a1ba9268aa11b82d63afc4762a32ff"
|
||||
integrity sha512-sB3rNhorW77HUdOjB4JkelZTdJGQKuXLl3gNg+BI8gJkTScspL1myfZzW/EM0dLEn+1eH+xW+wNqk0oIM9o7cw==
|
||||
dependencies:
|
||||
clsx "^1.1.1"
|
||||
lodash.isequal "^4.0.0"
|
||||
prop-types "^15.8.1"
|
||||
react-draggable "^4.0.0"
|
||||
react-resizable "^3.0.4"
|
||||
|
||||
react-is@^16.13.1, react-is@^16.7.0:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||
@ -2313,6 +2374,14 @@ react-remove-scroll@^2.5.5:
|
||||
use-callback-ref "^1.3.0"
|
||||
use-sidecar "^1.1.2"
|
||||
|
||||
react-resizable@^3.0.4:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.0.5.tgz#362721f2efbd094976f1780ae13f1ad7739786c1"
|
||||
integrity sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==
|
||||
dependencies:
|
||||
prop-types "15.x"
|
||||
react-draggable "^4.0.3"
|
||||
|
||||
react-router-dom@^6.14.2:
|
||||
version "6.14.2"
|
||||
resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.2.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user