diff --git a/data/configs/default.json b/data/configs/default.json index 36d29064f..2a5cd2b09 100644 --- a/data/configs/default.json +++ b/data/configs/default.json @@ -17,195 +17,6 @@ } ], "apps": [ - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990", - "name": "Donate", - "url": "https://ko-fi.com/ajnart", - "behaviour": { - "onClickUrl": "https://ko-fi.com/ajnart", - "externalUrl": "https://ko-fi.com/ajnart", - "isOpeningNewTab": true - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [ - 200 - ] - }, - "appearance": { - "iconUrl": "https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/61e1116779fc0a9bd5bdbcc7_Frame%206.png" - }, - "integration": { - "type": null, - "properties": [] - }, - "area": { - "type": "wrapper", - "properties": { - "id": "default" - } - }, - "shape": { - "location": { - "x": 0, - "y": 0 - }, - "size": { - "width": 3, - "height": 3 - } - } - }, - { - "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330", - "name": "Contribute", - "url": "https://github.com/ajnart/homarr", - "behaviour": { - "onClickUrl": "https://github.com/ajnart/homarr", - "externalUrl": "https://github.com/ajnart/homarr", - "isOpeningNewTab": true - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [ - 200 - ] - }, - "appearance": { - "iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/github.png" - }, - "integration": { - "type": null, - "properties": [] - }, - "area": { - "type": "wrapper", - "properties": { - "id": "default" - } - }, - "shape": { - "location": { - "x": 0, - "y": 3 - }, - "size": { - "width": 3, - "height": 3 - } - } - }, - { - "id": "5df743d9-5cb1-457c-85d2-64ff86855652", - "name": "Your app", - "url": "https://homarr.dev", - "appearance": { - "iconUrl": "/imgs/logo/logo.png" - }, - "network": { - "enabledStatusChecker": false, - "okStatus": [] - }, - "behaviour": { - "isOpeningNewTab": true, - "externalUrl": "https://homarr.dev" - }, - "area": { - "type": "wrapper", - "properties": { - "id": "default" - } - }, - "shape": { - "location": { - "x": 15, - "y": 5 - }, - "size": { - "width": 5, - "height": 4 - } - }, - "integration": { - "type": null, - "properties": [] - } - }, - { - "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": 3, - "y": 3 - }, - "size": { - "width": 3, - "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": 0, - "y": 6 - }, - "size": { - "width": 2, - "height": 2 - } - }, - "integration": { - "type": null, - "properties": [] - } - }, { "id": "76217a87-7151-42d0-b0cf-1b72aef63f83", "name": "Small app", @@ -229,8 +40,8 @@ }, "shape": { "location": { - "x": 17, - "y": 0 + "x": 0, + "y": 2 }, "size": { "width": 2, @@ -265,29 +76,43 @@ "properties": [] }, "area": { - "type": "wrapper", + "type": "category", "properties": { - "id": "default" + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" } }, "shape": { "location": { - "x": 3, - "y": 0 + "x": 0, + "y": 4 }, "size": { - "width": 3, + "width": 4, "height": 3 } } - } - ], - "widgets": [ + }, { - "id": "weather", - "properties": { - "displayInFahrenheit": false, - "location": "Paris" + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a990", + "name": "Donate", + "url": "https://ko-fi.com/ajnart", + "behaviour": { + "onClickUrl": "https://ko-fi.com/ajnart", + "externalUrl": "https://ko-fi.com/ajnart", + "isOpeningNewTab": true + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [ + 200 + ] + }, + "appearance": { + "iconUrl": "https://uploads-ssl.webflow.com/5c14e387dab576fe667689cf/61e1116779fc0a9bd5bdbcc7_Frame%206.png" + }, + "integration": { + "type": null, + "properties": [] }, "area": { "type": "category", @@ -297,15 +122,167 @@ }, "shape": { "location": { - "x": 6, - "y": 0 + "x": 2, + "y": 2 + }, + "size": { + "width": 2, + "height": 2 + } + } + }, + { + "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": 12 }, "size": { "width": 4, "height": 2 } + }, + "integration": { + "type": null, + "properties": [] } }, + { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a330", + "name": "Contribute", + "url": "https://github.com/ajnart/homarr", + "behaviour": { + "onClickUrl": "https://github.com/ajnart/homarr", + "externalUrl": "https://github.com/ajnart/homarr", + "isOpeningNewTab": true + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [ + 200 + ] + }, + "appearance": { + "iconUrl": "https://cdn.jsdelivr.net/gh/walkxhub/dashboard-icons/png/github.png" + }, + "integration": { + "type": null, + "properties": [] + }, + "area": { + "type": "category", + "properties": { + "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" + } + }, + "shape": { + "location": { + "x": 4, + "y": 2 + }, + "size": { + "width": 2, + "height": 2 + } + } + }, + { + "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": 8, + "y": 9 + }, + "size": { + "width": 4, + "height": 3 + } + } + }, + { + "id": "5df743d9-5cb1-457c-85d2-64ff86855652", + "name": "Your app", + "url": "https://homarr.dev", + "appearance": { + "iconUrl": "/imgs/logo/logo.png" + }, + "network": { + "enabledStatusChecker": false, + "okStatus": [] + }, + "behaviour": { + "isOpeningNewTab": true, + "externalUrl": "https://homarr.dev" + }, + "area": { + "type": "wrapper", + "properties": { + "id": "default" + } + }, + "shape": { + "location": { + "x": 0, + "y": 7 + }, + "size": { + "width": 6, + "height": 4 + } + }, + "integration": { + "type": null, + "properties": [] + } + } + ], + "widgets": [ { "id": "date", "properties": { @@ -317,6 +294,29 @@ "id": "47af36c0-47c1-4e5b-bfc7-ad645ee6a33f" } }, + "shape": { + "location": { + "x": 0, + "y": 0 + }, + "size": { + "width": 6, + "height": 2 + } + } + }, + { + "id": "weather", + "properties": { + "displayInFahrenheit": false, + "location": "Paris" + }, + "area": { + "type": "wrapper", + "properties": { + "id": "default" + } + }, "shape": { "location": { "x": 0, @@ -341,8 +341,8 @@ }, "shape": { "location": { - "x": 15, - "y": 0 + "x": 0, + "y": 2 }, "size": { "width": 5, diff --git a/src/components/Dashboard/Tiles/TileWrapper.tsx b/src/components/Dashboard/Tiles/TileWrapper.tsx index dfa3a62dc..f6469a2a4 100644 --- a/src/components/Dashboard/Tiles/TileWrapper.tsx +++ b/src/components/Dashboard/Tiles/TileWrapper.tsx @@ -35,9 +35,13 @@ export const GridstackTileWrapper = ({ data-type={type} data-id={id} gs-x={x} + data-gridstack-x={x} gs-y={y} + data-gridstack-y={y} gs-w={width} + data-gridstack-w={width} gs-h={height} + data-gridstack-h={height} gs-min-w={minWidth} gs-min-h={minHeight} gs-max-w={maxWidth} diff --git a/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts b/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts index b4255acc9..8d1bcd0a3 100644 --- a/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts +++ b/src/components/Dashboard/Wrappers/gridstack/init-gridstack.ts @@ -12,6 +12,7 @@ export const initializeGridstack = ( items: AppType[], widgets: IWidget[], isEditMode: boolean, + isLargerThanSm: boolean, events: { onChange: (changedNode: GridStackNode) => void; onAdd: (addedNode: GridStackNode) => void; @@ -19,7 +20,7 @@ export const initializeGridstack = ( ) => { if (!wrapperRef.current) return; // calculates the currently available count of columns - const columnCount = areaType === 'sidebar' ? 4 : 12; + const columnCount = areaType === 'sidebar' ? 4 : isLargerThanSm || typeof isLargerThanSm === 'undefined' ? 12 : 6; 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 1a3f514ca..12bafdfa1 100644 --- a/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts +++ b/src/components/Dashboard/Wrappers/gridstack/use-gridstack.ts @@ -11,11 +11,13 @@ import { import { useConfigContext } from '../../../../config/provider'; import { useConfigStore } from '../../../../config/store'; import { useResize } from '../../../../hooks/use-resize'; +import { useScreenLargerThan } from '../../../../hooks/useScreenLargerThan'; 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 { ShapeType } from '../../../../types/shape'; interface UseGristackReturnType { apps: AppType[]; @@ -31,6 +33,7 @@ export const useGridstack = ( areaType: 'wrapper' | 'category' | 'sidebar', areaId: string ): UseGristackReturnType => { + const isLargerThanSm = useScreenLargerThan('sm'); const isEditMode = useEditModeStore((x) => x.enabled); const { config, configVersion, name: configName } = useConfigContext(); const updateConfig = useConfigStore((x) => x.updateConfig); @@ -78,8 +81,48 @@ export const useGridstack = ( // change column count depending on the width and the gridRef useEffect(() => { if (areaType === 'sidebar') return; - gridRef.current?.column(12); - }, [gridRef, width]); + gridRef.current?.column(isLargerThanSm || typeof isLargerThanSm === 'undefined' ? 12 : 6, (column, prevColumn, newNodes, nodes) => { + let nextRow = 0; + let available = 6; + + if (column === prevColumn) { + newNodes.concat(nodes); + return; + } + + nodes.reverse().forEach(node => { + const width = parseInt(node.el!.getAttribute('data-gridstack-w')!, 10); + const height = parseInt(node.el!.getAttribute('data-gridstack-h')!, 10); + const x = parseInt(node.el!.getAttribute('data-gridstack-x')!, 10); + const y = parseInt(node.el!.getAttribute('data-gridstack-y')!, 10); + + if (column === 6) { + node.x = available >= width ? 6 - available : 0; + node.y = nextRow; + + if (width > 6) { + node.w = 6; + nextRow += 2; + available = 6; + } else if (available >= width) { + available -= width; + if (available === 0) { + nextRow += 2; + available = 6; + } + } else if (available < width) { + node.y = node.y! + 2; + available = 6 - width; + nextRow += 2; + } + } else { + node.x = y % 2 === 1 ? x + 6 : x; + node.y = Math.floor(y / 2); + } + newNodes.push(node); + }); + }); + }, [isLargerThanSm]); const onChange = isEditMode ? (changedNode: GridStackNode) => { @@ -236,6 +279,7 @@ export const useGridstack = ( items, widgets ?? [], isEditMode, + isLargerThanSm, { onChange, onAdd, diff --git a/src/styles/global.scss b/src/styles/global.scss index 0a5a5db71..4db17a0a3 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -18,19 +18,19 @@ .grid-stack>.grid-stack-item[gs-max-w="#{$i}"] { max-width: ($i / 12) * 100 + "%" } } -@for $i from 1 to 13 { - .grid-stack>.grid-stack-item[gs-h="#{$i}"] { height: ($i / 12) * 100 + "%" } - .grid-stack>.grid-stack-item[gs-min-h="#{$i}"] { min-height: ($i / 12) * 100 + "%" } - .grid-stack>.grid-stack-item[gs-max-h="#{$i}"] { max-height: ($i / 12) * 100 + "%" } +@for $i from 1 to 96 { + .grid-stack>.grid-stack-item[gs-h="#{$i}"] { height: $i * 64 + "px" } + .grid-stack>.grid-stack-item[gs-min-h="#{$i}"] { min-height: $i * 64 + "px" } + .grid-stack>.grid-stack-item[gs-max-h="#{$i}"] { max-height: $i * 64 + "px" } } -@for $i from 1 to 96 { +@for $i from 1 to 13 { .grid-stack>.grid-stack-item[gs-x="#{$i}"] { left: ($i / 12) * 100 + "%" } } @for $i from 1 to 96 { - .grid-stack>.grid-stack-item[gs-y="#{$i}"] { top: ($i / 12) * 100 + "%" } + .grid-stack>.grid-stack-item[gs-y="#{$i}"] { top: $i * 64 + "px" } } .grid-stack>.grid-stack-item>.grid-stack-item-content, @@ -54,3 +54,19 @@ .grid-stack.grid-stack-animate { transition: none; } + +@media screen and (max-width: 768px) { + @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 } + .grid-stack>.grid-stack-item[gs-max-w="#{$i}"] { max-width: percentage(($i / 6)) !important } + } + + @for $i from 1 to 7 { + .grid-stack>.grid-stack-item[gs-x="#{$i}"] { left: percentage(($i / 6)) } + } + + .grid-stack>.grid-stack-item { + min-width: percentage(1/6) !important; + } +} \ No newline at end of file