All files / publisher/hooks useActiveDeviceMetrics.ts

96% Statements 48/50
76.47% Branches 13/17
100% Functions 8/8
95.83% Lines 46/48

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 133 134 135 136 137 138 139                      23x     8x           23x   8x 8x     23x 8x 8x   8x 8x       7x   1x           8x 8x 15x             8x   8x     23x 15x 1x 1x                     14x 14x     23x 8x 8x   8x   8x   8x 15x   15x   15x   15x 7x   7x   7x                 15x 11x 11x       11x     15x   15x 12x       8x         8x                 23x        
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();
 
    const daysWithoutData = [];
 
    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;
 
      if (data.days_without_data) {
        daysWithoutData.push(...data.days_without_data);
      }
    }
 
    const resultArray = Array.from(series.entries()).map(([key, value]) => ({
      name: key,
      values: value,
    }));
 
    return {
      activeDevices: {
        buckets,
        series: resultArray,
      },
      daysWithoutData,
    };
  };
 
  return { status, data, isFetching };
}
 
export default useActiveDeviceMetrics;