2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-09-14 14:41:33 +00:00

feat(frontend): Add samples for dashboard (#10306)

* feat(forntend): Add sampels to dashboard
Closes #9990

* add sessions storage to disable sample dash once cleared/removed
This commit is contained in:
Matthias Mair
2025-09-14 12:47:15 +02:00
committed by GitHub
parent f3ec708a28
commit 9679e58212
2 changed files with 144 additions and 46 deletions

View File

@@ -1,5 +1,13 @@
import { t } from '@lingui/core/macro';
import { Alert, Card, Center, Divider, Loader, Text } from '@mantine/core';
import {
Alert,
Card,
Center,
Divider,
Loader,
Space,
Text
} from '@mantine/core';
import { useDisclosure, useHotkeys } from '@mantine/hooks';
import { IconExclamationCircle, IconInfoCircle } from '@tabler/icons-react';
import { useCallback, useEffect, useMemo, useState } from 'react';
@@ -21,15 +29,23 @@ export default function DashboardLayout() {
const [widgets, setWidgets] = useState<DashboardWidgetProps[]>([]);
// local/remote storage values for widget / layout
const [remoteWidgets, setRemoteWidgets, remoteLayouts, setRemoteLayouts] =
useLocalState(
useShallow((state) => [
state.widgets,
state.setWidgets,
state.layouts,
state.setLayouts
])
);
const [
remoteWidgets,
setRemoteWidgets,
remoteLayouts,
setRemoteLayouts,
showSampleDashboard,
setShowSampleDashboard
] = useLocalState(
useShallow((state) => [
state.widgets,
state.setWidgets,
state.layouts,
state.setLayouts,
state.showSampleDashboard,
state.setShowSampleDashboard
])
);
const [editing, setEditing] = useDisclosure(false);
const [removing, setRemoving] = useDisclosure(false);
@@ -75,6 +91,9 @@ export default function DashboardLayout() {
);
if (newWidget) {
if (showSampleDashboard) {
setShowSampleDashboard(false);
}
setWidgets([...widgets, newWidget]);
}
@@ -195,10 +214,48 @@ export default function DashboardLayout() {
// Clear all widgets from the dashboard
const clearWidgets = useCallback(() => {
if (showSampleDashboard) {
setShowSampleDashboard(false);
}
setWidgets([]);
setLayouts({});
}, []);
const defaultLayouts = {
lg: [
{
w: 6,
h: 4,
x: 0,
y: 0,
i: 'gstart',
minW: 5,
minH: 4,
moved: false,
static: false
},
{
w: 6,
h: 4,
x: 6,
y: 0,
i: 'news',
minW: 5,
minH: 4,
moved: false,
static: false
}
]
};
const loadWigs = ['news', 'gstart'];
const defaultWidgets = useMemo(() => {
return loadWigs
.map((lwid: string) =>
availableWidgets.items.find((wid) => wid.label === lwid)
)
.filter((widget): widget is DashboardWidgetProps => widget !== undefined);
}, [availableWidgets.items, defaultLayouts]);
return (
<>
<DashboardWidgetDrawer
@@ -228,43 +285,41 @@ export default function DashboardLayout() {
{layouts && loaded && availableWidgets.loaded ? (
<>
{widgetLabels.length == 0 ? (
<Center>
<Card shadow='xs' padding='xl' style={{ width: '100%' }}>
<Alert
color='blue'
title={t`No Widgets Selected`}
icon={<IconInfoCircle />}
>
<Text>{t`Use the menu to add widgets to the dashboard`}</Text>
</Alert>
</Card>
</Center>
<>
<Center>
<Card shadow='xs' padding='xl' style={{ width: '100%' }}>
<Alert
color='blue'
title={t`No Widgets Selected`}
icon={<IconInfoCircle />}
>
<Text>{t`Use the menu to add widgets to the dashboard`}</Text>
</Alert>
</Card>
</Center>
{showSampleDashboard && (
<>
<Space h='lg' />
{WidgetGrid(
defaultLayouts,
() => {},
editing,
defaultWidgets,
removing,
() => {}
)}
</>
)}
</>
) : (
<ReactGridLayout
className='dashboard-layout'
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
rowHeight={64}
layouts={layouts}
onLayoutChange={onLayoutChange}
compactType={'vertical'}
isDraggable={editing}
isResizable={editing}
margin={[10, 10]}
containerPadding={[0, 0]}
resizeHandles={['ne', 'se', 'sw', 'nw']}
>
{widgets.map((item: DashboardWidgetProps) => {
return DashboardWidget({
item: item,
editing: editing,
removing: removing,
onRemove: () => {
removeWidget(item.label);
}
});
})}
</ReactGridLayout>
WidgetGrid(
layouts,
onLayoutChange,
editing,
widgets,
removing,
removeWidget
)
)}
</>
) : (
@@ -275,3 +330,40 @@ export default function DashboardLayout() {
</>
);
}
function WidgetGrid(
layouts: {},
onLayoutChange: (layout: any, newLayouts: any) => void,
editing: boolean,
widgets: DashboardWidgetProps[],
removing: boolean,
removeWidget: (widget: string) => void
) {
return (
<ReactGridLayout
className='dashboard-layout'
breakpoints={{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }}
cols={{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }}
rowHeight={64}
layouts={layouts}
onLayoutChange={onLayoutChange}
compactType={'vertical'}
isDraggable={editing}
isResizable={editing}
margin={[10, 10]}
containerPadding={[0, 0]}
resizeHandles={['ne', 'se', 'sw', 'nw']}
>
{widgets.map((item: DashboardWidgetProps) => {
return DashboardWidget({
item: item,
editing: editing,
removing: removing,
onRemove: () => {
removeWidget(item.label);
}
});
})}
</ReactGridLayout>
);
}

View File

@@ -31,6 +31,8 @@ interface LocalStateProps {
setWidgets: (widgets: string[], noPatch?: boolean) => void;
layouts: any;
setLayouts: (layouts: any, noPatch?: boolean) => void;
showSampleDashboard: boolean;
setShowSampleDashboard: (value: boolean) => void;
// panels
lastUsedPanels: Record<string, string>;
setLastUsedPanel: (panelKey: string) => (value: string) => void;
@@ -118,6 +120,10 @@ export const useLocalState = create<LocalStateProps>()(
if (!noPatch)
patchUser('widgets', { widgets: get().widgets, layouts: newLayouts });
},
showSampleDashboard: true,
setShowSampleDashboard: (value) => {
set({ showSampleDashboard: value });
},
// panels
lastUsedPanels: {},
setLastUsedPanel: (panelKey) => (value) => {