add details button on overview
This commit is contained in:
@@ -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 (
|
||||
<button
|
||||
className="-mb-2 mt-5 flex w-full items-center justify-center gap-2 text-sm font-semibold"
|
||||
onClick={() => {
|
||||
pushModal('OverviewChartDetails', {
|
||||
chart: chart,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<ScanEyeIcon size={18} /> Details
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export default OverviewDetailsButton;
|
||||
@@ -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({
|
||||
</WidgetHead>
|
||||
<WidgetBody>
|
||||
<LazyChart hideID {...widget.chart} previous={false} />
|
||||
<OverviewDetailsButton chart={widget.chart} />
|
||||
</WidgetBody>
|
||||
</Widget>
|
||||
</>
|
||||
|
||||
@@ -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({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<OverviewDetailsButton chart={widget.chart} />
|
||||
</WidgetBody>
|
||||
</Widget>
|
||||
</>
|
||||
|
||||
@@ -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({
|
||||
</WidgetHead>
|
||||
<WidgetBody>
|
||||
<LazyChart hideID {...widget.chart} previous={false} />
|
||||
<OverviewDetailsButton chart={widget.chart} />
|
||||
</WidgetBody>
|
||||
</Widget>
|
||||
</>
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<OverviewDetailsButton chart={widget.chart} />
|
||||
</WidgetBody>
|
||||
</Widget>
|
||||
<Widget className="col-span-6 md:col-span-3">
|
||||
|
||||
@@ -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) {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<OverviewDetailsButton chart={widget.chart} />
|
||||
</WidgetBody>
|
||||
</Widget>
|
||||
</>
|
||||
|
||||
@@ -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({
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<OverviewDetailsButton chart={widget.chart} />
|
||||
</WidgetBody>
|
||||
</Widget>
|
||||
</>
|
||||
|
||||
@@ -20,7 +20,7 @@ export function WidgetHead({ className, ...props }: WidgetHeadProps) {
|
||||
return (
|
||||
<WidgetHeadBase
|
||||
className={cn(
|
||||
'flex flex-col rounded-t-xl p-0 [&_.title]:flex [&_.title]:items-center [&_.title]:justify-between [&_.title]:p-4',
|
||||
'flex flex-col rounded-t-xl p-0 [&_.title]:flex [&_.title]:items-center [&_.title]:justify-between [&_.title]:p-4 [&_.title]:font-semibold',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface ChartContextType extends IChartInput {
|
||||
editMode?: boolean;
|
||||
hideID?: boolean;
|
||||
onClick?: (item: IChartSerie) => void;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
type ChartProviderProps = {
|
||||
@@ -37,6 +38,7 @@ const ChartContext = createContext<ChartContextType | null>({
|
||||
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}
|
||||
|
||||
@@ -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]));
|
||||
|
||||
|
||||
25
apps/dashboard/src/modals/OverviewChartDetails.tsx
Normal file
25
apps/dashboard/src/modals/OverviewChartDetails.tsx
Normal file
@@ -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 (
|
||||
<ModalContent>
|
||||
<ModalHeader title={props.chart.name} />
|
||||
<ScrollArea className="-m-6 max-h-[calc(100vh-200px)]">
|
||||
<div className="p-6">
|
||||
<ChartSwitch {...props.chart} limit={999} chartType="bar" />
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</ModalContent>
|
||||
);
|
||||
};
|
||||
|
||||
export default OverviewChartDetails;
|
||||
@@ -62,6 +62,9 @@ const modals = {
|
||||
DateRangerPicker: dynamic(() => import('./DateRangerPicker'), {
|
||||
loading: Loading,
|
||||
}),
|
||||
OverviewChartDetails: dynamic(() => import('./OverviewChartDetails'), {
|
||||
loading: Loading,
|
||||
}),
|
||||
};
|
||||
|
||||
export const {
|
||||
|
||||
@@ -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),
|
||||
|
||||
Reference in New Issue
Block a user