edit.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import {useCallback} from 'react';
  2. import type {RouteComponentProps} from 'react-router';
  3. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  4. import {Alert} from 'sentry/components/alert';
  5. import LoadingError from 'sentry/components/loadingError';
  6. import LoadingIndicator from 'sentry/components/loadingIndicator';
  7. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  8. import {t} from 'sentry/locale';
  9. import type {Organization} from 'sentry/types/organization';
  10. import type {Project} from 'sentry/types/project';
  11. import {metric} from 'sentry/utils/analytics';
  12. import {useApiQuery} from 'sentry/utils/queryClient';
  13. import routeTitleGen from 'sentry/utils/routeTitle';
  14. import {useNavigate} from 'sentry/utils/useNavigate';
  15. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  16. import RuleForm from 'sentry/views/alerts/rules/metric/ruleForm';
  17. import type {MetricRule} from 'sentry/views/alerts/rules/metric/types';
  18. type RouteParams = {
  19. projectId: string;
  20. ruleId: string;
  21. };
  22. type Props = {
  23. onChangeTitle: (data: string) => void;
  24. organization: Organization;
  25. project: Project;
  26. userTeamIds: string[];
  27. } & RouteComponentProps<RouteParams, {}>;
  28. export function MetricRulesEdit({
  29. organization,
  30. params,
  31. project,
  32. userTeamIds,
  33. onChangeTitle,
  34. ...props
  35. }: Props) {
  36. const navigate = useNavigate();
  37. const {
  38. isLoading,
  39. isError,
  40. data: rule,
  41. error,
  42. } = useApiQuery<MetricRule>(
  43. [`/organizations/${organization.slug}/alert-rules/${params.ruleId}/`],
  44. {
  45. staleTime: 0,
  46. retry: false,
  47. onSuccess: data => {
  48. onChangeTitle(data[0]?.name ?? '');
  49. },
  50. onError: ({responseText}) => {
  51. const {detail} = JSON.parse(responseText ?? '');
  52. if (detail) {
  53. addErrorMessage(detail);
  54. }
  55. },
  56. }
  57. );
  58. const handleSubmitSuccess = useCallback(() => {
  59. metric.endSpan({name: 'saveAlertRule'});
  60. navigate(
  61. normalizeUrl({
  62. pathname: `/organizations/${organization.slug}/alerts/rules/details/${params.ruleId}/`,
  63. })
  64. );
  65. }, [params.ruleId, navigate, organization.slug]);
  66. if (isLoading) {
  67. return <LoadingIndicator />;
  68. }
  69. if (isError) {
  70. if (error?.status === 404) {
  71. return (
  72. <Alert type="error" showIcon>
  73. {t('This alert rule could not be found.')}
  74. </Alert>
  75. );
  76. }
  77. return <LoadingError />;
  78. }
  79. const title = routeTitleGen(
  80. rule?.name ? t('Alert - %s', rule?.name) : '',
  81. organization.slug,
  82. false,
  83. project?.slug
  84. );
  85. return (
  86. <SentryDocumentTitle title={title}>
  87. <RuleForm
  88. {...props}
  89. params={params}
  90. project={project}
  91. userTeamIds={userTeamIds}
  92. organization={organization}
  93. ruleId={params.ruleId}
  94. rule={rule}
  95. onSubmitSuccess={handleSubmitSuccess}
  96. disableProjectSelector
  97. />
  98. </SentryDocumentTitle>
  99. );
  100. }