fix: unable to select integration on board page (#450)
This commit is contained in:
@@ -13,6 +13,7 @@ import type { IntegrationKind, WidgetKind } from "@homarr/definitions";
|
||||
import { useModalAction } from "@homarr/modals";
|
||||
import { showSuccessNotification } from "@homarr/notifications";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import type { BoardItemIntegration } from "@homarr/validation";
|
||||
import {
|
||||
loadWidgetDynamic,
|
||||
reduceWidgetOptionsWithDefaultValues,
|
||||
@@ -53,7 +54,7 @@ export const WidgetPreviewPageContent = ({
|
||||
});
|
||||
const [state, setState] = useState<{
|
||||
options: Record<string, unknown>;
|
||||
integrations: string[];
|
||||
integrations: BoardItemIntegration[];
|
||||
}>({
|
||||
options: reduceWidgetOptionsWithDefaultValues(kind, {}),
|
||||
integrations: [],
|
||||
@@ -104,8 +105,10 @@ export const WidgetPreviewPageContent = ({
|
||||
<Comp
|
||||
options={state.options as never}
|
||||
integrations={state.integrations.map(
|
||||
(id) =>
|
||||
integrationData.find((integration) => integration.id === id)!,
|
||||
(stateIntegration) =>
|
||||
integrationData.find(
|
||||
(integration) => integration.id === stateIntegration.id,
|
||||
)!,
|
||||
)}
|
||||
width={dimensions.width}
|
||||
height={dimensions.height}
|
||||
|
||||
@@ -2,6 +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 { EmptySection, Item } from "~/app/[locale]/boards/_types";
|
||||
import { useUpdateBoard } from "~/app/[locale]/boards/(content)/_client";
|
||||
@@ -30,6 +31,11 @@ interface UpdateItemOptions {
|
||||
newOptions: Record<string, unknown>;
|
||||
}
|
||||
|
||||
interface UpdateItemIntegrations {
|
||||
itemId: string;
|
||||
newIntegrations: BoardItemIntegration[];
|
||||
}
|
||||
|
||||
interface CreateItem {
|
||||
kind: WidgetKind;
|
||||
}
|
||||
@@ -105,6 +111,36 @@ export const useItemActions = () => {
|
||||
[updateBoard],
|
||||
);
|
||||
|
||||
const updateItemIntegrations = useCallback(
|
||||
({ itemId, newIntegrations }: UpdateItemIntegrations) => {
|
||||
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 moving
|
||||
if (item.id !== itemId) return item;
|
||||
return {
|
||||
...item,
|
||||
...("integrations" in item
|
||||
? { integrations: newIntegrations }
|
||||
: {}),
|
||||
};
|
||||
}),
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
},
|
||||
[updateBoard],
|
||||
);
|
||||
|
||||
const moveAndResizeItem = useCallback(
|
||||
({ itemId, ...positionProps }: MoveAndResizeItem) => {
|
||||
updateBoard((previous) => ({
|
||||
@@ -200,6 +236,7 @@ export const useItemActions = () => {
|
||||
moveItemToSection,
|
||||
removeItem,
|
||||
updateItemOptions,
|
||||
updateItemIntegrations,
|
||||
createItem,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable react/no-unknown-property */
|
||||
// Ignored because of gridstack attributes
|
||||
|
||||
import { useMemo } from "react";
|
||||
import type { RefObject } from "react";
|
||||
import { ActionIcon, Card, Menu } from "@mantine/core";
|
||||
import { useElementSize } from "@mantine/hooks";
|
||||
@@ -13,6 +14,7 @@ import {
|
||||
import combineClasses from "clsx";
|
||||
import { useAtomValue } from "jotai";
|
||||
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { useConfirmModal, useModalAction } from "@homarr/modals";
|
||||
import { useScopedI18n } from "@homarr/translation/client";
|
||||
import {
|
||||
@@ -20,6 +22,7 @@ import {
|
||||
reduceWidgetOptionsWithDefaultValues,
|
||||
useServerDataFor,
|
||||
WidgetEditModal,
|
||||
widgetImports,
|
||||
} from "@homarr/widgets";
|
||||
|
||||
import type { Item } from "~/app/[locale]/boards/_types";
|
||||
@@ -116,25 +119,42 @@ const ItemMenu = ({ offset, item }: { offset: number; item: Item }) => {
|
||||
const { openModal } = useModalAction(WidgetEditModal);
|
||||
const { openConfirmModal } = useConfirmModal();
|
||||
const isEditMode = useAtomValue(editModeAtom);
|
||||
const { updateItemOptions, removeItem } = useItemActions();
|
||||
const { updateItemOptions, updateItemIntegrations, removeItem } =
|
||||
useItemActions();
|
||||
const { data: integrationData, isPending } =
|
||||
clientApi.integration.all.useQuery();
|
||||
const currentDefinition = useMemo(
|
||||
() => widgetImports[item.kind].definition,
|
||||
[item.kind],
|
||||
);
|
||||
|
||||
if (!isEditMode) return null;
|
||||
if (!isEditMode || isPending) return null;
|
||||
|
||||
const openEditModal = () => {
|
||||
openModal({
|
||||
kind: item.kind,
|
||||
value: {
|
||||
options: item.options,
|
||||
integrations: item.integrations.map(({ id }) => id),
|
||||
integrations: item.integrations,
|
||||
},
|
||||
onSuccessfulEdit: ({ options, integrations: _ }) => {
|
||||
onSuccessfulEdit: ({ options, integrations }) => {
|
||||
updateItemOptions({
|
||||
itemId: item.id,
|
||||
newOptions: options,
|
||||
});
|
||||
updateItemIntegrations({
|
||||
itemId: item.id,
|
||||
newIntegrations: integrations,
|
||||
});
|
||||
},
|
||||
integrationData: [],
|
||||
integrationSupport: false,
|
||||
integrationData: (integrationData ?? []).filter(
|
||||
(integration) =>
|
||||
"supportedIntegrations" in currentDefinition &&
|
||||
(currentDefinition.supportedIntegrations as string[]).some(
|
||||
(kind) => kind === integration.kind,
|
||||
),
|
||||
),
|
||||
integrationSupport: "supportedIntegrations" in currentDefinition,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -18,4 +18,8 @@ export const validation = {
|
||||
icons: iconsSchemas,
|
||||
};
|
||||
|
||||
export { createSectionSchema, sharedItemSchema } from "./shared";
|
||||
export {
|
||||
createSectionSchema,
|
||||
sharedItemSchema,
|
||||
type BoardItemIntegration,
|
||||
} from "./shared";
|
||||
|
||||
@@ -11,6 +11,8 @@ export const integrationSchema = z.object({
|
||||
url: z.string(),
|
||||
});
|
||||
|
||||
export type BoardItemIntegration = z.infer<typeof integrationSchema>;
|
||||
|
||||
export const sharedItemSchema = z.object({
|
||||
id: z.string(),
|
||||
xOffset: z.number(),
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Button, Group, Stack } from "@mantine/core";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import { createModal } from "@homarr/modals";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import type { BoardItemIntegration } from "@homarr/validation";
|
||||
|
||||
import { widgetImports } from "..";
|
||||
import { getInputForType } from "../_inputs";
|
||||
@@ -15,7 +16,7 @@ import { WidgetIntegrationSelect } from "../widget-integration-select";
|
||||
|
||||
export interface WidgetEditModalState {
|
||||
options: Record<string, unknown>;
|
||||
integrations: string[];
|
||||
integrations: BoardItemIntegration[];
|
||||
}
|
||||
|
||||
interface ModalProps<TSort extends WidgetKind> {
|
||||
|
||||
Reference in New Issue
Block a user