diff --git a/packages/api/src/router/widgets/index.ts b/packages/api/src/router/widgets/index.ts index 42d337271..b7a68d31d 100644 --- a/packages/api/src/router/widgets/index.ts +++ b/packages/api/src/router/widgets/index.ts @@ -34,6 +34,7 @@ export const widgetRouter = createTRPCRouter({ releases: lazy(() => import("./releases").then((mod) => mod.releasesRouter)), networkController: lazy(() => import("./network-controller").then((mod) => mod.networkControllerRouter)), unifiOs: lazy(() => import("./unifi-os").then((mod) => mod.unifiOsRouter)), + unifiSiteManager: lazy(() => import("./unifi-site-manager").then((mod) => mod.unifiSiteManagerRouter)), firewall: lazy(() => import("./firewall").then((mod) => mod.firewallRouter)), notifications: lazy(() => import("./notifications").then((mod) => mod.notificationsRouter)), timetable: lazy(() => import("./timetable").then((mod) => mod.timetableRouter)), diff --git a/packages/api/src/router/widgets/unifi-site-manager.ts b/packages/api/src/router/widgets/unifi-site-manager.ts new file mode 100644 index 000000000..cee3c7a91 --- /dev/null +++ b/packages/api/src/router/widgets/unifi-site-manager.ts @@ -0,0 +1,22 @@ +import { unifiSiteManagerRequestHandler } from "@homarr/request-handler/unifi-site-manager"; + +import { createManyIntegrationMiddleware } from "../../middlewares/integration"; +import { settleIntegrationQueries } from "../../settle-integrations"; +import { createTRPCRouter, publicProcedure } from "../../trpc"; + +export const unifiSiteManagerRouter = createTRPCRouter({ + overview: publicProcedure + .concat(createManyIntegrationMiddleware("query", "unifiSiteManager")) + .query(async ({ ctx }) => { + return await settleIntegrationQueries(ctx.integrations, async (integration) => { + const innerHandler = unifiSiteManagerRequestHandler.handler(integration, {}); + const { data, timestamp } = await innerHandler.getDataAsync(); + + return { + integration: { id: integration.id, name: integration.name, kind: integration.kind }, + overview: data, + updatedAt: timestamp, + }; + }); + }), +}); diff --git a/packages/request-handler/src/unifi-site-manager.ts b/packages/request-handler/src/unifi-site-manager.ts new file mode 100644 index 000000000..015ddfff3 --- /dev/null +++ b/packages/request-handler/src/unifi-site-manager.ts @@ -0,0 +1,20 @@ +import { createIntegrationAsync } from "@homarr/integrations"; +import type { UnifiSiteManagerOverview } from "@homarr/integrations/types"; + +import { createIntegrationRequestHandler } from "./lib/integration-request-handler"; + +export const unifiSiteManagerRequestHandler = createIntegrationRequestHandler< + UnifiSiteManagerOverview, + "unifiSiteManager", + Record +>({ + async requestAsync(integration, _input) { + const integrationInstance = await createIntegrationAsync(integration); + return await integrationInstance.getSiteOverviewAsync(); + }, + // Les compteurs cloud n'évoluent pas plus vite ; interroger davantage expose + // à une limitation de débit sans rien gagner. Aligné sur l'intervalle du widget. + cacheTtlMs: 5 * 60 * 1000, + fallbackToStaleOnError: true, + staleIfErrorTtlMs: 30 * 60 * 1000, +}); diff --git a/packages/widgets/src/unifi-site-manager/component.tsx b/packages/widgets/src/unifi-site-manager/component.tsx new file mode 100644 index 000000000..2fa33bddc --- /dev/null +++ b/packages/widgets/src/unifi-site-manager/component.tsx @@ -0,0 +1,7 @@ +"use client"; + +import type { WidgetComponentProps } from "../definition"; + +export default function UnifiSiteManagerWidget({ integrationIds, options }: WidgetComponentProps<"unifiSiteManager">) { + return
Unifi Site Manager
; +} diff --git a/packages/widgets/src/unifi-site-manager/index.ts b/packages/widgets/src/unifi-site-manager/index.ts new file mode 100644 index 000000000..b5364c7aa --- /dev/null +++ b/packages/widgets/src/unifi-site-manager/index.ts @@ -0,0 +1,15 @@ +import { IconCloudNetwork } from "@tabler/icons-react"; + +import { createWidgetDefinition } from "../definition"; +import { optionsBuilder } from "../options"; + +export const { definition, componentLoader } = createWidgetDefinition("unifiSiteManager", { + icon: IconCloudNetwork, + refetchInterval: 5 * 60, + supportedIntegrations: ["unifiSiteManager"], + integrationsRequired: true, + createOptions() { + return optionsBuilder.from((factory) => ({})); + }, + errors: {}, +}).withDynamicImport(() => import("./component"));