metricsExtractionRuleEditModal.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import {Fragment, useCallback, useMemo} from 'react';
  2. import {css} from '@emotion/react';
  3. import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
  4. import {
  5. type ModalOptions,
  6. type ModalRenderProps,
  7. openModal,
  8. } from 'sentry/actionCreators/modal';
  9. import {t} from 'sentry/locale';
  10. import type {MetricsExtractionRule} from 'sentry/types/metrics';
  11. import {useCardinalityLimitedMetricVolume} from 'sentry/utils/metrics/useCardinalityLimitedMetricVolume';
  12. import useOrganization from 'sentry/utils/useOrganization';
  13. import {
  14. aggregatesToGroups,
  15. createCondition as createExtractionCondition,
  16. explodeAggregateGroup,
  17. type FormData,
  18. MetricsExtractionRuleForm,
  19. } from 'sentry/views/settings/projectMetrics/metricsExtractionRuleForm';
  20. import {useUpdateMetricsExtractionRules} from 'sentry/views/settings/projectMetrics/utils/useMetricsExtractionRules';
  21. interface Props {
  22. metricExtractionRule: MetricsExtractionRule;
  23. onSubmitSuccess?: (data: FormData) => void;
  24. }
  25. export function MetricsExtractionRuleEditModal({
  26. Header,
  27. Body,
  28. closeModal,
  29. CloseButton,
  30. metricExtractionRule,
  31. onSubmitSuccess: onSubmitSuccessProp,
  32. }: Props & ModalRenderProps) {
  33. const organization = useOrganization();
  34. const updateExtractionRuleMutation = useUpdateMetricsExtractionRules(
  35. organization.slug,
  36. metricExtractionRule.projectId
  37. );
  38. const {data: cardinality} = useCardinalityLimitedMetricVolume({
  39. projects: [metricExtractionRule.projectId],
  40. });
  41. const initialData: FormData = useMemo(() => {
  42. return {
  43. spanAttribute: metricExtractionRule.spanAttribute,
  44. unit: metricExtractionRule.unit,
  45. aggregates: aggregatesToGroups(metricExtractionRule.aggregates),
  46. tags: metricExtractionRule.tags,
  47. conditions: metricExtractionRule.conditions.length
  48. ? metricExtractionRule.conditions
  49. : [createExtractionCondition()],
  50. };
  51. }, [metricExtractionRule]);
  52. const handleSubmit = useCallback(
  53. (
  54. data: FormData,
  55. onSubmitSuccess: (data: FormData) => void,
  56. onSubmitError: (error: any) => void
  57. ) => {
  58. const extractionRule: MetricsExtractionRule = {
  59. ...metricExtractionRule,
  60. spanAttribute: data.spanAttribute!,
  61. tags: data.tags,
  62. aggregates: data.aggregates.flatMap(explodeAggregateGroup),
  63. unit: data.unit,
  64. conditions: data.conditions,
  65. };
  66. updateExtractionRuleMutation.mutate(
  67. {
  68. metricsExtractionRules: [extractionRule],
  69. },
  70. {
  71. onSuccess: () => {
  72. onSubmitSuccess(data);
  73. onSubmitSuccessProp?.(data);
  74. addSuccessMessage(t('Metric extraction rule updated'));
  75. closeModal();
  76. },
  77. onError: error => {
  78. const message = error?.responseJSON?.detail
  79. ? (error.responseJSON.detail as string)
  80. : t('Unable to save your changes.');
  81. onSubmitError(message);
  82. addErrorMessage(message);
  83. },
  84. }
  85. );
  86. onSubmitSuccess(data);
  87. },
  88. [closeModal, metricExtractionRule, onSubmitSuccessProp, updateExtractionRuleMutation]
  89. );
  90. return (
  91. <Fragment>
  92. <Header>
  93. <h4>{t('Edit Metric')}</h4>
  94. </Header>
  95. <CloseButton />
  96. <Body>
  97. <MetricsExtractionRuleForm
  98. initialData={initialData}
  99. projectId={metricExtractionRule.projectId}
  100. submitLabel={t('Update')}
  101. cancelLabel={t('Cancel')}
  102. onCancel={closeModal}
  103. onSubmit={handleSubmit}
  104. cardinality={cardinality}
  105. submitDisabled={updateExtractionRuleMutation.isLoading}
  106. isEdit
  107. requireChanges
  108. />
  109. </Body>
  110. </Fragment>
  111. );
  112. }
  113. export const modalCss = css`
  114. width: 100%;
  115. max-width: 900px;
  116. `;
  117. export function openExtractionRuleEditModal(props: Props, options?: ModalOptions) {
  118. openModal(modalProps => <MetricsExtractionRuleEditModal {...props} {...modalProps} />, {
  119. modalCss,
  120. ...options,
  121. });
  122. }