diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx
index 0f3454653..e9551af52 100644
--- a/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx
+++ b/apps/nextjs/src/app/[locale]/boards/(content)/_client.tsx
@@ -5,7 +5,7 @@ import { Box, LoadingOverlay, Stack } from "@mantine/core";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
-import { useRequiredBoard } from "@homarr/boards/context";
+import { useCurrentLayout, useRequiredBoard } from "@homarr/boards/context";
import { BoardCategorySection } from "~/components/board/sections/category-section";
import { BoardEmptySection } from "~/components/board/sections/empty-section";
@@ -43,6 +43,7 @@ export const useUpdateBoard = () => {
export const ClientBoard = () => {
const board = useRequiredBoard();
+ const currentLayoutId = useCurrentLayout();
const isReady = useIsBoardReady();
const fullWidthSortedSections = board.sections
@@ -63,9 +64,10 @@ export const ClientBoard = () => {
{fullWidthSortedSections.map((section) =>
section.kind === "empty" ? (
-
+ // Unique keys per layout to always reinitialize the gridstack
+
) : (
-
+
),
)}
diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_creator.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_creator.tsx
index f501e95f9..49be8c37c 100644
--- a/apps/nextjs/src/app/[locale]/boards/(content)/_creator.tsx
+++ b/apps/nextjs/src/app/[locale]/boards/(content)/_creator.tsx
@@ -13,7 +13,7 @@ import { getI18n } from "@homarr/translation/server";
import { createMetaTitle } from "~/metadata";
import { createBoardLayout } from "../_layout-creator";
import type { Board } from "../_types";
-import { ClientBoard } from "./_client";
+import { DynamicClientBoard } from "./_dynamic-client";
import { BoardContentHeaderActions } from "./_header-actions";
export type Params = Record;
@@ -37,7 +37,7 @@ export const createBoardContentPage = >(
return (
-
+
);
},
diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_dynamic-client.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_dynamic-client.tsx
new file mode 100644
index 000000000..50b0aff66
--- /dev/null
+++ b/apps/nextjs/src/app/[locale]/boards/(content)/_dynamic-client.tsx
@@ -0,0 +1,7 @@
+"use client";
+
+import dynamic from "next/dynamic";
+
+export const DynamicClientBoard = dynamic(() => import("./_client").then((mod) => mod.ClientBoard), {
+ ssr: false,
+});
diff --git a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx
index f0c2eeb9f..99c0a7f41 100644
--- a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx
+++ b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_layout.tsx
@@ -1,43 +1,109 @@
"use client";
-import { Button, Grid, Group, Input, Slider, Stack } from "@mantine/core";
+import { Button, Fieldset, Grid, Group, Input, NumberInput, Slider, Stack, Text, TextInput } from "@mantine/core";
+import { clientApi } from "@homarr/api/client";
+import { createId } from "@homarr/db/client";
import { useZodForm } from "@homarr/form";
import { useI18n } from "@homarr/translation/client";
import { validation } from "@homarr/validation";
import type { Board } from "../../_types";
-import { useSavePartialSettingsMutation } from "./_shared";
interface Props {
board: Board;
}
export const LayoutSettingsContent = ({ board }: Props) => {
const t = useI18n();
- const { mutate: savePartialSettings, isPending } = useSavePartialSettingsMutation(board);
- const form = useZodForm(validation.board.savePartialSettings.pick({ columnCount: true }).required(), {
+ const utils = clientApi.useUtils();
+ const { mutate: saveLayouts, isPending } = clientApi.board.saveLayouts.useMutation({
+ onSettled() {
+ void utils.board.getBoardByName.invalidate({ name: board.name });
+ void utils.board.getHomeBoard.invalidate();
+ },
+ });
+ const form = useZodForm(validation.board.saveLayouts.omit({ id: true }).required(), {
initialValues: {
- columnCount: board.columnCount,
+ layouts: board.layouts,
},
});
return (