refactor: refactor chart render and perf pageview data handle logic

This commit is contained in:
moonrailgun 2024-02-23 00:38:18 +08:00
parent e79c4b4819
commit 4fe61a6d7c
2 changed files with 74 additions and 70 deletions

View File

@ -0,0 +1,46 @@
import { useMemo } from 'react';
import { useTheme } from '../hooks/useTheme';
import { DateUnit } from '@tianji/shared';
import React from 'react';
import { formatDate, formatDateWithUnit } from '../utils/date';
import { Column, ColumnConfig } from '@ant-design/charts';
export const TimeEventChart: React.FC<{
data: { x: string; y: number; type: string }[];
unit: DateUnit;
}> = React.memo((props) => {
const { colors } = useTheme();
const config = useMemo(
() =>
({
data: props.data,
isStack: true,
xField: 'x',
yField: 'y',
seriesField: 'type',
label: {
position: 'middle' as const,
style: {
fill: '#FFFFFF',
opacity: 0.6,
},
},
tooltip: {
title: (t) => formatDate(t),
},
color: [colors.chart.pv, colors.chart.uv],
xAxis: {
label: {
autoHide: true,
autoRotate: false,
formatter: (text) => formatDateWithUnit(text, props.unit),
},
},
} satisfies ColumnConfig),
[props.data, props.unit]
);
return <Column {...config} />;
});
TimeEventChart.displayName = 'TimeEventChart';

View File

@ -1,19 +1,12 @@
import { Button, message, Spin, Switch } from 'antd'; import { Button, message, Spin, Switch } from 'antd';
import React, { useMemo } from 'react'; import React from 'react';
import { Column, ColumnConfig } from '@ant-design/charts';
import { SyncOutlined } from '@ant-design/icons'; import { SyncOutlined } from '@ant-design/icons';
import { DateFilter } from '../DateFilter'; import { DateFilter } from '../DateFilter';
import { WebsiteInfo } from '../../api/model/website'; import { WebsiteInfo } from '../../api/model/website';
import { import { getDateArray } from '../../utils/date';
DateUnit,
formatDate,
formatDateWithUnit,
getDateArray,
} from '../../utils/date';
import { useEvent } from '../../hooks/useEvent'; import { useEvent } from '../../hooks/useEvent';
import { MetricCard } from './MetricCard'; import { MetricCard } from './MetricCard';
import { formatNumber, formatShortTime } from '../../utils/common'; import { formatNumber, formatShortTime } from '../../utils/common';
import { useTheme } from '../../hooks/useTheme';
import { WebsiteOnlineCount } from './WebsiteOnlineCount'; import { WebsiteOnlineCount } from './WebsiteOnlineCount';
import { useGlobalRangeDate } from '../../hooks/useGlobalRangeDate'; import { useGlobalRangeDate } from '../../hooks/useGlobalRangeDate';
import { MonitorHealthBar } from '../monitor/MonitorHealthBar'; import { MonitorHealthBar } from '../monitor/MonitorHealthBar';
@ -22,6 +15,7 @@ import { AppRouterOutput, trpc } from '../../api/trpc';
import { getUserTimezone } from '../../api/model/user'; import { getUserTimezone } from '../../api/model/user';
import { useGlobalStateStore } from '../../store/global'; import { useGlobalStateStore } from '../../store/global';
import { useTranslation } from '@i18next-toolkit/react'; import { useTranslation } from '@i18next-toolkit/react';
import { TimeEventChart } from '../TimeEventChart';
export const WebsiteOverview: React.FC<{ export const WebsiteOverview: React.FC<{
website: WebsiteInfo; website: WebsiteInfo;
@ -37,18 +31,32 @@ export const WebsiteOverview: React.FC<{
); );
const { const {
data, data: chartData = [],
isLoading: isLoadingPageview, isLoading: isLoadingPageview,
refetch: refetchPageview, refetch: refetchPageview,
} = trpc.website.pageviews.useQuery({ } = trpc.website.pageviews.useQuery(
{
workspaceId: website.workspaceId, workspaceId: website.workspaceId,
websiteId: website.id, websiteId: website.id,
startAt: startDate.valueOf(), startAt: startDate.valueOf(),
endAt: endDate.valueOf(), endAt: endDate.valueOf(),
unit, unit,
}); },
const pageviews = data?.pageviews ?? []; {
const sessions = data?.sessions ?? []; select(data) {
const pageviews = data.pageviews ?? [];
const sessions = data.sessions ?? [];
const pageviewsArr = getDateArray(pageviews, startDate, endDate, unit);
const sessionsArr = getDateArray(sessions, startDate, endDate, unit);
return [
...pageviewsArr.map((item) => ({ ...item, type: 'pageview' })),
...sessionsArr.map((item) => ({ ...item, type: 'session' })),
];
},
}
);
const { const {
data: stats, data: stats,
@ -71,16 +79,6 @@ export const WebsiteOverview: React.FC<{
message.success(t('Refreshed')); message.success(t('Refreshed'));
}); });
const chartData = useMemo(() => {
const pageviewsArr = getDateArray(pageviews, startDate, endDate, unit);
const sessionsArr = getDateArray(sessions, startDate, endDate, unit);
return [
...pageviewsArr.map((item) => ({ ...item, type: 'pageview' })),
...sessionsArr.map((item) => ({ ...item, type: 'session' })),
];
}, [pageviews, sessions, unit]);
const loading = isLoadingPageview || isLoadingStats; const loading = isLoadingPageview || isLoadingStats;
return ( return (
@ -145,7 +143,7 @@ export const WebsiteOverview: React.FC<{
</div> </div>
<div> <div>
<StatsChart data={chartData} unit={unit} /> <TimeEventChart data={chartData} unit={unit} />
</div> </div>
</Spin> </Spin>
); );
@ -216,43 +214,3 @@ export const MetricsBar: React.FC<{
); );
}); });
MetricsBar.displayName = 'MetricsBar'; MetricsBar.displayName = 'MetricsBar';
export const StatsChart: React.FC<{
data: { x: string; y: number; type: string }[];
unit: DateUnit;
}> = React.memo((props) => {
const { colors } = useTheme();
const config = useMemo(
() =>
({
data: props.data,
isStack: true,
xField: 'x',
yField: 'y',
seriesField: 'type',
label: {
position: 'middle' as const,
style: {
fill: '#FFFFFF',
opacity: 0.6,
},
},
tooltip: {
title: (t) => formatDate(t),
},
color: [colors.chart.pv, colors.chart.uv],
xAxis: {
label: {
autoHide: true,
autoRotate: false,
formatter: (text) => formatDateWithUnit(text, props.unit),
},
},
} satisfies ColumnConfig),
[props.data, props.unit]
);
return <Column {...config} />;
});
StatsChart.displayName = 'StatsChart';