All files / publisher/hooks useActiveDeviceMetrics.ts

95.74% Statements 45/47
73.33% Branches 11/15
100% Functions 8/8
95.55% Lines 43/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132                      11x     3x           11x   3x 3x     11x 3x 3x   3x 3x       2x   1x           3x 3x 10x             3x   3x     11x 10x 1x 1x                     9x 9x     11x 3x 3x   3x   3x 10x   10x   10x   10x 7x   7x   7x                 10x 9x 9x       9x     10x     3x         3x               11x        
import { useQuery } from "react-query";
 
function useActiveDeviceMetrics({
  snapId,
  period,
  type,
}: {
  snapId: string | undefined;
  period: string;
  type: string;
}) {
  const { status, data, isFetching } = useQuery({
    queryKey: ["activeDeviceMetrics", snapId, period, type],
    queryFn: async () => {
      return await fetchData();
    },
    retry: 0,
    refetchOnWindowFocus: false,
  });
 
  const parsePeriod = (period: string) => {
    /* eslint-disable @typescript-eslint/no-unused-vars */
    const [_, periodLength, periodTime] = period.trim().split(/(\d+)/);
    return { periodLength: +periodLength, periodTime };
  };
 
  const fetchData = async () => {
    const { periodTime, periodLength } = parsePeriod(period);
    const pagePeriodLengthInMonths = 3;
 
    let totalPage = 1;
    if (
      periodTime === "d" ||
      (periodTime === "m" && periodLength <= pagePeriodLengthInMonths)
    ) {
      totalPage = 1;
    } else {
      totalPage =
        periodTime === "y"
          ? Math.floor((periodLength * 12) / pagePeriodLengthInMonths)
          : Math.floor(periodLength / pagePeriodLengthInMonths);
    }
 
    const responses = [];
    for (let i = 1; i <= totalPage; i++) {
      responses.push(
        fetch(
          `/${snapId}/metrics/active-devices?active-devices=${type}&period=${period}&page=${i}&page-length=${pagePeriodLengthInMonths}`,
        ),
      );
    }
 
    const results = await Promise.all(responses);
 
    return await formatData(results);
  };
 
  const handleResponse = async (response: Response) => {
    if (!response.ok) {
      if (response.status === 404) {
        return {
          active_devices: {
            buckets: [],
            series: [],
          },
        };
      } else E{
        throw new Error("Unable to fetch latest active device information");
      }
    }
 
    const data = await response.json();
    return data;
  };
 
  const formatData = async (results: Response[]) => {
    const buckets = [];
    const series = new Map();
 
    let seriesThatAreAddedBefore = 0;
 
    for (const result of results.reverse()) {
      const data = await handleResponse(result);
 
      const activeDeviceBuckets = data.active_devices.buckets;
 
      buckets.push(...activeDeviceBuckets);
      // fill the array with 0's if the batch doesnt have that previous series
      for (const seriesKey of series.keys()) {
        const seriesExistInBatch = data.active_devices.series.find(
          (activeDeviceSeries: { name: string }) =>
            activeDeviceSeries.name === seriesKey,
        );
        Iif (!seriesExistInBatch) {
          series.set(seriesKey, [
            ...series.get(seriesKey),
            ...new Array(activeDeviceBuckets.length).fill(0),
          ]);
        }
      }
 
      // fill the array with 0's if new series introduced in the batch
      for (const activeDeviceSeries of data.active_devices.series) {
        const key = activeDeviceSeries.name;
        const prevData = series.has(key)
          ? series.get(key)
          : new Array(seriesThatAreAddedBefore).fill(0);
 
        series.set(key, [...prevData, ...activeDeviceSeries.values]);
      }
 
      seriesThatAreAddedBefore += activeDeviceBuckets.length;
    }
 
    const resultArray = Array.from(series.entries()).map(([key, value]) => ({
      name: key,
      values: value,
    }));
 
    return {
      activeDevices: {
        buckets,
        series: resultArray,
      },
    };
  };
 
  return { status, data, isFetching };
}
 
export default useActiveDeviceMetrics;