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),