diff --git a/apps/dashboard/src/components/overview/overview-details-button.tsx b/apps/dashboard/src/components/overview/overview-details-button.tsx new file mode 100644 index 00000000..7494c707 --- /dev/null +++ b/apps/dashboard/src/components/overview/overview-details-button.tsx @@ -0,0 +1,25 @@ +import { pushModal } from '@/modals'; +import { ScanEyeIcon } from 'lucide-react'; + +import type { IChartInput } from '@openpanel/validation'; + +type Props = { + chart: IChartInput; +}; + +const OverviewDetailsButton = ({ chart }: Props) => { + return ( + + ); +}; + +export default OverviewDetailsButton; diff --git a/apps/dashboard/src/components/overview/overview-latest-events/overview-latest-events.tsx b/apps/dashboard/src/components/overview/overview-latest-events/overview-latest-events.tsx index 4594abed..525616b9 100644 --- a/apps/dashboard/src/components/overview/overview-latest-events/overview-latest-events.tsx +++ b/apps/dashboard/src/components/overview/overview-latest-events/overview-latest-events.tsx @@ -5,6 +5,7 @@ import { useEventQueryFilters } from '@/hooks/useEventQueryFilters'; import { cn } from '@/utils/cn'; import { Widget, WidgetBody } from '../../widget'; +import OverviewDetailsButton from '../overview-details-button'; import { WidgetButtons, WidgetHead } from '../overview-widget'; import { useOverviewOptions } from '../useOverviewOptions'; import { useOverviewWidget } from '../useOverviewWidget'; @@ -121,6 +122,7 @@ export default function OverviewLatestEvents({ + diff --git a/apps/dashboard/src/components/overview/overview-top-devices.tsx b/apps/dashboard/src/components/overview/overview-top-devices.tsx index 4427f2ef..5ac4dee7 100644 --- a/apps/dashboard/src/components/overview/overview-top-devices.tsx +++ b/apps/dashboard/src/components/overview/overview-top-devices.tsx @@ -9,6 +9,7 @@ import type { IChartType } from '@openpanel/validation'; import { LazyChart } from '../report/chart/LazyChart'; import { Widget, WidgetBody } from '../widget'; import { OverviewChartToggle } from './overview-chart-toggle'; +import OverviewDetailsButton from './overview-details-button'; import { WidgetButtons, WidgetHead } from './overview-widget'; import { useOverviewOptions } from './useOverviewOptions'; import { useOverviewWidget } from './useOverviewWidget'; @@ -222,6 +223,7 @@ export default function OverviewTopDevices({ } }} /> + diff --git a/apps/dashboard/src/components/overview/overview-top-events/overview-top-events.tsx b/apps/dashboard/src/components/overview/overview-top-events/overview-top-events.tsx index 6971b340..8395c908 100644 --- a/apps/dashboard/src/components/overview/overview-top-events/overview-top-events.tsx +++ b/apps/dashboard/src/components/overview/overview-top-events/overview-top-events.tsx @@ -1,17 +1,15 @@ 'use client'; import { useState } from 'react'; -import { ChartSwitch } from '@/components/report/chart'; import { LazyChart } from '@/components/report/chart/LazyChart'; -import { Button } from '@/components/ui/button'; import { useEventQueryFilters } from '@/hooks/useEventQueryFilters'; import { cn } from '@/utils/cn'; -import { BarChartIcon, LineChart, LineChartIcon } from 'lucide-react'; import type { IChartType } from '@openpanel/validation'; import { Widget, WidgetBody } from '../../widget'; import { OverviewChartToggle } from '../overview-chart-toggle'; +import OverviewDetailsButton from '../overview-details-button'; import { WidgetButtons, WidgetHead } from '../overview-widget'; import { useOverviewOptions } from '../useOverviewOptions'; import { useOverviewWidget } from '../useOverviewWidget'; @@ -132,6 +130,7 @@ export default function OverviewTopEvents({ + diff --git a/apps/dashboard/src/components/overview/overview-top-geo.tsx b/apps/dashboard/src/components/overview/overview-top-geo.tsx index 4c56646f..e0c82678 100644 --- a/apps/dashboard/src/components/overview/overview-top-geo.tsx +++ b/apps/dashboard/src/components/overview/overview-top-geo.tsx @@ -10,6 +10,7 @@ import type { IChartType } from '@openpanel/validation'; import { LazyChart } from '../report/chart/LazyChart'; import { Widget, WidgetBody } from '../widget'; import { OverviewChartToggle } from './overview-chart-toggle'; +import OverviewDetailsButton from './overview-details-button'; import { WidgetButtons, WidgetHead } from './overview-widget'; import { useOverviewOptions } from './useOverviewOptions'; import { useOverviewWidget } from './useOverviewWidget'; @@ -157,6 +158,7 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) { } }} /> + diff --git a/apps/dashboard/src/components/overview/overview-top-pages.tsx b/apps/dashboard/src/components/overview/overview-top-pages.tsx index 350c4341..1e64739d 100644 --- a/apps/dashboard/src/components/overview/overview-top-pages.tsx +++ b/apps/dashboard/src/components/overview/overview-top-pages.tsx @@ -9,6 +9,7 @@ import type { IChartType } from '@openpanel/validation'; import { LazyChart } from '../report/chart/LazyChart'; import { Widget, WidgetBody } from '../widget'; import { OverviewChartToggle } from './overview-chart-toggle'; +import OverviewDetailsButton from './overview-details-button'; import OverviewTopBots from './overview-top-bots'; import { WidgetButtons, WidgetHead } from './overview-widget'; import { useOverviewOptions } from './useOverviewOptions'; @@ -154,6 +155,7 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) { }} /> )} + diff --git a/apps/dashboard/src/components/overview/overview-top-sources.tsx b/apps/dashboard/src/components/overview/overview-top-sources.tsx index b476483d..03bc4cf2 100644 --- a/apps/dashboard/src/components/overview/overview-top-sources.tsx +++ b/apps/dashboard/src/components/overview/overview-top-sources.tsx @@ -2,13 +2,16 @@ import { useState } from 'react'; import { useEventQueryFilters } from '@/hooks/useEventQueryFilters'; +import { pushModal } from '@/modals'; import { cn } from '@/utils/cn'; +import { ScanEyeIcon } from 'lucide-react'; import type { IChartType } from '@openpanel/validation'; import { LazyChart } from '../report/chart/LazyChart'; import { Widget, WidgetBody } from '../widget'; import { OverviewChartToggle } from './overview-chart-toggle'; +import OverviewDetailsButton from './overview-details-button'; import { WidgetButtons, WidgetHead } from './overview-widget'; import { useOverviewOptions } from './useOverviewOptions'; import { useOverviewWidget } from './useOverviewWidget'; @@ -324,6 +327,7 @@ export default function OverviewTopSources({ } }} /> + diff --git a/apps/dashboard/src/components/overview/overview-widget.tsx b/apps/dashboard/src/components/overview/overview-widget.tsx index b49034e4..8e981477 100644 --- a/apps/dashboard/src/components/overview/overview-widget.tsx +++ b/apps/dashboard/src/components/overview/overview-widget.tsx @@ -20,7 +20,7 @@ export function WidgetHead({ className, ...props }: WidgetHeadProps) { return ( void; + limit?: number; } type ChartProviderProps = { @@ -37,6 +38,7 @@ const ChartContext = createContext({ metric: 'sum', previous: false, projectId: '', + limit: undefined, }); export function ChartProvider({ @@ -44,6 +46,7 @@ export function ChartProvider({ editMode, previous, hideID, + limit, ...props }: ChartProviderProps) { return ( @@ -54,8 +57,9 @@ export function ChartProvider({ editMode: editMode ?? false, previous: previous ?? false, hideID: hideID ?? false, + limit, }), - [editMode, previous, hideID, props] + [editMode, previous, hideID, limit, props] )} > {children} diff --git a/apps/dashboard/src/components/report/chart/ReportBarChart.tsx b/apps/dashboard/src/components/report/chart/ReportBarChart.tsx index 3e616539..f8e1e6da 100644 --- a/apps/dashboard/src/components/report/chart/ReportBarChart.tsx +++ b/apps/dashboard/src/components/report/chart/ReportBarChart.tsx @@ -17,11 +17,11 @@ interface ReportBarChartProps { } export function ReportBarChart({ data }: ReportBarChartProps) { - const { editMode, metric, onClick } = useChartContext(); + const { editMode, metric, onClick, limit } = useChartContext(); const number = useNumber(); const series = useMemo( - () => (editMode ? data.series : data.series.slice(0, 10)), - [data, editMode] + () => (editMode ? data.series : data.series.slice(0, limit || 10)), + [data, editMode, limit] ); const maxCount = Math.max(...series.map((serie) => serie.metrics[metric])); diff --git a/apps/dashboard/src/modals/OverviewChartDetails.tsx b/apps/dashboard/src/modals/OverviewChartDetails.tsx new file mode 100644 index 00000000..78f7c0ef --- /dev/null +++ b/apps/dashboard/src/modals/OverviewChartDetails.tsx @@ -0,0 +1,25 @@ +import { ChartSwitch } from '@/components/report/chart'; +import { ScrollArea } from '@/components/ui/scroll-area'; + +import type { IChartInput } from '@openpanel/validation'; + +import { ModalContent, ModalHeader } from './Modal/Container'; + +type Props = { + chart: IChartInput; +}; + +const OverviewChartDetails = (props: Props) => { + return ( + + + +
+ +
+
+
+ ); +}; + +export default OverviewChartDetails; diff --git a/apps/dashboard/src/modals/index.tsx b/apps/dashboard/src/modals/index.tsx index 4959fc6a..d2a97eca 100644 --- a/apps/dashboard/src/modals/index.tsx +++ b/apps/dashboard/src/modals/index.tsx @@ -62,6 +62,9 @@ const modals = { DateRangerPicker: dynamic(() => import('./DateRangerPicker'), { loading: Loading, }), + OverviewChartDetails: dynamic(() => import('./OverviewChartDetails'), { + loading: Loading, + }), }; export const { diff --git a/packages/trpc/src/routers/chart.ts b/packages/trpc/src/routers/chart.ts index c32736f0..7fa25ba7 100644 --- a/packages/trpc/src/routers/chart.ts +++ b/packages/trpc/src/routers/chart.ts @@ -209,7 +209,9 @@ export const chartRouter = createTRPCRouter({ const final: FinalChart = { events: input.events, series: series.map((serie, index) => { - const previousSerie = previousSeries?.[index]; + const previousSerie = previousSeries?.find( + (item) => item.name === serie.name + ); const metrics = { sum: sum(serie.data.map((item) => item.count)), average: round(average(serie.data.map((item) => item.count)), 2),