From a2a65c9a54b9f9098d6a56c83007fc23cef189ee Mon Sep 17 00:00:00 2001 From: Thomas Date: Sat, 30 May 2026 01:09:54 +0200 Subject: [PATCH] Route integration creation to the new selector page (#5825) --- .../new/_integration-new-dropdown.tsx | 59 ------------------- .../new/_integration-new-select-grid.tsx | 21 +++++++ .../[locale]/manage/integrations/new/page.tsx | 25 +++----- .../app/[locale]/manage/integrations/page.tsx | 54 ++++------------- 4 files changed, 41 insertions(+), 118 deletions(-) delete mode 100644 apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-dropdown.tsx create mode 100644 apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-select-grid.tsx diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-dropdown.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-dropdown.tsx deleted file mode 100644 index 25333e127..000000000 --- a/apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-dropdown.tsx +++ /dev/null @@ -1,59 +0,0 @@ -"use client"; - -import type { ChangeEvent } from "react"; -import React, { useMemo, useState } from "react"; -import { Flex, Group, Menu, ScrollArea, Text, TextInput } from "@mantine/core"; -import { IconSearch } from "@tabler/icons-react"; - -import { getIntegrationName, integrationKinds } from "@homarr/definitions"; -import { useI18n } from "@homarr/translation/client"; -import { IntegrationAvatar, Link } from "@homarr/ui"; - -interface IntegrationCreateDropdownContentProps { - enableMockIntegration: boolean; -} - -export const IntegrationCreateDropdownContent = ({ enableMockIntegration }: IntegrationCreateDropdownContentProps) => { - const t = useI18n(); - const [search, setSearch] = useState(""); - - const filteredKinds = useMemo(() => { - return integrationKinds - .filter((kind) => enableMockIntegration || kind !== "mock") - .filter((kind) => getIntegrationName(kind).toLowerCase().includes(search.toLowerCase().trim())) - .sort((kindA, kindB) => getIntegrationName(kindA).localeCompare(getIntegrationName(kindB))); - }, [search, enableMockIntegration]); - - const handleSearch = React.useCallback( - (event: ChangeEvent) => setSearch(event.target.value), - [setSearch], - ); - - return ( - - } - placeholder={t("integration.page.list.search")} - value={search} - data-autofocus - onChange={handleSearch} - variant="filled" - /> - - {filteredKinds.length > 0 ? ( - - {filteredKinds.map((kind) => ( - - - - {getIntegrationName(kind)} - - - ))} - - ) : ( - {t("common.noResults")} - )} - - ); -}; diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-select-grid.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-select-grid.tsx new file mode 100644 index 000000000..cae5ee38b --- /dev/null +++ b/apps/nextjs/src/app/[locale]/manage/integrations/new/_integration-new-select-grid.tsx @@ -0,0 +1,21 @@ +"use client"; + +import { useRouter } from "next/navigation"; + +import type { IntegrationKind } from "@homarr/definitions"; + +import { IntegrationSelectGrid } from "~/components/integration/integration-select-grid"; + +interface IntegrationNewSelectGridProps { + enableMockIntegration: boolean; +} + +export const IntegrationNewSelectGrid = ({ enableMockIntegration }: IntegrationNewSelectGridProps) => { + const router = useRouter(); + + const handleSelect = (kind: IntegrationKind) => { + router.push(`/manage/integrations/new?kind=${kind}`); + }; + + return ; +}; diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx index 3aeb2057c..3194134c3 100644 --- a/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx +++ b/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx @@ -1,15 +1,16 @@ import { notFound } from "next/navigation"; -import { Button, Center, Container, Group, Stack, Text, Title } from "@mantine/core"; -import { IconArrowLeft } from "@tabler/icons-react"; +import { Container, Group, Stack, Title } from "@mantine/core"; import { z } from "zod/v4"; import { auth } from "@homarr/auth/next"; import { getIntegrationName, integrationKinds } from "@homarr/definitions"; import { getScopedI18n } from "@homarr/translation/server"; -import { IntegrationAvatar, Link } from "@homarr/ui"; +import { IntegrationAvatar } from "@homarr/ui"; import { DynamicBreadcrumb } from "~/components/navigation/dynamic-breadcrumb"; +import { env } from "~/env"; import { IntegrationNewFormWrapper } from "./_integration-new-form-wrapper"; +import { IntegrationNewSelectGrid } from "./_integration-new-select-grid"; interface NewIntegrationPageProps { searchParams: Promise<{ @@ -34,20 +35,10 @@ export default async function IntegrationsNewPage(props: NewIntegrationPageProps <> -
- - {t("action.create")} - {t("page.list.search")} - - -
+ + {t("action.create")} + +
); diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx index 994d63b3c..038e8ef62 100644 --- a/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx +++ b/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx @@ -1,5 +1,4 @@ import { Fragment } from "react"; -import type { PropsWithChildren } from "react"; import { redirect } from "next/navigation"; import { AccordionControl, @@ -8,12 +7,8 @@ import { ActionIcon, ActionIconGroup, Anchor, - Button, Divider, Group, - Menu, - MenuDropdown, - MenuTarget, Stack, Table, TableTbody, @@ -23,7 +18,7 @@ import { TableTr, Text, } from "@mantine/core"; -import { IconChevronDown, IconPencil, IconPlugX } from "@tabler/icons-react"; +import { IconPencil, IconPlugX } from "@tabler/icons-react"; import type { RouterOutputs } from "@homarr/api"; import { api } from "@homarr/api/server"; @@ -34,13 +29,11 @@ import { getIntegrationName } from "@homarr/definitions"; import { getScopedI18n } from "@homarr/translation/server"; import { CountBadge, IntegrationAvatar, Link } from "@homarr/ui"; -import { ManageMobilePrimaryAction } from "~/components/manage/manage-mobile-primary-action"; import { ManagePageLayout } from "~/components/manage/manage-page-layout"; +import { MobileAffixButton } from "~/components/manage/mobile-affix-button"; import { NoResults } from "~/components/no-results"; -import { env } from "~/env"; import { ActiveTabAccordion } from "../../../../components/active-tab-accordion"; import { DeleteIntegrationActionButton } from "./_integration-buttons"; -import { IntegrationCreateDropdownContent } from "./new/_integration-new-dropdown"; import classes from "./page.module.css"; interface IntegrationsPageProps { @@ -67,13 +60,9 @@ export default async function IntegrationsPage(props: IntegrationsPageProps) { title={t("page.list.title")} primaryAction={ canCreateIntegrations ? ( - - - - - - - + + {t("action.create")} + ) : undefined } floatingPrimaryAction={canCreateIntegrations} @@ -83,25 +72,6 @@ export default async function IntegrationsPage(props: IntegrationsPageProps) { ); } -const IntegrationSelectMenu = ({ children }: PropsWithChildren) => { - return ( - - {children} - - - - - ); -}; - interface IntegrationListProps { integrations: RouterOutputs["integration"]["all"]; activeTab?: IntegrationKind; @@ -134,12 +104,12 @@ const IntegrationList = async ({ integrations, activeTab }: IntegrationListProps return ( - {entries.map(([kind, integrations], index) => ( + {entries.map(([kind, kindIntegrations], index) => ( }> {getIntegrationName(kind)} - + @@ -152,7 +122,7 @@ const IntegrationList = async ({ integrations, activeTab }: IntegrationListProps - {integrations.map((integration) => ( + {kindIntegrations.map((integration) => ( {integration.name} @@ -173,7 +143,7 @@ const IntegrationList = async ({ integrations, activeTab }: IntegrationListProps > - + )} @@ -184,9 +154,9 @@ const IntegrationList = async ({ integrations, activeTab }: IntegrationListProps - {integrations.map((integration, index) => ( + {kindIntegrations.map((integration, integrationIndex) => ( - {index !== 0 && } + {integrationIndex !== 0 && } {integration.name} @@ -201,7 +171,7 @@ const IntegrationList = async ({ integrations, activeTab }: IntegrationListProps > - + )}