edit.tsx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import {browserHistory} from 'react-router';
  2. import styled from '@emotion/styled';
  3. import {Breadcrumbs} from 'sentry/components/breadcrumbs';
  4. import IdBadge from 'sentry/components/idBadge';
  5. import * as Layout from 'sentry/components/layouts/thirds';
  6. import LoadingError from 'sentry/components/loadingError';
  7. import LoadingIndicator from 'sentry/components/loadingIndicator';
  8. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  9. import {t} from 'sentry/locale';
  10. import {space} from 'sentry/styles/space';
  11. import {setApiQueryData, useApiQuery, useQueryClient} from 'sentry/utils/queryClient';
  12. import useOrganization from 'sentry/utils/useOrganization';
  13. import usePageFilters from 'sentry/utils/usePageFilters';
  14. import {useParams} from 'sentry/utils/useParams';
  15. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  16. import {makeMonitorDetailsQueryKey} from 'sentry/views/monitors/utils';
  17. import MonitorForm from './components/monitorForm';
  18. import type {Monitor} from './types';
  19. export default function EditMonitor() {
  20. const {monitorSlug} = useParams();
  21. const {selection} = usePageFilters();
  22. const organization = useOrganization();
  23. const queryClient = useQueryClient();
  24. const queryKey = makeMonitorDetailsQueryKey(organization, monitorSlug, {
  25. expand: ['alertRule'],
  26. });
  27. const {
  28. isLoading,
  29. isError,
  30. data: monitor,
  31. refetch,
  32. } = useApiQuery<Monitor>(queryKey, {
  33. cacheTime: 0,
  34. staleTime: 0,
  35. });
  36. function onSubmitSuccess(data: Monitor) {
  37. setApiQueryData(queryClient, queryKey, data);
  38. browserHistory.push(
  39. normalizeUrl({
  40. pathname: `/organizations/${organization.slug}/crons/${data.slug}/`,
  41. query: {
  42. environment: selection.environments,
  43. project: selection.projects,
  44. },
  45. })
  46. );
  47. }
  48. function getTitle() {
  49. if (monitor) {
  50. return `${monitor.name} - Crons - ${organization.slug}`;
  51. }
  52. return `Crons - ${organization.slug}`;
  53. }
  54. if (isLoading) {
  55. return <LoadingIndicator />;
  56. }
  57. if (isError) {
  58. return <LoadingError onRetry={refetch} message="Failed to load monitor." />;
  59. }
  60. return (
  61. <SentryDocumentTitle title={getTitle()}>
  62. <Layout.Page>
  63. <Layout.Header>
  64. <Layout.HeaderContent>
  65. <Breadcrumbs
  66. crumbs={[
  67. {
  68. label: t('Crons'),
  69. to: normalizeUrl(`/organizations/${organization.slug}/crons/`),
  70. },
  71. {
  72. label: (
  73. <MonitorBreadcrumb>
  74. <IdBadge
  75. disableLink
  76. project={monitor.project}
  77. avatarSize={16}
  78. hideName
  79. avatarProps={{hasTooltip: true, tooltip: monitor.project.slug}}
  80. />
  81. {monitor.name}
  82. </MonitorBreadcrumb>
  83. ),
  84. to: normalizeUrl(
  85. `/organizations/${organization.slug}/crons/${monitor.slug}/`
  86. ),
  87. },
  88. {
  89. label: t('Edit'),
  90. },
  91. ]}
  92. />
  93. <Layout.Title>{t('Edit Monitor')}</Layout.Title>
  94. </Layout.HeaderContent>
  95. </Layout.Header>
  96. <Layout.Body>
  97. <Layout.Main fullWidth>
  98. <MonitorForm
  99. monitor={monitor}
  100. apiMethod="PUT"
  101. apiEndpoint={`/organizations/${organization.slug}/monitors/${monitor.slug}/`}
  102. onSubmitSuccess={onSubmitSuccess}
  103. />
  104. </Layout.Main>
  105. </Layout.Body>
  106. </Layout.Page>
  107. </SentryDocumentTitle>
  108. );
  109. }
  110. const MonitorBreadcrumb = styled('div')`
  111. display: flex;
  112. gap: ${space(1)};
  113. align-items: center;
  114. `;