diff --git a/packages/frontend/src/components/MkChart.vue b/packages/frontend/src/components/MkChart.vue index adb3c134ae96..85c10a2cf2fc 100644 --- a/packages/frontend/src/components/MkChart.vue +++ b/packages/frontend/src/components/MkChart.vue @@ -28,6 +28,7 @@ import { useChartTooltip } from '@/scripts/use-chart-tooltip.js'; import { chartVLine } from '@/scripts/chart-vline.js'; import { alpha } from '@/scripts/color.js'; import date from '@/filters/date.js'; +import bytes from '@/filters/bytes.js'; import { initChart } from '@/scripts/init-chart.js'; import { chartLegend } from '@/scripts/chart-legend.js'; import MkChartLegend from '@/components/MkChartLegend.vue'; @@ -95,7 +96,7 @@ const getColor = (i) => { }; const now = new Date(); -let chartInstance: Chart = null; +let chartInstance: Chart | null = null; let chartData: { series: { name: string; @@ -108,9 +109,10 @@ let chartData: { y: number; }[]; }[]; -} = null; + bytes?: boolean; +} | null = null; -const chartEl = shallowRef(null); +const chartEl = shallowRef(null); const fetching = ref(true); const getDate = (ago: number) => { @@ -132,6 +134,7 @@ const format = (arr) => { const { handler: externalTooltipHandler } = useChartTooltip(); const render = () => { + if (chartData == null || chartEl.value == null) return; if (chartInstance) { chartInstance.destroy(); } @@ -188,7 +191,6 @@ const render = () => { stacked: props.stacked, offset: false, time: { - stepSize: 1, unit: props.span === 'day' ? 'month' : 'day', displayFormats: { day: 'M/d', @@ -198,6 +200,7 @@ const render = () => { grid: { }, ticks: { + stepSize: 1, display: props.detailed, maxRotation: 0, autoSkipPadding: 16, @@ -237,6 +240,9 @@ const render = () => { duration: 0, }, external: externalTooltipHandler, + callbacks: { + label: (item) => chartData?.bytes ? bytes(item.parsed.y * 1000, 1) : item.parsed.y.toString(), + }, }, zoom: props.detailed ? { pan: { @@ -265,10 +271,9 @@ const render = () => { }, }, } : undefined, - gradient, }, }, - plugins: [chartVLine(vLineColor), ...(props.detailed ? [chartLegend(legendEl.value)] : [])], + plugins: [gradient, chartVLine(vLineColor), ...(props.detailed && legendEl.value ? [chartLegend(legendEl.value)] : [])], }); }; @@ -566,7 +571,7 @@ const fetchDriveFilesChart = async (): Promise => { }; const fetchInstanceRequestsChart = async (): Promise => { - const raw = await os.apiGet('charts/instance', { host: props.args.host, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span }); return { series: [{ name: 'In', @@ -588,7 +593,7 @@ const fetchInstanceRequestsChart = async (): Promise => { }; const fetchInstanceUsersChart = async (total: boolean): Promise => { - const raw = await os.apiGet('charts/instance', { host: props.args.host, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span }); return { series: [{ name: 'Users', @@ -603,7 +608,7 @@ const fetchInstanceUsersChart = async (total: boolean): Promise => { - const raw = await os.apiGet('charts/instance', { host: props.args.host, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span }); return { series: [{ name: 'Notes', @@ -618,7 +623,7 @@ const fetchInstanceNotesChart = async (total: boolean): Promise => { - const raw = await os.apiGet('charts/instance', { host: props.args.host, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span }); return { series: [{ name: 'Following', @@ -641,7 +646,7 @@ const fetchInstanceFfChart = async (total: boolean): Promise = }; const fetchInstanceDriveUsageChart = async (total: boolean): Promise => { - const raw = await os.apiGet('charts/instance', { host: props.args.host, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span }); return { bytes: true, series: [{ @@ -649,7 +654,7 @@ const fetchInstanceDriveUsageChart = async (total: boolean): Promise => { - const raw = await os.apiGet('charts/instance', { host: props.args.host, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/instance', { host: props.args?.host, limit: props.limit, span: props.span }); return { series: [{ name: 'Drive files', @@ -672,11 +677,11 @@ const fetchInstanceDriveFilesChart = async (total: boolean): Promise => { - const raw = await os.apiGet('charts/user/notes', { userId: props.args.user.id, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/user/notes', { userId: props.args?.user?.id, limit: props.limit, span: props.span }); return { - series: [...(props.args.withoutAll ? [] : [{ + series: [...(props.args?.withoutAll ? [] : [{ name: 'All', - type: 'line', + type: 'line' as const, data: format(sum(raw.inc, negate(raw.dec))), color: '#888888', }]), { @@ -704,7 +709,7 @@ const fetchPerUserNotesChart = async (): Promise => { }; const fetchPerUserPvChart = async (): Promise => { - const raw = await os.apiGet('charts/user/pv', { userId: props.args.user.id, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/user/pv', { userId: props.args?.user?.id, limit: props.limit, span: props.span }); return { series: [{ name: 'Unique PV (user)', @@ -731,7 +736,7 @@ const fetchPerUserPvChart = async (): Promise => { }; const fetchPerUserFollowingChart = async (): Promise => { - const raw = await os.apiGet('charts/user/following', { userId: props.args.user.id, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/user/following', { userId: props.args?.user?.id, limit: props.limit, span: props.span }); return { series: [{ name: 'Local', @@ -746,7 +751,7 @@ const fetchPerUserFollowingChart = async (): Promise => { }; const fetchPerUserFollowersChart = async (): Promise => { - const raw = await os.apiGet('charts/user/following', { userId: props.args.user.id, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/user/following', { userId: props.args?.user?.id, limit: props.limit, span: props.span }); return { series: [{ name: 'Local', @@ -761,8 +766,9 @@ const fetchPerUserFollowersChart = async (): Promise => { }; const fetchPerUserDriveChart = async (): Promise => { - const raw = await os.apiGet('charts/user/drive', { userId: props.args.user.id, limit: props.limit, span: props.span }); + const raw = await os.apiGet('charts/user/drive', { userId: props.args?.user?.id, limit: props.limit, span: props.span }); return { + bytes: true, series: [{ name: 'Inc', type: 'area', @@ -806,6 +812,8 @@ const fetchAndRender = async () => { case 'per-user-following': return fetchPerUserFollowingChart(); case 'per-user-followers': return fetchPerUserFollowersChart(); case 'per-user-drive': return fetchPerUserDriveChart(); + + default: return null; } }; fetching.value = true;