index.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import {Fragment} from 'react';
  2. import styled from '@emotion/styled';
  3. import {addSuccessMessage} from 'sentry/actionCreators/indicator';
  4. import {Button} from 'sentry/components/button';
  5. import {Alert} from 'sentry/components/core/alert';
  6. import ApiForm from 'sentry/components/forms/apiForm';
  7. import HiddenField from 'sentry/components/forms/fields/hiddenField';
  8. import LoadingIndicator from 'sentry/components/loadingIndicator';
  9. import NarrowLayout from 'sentry/components/narrowLayout';
  10. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  11. import {t, tct} from 'sentry/locale';
  12. import {space} from 'sentry/styles/space';
  13. import type {RouteComponentProps} from 'sentry/types/legacyReactRouter';
  14. import type {Organization} from 'sentry/types/organization';
  15. import {browserHistory} from 'sentry/utils/browserHistory';
  16. import {useApiQuery} from 'sentry/utils/queryClient';
  17. import normalizeUrl from 'sentry/utils/url/normalizeUrl';
  18. import {useParams} from 'sentry/utils/useParams';
  19. type Props = RouteComponentProps<{orgId: string}>;
  20. function OrganizationRestore(_props: Props) {
  21. const params = useParams<{orgId: string}>();
  22. return (
  23. <SentryDocumentTitle title={t('Restore Organization')}>
  24. <NarrowLayout>
  25. <h3>{t('Deletion Scheduled')}</h3>
  26. <OrganizationRestoreBody orgSlug={params.orgId} />
  27. </NarrowLayout>
  28. </SentryDocumentTitle>
  29. );
  30. }
  31. type BodyProps = {
  32. orgSlug: string;
  33. };
  34. function OrganizationRestoreBody({orgSlug}: BodyProps) {
  35. const endpoint = `/organizations/${orgSlug}/`;
  36. const {isPending, isError, data} = useApiQuery<Organization>([endpoint], {
  37. staleTime: 0,
  38. });
  39. if (isPending) {
  40. return <LoadingIndicator />;
  41. }
  42. if (isError) {
  43. return (
  44. <Alert.Container>
  45. <Alert type="error">{t('There was an error loading your organization.')}</Alert>
  46. </Alert.Container>
  47. );
  48. }
  49. if (data.status.id === 'active') {
  50. browserHistory.replace(normalizeUrl(`/organizations/${orgSlug}/issues/`));
  51. return null;
  52. }
  53. if (data.status.id === 'pending_deletion') {
  54. return <RestoreForm organization={data} endpoint={endpoint} />;
  55. }
  56. return (
  57. <p>
  58. {t(
  59. 'Sorry, but this organization is currently in progress of being deleted. No turning back.'
  60. )}
  61. </p>
  62. );
  63. }
  64. type RestoreFormProps = {
  65. endpoint: string;
  66. organization: Organization;
  67. };
  68. function RestoreForm({endpoint, organization}: RestoreFormProps) {
  69. return (
  70. <Fragment>
  71. <ApiForm
  72. apiEndpoint={endpoint}
  73. apiMethod="PUT"
  74. submitLabel={t('Restore Organization')}
  75. onSubmitSuccess={() => {
  76. addSuccessMessage(t('Organization Restored'));
  77. // Use window.location to ensure page reloads
  78. window.location.assign(
  79. normalizeUrl(`/organizations/${organization.slug}/issues/`)
  80. );
  81. }}
  82. initialData={{cancelDeletion: 1}}
  83. hideFooter
  84. >
  85. <HiddenField name="cancelDeletion" />
  86. <p>
  87. {tct('The [name] organization is currently scheduled for deletion.', {
  88. name: <strong>{organization.slug}</strong>,
  89. })}
  90. </p>
  91. <p>
  92. {t(
  93. 'Would you like to cancel this process and restore the organization back to the original state?'
  94. )}
  95. </p>
  96. <ButtonWrapper>
  97. <Button data-test-id="form-submit" priority="primary" type="submit">
  98. {t('Restore Organization')}
  99. </Button>
  100. </ButtonWrapper>
  101. </ApiForm>
  102. <p>
  103. {t(
  104. 'Note: Restoration is available until deletion has started. Once it begins, there is no recovering the data that has been removed.'
  105. )}
  106. </p>
  107. </Fragment>
  108. );
  109. }
  110. const ButtonWrapper = styled('div')`
  111. margin-bottom: ${space(2)};
  112. `;
  113. export default OrganizationRestore;