148 lines
3.4 KiB
TypeScript
Raw Normal View History

2022-03-11 11:20:52 +05:30
import { Chart, TimeUnit } from 'chart.js';
import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
import { GlobalReducer } from 'types/reducer/globalTime';
2022-03-11 13:39:04 +05:30
interface ITimeUnit {
[key: string]: TimeUnit;
}
interface IAxisTimeUintConfig {
2022-03-11 11:20:52 +05:30
unitName: TimeUnit;
multiplier: number;
}
interface IAxisTimeConfig {
unitName: TimeUnit;
stepSize: number;
}
export interface ITimeRange {
minTime: number | null;
maxTime: number | null;
}
2022-03-11 13:39:04 +05:30
export const TIME_UNITS: ITimeUnit = {
millisecond: 'millisecond',
second: 'second',
minute: 'minute',
hour: 'hour',
day: 'day',
week: 'week',
month: 'month',
year: 'year',
};
const TIME_UNITS_CONFIG: IAxisTimeUintConfig[] = [
2022-03-11 11:20:52 +05:30
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.millisecond,
2022-03-11 11:20:52 +05:30
multiplier: 1,
},
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.second,
2022-03-11 11:20:52 +05:30
multiplier: 1 / 1e3,
},
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.minute,
2022-03-11 11:20:52 +05:30
multiplier: 1 / (1e3 * 60),
},
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.hour,
2022-03-11 11:20:52 +05:30
multiplier: 1 / (1e3 * 60 * 60),
},
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.day,
2022-03-11 11:20:52 +05:30
multiplier: 1 / (1e3 * 60 * 60 * 24),
},
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.week,
2022-03-11 11:20:52 +05:30
multiplier: 1 / (1e3 * 60 * 60 * 24 * 7),
},
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.month,
2022-03-11 11:20:52 +05:30
multiplier: 1 / (1e3 * 60 * 60 * 24 * 30),
},
{
2022-03-11 13:39:04 +05:30
unitName: TIME_UNITS.year,
2022-03-11 11:20:52 +05:30
multiplier: 1 / (1e3 * 60 * 60 * 24 * 365),
},
];
2022-03-11 13:39:04 +05:30
/**
* Accepts Chart.js data's data-structure and returns the relevant time unit for the axis based on the range of the data.
*/
2022-03-11 11:20:52 +05:30
export const useXAxisTimeUnit = (data: Chart['data']): IAxisTimeConfig => {
2022-03-11 13:39:04 +05:30
// Local time is the time range inferred from the input chart data.
let localTime: ITimeRange | null;
try {
2022-03-11 11:20:52 +05:30
let minTime = Number.POSITIVE_INFINITY;
let maxTime = Number.NEGATIVE_INFINITY;
data?.labels?.forEach((timeStamp: string | number): void => {
if (typeof timeStamp === 'string') timeStamp = Date.parse(timeStamp);
2022-03-11 11:20:52 +05:30
minTime = Math.min(timeStamp, minTime);
maxTime = Math.max(timeStamp, maxTime);
});
localTime = {
minTime: minTime === Number.POSITIVE_INFINITY ? null : minTime,
maxTime: maxTime === Number.NEGATIVE_INFINITY ? null : maxTime,
};
2022-03-11 13:39:04 +05:30
} catch (error) {
localTime = null;
console.error(error);
2022-03-11 11:20:52 +05:30
}
2022-03-11 13:39:04 +05:30
// Global time is the time selected from the global time selector menu.
2022-03-11 11:20:52 +05:30
const globalTime = useSelector<AppState, GlobalReducer>(
(state) => state.globalTime,
);
2022-03-11 13:39:04 +05:30
// Use local time if valid else use the global time range
2022-03-11 11:20:52 +05:30
const { maxTime, minTime } = useMemo(() => {
if (localTime && localTime.maxTime && localTime.minTime) {
return {
minTime: localTime.minTime,
maxTime: localTime.maxTime,
};
} else {
return {
minTime: globalTime.minTime / 1e6,
maxTime: globalTime.maxTime / 1e6,
};
}
}, [globalTime, localTime]);
2022-03-11 13:39:04 +05:30
2022-03-11 11:20:52 +05:30
return convertTimeRange(minTime, maxTime);
};
2022-03-11 13:39:04 +05:30
/**
* Finds the relevant time unit based on the input time stamps (in ms)
*/
export const convertTimeRange = (
start: number,
end: number,
): IAxisTimeConfig => {
2022-03-11 11:20:52 +05:30
const MIN_INTERVALS = 6;
const range = end - start;
2022-03-11 13:39:04 +05:30
let relevantTimeUnit = TIME_UNITS_CONFIG[1];
2022-03-11 11:20:52 +05:30
let stepSize = 1;
2022-03-11 13:39:04 +05:30
try {
for (let idx = TIME_UNITS_CONFIG.length - 1; idx >= 0; idx--) {
const timeUnit = TIME_UNITS_CONFIG[idx];
const units = range * timeUnit.multiplier;
const steps = units / MIN_INTERVALS;
if (steps >= 1) {
relevantTimeUnit = timeUnit;
stepSize = steps;
break;
}
2022-03-11 11:20:52 +05:30
}
2022-03-11 13:39:04 +05:30
} catch (error) {
console.error(error);
2022-03-11 11:20:52 +05:30
}
return {
unitName: relevantTimeUnit.unitName,
stepSize: Math.floor(stepSize) || 1,
};
};