customMeasurementsProvider.tsx 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import {useEffect, useState} from 'react';
  2. import {Query} from 'history';
  3. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  4. import {Client} from 'sentry/api';
  5. import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
  6. import {t} from 'sentry/locale';
  7. import {Organization, PageFilters} from 'sentry/types';
  8. import handleXhrErrorResponse from 'sentry/utils/handleXhrErrorResponse';
  9. import {MeasurementCollection} from 'sentry/utils/measurements/measurements';
  10. import useApi from 'sentry/utils/useApi';
  11. import {
  12. CustomMeasurementsContext,
  13. CustomMeasurementsContextValue,
  14. } from './customMeasurementsContext';
  15. function fetchCustomMeasurements(
  16. api: Client,
  17. organization: Organization,
  18. selection?: PageFilters
  19. ): Promise<MeasurementCollection> {
  20. const query: Query = selection?.datetime
  21. ? {...normalizeDateTimeParams(selection.datetime)}
  22. : {};
  23. if (selection?.projects) {
  24. query.project = selection.projects.map(String);
  25. }
  26. return api.requestPromise(`/organizations/${organization.slug}/measurements-meta/`, {
  27. method: 'GET',
  28. query,
  29. });
  30. }
  31. type CustomMeasurementsProviderProps = {
  32. children:
  33. | React.ReactNode
  34. | ((props: CustomMeasurementsContextValue) => React.ReactNode);
  35. organization: Organization;
  36. selection?: PageFilters;
  37. };
  38. export function CustomMeasurementsProvider({
  39. children,
  40. organization,
  41. selection,
  42. }: CustomMeasurementsProviderProps) {
  43. const api = useApi();
  44. const [state, setState] = useState({customMeasurements: {}});
  45. useEffect(() => {
  46. let shouldCancelRequest = false;
  47. fetchCustomMeasurements(api, organization, selection)
  48. .then(response => {
  49. if (shouldCancelRequest) {
  50. return;
  51. }
  52. const newCustomMeasurements = Object.keys(response).reduce<MeasurementCollection>(
  53. (acc, customMeasurement) => {
  54. acc[customMeasurement] = {
  55. key: customMeasurement,
  56. name: customMeasurement,
  57. };
  58. return acc;
  59. },
  60. {}
  61. );
  62. setState({customMeasurements: newCustomMeasurements});
  63. })
  64. .catch(e => {
  65. if (shouldCancelRequest) {
  66. return;
  67. }
  68. const errorResponse = e?.responseJSON ?? t('Unable to fetch custom measurements');
  69. addErrorMessage(errorResponse);
  70. handleXhrErrorResponse(errorResponse)(e);
  71. });
  72. return () => {
  73. shouldCancelRequest = true;
  74. };
  75. }, [selection, api, organization]);
  76. return (
  77. <CustomMeasurementsContext.Provider value={state}>
  78. {typeof children === 'function' ? children(state) : children}
  79. </CustomMeasurementsContext.Provider>
  80. );
  81. }