From d886bbdaade38872b23c5f7c9eb27b39bd6fba4c Mon Sep 17 00:00:00 2001 From: Meierschlumpf Date: Sat, 7 Jan 2023 23:25:13 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20issues=20with=20gridstack?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Overview/AvailableElementsOverview.tsx | 33 +--------- .../Dashboard/Tiles/TileWrapper.tsx | 66 ++++++++++++------- .../Dashboard/Wrappers/WrapperContent.tsx | 4 +- .../Wrappers/gridstack/init-gridstack.ts | 26 +++++++- .../Wrappers/gridstack/use-gridstack.ts | 54 ++++++++++++++- .../Actions/ToggleEditMode/ToggleEditMode.tsx | 14 ++-- src/modules/Docker/ContainerActionBar.tsx | 33 +--------- src/tools/config/migrateConfig.ts | 22 ++----- 8 files changed, 139 insertions(+), 113 deletions(-) diff --git a/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx b/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx index be42293aa..0304bc473 100644 --- a/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx +++ b/src/components/Dashboard/Modals/SelectElement/Components/Overview/AvailableElementsOverview.tsx @@ -111,38 +111,7 @@ export const AvailableElementTypes = ({ id: getLowestWrapper()?.id ?? 'default', }, }, - shape: { - sm: { - location: { - x: 0, - y: 0, - }, - size: { - width: appTileDefinition.minWidth, - height: appTileDefinition.minHeight, - }, - }, - md: { - location: { - x: 0, - y: 0, - }, - size: { - width: appTileDefinition.minWidth, - height: appTileDefinition.minHeight, - }, - }, - lg: { - location: { - x: 0, - y: 0, - }, - size: { - width: appTileDefinition.minWidth, - height: appTileDefinition.minHeight, - }, - }, - }, + shape: {}, integration: { type: null, properties: [], diff --git a/src/components/Dashboard/Tiles/TileWrapper.tsx b/src/components/Dashboard/Tiles/TileWrapper.tsx index f6469a2a4..47803e519 100644 --- a/src/components/Dashboard/Tiles/TileWrapper.tsx +++ b/src/components/Dashboard/Tiles/TileWrapper.tsx @@ -1,5 +1,6 @@ /* eslint-disable react/no-unknown-property */ import { ReactNode, RefObject } from 'react'; +import widgets from '../../../widgets'; interface GridstackTileWrapperProps { id: string; @@ -29,25 +30,46 @@ export const GridstackTileWrapper = ({ maxHeight, children, itemRef, -}: GridstackTileWrapperProps) => ( -
- {children} -
-); +}: GridstackTileWrapperProps) => { + const locationProperties = useLocationProperties(x, y); + const normalizedWidth = width ?? minWidth; + + const normalizedHeight = height ?? minHeight; + + return ( +
+ {children} +
+ ); +}; + +const useLocationProperties = (x: number | undefined, y: number | undefined) => { + const isLocationDefined = x !== undefined && y !== undefined; + + if (!isLocationDefined) { + return { + 'gs-auto-position': 'true', + }; + } + + return { + 'gs-x': x.toString(), + 'data-gridstack-x': x.toString(), + 'gs-y': y.toString(), + 'data-gridstack-y': y.toString(), + }; +}; diff --git a/src/components/Dashboard/Wrappers/WrapperContent.tsx b/src/components/Dashboard/Wrappers/WrapperContent.tsx index cfb82ae39..5a864b6ab 100644 --- a/src/components/Dashboard/Wrappers/WrapperContent.tsx +++ b/src/components/Dashboard/Wrappers/WrapperContent.tsx @@ -34,8 +34,8 @@ export function WrapperContent({ apps, refs, widgets }: WrapperContentProps) { key={app.id} itemRef={refs.items.current[app.id]} {...tile} - {...app.shape[shapeSize]?.location} - {...app.shape[shapeSize]?.size} + {...(app.shape[shapeSize]?.location ?? {})} + {...(app.shape[shapeSize]?.size ?? {})} > diff --git a/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts b/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts index 36836222d..6da312a9d 100644 --- a/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts +++ b/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts @@ -1,4 +1,4 @@ -import { GridStack, GridStackNode } from 'fily-publish-gridstack'; +import { GridItemHTMLElement, GridStack, GridStackNode } from 'fily-publish-gridstack'; import { MutableRefObject, RefObject } from 'react'; import { AppType } from '../../../../types/app'; import { ShapeType } from '../../../../types/shape'; @@ -15,6 +15,7 @@ export const initializeGridstack = ( isEditMode: boolean, wrapperColumnCount: 3 | 6 | 12, shapeSize: 'sm' | 'md' | 'lg', + tilesWithUnknownLocation: TileWithUnknownLocation[], events: { onChange: (changedNode: GridStackNode) => void; onAdd: (addedNode: GridStackNode) => void; @@ -68,11 +69,25 @@ export const initializeGridstack = ( const item = itemRefs.current[id]?.current; setAttributesFromShape(item, shape[shapeSize]); item && grid.makeWidget(item as HTMLDivElement); + if (!shape[shapeSize] && item) { + const gridItemElement = item as GridItemHTMLElement; + if (gridItemElement.gridstackNode) { + const { x, y, w, h } = gridItemElement.gridstackNode; + tilesWithUnknownLocation.push({ x, y, w, h, type: 'app', id }); + } + } }); widgets.forEach(({ id, shape }) => { const item = itemRefs.current[id]?.current; setAttributesFromShape(item, shape[shapeSize]); item && grid.makeWidget(item as HTMLDivElement); + if (!shape[shapeSize] && item) { + const gridItemElement = item as GridItemHTMLElement; + if (gridItemElement.gridstackNode) { + const { x, y, w, h } = gridItemElement.gridstackNode; + tilesWithUnknownLocation.push({ x, y, w, h, type: 'widget', id }); + } + } }); grid.batchUpdate(false); }; @@ -84,3 +99,12 @@ function setAttributesFromShape(ref: HTMLDivElement | null, sizedShape: ShapeTyp ref.setAttribute('gs-w', sizedShape.size.width.toString()); ref.setAttribute('gs-h', sizedShape.size.height.toString()); } + +export type TileWithUnknownLocation = { + x?: number; + y?: number; + w?: number; + h?: number; + type: 'app' | 'widget'; + id: string; +}; diff --git a/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts b/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts index 5c401f5ac..8a87cca8a 100644 --- a/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts +++ b/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts @@ -6,7 +6,7 @@ import { AppType } from '../../../../types/app'; import { AreaType } from '../../../../types/area'; import { IWidget } from '../../../../widgets/widgets'; import { useEditModeStore } from '../../Views/useEditModeStore'; -import { initializeGridstack } from './init-gridstack'; +import { initializeGridstack, TileWithUnknownLocation } from './init-gridstack'; import { useGridstackStore, useWrapperColumnCount } from './store'; interface UseGristackReturnType { @@ -232,6 +232,7 @@ export const useGridstack = ( // initialize the gridstack useEffect(() => { + const tilesWithUnknownLocation: TileWithUnknownLocation[] = []; initializeGridstack( areaType, wrapperRef, @@ -243,11 +244,62 @@ export const useGridstack = ( isEditMode, wrapperColumnCount, shapeSize, + tilesWithUnknownLocation, { onChange, onAdd, } ); + if (!configName) return; + updateConfig(configName, (prev) => ({ + ...prev, + apps: prev.apps.map((app) => { + const currentUnknownLocation = tilesWithUnknownLocation.find( + (x) => x.type === 'app' && x.id === app.id + ); + if (!currentUnknownLocation) return app; + + return { + ...app, + shape: { + ...app.shape, + [shapeSize]: { + location: { + x: currentUnknownLocation.x, + y: currentUnknownLocation.y, + }, + size: { + width: currentUnknownLocation.w, + height: currentUnknownLocation.h, + }, + }, + }, + }; + }), + widgets: prev.widgets.map((widget) => { + const currentUnknownLocation = tilesWithUnknownLocation.find( + (x) => x.type === 'widget' && x.id === widget.id + ); + if (!currentUnknownLocation) return widget; + + return { + ...widget, + shape: { + ...widget.shape, + [shapeSize]: { + location: { + x: currentUnknownLocation.x, + y: currentUnknownLocation.y, + }, + size: { + width: currentUnknownLocation.w, + height: currentUnknownLocation.h, + }, + }, + }, + }; + }), + })); }, [items, wrapperRef.current, widgets, wrapperColumnCount]); return { diff --git a/src/components/layout/header/Actions/ToggleEditMode/ToggleEditMode.tsx b/src/components/layout/header/Actions/ToggleEditMode/ToggleEditMode.tsx index 72ac9922d..a4b7a8df5 100644 --- a/src/components/layout/header/Actions/ToggleEditMode/ToggleEditMode.tsx +++ b/src/components/layout/header/Actions/ToggleEditMode/ToggleEditMode.tsx @@ -20,16 +20,14 @@ export const ToggleEditModeAction = () => { const smallerThanSm = useScreenSmallerThan('sm'); const { config } = useConfigContext(); - useEffect(() => { - if (enabled || config === undefined || config?.schemaVersion === undefined) return; - const configName = getCookie('config-name')?.toString() ?? 'default'; - axios.put(`/api/configs/${configName}`, { ...config }); - Consola.log('Saved config to server', configName); - }, [enabled]); - const toggleButtonClicked = () => { toggleEditMode(); - if (!enabled) { + if (enabled || config === undefined || config?.schemaVersion === undefined) { + const configName = getCookie('config-name')?.toString() ?? 'default'; + axios.put(`/api/configs/${configName}`, { ...config }); + Consola.log('Saved config to server', configName); + hideNotification('toggle-edit-mode'); + } else if (!enabled) { showNotification({ styles: (theme) => ({ root: { diff --git a/src/modules/Docker/ContainerActionBar.tsx b/src/modules/Docker/ContainerActionBar.tsx index da7388c73..9036fce07 100644 --- a/src/modules/Docker/ContainerActionBar.tsx +++ b/src/modules/Docker/ContainerActionBar.tsx @@ -189,38 +189,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction id: getLowestWrapper()?.id ?? 'default', }, }, - shape: { - sm: { - location: { - x: 0, - y: 0, - }, - size: { - width: appTileDefinition.minWidth, - height: appTileDefinition.minHeight, - }, - }, - md: { - location: { - x: 0, - y: 0, - }, - size: { - width: appTileDefinition.minWidth, - height: appTileDefinition.minHeight, - }, - }, - lg: { - location: { - x: 0, - y: 0, - }, - size: { - width: appTileDefinition.minWidth, - height: appTileDefinition.minHeight, - }, - }, - }, + shape: {}, integration: { type: null, properties: [], diff --git a/src/tools/config/migrateConfig.ts b/src/tools/config/migrateConfig.ts index a98e5dd29..11cbe9c8b 100644 --- a/src/tools/config/migrateConfig.ts +++ b/src/tools/config/migrateConfig.ts @@ -34,9 +34,9 @@ export function migrateConfig(config: Config): ConfigType { }, customization: { colors: { - primary: config.settings.primaryColor, - secondary: config.settings.secondaryColor, - shade: config.settings.primaryShade, + primary: config.settings.primaryColor ?? 'red', + secondary: config.settings.secondaryColor ?? 'orange', + shade: config.settings.primaryShade ?? 7, }, layout: { enabledDocker: config.modules.docker?.enabled ?? false, @@ -60,7 +60,7 @@ export function migrateConfig(config: Config): ConfigType { if (!categoryName) { newConfig.apps.push( - migrateService(service, index, { + migrateService(service, { type: 'wrapper', properties: { id: 'default', @@ -77,7 +77,7 @@ export function migrateConfig(config: Config): ConfigType { } newConfig.apps.push( - migrateService(service, index, { type: 'category', properties: { id: category.id } }) + migrateService(service, { type: 'category', properties: { id: category.id } }) ); }); @@ -114,11 +114,7 @@ const getShapeForColumnCount = (index: number, columnCount: number) => ({ }, }); -const migrateService = ( - oldService: serviceItem, - serviceIndex: number, - areaType: AreaType -): AppType => ({ +const migrateService = (oldService: serviceItem, areaType: AreaType): AppType => ({ id: uuidv4(), name: oldService.name, url: oldService.url, @@ -135,11 +131,7 @@ const migrateService = ( }, integration: migrateIntegration(oldService), area: areaType, - shape: { - lg: getShapeForColumnCount(serviceIndex, 12), - md: getShapeForColumnCount(serviceIndex, 6), - sm: getShapeForColumnCount(serviceIndex, 3), - }, + shape: {}, }); const migrateModules = (config: Config): IWidget[] => {