From 558761ca9db57f241f2cd02bdb4545e9f4d1b202 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carl-Gerhard=20Lindesva=CC=88rd?= Date: Thu, 12 Sep 2024 09:30:48 +0200 Subject: [PATCH] refactor(dashboard): the chart component is now cleaned up and easier to extend --- .../dashboards/[dashboardId]/list-reports.tsx | 28 +- .../[projectId]/events/charts.tsx | 10 +- .../[projectId]/layout-content.tsx | 6 +- .../[projectId]/pages/pages-table.tsx | 77 +-- .../profiles/[profileId]/profile-charts.tsx | 6 +- .../profile-metrics/profile-metrics.tsx | 6 +- .../[projectId]/realtime/page.tsx | 27 +- .../[projectId]/reports/report-editor.tsx | 4 +- .../retention/last-active-users/chart.tsx | 119 ++--- .../[projectId]/retention/page.tsx | 2 +- .../retention/rolling-active-users/chart.tsx | 178 +++---- .../users-retention-series/chart.tsx | 118 ++--- .../src/components/events/event-list-item.tsx | 2 +- .../events/list-properties-icon.tsx | 9 +- .../src/components/events/table/columns.tsx | 2 +- .../overview-filters-drawer-content.tsx | 2 +- .../overview/overview-live-histogram.tsx | 4 +- .../components/overview/overview-metrics.tsx | 21 +- .../overview/overview-top-devices.tsx | 459 ++++++++-------- .../overview-top-events.tsx | 200 +++---- .../components/overview/overview-top-geo.tsx | 242 +++++---- .../overview/overview-top-pages.tsx | 243 +++++---- .../overview/overview-top-sources.tsx | 489 +++++++++--------- .../components/overview/useOverviewWidget.tsx | 4 +- .../src/components/profiles/table/columns.tsx | 2 +- .../components/report-chart/area/chart.tsx | 279 ++++++++++ .../components/report-chart/area/index.tsx | 59 +++ .../report-chart/aspect-container.tsx | 32 ++ .../bar/chart.tsx} | 89 +--- .../src/components/report-chart/bar/index.tsx | 63 +++ .../components/report-chart/common/axis.tsx | 81 +++ .../components/report-chart/common/empty.tsx | 13 + .../components/report-chart/common/error.tsx | 15 + .../report-chart/common/loading.tsx | 3 + .../common/previous-diff-indicator.tsx} | 16 +- .../common/report-chart-tooltip.tsx} | 12 +- .../common/report-table.tsx} | 31 +- .../common/serie-icon.flags.tsx} | 0 .../common/serie-icon.tsx} | 4 +- .../common/serie-icon.urls.ts} | 0 .../common/serie-name.tsx} | 15 +- .../src/components/report-chart/context.tsx | 84 +++ .../funnel/chart.tsx} | 69 +-- .../components/report-chart/funnel/index.tsx | 71 +++ .../report-chart/histogram/chart.tsx | 130 +++++ .../report-chart/histogram/index.tsx | 59 +++ .../src/components/report-chart/index.tsx | 66 +++ .../components/report-chart/line/chart.tsx | 279 ++++++++++ .../components/report-chart/line/index.tsx | 59 +++ .../map/chart.tsx} | 10 +- .../src/components/report-chart/map/index.tsx | 55 ++ .../metric/chart.tsx} | 17 +- .../components/report-chart/metric/index.tsx | 65 +++ .../metric/metric-card.tsx} | 67 ++- .../pie/chart.tsx} | 79 ++- .../src/components/report-chart/pie/index.tsx | 59 +++ .../src/components/report-chart/shortcut.tsx | 43 ++ .../src/components/report/chart/Chart.tsx | 101 ---- .../components/report/chart/ChartEmpty.tsx | 29 -- .../components/report/chart/ChartLoading.tsx | 20 - .../components/report/chart/ChartProvider.tsx | 44 -- .../src/components/report/chart/LazyChart.tsx | 36 -- .../report/chart/ReportAreaChart.tsx | 116 ----- .../report/chart/ReportHistogramChart.tsx | 137 ----- .../report/chart/ReportLineChart.tsx | 293 ----------- .../report/chart/ResponsiveContainer.tsx | 45 -- .../components/report/chart/chart-utils.ts | 11 - .../src/components/report/chart/index.tsx | 90 ---- .../components/report/funnel/Funnel.old.tsx | 176 ------- .../src/components/report/funnel/index.tsx | 37 -- apps/dashboard/src/components/stats.tsx | 30 ++ apps/dashboard/src/components/ui/sheet.tsx | 17 +- .../src/hocs/with-loading-widget.tsx | 3 +- .../src/modals/OverviewChartDetails.tsx | 10 +- apps/dashboard/src/modals/event-details.tsx | 4 +- apps/dashboard/src/styles/globals.css | 2 +- 76 files changed, 2910 insertions(+), 2475 deletions(-) create mode 100644 apps/dashboard/src/components/report-chart/area/chart.tsx create mode 100644 apps/dashboard/src/components/report-chart/area/index.tsx create mode 100644 apps/dashboard/src/components/report-chart/aspect-container.tsx rename apps/dashboard/src/components/{report/chart/ReportBarChart.tsx => report-chart/bar/chart.tsx} (54%) create mode 100644 apps/dashboard/src/components/report-chart/bar/index.tsx create mode 100644 apps/dashboard/src/components/report-chart/common/axis.tsx create mode 100644 apps/dashboard/src/components/report-chart/common/empty.tsx create mode 100644 apps/dashboard/src/components/report-chart/common/error.tsx create mode 100644 apps/dashboard/src/components/report-chart/common/loading.tsx rename apps/dashboard/src/components/{report/PreviousDiffIndicator.tsx => report-chart/common/previous-diff-indicator.tsx} (84%) rename apps/dashboard/src/components/{report/chart/ReportChartTooltip.tsx => report-chart/common/report-chart-tooltip.tsx} (93%) rename apps/dashboard/src/components/{report/chart/ReportTable.tsx => report-chart/common/report-table.tsx} (90%) rename apps/dashboard/src/components/{report/chart/SerieIcon.flags.tsx => report-chart/common/serie-icon.flags.tsx} (100%) rename apps/dashboard/src/components/{report/chart/SerieIcon.tsx => report-chart/common/serie-icon.tsx} (96%) rename apps/dashboard/src/components/{report/chart/SerieIcon.urls.ts => report-chart/common/serie-icon.urls.ts} (100%) rename apps/dashboard/src/components/{report/chart/SerieName.tsx => report-chart/common/serie-name.tsx} (74%) create mode 100644 apps/dashboard/src/components/report-chart/context.tsx rename apps/dashboard/src/components/{report/funnel/Funnel.tsx => report-chart/funnel/chart.tsx} (84%) create mode 100644 apps/dashboard/src/components/report-chart/funnel/index.tsx create mode 100644 apps/dashboard/src/components/report-chart/histogram/chart.tsx create mode 100644 apps/dashboard/src/components/report-chart/histogram/index.tsx create mode 100644 apps/dashboard/src/components/report-chart/index.tsx create mode 100644 apps/dashboard/src/components/report-chart/line/chart.tsx create mode 100644 apps/dashboard/src/components/report-chart/line/index.tsx rename apps/dashboard/src/components/{report/chart/ReportMapChart.tsx => report-chart/map/chart.tsx} (80%) create mode 100644 apps/dashboard/src/components/report-chart/map/index.tsx rename apps/dashboard/src/components/{report/chart/ReportMetricChart.tsx => report-chart/metric/chart.tsx} (57%) create mode 100644 apps/dashboard/src/components/report-chart/metric/index.tsx rename apps/dashboard/src/components/{report/chart/MetricCard.tsx => report-chart/metric/metric-card.tsx} (63%) rename apps/dashboard/src/components/{report/chart/ReportPieChart.tsx => report-chart/pie/chart.tsx} (57%) create mode 100644 apps/dashboard/src/components/report-chart/pie/index.tsx create mode 100644 apps/dashboard/src/components/report-chart/shortcut.tsx delete mode 100644 apps/dashboard/src/components/report/chart/Chart.tsx delete mode 100644 apps/dashboard/src/components/report/chart/ChartEmpty.tsx delete mode 100644 apps/dashboard/src/components/report/chart/ChartLoading.tsx delete mode 100644 apps/dashboard/src/components/report/chart/ChartProvider.tsx delete mode 100644 apps/dashboard/src/components/report/chart/LazyChart.tsx delete mode 100644 apps/dashboard/src/components/report/chart/ReportAreaChart.tsx delete mode 100644 apps/dashboard/src/components/report/chart/ReportHistogramChart.tsx delete mode 100644 apps/dashboard/src/components/report/chart/ReportLineChart.tsx delete mode 100644 apps/dashboard/src/components/report/chart/ResponsiveContainer.tsx delete mode 100644 apps/dashboard/src/components/report/chart/chart-utils.ts delete mode 100644 apps/dashboard/src/components/report/chart/index.tsx delete mode 100644 apps/dashboard/src/components/report/funnel/Funnel.old.tsx delete mode 100644 apps/dashboard/src/components/report/funnel/index.tsx create mode 100644 apps/dashboard/src/components/stats.tsx diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/dashboards/[dashboardId]/list-reports.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/dashboards/[dashboardId]/list-reports.tsx index caed65bb..ab2b40e7 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/dashboards/[dashboardId]/list-reports.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/dashboards/[dashboardId]/list-reports.tsx @@ -1,9 +1,8 @@ 'use client'; -import { StickyBelowHeader } from '@/app/(app)/[organizationSlug]/[projectId]/layout-sticky-below-header'; import { FullPageEmptyState } from '@/components/full-page-empty-state'; import { useOverviewOptions } from '@/components/overview/useOverviewOptions'; -import { LazyChart } from '@/components/report/chart/LazyChart'; +import { ReportChart } from '@/components/report-chart'; import { Button } from '@/components/ui/button'; import { DropdownMenu, @@ -133,17 +132,22 @@ export function ListReports({ reports, dashboard }: ListReportsProps) { /> -
- +
diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/events/charts.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/events/charts.tsx index 7d89772e..42789fcb 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/events/charts.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/events/charts.tsx @@ -2,7 +2,7 @@ import { OverviewFiltersButtons } from '@/components/overview/filters/overview-filters-buttons'; import { OverviewFiltersDrawer } from '@/components/overview/filters/overview-filters-drawer'; -import { ChartRootShortcut } from '@/components/report/chart'; +import { ReportChartShortcut } from '@/components/report-chart/shortcut'; import { Widget, WidgetBody, WidgetHead } from '@/components/widget'; import { useEventQueryFilters, @@ -44,7 +44,7 @@ function Charts({ projectId }: Props) { Events per day - Event distribution - Event distribution - Event distribution - {children}; + return
{children}
; } - return
{children}
; + return ( +
{children}
+ ); } diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/pages/pages-table.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/pages/pages-table.tsx index c8eaf9f6..14013078 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/pages/pages-table.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/pages/pages-table.tsx @@ -1,7 +1,7 @@ 'use client'; import { memo } from 'react'; -import { LazyChart } from '@/components/report/chart/LazyChart'; +import { ReportChart } from '@/components/report-chart'; import { useNumber } from '@/hooks/useNumerFormatter'; import { cn } from '@/utils/cn'; import isEqual from 'lodash.isequal'; @@ -71,41 +71,46 @@ export const PagesTable = memo( index === data.length - 1 && 'rounded-br-md' )} > - diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-charts.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-charts.tsx index 6d01f60a..214b4a8f 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-charts.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-charts.tsx @@ -1,7 +1,7 @@ 'use client'; import { memo } from 'react'; -import { ChartRoot } from '@/components/report/chart'; +import { ReportChart } from '@/components/report-chart'; import { Widget, WidgetBody, WidgetHead } from '@/components/widget'; import type { IChartProps } from '@openpanel/validation'; @@ -85,7 +85,7 @@ const ProfileCharts = ({ profileId, projectId }: Props) => { Page views - + @@ -93,7 +93,7 @@ const ProfileCharts = ({ profileId, projectId }: Props) => { Events per day - + diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-metrics/profile-metrics.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-metrics/profile-metrics.tsx index da7e3659..ebe07673 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-metrics/profile-metrics.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/profiles/[profileId]/profile-metrics/profile-metrics.tsx @@ -18,7 +18,7 @@ function Card({ title, value }: { title: string; value: string }) { return (
{title}
-
{value}
+
{value}
); } @@ -27,7 +27,7 @@ function Info({ title, value }: { title: string; value: string }) { return (
{title}
-
{value || '-'}
+
{value || '-'}
); } @@ -40,7 +40,7 @@ const ProfileMetrics = ({ data, profile }: Props) => { const number = useNumber(); return (
-
+
-
Cities
-
Referrers
-
{report.ready && ( - + )}
diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/last-active-users/chart.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/last-active-users/chart.tsx index b2db1eb0..5af24f1d 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/last-active-users/chart.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/last-active-users/chart.tsx @@ -1,13 +1,15 @@ 'use client'; -import { getYAxisWidth } from '@/components/report/chart/chart-utils'; -import { ResponsiveContainer } from '@/components/report/chart/ResponsiveContainer'; -import { useNumber } from '@/hooks/useNumerFormatter'; +import { + useXAxisProps, + useYAxisProps, +} from '@/components/report-chart/common/axis'; import { getChartColor } from '@/utils/theme'; import { Area, AreaChart, Tooltip as RechartTooltip, + ResponsiveContainer, XAxis, YAxis, } from 'recharts'; @@ -39,69 +41,62 @@ function Tooltip(props: any) { } const Chart = ({ data }: Props) => { - const max = Math.max(...data.map((d) => d.users)); - const number = useNumber(); + const xAxisProps = useXAxisProps(); + const yAxisProps = useYAxisProps({ + data: data.map((d) => d.users), + }); return ( -
+
- {({ width, height }) => ( - - - - - - - + + + + + + + - } /> + } /> - - - - - )} + + + +
); diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/page.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/page.tsx index da39f6a6..d25f24e0 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/page.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/page.tsx @@ -55,7 +55,7 @@ const Retention = ({ params: { projectId } }: Props) => { - + {/* */}
diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/rolling-active-users/chart.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/rolling-active-users/chart.tsx index 2cdee07c..9dc0ff1b 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/rolling-active-users/chart.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/rolling-active-users/chart.tsx @@ -1,13 +1,15 @@ 'use client'; -import { getYAxisWidth } from '@/components/report/chart/chart-utils'; -import { ResponsiveContainer } from '@/components/report/chart/ResponsiveContainer'; -import { useNumber } from '@/hooks/useNumerFormatter'; +import { + useXAxisProps, + useYAxisProps, +} from '@/components/report-chart/common/axis'; import { getChartColor } from '@/utils/theme'; import { Area, AreaChart, Tooltip as RechartTooltip, + ResponsiveContainer, XAxis, YAxis, } from 'recharts'; @@ -50,106 +52,94 @@ function Tooltip(props: any) { } const Chart = ({ data }: Props) => { - const max = Math.max(...data.monthly.map((d) => d.users)); - const number = useNumber(); const rechartData = data.daily.map((d) => ({ - date: d.date, + date: new Date(d.date).getTime(), dau: d.users, wau: data.weekly.find((w) => w.date === d.date)?.users, mau: data.monthly.find((m) => m.date === d.date)?.users, })); + const xAxisProps = useXAxisProps({ interval: 'day' }); + const yAxisProps = useYAxisProps({ + data: data.monthly.map((d) => d.users), + }); return ( -
+
- {({ width, height }) => ( - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - } /> + } /> - - - - - - - )} + + + + + +
); diff --git a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/users-retention-series/chart.tsx b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/users-retention-series/chart.tsx index be03e574..fe5fae6f 100644 --- a/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/users-retention-series/chart.tsx +++ b/apps/dashboard/src/app/(app)/[organizationSlug]/[projectId]/retention/users-retention-series/chart.tsx @@ -1,15 +1,17 @@ 'use client'; -import { getYAxisWidth } from '@/components/report/chart/chart-utils'; -import { ResponsiveContainer } from '@/components/report/chart/ResponsiveContainer'; +import { + useXAxisProps, + useYAxisProps, +} from '@/components/report-chart/common/axis'; import { useFormatDateInterval } from '@/hooks/useFormatDateInterval'; -import { useNumber } from '@/hooks/useNumerFormatter'; import { formatDate } from '@/utils/date'; import { getChartColor } from '@/utils/theme'; import { Area, AreaChart, Tooltip as RechartTooltip, + ResponsiveContainer, XAxis, YAxis, } from 'recharts'; @@ -54,69 +56,61 @@ function Tooltip({ payload }: any) { } const Chart = ({ data }: Props) => { - const max = Math.max(...data.map((d) => d.retention)); - const number = useNumber(); + const xAxisProps = useXAxisProps(); + const yAxisProps = useYAxisProps({ + data: data.map((d) => d.retention), + }); return ( -
+
- {({ width, height }) => ( - - - - - - - + + + + + + + - } /> + } /> - - formatDate(new Date(m))} - tickLine={false} - allowDuplicatedCategory={false} - label={{ - value: 'DATE', - position: 'insideBottom', - offset: 0, - fontSize: 10, - }} - /> - - - )} + + formatDate(new Date(m))} + allowDuplicatedCategory={false} + label={{ + value: 'DATE', + position: 'insideBottom', + offset: 0, + fontSize: 10, + }} + /> + +
); diff --git a/apps/dashboard/src/components/events/event-list-item.tsx b/apps/dashboard/src/components/events/event-list-item.tsx index 6ed0db7c..740d2189 100644 --- a/apps/dashboard/src/components/events/event-list-item.tsx +++ b/apps/dashboard/src/components/events/event-list-item.tsx @@ -1,6 +1,5 @@ 'use client'; -import { SerieIcon } from '@/components/report/chart/SerieIcon'; import { Tooltiper } from '@/components/ui/tooltip'; import { useAppParams } from '@/hooks/useAppParams'; import { useNumber } from '@/hooks/useNumerFormatter'; @@ -11,6 +10,7 @@ import Link from 'next/link'; import type { IServiceEvent, IServiceEventMinimal } from '@openpanel/db'; +import { SerieIcon } from '../report-chart/common/serie-icon'; import { EventIcon } from './event-icon'; type EventListItemProps = IServiceEventMinimal | IServiceEvent; diff --git a/apps/dashboard/src/components/events/list-properties-icon.tsx b/apps/dashboard/src/components/events/list-properties-icon.tsx index b89654a8..b9e0dce9 100644 --- a/apps/dashboard/src/components/events/list-properties-icon.tsx +++ b/apps/dashboard/src/components/events/list-properties-icon.tsx @@ -1,10 +1,5 @@ -import { SerieIcon } from '../report/chart/SerieIcon'; -import { - Tooltip, - TooltipContent, - Tooltiper, - TooltipTrigger, -} from '../ui/tooltip'; +import { SerieIcon } from '../report-chart/common/serie-icon'; +import { Tooltiper } from '../ui/tooltip'; interface Props { country?: string; diff --git a/apps/dashboard/src/components/events/table/columns.tsx b/apps/dashboard/src/components/events/table/columns.tsx index b32ace32..56a9a3f5 100644 --- a/apps/dashboard/src/components/events/table/columns.tsx +++ b/apps/dashboard/src/components/events/table/columns.tsx @@ -1,6 +1,6 @@ import { EventIcon } from '@/components/events/event-icon'; import { ProjectLink } from '@/components/links'; -import { SerieIcon } from '@/components/report/chart/SerieIcon'; +import { SerieIcon } from '@/components/report-chart/common/serie-icon'; import { TooltipComplete } from '@/components/tooltip-complete'; import { useNumber } from '@/hooks/useNumerFormatter'; import { pushModal } from '@/modals'; diff --git a/apps/dashboard/src/components/overview/filters/overview-filters-drawer-content.tsx b/apps/dashboard/src/components/overview/filters/overview-filters-drawer-content.tsx index 348c68ef..cdcbf9e2 100644 --- a/apps/dashboard/src/components/overview/filters/overview-filters-drawer-content.tsx +++ b/apps/dashboard/src/components/overview/filters/overview-filters-drawer-content.tsx @@ -12,7 +12,7 @@ import { import { useProfileProperties } from '@/hooks/useProfileProperties'; import { useProfileValues } from '@/hooks/useProfileValues'; import { usePropertyValues } from '@/hooks/usePropertyValues'; -import { GlobeIcon, XIcon } from 'lucide-react'; +import { XIcon } from 'lucide-react'; import type { Options as NuqsOptions } from 'nuqs'; import type { diff --git a/apps/dashboard/src/components/overview/overview-live-histogram.tsx b/apps/dashboard/src/components/overview/overview-live-histogram.tsx index 36b57e03..ba0ced38 100644 --- a/apps/dashboard/src/components/overview/overview-live-histogram.tsx +++ b/apps/dashboard/src/components/overview/overview-live-histogram.tsx @@ -81,7 +81,7 @@ export function OverviewLiveHistogram({ {staticArray.map((percent, i) => (
))} @@ -101,7 +101,7 @@ export function OverviewLiveHistogram({
{ setMetric(index); }} > - + ))}
-
diff --git a/apps/dashboard/src/components/overview/overview-top-devices.tsx b/apps/dashboard/src/components/overview/overview-top-devices.tsx index 5a998af6..6dfc63e9 100644 --- a/apps/dashboard/src/components/overview/overview-top-devices.tsx +++ b/apps/dashboard/src/components/overview/overview-top-devices.tsx @@ -7,7 +7,7 @@ import { cn } from '@/utils/cn'; import { NOT_SET_VALUE } from '@openpanel/constants'; import type { IChartType } from '@openpanel/validation'; -import { LazyChart } from '../report/chart/LazyChart'; +import { ReportChart } from '../report-chart'; import { Widget, WidgetBody } from '../widget'; import { OverviewChartToggle } from './overview-chart-toggle'; import OverviewDetailsButton from './overview-details-button'; @@ -31,238 +31,258 @@ export default function OverviewTopDevices({ title: 'Top devices', btn: 'Devices', chart: { - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'user', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'device', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top devices', - range: range, - previous: previous, - metric: 'sum', + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'user', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'device', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top devices', + range: range, + previous: previous, + metric: 'sum', + }, }, }, browser: { title: 'Top browser', btn: 'Browser', chart: { - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'user', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'browser', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top browser', - range: range, - previous: previous, - metric: 'sum', + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'user', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'browser', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top browser', + range: range, + previous: previous, + metric: 'sum', + }, }, }, browser_version: { title: 'Top Browser Version', btn: 'Browser Version', chart: { - renderSerieName(name) { - return name[1] || NOT_SET_VALUE; + options: { + renderSerieName(name) { + return name[1] || NOT_SET_VALUE; + }, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'user', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'browser', + }, + { + id: 'B', + name: 'browser_version', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top Browser Version', + range: range, + previous: previous, + metric: 'sum', }, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'user', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'browser', - }, - { - id: 'B', - name: 'browser_version', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top Browser Version', - range: range, - previous: previous, - metric: 'sum', }, }, os: { title: 'Top OS', btn: 'OS', chart: { - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'user', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'os', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top OS', - range: range, - previous: previous, - metric: 'sum', + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'user', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'os', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top OS', + range: range, + previous: previous, + metric: 'sum', + }, }, }, os_version: { title: 'Top OS version', btn: 'OS Version', chart: { - renderSerieName(name) { - return name[1] || NOT_SET_VALUE; + options: { + renderSerieName(name) { + return name[1] || NOT_SET_VALUE; + }, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'user', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'os', + }, + { + id: 'B', + name: 'os_version', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top OS version', + range: range, + previous: previous, + metric: 'sum', }, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'user', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'os', - }, - { - id: 'B', - name: 'os_version', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top OS version', - range: range, - previous: previous, - metric: 'sum', }, }, brands: { title: 'Top Brands', btn: 'Brands', chart: { - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'user', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'brand', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top Brands', - range: range, - previous: previous, - metric: 'sum', + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'user', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'brand', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top Brands', + range: range, + previous: previous, + metric: 'sum', + }, }, }, models: { title: 'Top Models', btn: 'Models', chart: { - renderSerieName(name) { - return name[1] || NOT_SET_VALUE; + options: { + renderSerieName(name) { + return name[1] || NOT_SET_VALUE; + }, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'user', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'brand', + }, + { + id: 'B', + name: 'model', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top Models', + range: range, + previous: previous, + metric: 'sum', }, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'user', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'brand', - }, - { - id: 'B', - name: 'model', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top Models', - range: range, - previous: previous, - metric: 'sum', }, }, }); @@ -285,33 +305,38 @@ export default function OverviewTopDevices({ - { - switch (widget.key) { - case 'devices': - setFilter('device', item.names[0]); - break; - case 'browser': - setFilter('browser', item.names[0]); - break; - case 'browser_version': - setFilter('browser_version', item.names[1]); - break; - case 'os': - setFilter('os', item.names[0]); - break; - case 'os_version': - setFilter('os_version', item.names[1]); - break; - } + { + switch (widget.key) { + case 'devices': + setFilter('device', item.names[0]); + break; + case 'browser': + setFilter('browser', item.names[0]); + break; + case 'browser_version': + setFilter('browser_version', item.names[1]); + break; + case 'os': + setFilter('os', item.names[0]); + break; + case 'os_version': + setFilter('os_version', item.names[1]); + break; + } + }, + }} + report={{ + ...widget.chart.report, + previous: false, }} /> - + 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 ac6ba4ae..642cd56d 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,7 +1,7 @@ 'use client'; import { useState } from 'react'; -import { LazyChart } from '@/components/report/chart/LazyChart'; +import { ReportChart } from '@/components/report-chart'; import { useEventQueryFilters } from '@/hooks/useEventQueryFilters'; import { cn } from '@/utils/cn'; @@ -31,70 +31,74 @@ export default function OverviewTopEvents({ title: 'Top events', btn: 'Your', chart: { - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters: [ - ...filters, - { - id: 'ex_session', - name: 'name', - operator: 'isNot', - value: ['session_start', 'session_end', 'screen_view'], - }, - ], - id: 'A', - name: '*', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'name', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Your top events', - range: range, - previous: previous, - metric: 'sum', + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters: [ + ...filters, + { + id: 'ex_session', + name: 'name', + operator: 'isNot', + value: ['session_start', 'session_end', 'screen_view'], + }, + ], + id: 'A', + name: '*', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'name', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Your top events', + range: range, + previous: previous, + metric: 'sum', + }, }, }, all: { title: 'Top events', btn: 'All', chart: { - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters: [...filters], - id: 'A', - name: '*', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'name', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'All top events', - range: range, - previous: previous, - metric: 'sum', + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters: [...filters], + id: 'A', + name: '*', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'name', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'All top events', + range: range, + previous: previous, + metric: 'sum', + }, }, }, conversions: { @@ -102,39 +106,41 @@ export default function OverviewTopEvents({ btn: 'Conversions', hide: conversions.length === 0, chart: { - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters: [ - ...filters, - { - id: 'conversion', - name: 'name', - operator: 'is', - value: conversions, - }, - ], - id: 'A', - name: '*', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'name', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Conversions', - range: range, - previous: previous, - metric: 'sum', + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters: [ + ...filters, + { + id: 'conversion', + name: 'name', + operator: 'is', + value: conversions, + }, + ], + id: 'A', + name: '*', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'name', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Conversions', + range: range, + previous: previous, + metric: 'sum', + }, }, }, }); @@ -159,10 +165,16 @@ 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 375da2a7..84e1a566 100644 --- a/apps/dashboard/src/components/overview/overview-top-geo.tsx +++ b/apps/dashboard/src/components/overview/overview-top-geo.tsx @@ -1,7 +1,6 @@ 'use client'; import { useState } from 'react'; -import { ChartRoot } from '@/components/report/chart'; import { useEventQueryFilters } from '@/hooks/useEventQueryFilters'; import { getCountry } from '@/translations/countries'; import { cn } from '@/utils/cn'; @@ -9,7 +8,7 @@ import { cn } from '@/utils/cn'; import { NOT_SET_VALUE } from '@openpanel/constants'; import type { IChartType } from '@openpanel/validation'; -import { LazyChart } from '../report/chart/LazyChart'; +import { ReportChart } from '../report-chart'; import { Widget, WidgetBody } from '../widget'; import { OverviewChartToggle } from './overview-chart-toggle'; import OverviewDetailsButton from './overview-details-button'; @@ -31,110 +30,122 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) { title: 'Top countries', btn: 'Countries', chart: { - renderSerieName(name) { - return getCountry(name[0]) || NOT_SET_VALUE; + options: { + renderSerieName(name) { + return getCountry(name[0]) || NOT_SET_VALUE; + }, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'country', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top countries', + range: range, + previous: previous, + metric: 'sum', }, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'country', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top countries', - range: range, - previous: previous, - metric: 'sum', }, }, regions: { title: 'Top regions', btn: 'Regions', chart: { - renderSerieName(name) { - return name[1] || NOT_SET_VALUE; + options: { + renderSerieName(name) { + return name[1] || NOT_SET_VALUE; + }, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'country', + }, + { + id: 'B', + name: 'region', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top regions', + range: range, + previous: previous, + metric: 'sum', }, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'country', - }, - { - id: 'B', - name: 'region', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top regions', - range: range, - previous: previous, - metric: 'sum', }, }, cities: { title: 'Top cities', btn: 'Cities', chart: { - renderSerieName(name) { - return name[1] || NOT_SET_VALUE; + options: { + renderSerieName(name) { + return name[1] || NOT_SET_VALUE; + }, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters, + id: 'A', + name: isPageFilter ? 'screen_view' : 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'country', + }, + { + id: 'B', + name: 'city', + }, + ], + chartType, + lineType: 'monotone', + interval: interval, + name: 'Top cities', + range: range, + previous: previous, + metric: 'sum', }, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters, - id: 'A', - name: isPageFilter ? 'screen_view' : 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'country', - }, - { - id: 'B', - name: 'city', - }, - ], - chartType, - lineType: 'monotone', - interval: interval, - name: 'Top cities', - range: range, - previous: previous, - metric: 'sum', }, }, }); @@ -157,29 +168,34 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) { - { - switch (widget.key) { - case 'countries': - setWidget('regions'); - setFilter('country', item.names[0]); - break; - case 'regions': - setWidget('cities'); - setFilter('region', item.names[1]); - break; - case 'cities': - setFilter('city', item.names[1]); - break; - } + { + switch (widget.key) { + case 'countries': + setWidget('regions'); + setFilter('country', item.names[0]); + break; + case 'regions': + setWidget('cities'); + setFilter('region', item.names[1]); + break; + case 'cities': + setFilter('city', item.names[1]); + break; + } + }, + ...widget.chart.options, + }} + report={{ + ...widget.chart.report, + previous: false, }} /> - + @@ -188,9 +204,9 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
Map
- { if (domain) { + if (names[0] === NOT_SET_VALUE) { + return names[1]; + } + return names.join(''); } return ( @@ -44,108 +48,120 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) { title: 'Top pages', btn: 'Top pages', chart: { - renderSerieName, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters, - id: 'A', - name: 'screen_view', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'origin', - }, - { - id: 'B', - name: 'path', - }, - ], - chartType, - lineType: 'monotone', - interval, - name: 'Top pages', - range, - previous, - metric: 'sum', + options: { + renderSerieName, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters, + id: 'A', + name: 'screen_view', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'origin', + }, + { + id: 'B', + name: 'path', + }, + ], + chartType, + lineType: 'monotone', + interval, + name: 'Top pages', + range, + previous, + metric: 'sum', + }, }, }, entries: { title: 'Entry Pages', btn: 'Entries', chart: { - renderSerieName, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters, - id: 'A', - name: 'session_start', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'origin', - }, - { - id: 'B', - name: 'path', - }, - ], - chartType, - lineType: 'monotone', - interval, - name: 'Entry Pages', - range, - previous, - metric: 'sum', + options: { + renderSerieName, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters, + id: 'A', + name: 'session_start', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'origin', + }, + { + id: 'B', + name: 'path', + }, + ], + chartType, + lineType: 'monotone', + interval, + name: 'Entry Pages', + range, + previous, + metric: 'sum', + }, }, }, exits: { title: 'Exit Pages', btn: 'Exits', chart: { - renderSerieName, - limit: 10, - projectId, - startDate, - endDate, - events: [ - { - segment: 'event', - filters, - id: 'A', - name: 'session_end', - }, - ], - breakdowns: [ - { - id: 'A', - name: 'origin', - }, - { - id: 'B', - name: 'path', - }, - ], - chartType, - lineType: 'monotone', - interval, - name: 'Exit Pages', - range, - previous, - metric: 'sum', + options: { + renderSerieName, + }, + report: { + limit: 10, + projectId, + startDate, + endDate, + events: [ + { + segment: 'event', + filters, + id: 'A', + name: 'session_end', + }, + ], + breakdowns: [ + { + id: 'A', + name: 'origin', + }, + { + id: 'B', + name: 'path', + }, + ], + chartType, + lineType: 'monotone', + interval, + name: 'Exit Pages', + range, + previous, + metric: 'sum', + }, }, }, bot: { @@ -177,32 +193,37 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) { {widget.key === 'bot' ? ( ) : ( - [ - { - title: 'Visit page', - icon: ExternalLinkIcon, - onClick: () => { - window.open(serie.names.join(''), '_blank'); + [ + { + title: 'Visit page', + icon: ExternalLinkIcon, + onClick: () => { + window.open(serie.names.join(''), '_blank'); + }, }, - }, - { - title: 'Set filter', - icon: FilterIcon, - onClick: () => { - setFilter('path', serie.names[1]); + { + title: 'Set filter', + icon: FilterIcon, + onClick: () => { + setFilter('path', serie.names[1]); + }, }, - }, - ]} + ], + ...widget.chart.options, + }} + report={{ + ...widget.chart.report, + previous: false, + }} /> )} - {widget.chart?.name && ( + {widget.chart?.report?.name && ( - +
-