1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-09-28 17:55:15 +02:00
unleash.unleash/frontend/src/hooks/useTrafficData.ts
Thomas Heartman 2980c0de4e
refactor(1-3336): useTrafficData / NetworkTrafficUsage.tsx cleanup (#9191)
This PR refactors the `NetworkTrafficUsage.tsx` and `useTrafficData`
files a bit.

The primary objective was to make the network traffic usage component
easier to work with, so I suggest to the reviewer that they start there.

Part of that refactoring, was taking things out of the useTraffic hook
that didn't need to be there. In the end, I'd removed so much that I
didn't even need the hook itself in the new component, so I switched
that to a regular useState.

It made more sense to me to put some of the functions inside the hook
into a separate file and import them directly (because they don't rely
on any hook state), so I have done that and removed those functions from
the trafficData hook. In this case, I also moved the tests.

I have not added any new tests in this PR, but will do so in a
follow-up. The functions I intend to test have been marked as such.
2025-02-04 10:32:59 +01:00

172 lines
4.6 KiB
TypeScript

import type { ChartDatasetType } from 'component/admin/network/NetworkTrafficUsage/chart-functions';
import type { IInstanceTrafficMetricsResponse } from './api/getters/useInstanceTrafficMetrics/useInstanceTrafficMetrics';
import { useState } from 'react';
export type SelectablePeriod = {
key: string;
dayCount: number;
label: string;
year: number;
month: number;
};
export type EndpointInfo = {
label: string;
color: string;
order: number;
};
const endpointsInfo: Record<string, EndpointInfo> = {
'/api/admin': {
label: 'Admin',
color: '#6D66D9',
order: 1,
},
'/api/frontend': {
label: 'Frontend',
color: '#A39EFF',
order: 2,
},
'/api/client': {
label: 'Server',
color: '#D8D6FF',
order: 3,
},
};
const padMonth = (month: number): string => month.toString().padStart(2, '0');
export const toSelectablePeriod = (
date: Date,
label?: string,
): SelectablePeriod => {
const year = date.getFullYear();
const month = date.getMonth();
const period = `${year}-${padMonth(month + 1)}`;
const dayCount = new Date(year, month + 1, 0).getDate();
return {
key: period,
year,
month,
dayCount,
label:
label ||
date.toLocaleString('en-US', { month: 'long', year: 'numeric' }),
};
};
const currentDate = new Date(Date.now());
const currentPeriod = toSelectablePeriod(currentDate, 'Current month');
const getSelectablePeriods = (): SelectablePeriod[] => {
const selectablePeriods = [currentPeriod];
for (
let subtractMonthCount = 1;
subtractMonthCount < 13;
subtractMonthCount++
) {
// JavaScript wraps around the year, so we don't need to handle that.
const date = new Date(
currentDate.getFullYear(),
currentDate.getMonth() - subtractMonthCount,
1,
);
if (date > new Date('2024-03-31')) {
selectablePeriods.push(toSelectablePeriod(date));
}
}
return selectablePeriods;
};
const toPeriodsRecord = (
periods: SelectablePeriod[],
): Record<string, SelectablePeriod> => {
return periods.reduce(
(acc, period) => {
acc[period.key] = period;
return acc;
},
{} as Record<string, SelectablePeriod>,
);
};
const toChartData = (
days: number[],
traffic: IInstanceTrafficMetricsResponse,
endpointsInfo: Record<string, EndpointInfo>,
): ChartDatasetType[] => {
if (!traffic || !traffic.usage || !traffic.usage.apiData) {
return [];
}
const data = traffic.usage.apiData
.filter((item) => !!endpointsInfo[item.apiPath])
.sort(
(item1: any, item2: any) =>
endpointsInfo[item1.apiPath].order -
endpointsInfo[item2.apiPath].order,
)
.map((item: any) => {
const daysRec = days.reduce(
(acc, day: number) => {
acc[`d${day}`] = 0;
return acc;
},
{} as Record<string, number>,
);
for (const dayKey in item.days) {
const day = item.days[dayKey];
const dayNum = new Date(Date.parse(day.day)).getUTCDate();
daysRec[`d${dayNum}`] = day.trafficTypes[0].count;
}
const epInfo = endpointsInfo[item.apiPath];
return {
label: epInfo.label,
data: Object.values(daysRec),
backgroundColor: epInfo.color,
hoverBackgroundColor: epInfo.color,
};
});
return data;
};
const toTrafficUsageSum = (trafficData: ChartDatasetType[]): number => {
const data = trafficData.reduce(
(acc: number, current: ChartDatasetType) => {
return (
acc +
current.data.reduce(
(acc_inner, current_inner) => acc_inner + current_inner,
0,
)
);
},
0,
);
return data;
};
const getDayLabels = (dayCount: number): number[] => {
return [...Array(dayCount).keys()].map((i) => i + 1);
};
export const useTrafficDataEstimation = () => {
const selectablePeriods = getSelectablePeriods();
const record = toPeriodsRecord(selectablePeriods);
const [period, setPeriod] = useState<string>(selectablePeriods[0].key);
return {
record,
period,
setPeriod,
selectablePeriods,
getDayLabels,
currentPeriod,
toChartData,
toTrafficUsageSum,
endpointsInfo,
};
};