Files
homarr/apps/nextjs/src/components/board/sections/dynamic/dynamic-actions.ts
Meier Lukas 9ce172e78a feat: add dynamic section (#842)
* chore: add parent_section_id and change position to x and y_offset for sqlite section table

* chore: rename existing positions to x_offset and y_offset

* chore: add related mysql migration

* chore: add missing height and width to section table

* fix: missing width and height in migration copy script

* fix: typecheck issues

* fix: test not working caused by unsimilar schemas

* wip: add dynamic section

* refactor: improve structure of gridstack sections

* feat: add rendering of dynamic sections

* feat: add saving of moved sections

* wip: add static row count, restrict min-width and height

* chore: address pull request feedback

* fix: format issues

* fix: size calculation within dynamic sections

* fix: on resize not called when min width or height is reached

* fix: size of items while dragging is to big

* chore: temporarly remove migration files

* chore: readd migrations

* fix: format and deepsource issues

* chore: remove db_dev.sqlite file

* chore: add *.sqlite to .gitignore

* chore: address pull request feedback

* feat: add dynamic section actions for adding and removing them
2024-08-10 12:37:16 +02:00

90 lines
2.9 KiB
TypeScript

import { useCallback } from "react";
import { createId } from "@homarr/db/client";
import type { DynamicSection, EmptySection } from "~/app/[locale]/boards/_types";
import { useUpdateBoard } from "~/app/[locale]/boards/(content)/_client";
interface RemoveDynamicSection {
id: string;
}
export const useDynamicSectionActions = () => {
const { updateBoard } = useUpdateBoard();
const addDynamicSection = useCallback(() => {
updateBoard((previous) => {
const lastSection = previous.sections
.filter((section): section is EmptySection => section.kind === "empty")
.sort((sectionA, sectionB) => sectionB.yOffset - sectionA.yOffset)[0];
if (!lastSection) return previous;
const newSection = {
id: createId(),
kind: "dynamic",
height: 1,
width: 1,
items: [],
parentSectionId: lastSection.id,
// We omit xOffset and yOffset because gridstack will use the first available position
} satisfies Omit<DynamicSection, "xOffset" | "yOffset">;
return {
...previous,
sections: previous.sections.concat(newSection as unknown as DynamicSection),
};
});
}, [updateBoard]);
const removeDynamicSection = useCallback(
({ id }: RemoveDynamicSection) => {
updateBoard((previous) => {
const sectionToRemove = previous.sections.find(
(section): section is DynamicSection => section.id === id && section.kind === "dynamic",
);
if (!sectionToRemove) return previous;
return {
...previous,
sections: previous.sections
.filter((section) => section.id !== id)
.map((section) => {
if (section.id === sectionToRemove.parentSectionId) {
return {
...section,
// Add items from the removed section to the parent section
items: section.items.concat(
sectionToRemove.items.map((item) => ({
...item,
xOffset: sectionToRemove.xOffset + item.xOffset,
yOffset: sectionToRemove.yOffset + item.yOffset,
})),
),
};
}
if (section.kind === "dynamic" && section.parentSectionId === sectionToRemove.id) {
// Change xOffset and yOffset of sections that were below the removed section and set parentSectionId to the parent of the removed section
return {
...section,
parentSectionId: sectionToRemove.parentSectionId,
yOffset: section.yOffset + sectionToRemove.yOffset,
xOffset: section.xOffset + sectionToRemove.xOffset,
};
}
return section;
}),
};
});
},
[updateBoard],
);
return {
addDynamicSection,
removeDynamicSection,
};
};