From a454002c6c8d1b9dfabcc5adf0a0e31d3f9b3982 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Wed, 24 Jun 2026 12:43:29 +0000 Subject: [PATCH] Fix for dashboard dragging / moving - Update react-grid-layout - Shim for vite.config.ts --- src/frontend/package.json | 4 +- .../components/dashboard/DashboardLayout.tsx | 86 +++++++++++-------- src/frontend/vite.config.ts | 3 +- src/frontend/yarn.lock | 38 ++++---- 4 files changed, 75 insertions(+), 56 deletions(-) diff --git a/src/frontend/package.json b/src/frontend/package.json index 10e1d887c8..22721f78a0 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -95,7 +95,7 @@ "qrcode": "^1.5.4", "react": "^19.2.7", "react-dom": "^19.2.7", - "react-grid-layout": "1.4.4", + "react-grid-layout": "2.2.3", "react-hook-form": "^7.78.0", "react-is": "^19.2.7", "react-router-dom": "^6.30.4", @@ -122,7 +122,7 @@ "@types/qrcode": "^1.5.6", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "@types/react-grid-layout": "^1.3.5", + "@types/react-grid-layout": "^2.1.0", "@types/react-router-dom": "^5.3.3", "@types/react-window": "^1.8.8", "@vanilla-extract/vite-plugin": "^5.2.2", diff --git a/src/frontend/src/components/dashboard/DashboardLayout.tsx b/src/frontend/src/components/dashboard/DashboardLayout.tsx index 0278bc60f8..da46af1d86 100644 --- a/src/frontend/src/components/dashboard/DashboardLayout.tsx +++ b/src/frontend/src/components/dashboard/DashboardLayout.tsx @@ -11,7 +11,11 @@ import { import { useDisclosure } from '@mantine/hooks'; import { IconExclamationCircle, IconInfoCircle } from '@tabler/icons-react'; import { useCallback, useEffect, useMemo, useState } from 'react'; -import { type Layout, Responsive, WidthProvider } from 'react-grid-layout'; +import { + ResponsiveGridLayout, + useContainerWidth, + verticalCompactor +} from 'react-grid-layout'; import { useInvenTreeHotkeys } from '@lib/functions/Events'; import { useShallow } from 'zustand/react/shallow'; @@ -22,8 +26,6 @@ import DashboardMenu from './DashboardMenu'; import DashboardWidget, { type DashboardWidgetProps } from './DashboardWidget'; import DashboardWidgetDrawer from './DashboardWidgetDrawer'; -const ReactGridLayout = WidthProvider(Responsive); - export default function DashboardLayout() { const user = useUserState(); @@ -129,9 +131,7 @@ export default function DashboardLayout() { const _layouts: any = { ...layouts }; Object.keys(_layouts).forEach((key) => { - _layouts[key] = _layouts[key].filter( - (item: Layout) => item.i !== widget - ); + _layouts[key] = _layouts[key].filter((item: any) => item.i !== widget); }); setLayouts(_layouts); @@ -142,7 +142,7 @@ export default function DashboardLayout() { // When the layout is rendered, ensure that the widget attributes are observed const updateLayoutForWidget = useCallback( (layout: any[], widgets: any[], overrideSize: boolean) => { - return layout.map((item: Layout): Layout => { + return layout.map((item: any) => { // Find the matching widget const widget = widgets.find( (widget: DashboardWidgetProps) => widget.label === item.i @@ -191,7 +191,7 @@ export default function DashboardLayout() { const reducedLayouts: any = {}; // Reduce the layouts to exclude default attributes from the dataset Object.keys(newLayouts).forEach((key) => { - reducedLayouts[key] = newLayouts[key].map((item: Layout) => { + reducedLayouts[key] = newLayouts[key].map((item: any) => { return { ...item, moved: item.moved ? true : undefined, @@ -316,26 +316,26 @@ export default function DashboardLayout() { {showSampleDashboard && ( <> - {WidgetGrid( - defaultLayouts, - () => {}, - editing, - defaultWidgets, - removing, - () => {} - )} + {}} + editing={editing} + widgets={defaultWidgets} + removing={removing} + removeWidget={() => {}} + /> )} ) : ( - WidgetGrid( - layouts, - onLayoutChange, - editing, - widgets, - removing, - removeWidget - ) + )} ) : ( @@ -347,28 +347,38 @@ export default function DashboardLayout() { ); } -function WidgetGrid( - layouts: {}, - onLayoutChange: (layout: any, newLayouts: any) => void, - editing: boolean, - widgets: DashboardWidgetProps[], - removing: boolean, - removeWidget: (widget: string) => void -) { +function WidgetGrid({ + layouts, + onLayoutChange, + editing, + widgets, + removing, + removeWidget +}: { + layouts: {}; + onLayoutChange: (layout: any, newLayouts: any) => void; + editing: boolean; + widgets: DashboardWidgetProps[]; + removing: boolean; + removeWidget: (widget: string) => void; +}) { + const { width, containerRef } = useContainerWidth(); + return ( - {widgets.map((item: DashboardWidgetProps) => { return DashboardWidget({ @@ -380,6 +390,6 @@ function WidgetGrid( } }); })} - + ); } diff --git a/src/frontend/vite.config.ts b/src/frontend/vite.config.ts index 2aa813204e..19175a62ba 100644 --- a/src/frontend/vite.config.ts +++ b/src/frontend/vite.config.ts @@ -90,7 +90,8 @@ export default defineConfig(({ command, mode }) => { } }, define: { - ...__INVENTREE_VERSION_INFO__ + ...__INVENTREE_VERSION_INFO__, + 'process.env.NODE_ENV': JSON.stringify(mode) } }; }); diff --git a/src/frontend/yarn.lock b/src/frontend/yarn.lock index 0612b6ef65..4b79b9b7b3 100644 --- a/src/frontend/yarn.lock +++ b/src/frontend/yarn.lock @@ -1787,12 +1787,12 @@ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.2.3.tgz#c1e305d15a52a3e508d54dca770d202cb63abf2c" integrity sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ== -"@types/react-grid-layout@^1.3.5": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-1.3.6.tgz#394f9995df1192b7d0cfe33ce017ec70356e7e73" - integrity sha512-Cw7+sb3yyjtmxwwJiXtEXcu5h4cgs+sCGkHwHXsFmPyV30bf14LeD/fa2LwQovuD2HWxCcjIdNhDlcYGj95qGA== +"@types/react-grid-layout@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-2.1.0.tgz#e6043ff473a7f6704513bf387ab41722bb8f24b2" + integrity sha512-pHEjVg9ert6BDFHFQ1IEdLUkd2gasJvyti5lV2kE46N/R07ZiaSZpAXeXJAA1MXy/Qby23fZmiuEgZkITxPXug== dependencies: - "@types/react" "*" + react-grid-layout "*" "@types/react-router-dom@^5.3.3": version "5.3.3" @@ -2294,7 +2294,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -clsx@^2.0.0, clsx@^2.1.1: +clsx@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== @@ -4005,7 +4005,15 @@ react-dom@^19.2.7: dependencies: scheduler "^0.27.0" -react-draggable@^4.4.5, react-draggable@^4.5.0: +react-draggable@^4.4.6: + version "4.7.0" + resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.7.0.tgz#29ff90b2feb9ddd320419bfff866035c4dfc7156" + integrity sha512-kTpANmKWVnFXiZ76Ag2ZowiFStuBYnJ606PI1TbUsOg29/400/JNIxI9+CuenhiAqFuXWJffz6F4UI3R51kUug== + dependencies: + clsx "^2.1.1" + prop-types "^15.8.1" + +react-draggable@^4.5.0: version "4.6.0" resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.6.0.tgz#bae07fc729afe1a80c6cedd4775cc0d6856a0e0b" integrity sha512-g4vqY53xhmPrBnZvGP+1YQV0eYnB3o0VLzoi6q2IpwnQrxIZ34tYRKpVtsWIXPg4D/pvLn+oYCW5gOK2cWIrgA== @@ -4022,16 +4030,16 @@ react-dropzone@15.0.0: file-selector "^2.1.0" prop-types "^15.8.1" -react-grid-layout@1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-1.4.4.tgz#0bdb19d6db061556868fef1f430cc8c14d21f131" - integrity sha512-7+Lg8E8O8HfOH5FrY80GCIR1SHTn2QnAYKh27/5spoz+OHhMmEhU/14gIkRzJOtympDPaXcVRX/nT1FjmeOUmQ== +react-grid-layout@*, react-grid-layout@2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-2.2.3.tgz#6daf24b8c48448af617238520dd233a9375e2f16" + integrity sha512-OAEJHBxmfuxQfVtZwRzmsokijGlBgzYIJ7MUlLk/VSa43SaGzu15w5D0P2RDrfX5EvP9POMbL6bFrai/huDzbQ== dependencies: - clsx "^2.0.0" + clsx "^2.1.1" fast-equals "^4.0.3" prop-types "^15.8.1" - react-draggable "^4.4.5" - react-resizable "^3.0.5" + react-draggable "^4.4.6" + react-resizable "^3.1.3" resize-observer-polyfill "^1.5.1" react-hook-form@^7.78.0: @@ -4091,7 +4099,7 @@ react-remove-scroll@^2.7.2: use-callback-ref "^1.3.3" use-sidecar "^1.1.3" -react-resizable@^3.0.5: +react-resizable@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.2.0.tgz#09a6f77fcc4d59ca810098f58e46f39376cacef5" integrity sha512-3NKQ0SLZV7rs3LQHeXlOzDSRQfFrkX6TVet77/Qk03zqiZyee37b7N8/gwDJAA8UUjRz7PdWCCy49hcso45SMQ==