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                      25x     10x           25x   10x 10x     25x 10x 10x   10x 10x       9x   1x           10x 10x 17x             10x   10x     25x 17x 1x 1x                     16x 16x     25x 10x 10x   10x   10x 17x   17x   17x   17x 7x   7x   7x                 17x 12x 12x       12x     17x     10x         10x               25x        
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;