diff --git a/src/server/api/root.ts b/src/server/api/root.ts index b032f1587..28d8cc9e0 100644 --- a/src/server/api/root.ts +++ b/src/server/api/root.ts @@ -4,6 +4,7 @@ import { rssRouter } from './routers/rss'; import { configRouter } from './routers/config'; import { dockerRouter } from './routers/docker/router'; import { iconRouter } from './routers/icon'; +import { dashDotRouter } from './routers/dash-dot'; /** * This is the primary router for your server. @@ -16,6 +17,7 @@ export const rootRouter = createTRPCRouter({ config: configRouter, docker: dockerRouter, icon: iconRouter, + dashDot: dashDotRouter, }); // export type definition of API diff --git a/src/server/api/routers/dash-dot.ts b/src/server/api/routers/dash-dot.ts new file mode 100644 index 000000000..efd037ebb --- /dev/null +++ b/src/server/api/routers/dash-dot.ts @@ -0,0 +1,45 @@ +import axios from 'axios'; +import { z } from 'zod'; +import { TRPCError } from '@trpc/server'; +import { createTRPCRouter, publicProcedure } from '../trpc'; + +const dashDotUrlSchema = z.string().url(); + +const removeLeadingSlash = (x: string) => (x.endsWith('/') ? x.substring(0, x.length - 1) : x); + +export const dashDotRouter = createTRPCRouter({ + info: publicProcedure + .input( + z.object({ + url: dashDotUrlSchema.transform(removeLeadingSlash), + }) + ) + .output( + z.object({ + storage: z.array( + z.object({ + size: z.number(), + }) + ), + network: z.object({ + speedUp: z.number(), + speedDown: z.number(), + }), + }) + ) + .query(async ({ input }) => { + const response = await axios.get(`${input.url}/info`).catch((error) => { + if (error.response.status === 404) { + throw new TRPCError({ + code: 'NOT_FOUND', + message: 'Unable to find specified dash-dot instance', + }); + } + + throw new TRPCError({ + code: 'INTERNAL_SERVER_ERROR', + }); + }); + return response.data; + }), +}); diff --git a/src/widgets/dashDot/DashDotCompactNetwork.tsx b/src/widgets/dashDot/DashDotCompactNetwork.tsx index 815b136b7..a62416daf 100644 --- a/src/widgets/dashDot/DashDotCompactNetwork.tsx +++ b/src/widgets/dashDot/DashDotCompactNetwork.tsx @@ -2,21 +2,13 @@ import { Group, Stack, Text } from '@mantine/core'; import { IconArrowNarrowDown, IconArrowNarrowUp } from '@tabler/icons-react'; import { useTranslation } from 'next-i18next'; import { bytes } from '../../tools/bytesHelper'; +import { RouterOutputs } from '~/utils/api'; interface DashDotCompactNetworkProps { info: DashDotInfo; } -export interface DashDotInfo { - storage: { - size: number; - disks: { device: string; brand: string; type: string }[]; - }[]; - network: { - speedUp: number; - speedDown: number; - }; -} +export type DashDotInfo = RouterOutputs['dashDot']['info']; export const DashDotCompactNetwork = ({ info }: DashDotCompactNetworkProps) => { const { t } = useTranslation('modules/dashdot'); diff --git a/src/widgets/dashDot/DashDotGraph.tsx b/src/widgets/dashDot/DashDotGraph.tsx index d26bd0e90..a93e11105 100644 --- a/src/widgets/dashDot/DashDotGraph.tsx +++ b/src/widgets/dashDot/DashDotGraph.tsx @@ -1,4 +1,4 @@ -import { createStyles, Title, useMantineTheme, getStylesRef } from '@mantine/core'; +import { Title, createStyles, getStylesRef, useMantineTheme } from '@mantine/core'; import { useTranslation } from 'next-i18next'; import { DashDotCompactNetwork, DashDotInfo } from './DashDotCompactNetwork'; import { DashDotCompactStorage } from './DashDotCompactStorage'; diff --git a/src/widgets/dashDot/DashDotTile.tsx b/src/widgets/dashDot/DashDotTile.tsx index 397515f2c..2c07c3fd6 100644 --- a/src/widgets/dashDot/DashDotTile.tsx +++ b/src/widgets/dashDot/DashDotTile.tsx @@ -1,12 +1,9 @@ import { Center, createStyles, Grid, Stack, Text, Title } from '@mantine/core'; import { IconUnlink } from '@tabler/icons-react'; -import { useQuery } from '@tanstack/react-query'; -import axios from 'axios'; import { useTranslation } from 'next-i18next'; -import { useConfigContext } from '../../config/provider'; +import { api } from '~/utils/api'; import { defineWidget } from '../helper'; import { IWidget } from '../widgets'; -import { DashDotInfo } from './DashDotCompactNetwork'; import { DashDotGraph } from './DashDotGraph'; const definition = defineWidget({ @@ -161,10 +158,9 @@ function DashDotTile({ widget }: DashDotTileProps) { const detectedProtocolDowngrade = locationProtocol === 'https:' && dashDotUrl.toLowerCase().startsWith('http:'); - const { data: info } = useDashDotInfo({ + const { data: info } = useDashDotInfoQuery({ dashDotUrl, enabled: !detectedProtocolDowngrade, - widgetId: widget.id, }); if (detectedProtocolDowngrade) { @@ -212,37 +208,16 @@ function DashDotTile({ widget }: DashDotTileProps) { ); } - -const useDashDotInfo = ({ - dashDotUrl, - enabled, - widgetId, -}: { - dashDotUrl: string; - enabled: boolean; - widgetId: string; -}) => { - const { name: configName } = useConfigContext(); - return useQuery({ - refetchInterval: 50000, - queryKey: [ - 'dashdot/info', - { - configName, - dashDotUrl, - }, - ], - queryFn: () => fetchDashDotInfo(configName, widgetId), - enabled, - }); -}; - -const fetchDashDotInfo = async (configName: string | undefined, widgetId: string) => { - if (!configName) return {} as DashDotInfo; - return (await ( - await axios.get('/api/modules/dashdot/info', { params: { configName, widgetId } }) - ).data) as DashDotInfo; -}; +const useDashDotInfoQuery = ({ dashDotUrl, enabled }: { dashDotUrl: string; enabled: boolean }) => + api.dashDot.info.useQuery( + { + url: dashDotUrl, + }, + { + refetchInterval: 50000, + enabled, + } + ); export const useDashDotTileStyles = createStyles((theme) => ({ graphsContainer: {