123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- import {createContext, useContext, useEffect, useState} from 'react';
- import * as Sentry from '@sentry/react';
- import {dropUndefinedKeys} from '@sentry/utils';
- import * as reactQuery from '@tanstack/react-query';
- import {ApiResult} from 'sentry/api';
- import type {Group, GroupStats, Organization, PageFilters} from 'sentry/types';
- import {getUtcDateString} from 'sentry/utils/dates';
- import {UseQueryResult} from 'sentry/utils/queryClient';
- import RequestError from 'sentry/utils/requestError/requestError';
- import useApi from 'sentry/utils/useApi';
- function getEndpointParams(
- p: Pick<GroupStatsProviderProps, 'selection' | 'period' | 'query' | 'groupIds'>
- ): StatEndpointParams {
- const params: StatEndpointParams = {
- project: p.selection.projects,
- environment: p.selection.environments,
- groupStatsPeriod: p.period,
- query: p.query,
- groups: p.groupIds,
- ...p.selection.datetime,
- };
- if (p.selection.datetime.period) {
- delete params.period;
- params.statsPeriod = p.selection.datetime.period;
- }
- if (params.end) {
- params.end = getUtcDateString(params.end);
- }
- if (params.start) {
- params.start = getUtcDateString(params.start);
- }
- return dropUndefinedKeys(params);
- }
- const GroupStatsContext = createContext<UseQueryResult<
- Record<string, GroupStats>
- > | null>(null);
- export function useGroupStats(group: Group): GroupStats {
- const ctx = useContext(GroupStatsContext);
- if (!ctx) {
- return group;
- }
- return ctx.data?.[group.id] ?? group;
- }
- interface StatEndpointParams extends Partial<PageFilters['datetime']> {
- environment: string[];
- groups: Group['id'][];
- project: number[];
- cursor?: string;
- expand?: string | string[];
- groupStatsPeriod?: string | null;
- page?: number | string;
- query?: string | undefined;
- sort?: string;
- statsPeriod?: string | null;
- }
- export type GroupStatsQuery = UseQueryResult<Record<string, GroupStats>, RequestError>;
- export interface GroupStatsProviderProps {
- children: React.ReactNode;
- groupIds: Group['id'][];
- organization: Organization;
- period: string;
- selection: PageFilters;
- onStatsQuery?: (query: GroupStatsQuery) => void;
- query?: string;
- }
- export function GroupStatsProvider(props: GroupStatsProviderProps) {
- const api = useApi();
- const [groupStats, setGroupStats] = useState<Record<string, GroupStats>>({});
- const queryFn = (): Promise<Record<string, GroupStats>> => {
- const promise = api
- .requestPromise<true>(`/organizations/${props.organization.slug}/issues-stats/`, {
- method: 'GET',
- query: getEndpointParams({
- selection: props.selection,
- period: props.period,
- query: props.query,
- groupIds: props.groupIds,
- }),
- includeAllArgs: true,
- })
- .then((resp: ApiResult<GroupStats[]>): Record<string, GroupStats> => {
- const map: Record<string, GroupStats> = {...groupStats};
- if (!resp || !Array.isArray(resp[0])) {
- return map;
- }
- for (const stat of resp[0]) {
- map[stat.id] = stat;
- }
- setGroupStats(map);
- return map;
- })
- .catch(e => {
- Sentry.captureException(e);
- return {};
- });
- return promise;
- };
- const statsQuery = reactQuery.useQuery<Record<string, GroupStats>, RequestError>(
- [
- `/organizations/${props.organization.slug}/issues-stats/`,
- props.selection,
- props.period,
- props.query,
- props.groupIds,
- ],
- queryFn,
- {
- enabled: props.groupIds.length > 0,
- staleTime: Infinity,
- }
- );
- const onStatsQuery = props.onStatsQuery;
- useEffect(() => {
- onStatsQuery?.(statsQuery);
- // We only want to fire the observer when the status changes
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [statsQuery.status, onStatsQuery]);
- return (
- // @ts-expect-error we are overriding data with the stored version
- <GroupStatsContext.Provider value={{...statsQuery, data: groupStats}}>
- {props.children}
- </GroupStatsContext.Provider>
- );
- }
|