Files
homarr/apps/nextjs/src/components/board/items/actions/create-item.ts
T
Thomas f10bb3ae23 feat: auto-open widget settings on add with all integrations pre-selected (#5767)
When adding a widget from the "Choose item to add" modal, the widget
edit modal now opens immediately after placement, allowing the user to
configure options and integrations before the widget renders.

All available integrations for the widget are selected by default.
2026-05-23 16:19:36 +02:00

75 lines
2.0 KiB
TypeScript

import { getBoardLayouts } from "@homarr/boards/context";
import { createId } from "@homarr/common";
import type { Modify } from "@homarr/common/types";
import type { WidgetKind } from "@homarr/definitions";
import type { Board, EmptySection, Item, ItemLayout } from "~/app/[locale]/boards/_types";
import { getFirstEmptyPosition } from "./empty-position";
import { getSectionElements } from "./section-elements";
export interface CreateItemInput {
id?: string;
kind: WidgetKind;
options?: Record<string, unknown>;
integrationIds?: string[];
}
export const createItemCallback =
({ id, kind, options = {}, integrationIds = [] }: CreateItemInput) =>
(previous: Board): Board => {
const firstSection = previous.sections
.filter((section): section is EmptySection => section.kind === "empty")
.sort((sectionA, sectionB) => sectionA.yOffset - sectionB.yOffset)
.at(0);
if (!firstSection) return previous;
const widget = {
id: id ?? createId(),
kind,
options,
layouts: createItemLayouts(previous, firstSection),
integrationIds,
advancedOptions: {
title: null,
customCssClasses: [],
borderColor: "",
},
} satisfies Modify<
Item,
{
kind: WidgetKind;
}
>;
return {
...previous,
items: previous.items.concat(widget),
};
};
const createItemLayouts = (board: Board, currentSection: EmptySection): ItemLayout[] => {
const layouts = getBoardLayouts(board);
return layouts.map((layoutId) => {
const boardLayout = board.layouts.find((layout) => layout.id === layoutId);
const elements = getSectionElements(board, { sectionId: currentSection.id, layoutId });
const emptyPosition = boardLayout
? getFirstEmptyPosition(elements, boardLayout.columnCount)
: { xOffset: 0, yOffset: 0 };
if (!emptyPosition) {
throw new Error("Your board is full");
}
return {
width: 1,
height: 1,
...emptyPosition,
sectionId: currentSection.id,
layoutId,
};
});
};