edit.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import {useCallback, useEffect} from 'react';
  2. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  3. import {Alert} from 'sentry/components/core/alert';
  4. import LoadingError from 'sentry/components/loadingError';
  5. import LoadingIndicator from 'sentry/components/loadingIndicator';
  6. import {t} from 'sentry/locale';
  7. import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
  8. import type {Organization} from 'sentry/types/organization';
  9. import type {Project} from 'sentry/types/project';
  10. import {metric} from 'sentry/utils/analytics';
  11. import normalizeUrl from 'sentry/utils/url/normalizeUrl';
  12. import {useNavigate} from 'sentry/utils/useNavigate';
  13. import {makeAlertsPathname} from 'sentry/views/alerts/pathnames';
  14. import RuleForm from 'sentry/views/alerts/rules/metric/ruleForm';
  15. import {useMetricRule} from 'sentry/views/alerts/rules/metric/utils/useMetricRule';
  16. type RouteParams = {
  17. projectId: string;
  18. ruleId: string;
  19. };
  20. type Props = {
  21. onChangeTitle: (data: string) => void;
  22. organization: Organization;
  23. project: Project;
  24. userTeamIds: string[];
  25. } & RouteComponentProps<RouteParams>;
  26. export function MetricRulesEdit({
  27. organization,
  28. params,
  29. project,
  30. userTeamIds,
  31. onChangeTitle,
  32. ...props
  33. }: Props) {
  34. const navigate = useNavigate();
  35. const {
  36. isPending,
  37. isError,
  38. data: rule,
  39. error,
  40. } = useMetricRule(
  41. {
  42. orgSlug: organization.slug,
  43. ruleId: params.ruleId,
  44. },
  45. {refetchOnMount: true}
  46. );
  47. useEffect(() => {
  48. if (!isPending && rule) {
  49. onChangeTitle(rule.name ?? '');
  50. }
  51. }, [onChangeTitle, isPending, rule]);
  52. useEffect(() => {
  53. if (isError && error?.responseText) {
  54. try {
  55. const {detail} = JSON.parse(error.responseText);
  56. if (detail) {
  57. addErrorMessage(detail);
  58. }
  59. } catch {
  60. // Ignore
  61. }
  62. }
  63. }, [isError, error]);
  64. const handleSubmitSuccess = useCallback(() => {
  65. metric.endSpan({name: 'saveAlertRule'});
  66. navigate(
  67. normalizeUrl({
  68. pathname: makeAlertsPathname({
  69. path: `/rules/details/${params.ruleId}/`,
  70. organization,
  71. }),
  72. })
  73. );
  74. }, [navigate, params.ruleId, organization]);
  75. if (isPending) {
  76. return <LoadingIndicator />;
  77. }
  78. if (isError) {
  79. if (error?.status === 404) {
  80. return (
  81. <Alert.Container>
  82. <Alert type="error" showIcon>
  83. {t('This alert rule could not be found.')}
  84. </Alert>
  85. </Alert.Container>
  86. );
  87. }
  88. return <LoadingError />;
  89. }
  90. return (
  91. <RuleForm
  92. {...props}
  93. // HACK: gnarly workaround to force the component to re-render when rule updates
  94. // Remove this once the RuleForm component is refactored to use `react-query`
  95. key={JSON.stringify(rule)}
  96. params={params}
  97. project={project}
  98. userTeamIds={userTeamIds}
  99. organization={organization}
  100. ruleId={params.ruleId}
  101. rule={rule}
  102. onSubmitSuccess={handleSubmitSuccess}
  103. disableProjectSelector
  104. />
  105. );
  106. }