customMeasurementsProvider.tsx 2.9 KB

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