feat: add custom css for board and custom classes in advanced options for items (#512)
* feat: add custom css for board and custom classes in advanced options for items * chore: add mysql migration * fix: test not working * fix: format issues * fix: typecheck issue * fix: build issue * chore: add missing translations * fix: merge issues related to migrations * fix: format issues * fix: merge issue with migration * fix: format issue
This commit is contained in:
@@ -2,7 +2,7 @@ import { useCallback } from "react";
|
||||
|
||||
import { createId } from "@homarr/db/client";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import type { BoardItemIntegration } from "@homarr/validation";
|
||||
import type { BoardItemAdvancedOptions, BoardItemIntegration } from "@homarr/validation";
|
||||
|
||||
import type { EmptySection, Item } from "~/app/[locale]/boards/_types";
|
||||
import { useUpdateBoard } from "~/app/[locale]/boards/(content)/_client";
|
||||
@@ -31,6 +31,11 @@ interface UpdateItemOptions {
|
||||
newOptions: Record<string, unknown>;
|
||||
}
|
||||
|
||||
interface UpdateItemAdvancedOptions {
|
||||
itemId: string;
|
||||
newAdvancedOptions: BoardItemAdvancedOptions;
|
||||
}
|
||||
|
||||
interface UpdateItemIntegrations {
|
||||
itemId: string;
|
||||
newIntegrations: BoardItemIntegration[];
|
||||
@@ -59,6 +64,9 @@ export const useItemActions = () => {
|
||||
width: 1,
|
||||
height: 1,
|
||||
integrations: [],
|
||||
advancedOptions: {
|
||||
customCssClasses: [],
|
||||
},
|
||||
} satisfies Omit<Item, "kind" | "yOffset" | "xOffset"> & {
|
||||
kind: WidgetKind;
|
||||
};
|
||||
@@ -91,7 +99,7 @@ export const useItemActions = () => {
|
||||
return {
|
||||
...section,
|
||||
items: section.items.map((item) => {
|
||||
// Return same item if item is not the one we're moving
|
||||
// Return same item if item is not the one we're changing
|
||||
if (item.id !== itemId) return item;
|
||||
return {
|
||||
...item,
|
||||
@@ -106,6 +114,33 @@ export const useItemActions = () => {
|
||||
[updateBoard],
|
||||
);
|
||||
|
||||
const updateItemAdvancedOptions = useCallback(
|
||||
({ itemId, newAdvancedOptions }: UpdateItemAdvancedOptions) => {
|
||||
updateBoard((previous) => {
|
||||
if (!previous) return previous;
|
||||
return {
|
||||
...previous,
|
||||
sections: previous.sections.map((section) => {
|
||||
// Return same section if item is not in it
|
||||
if (!section.items.some((item) => item.id === itemId)) return section;
|
||||
return {
|
||||
...section,
|
||||
items: section.items.map((item) => {
|
||||
// Return same item if item is not the one we're changing
|
||||
if (item.id !== itemId) return item;
|
||||
return {
|
||||
...item,
|
||||
advancedOptions: newAdvancedOptions,
|
||||
};
|
||||
}),
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
},
|
||||
[updateBoard],
|
||||
);
|
||||
|
||||
const updateItemIntegrations = useCallback(
|
||||
({ itemId, newIntegrations }: UpdateItemIntegrations) => {
|
||||
updateBoard((previous) => {
|
||||
@@ -224,6 +259,7 @@ export const useItemActions = () => {
|
||||
moveItemToSection,
|
||||
removeItem,
|
||||
updateItemOptions,
|
||||
updateItemAdvancedOptions,
|
||||
updateItemIntegrations,
|
||||
createItem,
|
||||
};
|
||||
|
||||
@@ -70,7 +70,11 @@ const BoardItem = ({ refs, item, opacity }: ItemProps) => {
|
||||
>
|
||||
<Card
|
||||
ref={ref}
|
||||
className={combineClasses(classes.itemCard, "grid-stack-item-content")}
|
||||
className={combineClasses(
|
||||
classes.itemCard,
|
||||
"grid-stack-item-content",
|
||||
item.advancedOptions.customCssClasses.join(" "),
|
||||
)}
|
||||
withBorder
|
||||
styles={{
|
||||
root: {
|
||||
@@ -123,7 +127,7 @@ const ItemMenu = ({ offset, item }: { offset: number; item: Item }) => {
|
||||
const { openModal } = useModalAction(WidgetEditModal);
|
||||
const { openConfirmModal } = useConfirmModal();
|
||||
const isEditMode = useAtomValue(editModeAtom);
|
||||
const { updateItemOptions, updateItemIntegrations, removeItem } = useItemActions();
|
||||
const { updateItemOptions, updateItemAdvancedOptions, updateItemIntegrations, removeItem } = useItemActions();
|
||||
const { data: integrationData, isPending } = clientApi.integration.all.useQuery();
|
||||
const currentDefinition = useMemo(() => widgetImports[item.kind].definition, [item.kind]);
|
||||
|
||||
@@ -133,14 +137,19 @@ const ItemMenu = ({ offset, item }: { offset: number; item: Item }) => {
|
||||
openModal({
|
||||
kind: item.kind,
|
||||
value: {
|
||||
advancedOptions: item.advancedOptions,
|
||||
options: item.options,
|
||||
integrations: item.integrations,
|
||||
},
|
||||
onSuccessfulEdit: ({ options, integrations }) => {
|
||||
onSuccessfulEdit: ({ options, integrations, advancedOptions }) => {
|
||||
updateItemOptions({
|
||||
itemId: item.id,
|
||||
newOptions: options,
|
||||
});
|
||||
updateItemAdvancedOptions({
|
||||
itemId: item.id,
|
||||
newAdvancedOptions: advancedOptions,
|
||||
});
|
||||
updateItemIntegrations({
|
||||
itemId: item.id,
|
||||
newIntegrations: integrations,
|
||||
|
||||
Reference in New Issue
Block a user