fix: unable to select integration on board page (#450)

This commit is contained in:
Meier Lukas
2024-05-06 21:12:55 +02:00
committed by GitHub
parent dc0184af07
commit c88464498f
6 changed files with 78 additions and 11 deletions

View File

@@ -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}

View File

@@ -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,
};
};

View File

@@ -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,
});
};

View File

@@ -18,4 +18,8 @@ export const validation = {
icons: iconsSchemas,
};
export { createSectionSchema, sharedItemSchema } from "./shared";
export {
createSectionSchema,
sharedItemSchema,
type BoardItemIntegration,
} from "./shared";

View File

@@ -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(),

View File

@@ -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> {