"use client"; import { ScrollArea, Stack, Text } from "@mantine/core"; import { clientApi } from "@homarr/api/client"; import type { TracearrDashboardData } from "@homarr/integrations/types"; import { useScopedI18n } from "@homarr/translation/client"; import type { WidgetComponentProps } from "../definition"; import { NoIntegrationDataError } from "../errors/no-data-integration"; import { RecentActivityList } from "./recent-activity-section"; import { StatsBar } from "./stats-section"; import { StreamsList } from "./streams-section"; import { ViolationsList } from "./violations-section"; export default function TracearrWidget({ options, integrationIds, width, }: WidgetComponentProps<"tracearr">) { if (integrationIds.length === 0) { throw new NoIntegrationDataError(); } return ; } interface TracearrContentProps { integrationIds: string[]; options: WidgetComponentProps<"tracearr">["options"]; width: number; } function TracearrContent({ integrationIds, options, width }: TracearrContentProps) { const t = useScopedI18n("widget.tracearr"); const { data: dashboardData = [] } = clientApi.widget.tracearr.getDashboard.useQuery({ integrationIds }); // Merge data from all integrations const combined = dashboardData.reduce( (acc, item) => { const { stats, streams, violations, recentActivity } = item.dashboard; const vData = violations ?? { data: [], meta: { total: 0, page: 1, pageSize: 5 } }; const aData = recentActivity ?? { data: [], meta: { total: 0, page: 1, pageSize: 5 } }; return { stats: { activeStreams: acc.stats.activeStreams + stats.activeStreams, totalUsers: acc.stats.totalUsers + stats.totalUsers, totalSessions: acc.stats.totalSessions + stats.totalSessions, recentViolations: acc.stats.recentViolations + stats.recentViolations, timestamp: stats.timestamp, }, streams: { data: [...acc.streams.data, ...streams.data], summary: { total: acc.streams.summary.total + streams.summary.total, transcodes: acc.streams.summary.transcodes + streams.summary.transcodes, directStreams: acc.streams.summary.directStreams + streams.summary.directStreams, directPlays: acc.streams.summary.directPlays + streams.summary.directPlays, totalBitrate: streams.summary.totalBitrate, byServer: [...acc.streams.summary.byServer, ...streams.summary.byServer], }, }, violations: { data: [...(acc.violations?.data ?? []), ...vData.data], meta: { total: (acc.violations?.meta.total ?? 0) + vData.meta.total, page: 1, pageSize: 5, }, }, recentActivity: { data: [...(acc.recentActivity?.data ?? []), ...aData.data], meta: { total: (acc.recentActivity?.meta.total ?? 0) + aData.meta.total, page: 1, pageSize: 5, }, }, }; }, { stats: { activeStreams: 0, totalUsers: 0, totalSessions: 0, recentViolations: 0, timestamp: "" }, streams: { data: [], summary: { total: 0, transcodes: 0, directStreams: 0, directPlays: 0, totalBitrate: "0", byServer: [] }, }, violations: null, recentActivity: null, }, ); const noSectionsEnabled = !options.showStats && !options.showStreams && !options.showRecentActivity && !options.showViolations; return ( {options.showStats && } {options.showStreams && } {options.showViolations && } {options.showRecentActivity && } {noSectionsEnabled && ( {t("noSectionsEnabled")} )} ); }