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.
This commit is contained in:
1 parent
af1991a4a3
commit
f10bb3ae23
2 files changed
+51
-8
No files matched your search
@@ -8,12 +8,14 @@ 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 =
|
||||
({ kind, options = {} }: CreateItemInput) =>
|
||||
({ id, kind, options = {}, integrationIds = [] }: CreateItemInput) =>
|
||||
(previous: Board): Board => {
|
||||
const firstSection = previous.sections
|
||||
.filter((section): section is EmptySection => section.kind === "empty")
|
||||
@@ -23,11 +25,11 @@ export const createItemCallback =
|
||||
if (!firstSection) return previous;
|
||||
|
||||
const widget = {
|
||||
id: createId(),
|
||||
id: id ?? createId(),
|
||||
kind,
|
||||
options,
|
||||
layouts: createItemLayouts(previous, firstSection),
|
||||
integrationIds: [],
|
||||
integrationIds,
|
||||
advancedOptions: {
|
||||
title: null,
|
||||
customCssClasses: [],
|
||||
|
||||
@@ -2,20 +2,26 @@ import { useMemo, useState } from "react";
|
||||
import { Avatar, Button, Card, Center, Grid, Group, Input, Stack, Text, Tooltip } from "@mantine/core";
|
||||
import { IconSearch } from "@tabler/icons-react";
|
||||
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import { clientApi } from "@homarr/api/client";
|
||||
import { createId, objectEntries } from "@homarr/common";
|
||||
import { getIconUrl, getIntegrationName } from "@homarr/definitions";
|
||||
import type { IntegrationKind, WidgetKind } from "@homarr/definitions";
|
||||
import { createModal } from "@homarr/modals";
|
||||
import { createModal, useModalAction } from "@homarr/modals";
|
||||
import { useSettings } from "@homarr/settings";
|
||||
import { useI18n } from "@homarr/translation/client";
|
||||
import type { TablerIcon } from "@homarr/ui";
|
||||
import { widgetImports } from "@homarr/widgets";
|
||||
import { reduceWidgetOptionsWithDefaultValues, widgetImports } from "@homarr/widgets";
|
||||
import { WidgetEditModal } from "@homarr/widgets/modals";
|
||||
|
||||
import { useItemActions } from "./item-actions";
|
||||
|
||||
export const ItemSelectModal = createModal<void>(({ actions }) => {
|
||||
const [search, setSearch] = useState("");
|
||||
const t = useI18n();
|
||||
const { createItem } = useItemActions();
|
||||
const { createItem, updateItemOptions, updateItemAdvancedOptions, updateItemIntegrations } = useItemActions();
|
||||
const { openModal: openEditModal } = useModalAction(WidgetEditModal);
|
||||
const { data: integrationData } = clientApi.integration.all.useQuery();
|
||||
const settings = useSettings();
|
||||
|
||||
const items = useMemo(
|
||||
() =>
|
||||
@@ -40,8 +46,43 @@ export const ItemSelectModal = createModal<void>(({ actions }) => {
|
||||
);
|
||||
|
||||
const handleAdd = (kind: WidgetKind) => {
|
||||
createItem({ kind });
|
||||
const definition = widgetImports[kind].definition;
|
||||
const hasIntegrationSupport = "supportedIntegrations" in definition;
|
||||
|
||||
const matchingIntegrations = hasIntegrationSupport
|
||||
? (integrationData ?? []).filter((integration) =>
|
||||
(definition.supportedIntegrations as string[]).includes(integration.kind),
|
||||
)
|
||||
: [];
|
||||
|
||||
const integrationIds = matchingIntegrations.map((i) => i.id);
|
||||
const itemId = createId();
|
||||
const defaultOptions = reduceWidgetOptionsWithDefaultValues(kind, settings);
|
||||
|
||||
createItem({ id: itemId, kind, integrationIds });
|
||||
actions.closeModal();
|
||||
|
||||
openEditModal(
|
||||
{
|
||||
kind,
|
||||
value: {
|
||||
advancedOptions: { title: null, customCssClasses: [], borderColor: "" },
|
||||
options: defaultOptions,
|
||||
integrationIds,
|
||||
},
|
||||
onSuccessfulEdit: ({ options, integrationIds: newIntegrationIds, advancedOptions }) => {
|
||||
updateItemOptions({ itemId, newOptions: options });
|
||||
updateItemAdvancedOptions({ itemId, newAdvancedOptions: advancedOptions });
|
||||
updateItemIntegrations({ itemId, newIntegrations: newIntegrationIds });
|
||||
},
|
||||
integrationData: matchingIntegrations,
|
||||
integrationSupport: hasIntegrationSupport,
|
||||
settings,
|
||||
},
|
||||
{
|
||||
title: (titleT) => `${titleT("item.edit.title")} - ${titleT(`widget.${kind}.name`)}`,
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user