multiple breakpoints
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
useEventQueryFilters,
|
||||
useEventQueryNamesFilter,
|
||||
} from '@/hooks/useEventQueryFilters';
|
||||
import { getPropertyLabel } from '@/translations/properties';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { X } from 'lucide-react';
|
||||
import type { Options as NuqsOptions } from 'nuqs';
|
||||
@@ -47,7 +48,7 @@ export function OverviewFiltersButtons({
|
||||
icon={X}
|
||||
onClick={() => setFilter(filter.name, filter.value[0], 'is')}
|
||||
>
|
||||
<span className="mr-1">{filter.name} is</span>
|
||||
<span className="mr-1">{getPropertyLabel(filter.name)} is</span>
|
||||
<strong>{filter.value[0]}</strong>
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useOverviewOptions } from '@/components/overview/useOverviewOptions';
|
||||
import { ChartSwitch } from '@/components/report/chart';
|
||||
import { ChartRoot } from '@/components/report/chart';
|
||||
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
@@ -205,7 +205,7 @@ export default function OverviewMetrics({ projectId }: OverviewMetricsProps) {
|
||||
setMetric(index);
|
||||
}}
|
||||
>
|
||||
<ChartSwitch hideID {...report} />
|
||||
<ChartRoot hideID {...report} />
|
||||
</button>
|
||||
))}
|
||||
<div
|
||||
@@ -217,7 +217,7 @@ export default function OverviewMetrics({ projectId }: OverviewMetricsProps) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="card col-span-6 p-4">
|
||||
<ChartSwitch
|
||||
<ChartRoot
|
||||
key={selectedMetric.id}
|
||||
hideID
|
||||
{...selectedMetric}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useState } from 'react';
|
||||
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { NOT_SET_VALUE } from '@openpanel/constants';
|
||||
import type { IChartType } from '@openpanel/validation';
|
||||
|
||||
import { LazyChart } from '../report/chart/LazyChart';
|
||||
@@ -51,7 +52,7 @@ export default function OverviewTopDevices({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top devices',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -82,7 +83,7 @@ export default function OverviewTopDevices({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top browser',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -92,6 +93,9 @@ export default function OverviewTopDevices({
|
||||
title: 'Top Browser Version',
|
||||
btn: 'Browser Version',
|
||||
chart: {
|
||||
renderSerieName(name) {
|
||||
return name[1] || NOT_SET_VALUE;
|
||||
},
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -107,13 +111,17 @@ export default function OverviewTopDevices({
|
||||
breakdowns: [
|
||||
{
|
||||
id: 'A',
|
||||
name: 'browser',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
name: 'browser_version',
|
||||
},
|
||||
],
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top Browser Version',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -144,7 +152,7 @@ export default function OverviewTopDevices({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top OS',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -154,6 +162,9 @@ export default function OverviewTopDevices({
|
||||
title: 'Top OS version',
|
||||
btn: 'OS Version',
|
||||
chart: {
|
||||
renderSerieName(name) {
|
||||
return name[1] || NOT_SET_VALUE;
|
||||
},
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -169,13 +180,17 @@ export default function OverviewTopDevices({
|
||||
breakdowns: [
|
||||
{
|
||||
id: 'A',
|
||||
name: 'os',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
name: 'os_version',
|
||||
},
|
||||
],
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top OS version',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -211,19 +226,19 @@ export default function OverviewTopDevices({
|
||||
onClick={(item) => {
|
||||
switch (widget.key) {
|
||||
case 'devices':
|
||||
setFilter('device', item.name);
|
||||
setFilter('device', item.names[0]);
|
||||
break;
|
||||
case 'browser':
|
||||
setFilter('browser', item.name);
|
||||
setFilter('browser', item.names[0]);
|
||||
break;
|
||||
case 'browser_version':
|
||||
setFilter('browser_version', item.name);
|
||||
setFilter('browser_version', item.names[1]);
|
||||
break;
|
||||
case 'os':
|
||||
setFilter('os', item.name);
|
||||
setFilter('os', item.names[0]);
|
||||
break;
|
||||
case 'os_version':
|
||||
setFilter('os_version', item.name);
|
||||
setFilter('os_version', item.names[1]);
|
||||
break;
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -60,7 +60,7 @@ export default function OverviewTopEvents({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Your top events',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -91,7 +91,7 @@ export default function OverviewTopEvents({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'All top events',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -131,7 +131,7 @@ export default function OverviewTopEvents({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Conversions',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { ChartSwitch } from '@/components/report/chart';
|
||||
import { ChartRoot } from '@/components/report/chart';
|
||||
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
|
||||
import { getCountry } from '@/translations/countries';
|
||||
import { cn } from '@/utils/cn';
|
||||
|
||||
import { NOT_SET_VALUE } from '@openpanel/constants';
|
||||
import type { IChartType } from '@openpanel/validation';
|
||||
|
||||
import { LazyChart } from '../report/chart/LazyChart';
|
||||
@@ -29,6 +31,9 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
title: 'Top countries',
|
||||
btn: 'Countries',
|
||||
chart: {
|
||||
renderSerieName(name) {
|
||||
return getCountry(name[0]) || NOT_SET_VALUE;
|
||||
},
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -50,7 +55,7 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top countries',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -60,6 +65,9 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
title: 'Top regions',
|
||||
btn: 'Regions',
|
||||
chart: {
|
||||
renderSerieName(name) {
|
||||
return name[1] || NOT_SET_VALUE;
|
||||
},
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -75,13 +83,17 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
breakdowns: [
|
||||
{
|
||||
id: 'A',
|
||||
name: 'country',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
name: 'region',
|
||||
},
|
||||
],
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top regions',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -91,6 +103,9 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
title: 'Top cities',
|
||||
btn: 'Cities',
|
||||
chart: {
|
||||
renderSerieName(name) {
|
||||
return name[1] || NOT_SET_VALUE;
|
||||
},
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -106,13 +121,17 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
breakdowns: [
|
||||
{
|
||||
id: 'A',
|
||||
name: 'country',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
name: 'city',
|
||||
},
|
||||
],
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top cities',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -149,14 +168,14 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
switch (widget.key) {
|
||||
case 'countries':
|
||||
setWidget('regions');
|
||||
setFilter('country', item.name);
|
||||
setFilter('country', item.names[0]);
|
||||
break;
|
||||
case 'regions':
|
||||
setWidget('cities');
|
||||
setFilter('region', item.name);
|
||||
setFilter('region', item.names[1]);
|
||||
break;
|
||||
case 'cities':
|
||||
setFilter('city', item.name);
|
||||
setFilter('city', item.names[1]);
|
||||
break;
|
||||
}
|
||||
}}
|
||||
@@ -169,7 +188,7 @@ export default function OverviewTopGeo({ projectId }: OverviewTopGeoProps) {
|
||||
<div className="title">Map</div>
|
||||
</WidgetHead>
|
||||
<WidgetBody>
|
||||
<ChartSwitch
|
||||
<ChartRoot
|
||||
hideID
|
||||
{...{
|
||||
projectId,
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
import { useState } from 'react';
|
||||
import { useEventQueryFilters } from '@/hooks/useEventQueryFilters';
|
||||
import { cn } from '@/utils/cn';
|
||||
import { ExternalLinkIcon, FilterIcon } from 'lucide-react';
|
||||
|
||||
import { NOT_SET_VALUE } from '@openpanel/constants';
|
||||
import type { IChartType } from '@openpanel/validation';
|
||||
|
||||
import { LazyChart } from '../report/chart/LazyChart';
|
||||
import { Tooltiper } from '../ui/tooltip';
|
||||
import { Widget, WidgetBody } from '../widget';
|
||||
import { OverviewChartToggle } from './overview-chart-toggle';
|
||||
import OverviewDetailsButton from './overview-details-button';
|
||||
@@ -23,11 +26,19 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
useOverviewOptions();
|
||||
const [chartType, setChartType] = useState<IChartType>('bar');
|
||||
const [filters, setFilter] = useEventQueryFilters();
|
||||
const renderSerieName = (names: string[]) => {
|
||||
return (
|
||||
<Tooltiper content={names.join('')} side="left" className="text-left">
|
||||
{names[1] || NOT_SET_VALUE}
|
||||
</Tooltiper>
|
||||
);
|
||||
};
|
||||
const [widget, setWidget, widgets] = useOverviewWidget('pages', {
|
||||
top: {
|
||||
title: 'Top pages',
|
||||
btn: 'Top pages',
|
||||
chart: {
|
||||
renderSerieName,
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -43,13 +54,17 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
breakdowns: [
|
||||
{
|
||||
id: 'A',
|
||||
name: 'origin',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
name: 'path',
|
||||
},
|
||||
],
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top pages',
|
||||
range,
|
||||
previous,
|
||||
metric: 'sum',
|
||||
@@ -59,6 +74,7 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
title: 'Entry Pages',
|
||||
btn: 'Entries',
|
||||
chart: {
|
||||
renderSerieName,
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -74,13 +90,17 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
breakdowns: [
|
||||
{
|
||||
id: 'A',
|
||||
name: 'origin',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
name: 'path',
|
||||
},
|
||||
],
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval,
|
||||
name: 'Top sources',
|
||||
name: 'Entry Pages',
|
||||
range,
|
||||
previous,
|
||||
metric: 'sum',
|
||||
@@ -90,6 +110,7 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
title: 'Exit Pages',
|
||||
btn: 'Exits',
|
||||
chart: {
|
||||
renderSerieName,
|
||||
limit: 10,
|
||||
projectId,
|
||||
startDate,
|
||||
@@ -105,13 +126,17 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
breakdowns: [
|
||||
{
|
||||
id: 'A',
|
||||
name: 'origin',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
name: 'path',
|
||||
},
|
||||
],
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval,
|
||||
name: 'Top sources',
|
||||
name: 'Exit Pages',
|
||||
range,
|
||||
previous,
|
||||
metric: 'sum',
|
||||
@@ -153,9 +178,22 @@ export default function OverviewTopPages({ projectId }: OverviewTopPagesProps) {
|
||||
hideID
|
||||
{...widget.chart}
|
||||
previous={false}
|
||||
onClick={(item) => {
|
||||
setFilter('path', item.name);
|
||||
}}
|
||||
dropdownMenuContent={(serie) => [
|
||||
{
|
||||
title: 'Visit page',
|
||||
icon: ExternalLinkIcon,
|
||||
onClick: () => {
|
||||
window.open(serie.names.join(''), '_blank');
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Set filter',
|
||||
icon: FilterIcon,
|
||||
onClick: () => {
|
||||
setFilter('path', serie.names[1]);
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
{widget.chart?.name && <OverviewDetailsButton chart={widget.chart} />}
|
||||
|
||||
@@ -53,7 +53,7 @@ export default function OverviewTopSources({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top groups',
|
||||
name: 'Top sources',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -84,7 +84,7 @@ export default function OverviewTopSources({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'Top urls',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -146,7 +146,7 @@ export default function OverviewTopSources({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'UTM Source',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -177,7 +177,7 @@ export default function OverviewTopSources({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'UTM Medium',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -208,7 +208,7 @@ export default function OverviewTopSources({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'UTM Campaign',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -239,7 +239,7 @@ export default function OverviewTopSources({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'UTM Term',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -270,7 +270,7 @@ export default function OverviewTopSources({
|
||||
chartType,
|
||||
lineType: 'monotone',
|
||||
interval: interval,
|
||||
name: 'Top sources',
|
||||
name: 'UTM Content',
|
||||
range: range,
|
||||
previous: previous,
|
||||
metric: 'sum',
|
||||
@@ -307,30 +307,30 @@ export default function OverviewTopSources({
|
||||
onClick={(item) => {
|
||||
switch (widget.key) {
|
||||
case 'all':
|
||||
setFilter('referrer_name', item.name);
|
||||
setFilter('referrer_name', item.names[0]);
|
||||
setWidget('domain');
|
||||
break;
|
||||
case 'domain':
|
||||
setFilter('referrer', item.name);
|
||||
setFilter('referrer', item.names[0]);
|
||||
break;
|
||||
case 'type':
|
||||
setFilter('referrer_type', item.name);
|
||||
setFilter('referrer_type', item.names[0]);
|
||||
setWidget('domain');
|
||||
break;
|
||||
case 'utm_source':
|
||||
setFilter('properties.__query.utm_source', item.name);
|
||||
setFilter('properties.__query.utm_source', item.names[0]);
|
||||
break;
|
||||
case 'utm_medium':
|
||||
setFilter('properties.__query.utm_medium', item.name);
|
||||
setFilter('properties.__query.utm_medium', item.names[0]);
|
||||
break;
|
||||
case 'utm_campaign':
|
||||
setFilter('properties.__query.utm_campaign', item.name);
|
||||
setFilter('properties.__query.utm_campaign', item.names[0]);
|
||||
break;
|
||||
case 'utm_term':
|
||||
setFilter('properties.__query.utm_term', item.name);
|
||||
setFilter('properties.__query.utm_term', item.names[0]);
|
||||
break;
|
||||
case 'utm_content':
|
||||
setFilter('properties.__query.utm_content', item.name);
|
||||
setFilter('properties.__query.utm_content', item.names[0]);
|
||||
break;
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { parseAsStringEnum, useQueryState } from 'nuqs';
|
||||
|
||||
import { mapKeys } from '@openpanel/validation';
|
||||
import type { IChartProps } from '@openpanel/validation';
|
||||
|
||||
import type { IChartRoot } from '../report/chart';
|
||||
|
||||
export function useOverviewWidget<T extends string>(
|
||||
key: string,
|
||||
widgets: Record<
|
||||
T,
|
||||
{ title: string; btn: string; chart: IChartProps; hide?: boolean }
|
||||
{ title: string; btn: string; chart: IChartRoot; hide?: boolean }
|
||||
>
|
||||
) {
|
||||
const keys = Object.keys(widgets) as T[];
|
||||
|
||||
Reference in New Issue
Block a user