From d439ba1842bba6e3097f76b03b9c940f9569051d Mon Sep 17 00:00:00 2001 From: Meierschlumpf Date: Wed, 4 Jan 2023 19:06:19 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Improve=20resposivnes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- data/configs/default.json | 316 +++++++++--------- .../Wrappers/gridstack/init-gridstack.ts | 4 +- .../Wrappers/gridstack/use-gridstack.ts | 78 ++++- src/styles/global.scss | 18 +- src/widgets/date/DateTile.tsx | 2 +- src/widgets/weather/WeatherTile.tsx | 2 +- 6 files changed, 244 insertions(+), 176 deletions(-) diff --git a/data/configs/default.json b/data/configs/default.json index 7a2b6bb23..6e713cc61 100644 --- a/data/configs/default.json +++ b/data/configs/default.json @@ -17,81 +17,6 @@ } ], "apps": [ - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33a", - "name": "Documentation", - "url": "https://homarr.dev", - "behaviour": { - "onClickUrl": "https://homarr.dev", - "externalUrl": "https://homarr.dev", - "isOpeningNewTab": true - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [ - 200 - ] - }, - "appearance": { - "iconUrl": "/imgs/logo/logo.png" - }, - "integration": { - "type": null, - "properties": [] - }, - "area": { - "type": "wrapper", - "properties": { - "id": "default" - } - }, - "shape": { - "location": { - "x": 0, - "y": 11 - }, - "size": { - "width": 4, - "height": 3 - } - } - }, - { - "id": "e41a11f5-9c6e-41bc-ac0e-4c4c47582faa", - "name": "Your app", - "url": "https://homarr.dev", - "appearance": { - "iconUrl": "/imgs/logo/logo.png" - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [] - }, - "behaviour": { - "isOpeningNewTab": true, - "externalUrl": "" - }, - "area": { - "type": "wrapper", - "properties": { - "id": "default" - } - }, - "shape": { - "location": { - "x": 8, - "y": 10 - }, - "size": { - "width": 4, - "height": 2 - } - }, - "integration": { - "type": null, - "properties": [] - } - }, { "id": "5df743d9-5cb1-457c-85d2-64ff86855652", "name": "Your app", @@ -128,6 +53,42 @@ "properties": [] } }, + { + "id": "76217a87-7151-42d0-b0cf-1b72aef63f83", + "name": "Small app", + "url": "https://homarr.dev", + "appearance": { + "iconUrl": "/imgs/logo/logo.png" + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [] + }, + "behaviour": { + "isOpeningNewTab": true, + "externalUrl": "https://homarr.dev" + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "location": { + "x": 4, + "y": 0 + }, + "size": { + "width": 1, + "height": 1 + } + }, + "integration": { + "type": null, + "properties": [] + } + }, { "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330", "name": "Contribute", @@ -158,7 +119,7 @@ }, "shape": { "location": { - "x": 4, + "x": 7, "y": 0 }, "size": { @@ -167,42 +128,6 @@ } } }, - { - "id": "76217a87-7151-42d0-b0cf-1b72aef63f83", - "name": "Small app", - "url": "https://homarr.dev", - "appearance": { - "iconUrl": "/imgs/logo/logo.png" - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [] - }, - "behaviour": { - "isOpeningNewTab": true, - "externalUrl": "https://homarr.dev" - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "location": { - "x": 5, - "y": 0 - }, - "size": { - "width": 1, - "height": 1 - } - }, - "integration": { - "type": null, - "properties": [] - } - }, { "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a337", "name": "Discord", @@ -242,6 +167,45 @@ } } }, + { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33a", + "name": "Documentation", + "url": "https://homarr.dev", + "behaviour": { + "onClickUrl": "https://homarr.dev", + "externalUrl": "https://homarr.dev", + "isOpeningNewTab": true + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [ + 200 + ] + }, + "appearance": { + "iconUrl": "/imgs/logo/logo.png" + }, + "integration": { + "type": null, + "properties": [] + }, + "area": { + "type": "wrapper", + "properties": { + "id": "default" + } + }, + "shape": { + "location": { + "x": 0, + "y": 11 + }, + "size": { + "width": 4, + "height": 3 + } + } + }, { "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990", "name": "Donate", @@ -272,7 +236,7 @@ }, "shape": { "location": { - "x": 7, + "x": 5, "y": 0 }, "size": { @@ -280,54 +244,45 @@ "height": 1 } } + }, + { + "id": "e41a11f5-9c6e-41bc-ac0e-4c4c47582faa", + "name": "Your app", + "url": "https://homarr.dev", + "appearance": { + "iconUrl": "/imgs/logo/logo.png" + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [] + }, + "behaviour": { + "isOpeningNewTab": true, + "externalUrl": "" + }, + "area": { + "type": "wrapper", + "properties": { + "id": "default" + } + }, + "shape": { + "location": { + "x": 8, + "y": 10 + }, + "size": { + "width": 4, + "height": 2 + } + }, + "integration": { + "type": null, + "properties": [] + } } ], "widgets": [ - { - "id": "weather", - "properties": { - "displayInFahrenheit": false, - "location": "Paris" - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "location": { - "x": 0, - "y": 0 - }, - "size": { - "width": 2, - "height": 2 - } - } - }, - { - "id": "date", - "properties": { - "display24HourFormat": true - }, - "area": { - "type": "category", - "properties": { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" - } - }, - "shape": { - "location": { - "x": 2, - "y": 0 - }, - "size": { - "width": 2, - "height": 2 - } - } - }, { "id": "calendar", "properties": { @@ -349,6 +304,51 @@ "height": 5 } } + }, + { + "id": "weather", + "properties": { + "displayInFahrenheit": false, + "location": "Paris" + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "location": { + "x": 0, + "y": 0 + }, + "size": { + "width": 4, + "height": 1 + } + } + }, + { + "id": "date", + "properties": { + "display24HourFormat": true + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "location": { + "x": 8, + "y": 0 + }, + "size": { + "width": 4, + "height": 1 + } + } } ], "settings": { diff --git a/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts b/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts index 8d1bcd0a3..3ae5923cc 100644 --- a/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts +++ b/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts @@ -12,7 +12,7 @@ export const initializeGridstack = ( items: AppType[], widgets: IWidget[], isEditMode: boolean, - isLargerThanSm: boolean, + wrapperColumnCount: 3 | 6 | 12, events: { onChange: (changedNode: GridStackNode) => void; onAdd: (addedNode: GridStackNode) => void; @@ -20,7 +20,7 @@ export const initializeGridstack = ( ) => { if (!wrapperRef.current) return; // calculates the currently available count of columns - const columnCount = areaType === 'sidebar' ? 4 : isLargerThanSm || typeof isLargerThanSm === 'undefined' ? 12 : 6; + const columnCount = areaType === 'sidebar' ? 4 : wrapperColumnCount; const minRow = areaType !== 'sidebar' ? 1 : Math.floor(wrapperRef.current.offsetHeight / 64); // initialize gridstack const newGrid = gridRef; diff --git a/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts b/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts index f56cec96d..7b9cfc8fe 100644 --- a/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts +++ b/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts @@ -28,11 +28,18 @@ interface UseGristackReturnType { }; } +const useWrapperColumnCount = () => { + const isLargerThanSm = useScreenLargerThan('sm'); + const isLargerThanXl = useScreenLargerThan('xl'); + + return typeof isLargerThanXl === 'undefined' || isLargerThanXl ? 12 : isLargerThanSm ? 6 : 3; +}; + export const useGridstack = ( areaType: 'wrapper' | 'category' | 'sidebar', areaId: string ): UseGristackReturnType => { - const isLargerThanSm = useScreenLargerThan('sm'); + const wrapperColumnCount = useWrapperColumnCount(); const isEditMode = useEditModeStore((x) => x.enabled); const { config, configVersion, name: configName } = useConfigContext(); const updateConfig = useConfigStore((x) => x.updateConfig); @@ -82,59 +89,104 @@ export const useGridstack = ( useEffect(() => { if (areaType === 'sidebar') return; gridRef.current?.column( - isLargerThanSm || typeof isLargerThanSm === 'undefined' ? 12 : 6, + wrapperColumnCount, (column, prevColumn, newNodes, nodes) => { let nextRow = 0; - let available = 6; + let available = column; if (column === prevColumn) { newNodes.concat(nodes); return; } - nodes.reverse().forEach((node) => { + const getGridstackAttribute = (node: GridStackNode, path: 'x' | 'y' | 'w' | 'h'): number => parseInt(node.el!.getAttribute(`data-gridstack-${path}`)!, 10); + + const getGridstackAttributes = (node: GridStackNode) => ({ + width: getGridstackAttribute(node, 'w'), + height: getGridstackAttribute(node, 'h'), + x: getGridstackAttribute(node, 'x'), + y: getGridstackAttribute(node, 'y'), + }); + + const sortNodes = (a: GridStackNode, b: GridStackNode) => { + const aAttributes = getGridstackAttributes(a); + const bAttributes = getGridstackAttributes(b); + + const differenceY = aAttributes.y - bAttributes.y; + + return differenceY !== 0 ? differenceY : aAttributes.x - bAttributes.x; + }; + + const sorted = nodes.sort(sortNodes); + + console.log(sorted); + + sorted.forEach((node) => { const newnode = node; const width = parseInt(newnode.el!.getAttribute('data-gridstack-w')!, 10); const height = parseInt(newnode.el!.getAttribute('data-gridstack-h')!, 10); const x = parseInt(newnode.el!.getAttribute('data-gridstack-x')!, 10); const y = parseInt(newnode.el!.getAttribute('data-gridstack-y')!, 10); + const moveYDown = 1; - if (column === 6) { + if (column === 3) { + newnode.x = available >= width ? 3 - available : 0; + newnode.y = available === 3 || available >= width ? nextRow : nextRow += moveYDown; + + if (width > 3) { + newnode.w = 3; + nextRow += moveYDown; + available = 3; + } else if (available >= width) { + available -= width; + if (available === 0) { + nextRow += moveYDown; + available = 3; + } + } else if (available < width) { + newnode.y = newnode.y! + moveYDown; + available = 3 - width; + nextRow += moveYDown; + } + } else if (column === 6) { newnode.x = available >= width ? 6 - available : 0; newnode.y = nextRow; if (width > 6) { newnode.w = 6; - nextRow += 2; + nextRow += moveYDown; available = 6; } else if (available >= width) { available -= width; if (available === 0) { - nextRow += 2; + nextRow += moveYDown; available = 6; } } else if (available < width) { - newnode.y = newnode.y! + 2; + newnode.y = newnode.y! + moveYDown; available = 6 - width; - nextRow += 2; + nextRow += moveYDown; } } else { newnode.x = y % 2 === 1 ? x + 6 : x; newnode.y = Math.floor(y / 2); } + + console.log(newnode); + newNodes.push(newnode); }); } ); - }, [isLargerThanSm]); + }, [wrapperColumnCount]); useEffect(() => { if (width === 0) return; - const widgetWidth = width / (isLargerThanSm ? 12 : 6); + const widgetWidth = width / wrapperColumnCount; // widget width is used to define sizes of gridstack items within global.scss root.style.setProperty('--gridstack-widget-width', widgetWidth.toString()); gridRef.current?.cellHeight(widgetWidth); - }, [width, isLargerThanSm]); + }, [width, wrapperColumnCount]); const onChange = isEditMode ? (changedNode: GridStackNode) => { @@ -291,7 +343,7 @@ export const useGridstack = ( items, widgets ?? [], isEditMode, - isLargerThanSm, + wrapperColumnCount, { onChange, onAdd, diff --git a/src/styles/global.scss b/src/styles/global.scss index 76121cc0e..5c605a390 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -59,7 +59,7 @@ transition: none; } -@media screen and (max-width: 768px) { +@media screen and (max-width: 1400px) { @for $i from 1 to 7 { .grid-stack>.grid-stack-item[gs-w="#{$i}"] { width: percentage(($i / 6)) !important } .grid-stack>.grid-stack-item[gs-min-w="#{$i}"] { min-width: percentage(($i / 6)) !important } @@ -73,4 +73,20 @@ .grid-stack>.grid-stack-item { min-width: percentage(1/6) !important; } +} + +@media screen and (max-width: 768px) { + @for $i from 1 to 4 { + .grid-stack>.grid-stack-item[gs-w="#{$i}"] { width: percentage(($i / 3)) !important } + .grid-stack>.grid-stack-item[gs-min-w="#{$i}"] { min-width: percentage(($i / 3)) !important } + .grid-stack>.grid-stack-item[gs-max-w="#{$i}"] { max-width: percentage(($i / 3)) !important } + } + + @for $i from 1 to 4 { + .grid-stack>.grid-stack-item[gs-x="#{$i}"] { left: percentage(($i / 3)) } + } + + .grid-stack>.grid-stack-item { + min-width: percentage(1/3) !important; + } } \ No newline at end of file diff --git a/src/widgets/date/DateTile.tsx b/src/widgets/date/DateTile.tsx index 653f813c5..843dc2564 100644 --- a/src/widgets/date/DateTile.tsx +++ b/src/widgets/date/DateTile.tsx @@ -17,7 +17,7 @@ const definition = defineWidget({ }, gridstack: { minWidth: 2, - minHeight: 2, + minHeight: 1, maxWidth: 12, maxHeight: 12, }, diff --git a/src/widgets/weather/WeatherTile.tsx b/src/widgets/weather/WeatherTile.tsx index 677d4bd6c..b053a0a2a 100644 --- a/src/widgets/weather/WeatherTile.tsx +++ b/src/widgets/weather/WeatherTile.tsx @@ -20,7 +20,7 @@ const definition = defineWidget({ }, gridstack: { minWidth: 2, - minHeight: 2, + minHeight: 1, maxWidth: 12, maxHeight: 12, },