index.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import {Fragment} from 'react';
  2. import {browserHistory, RouteComponentProps} from 'react-router';
  3. import {addLoadingMessage} from 'sentry/actionCreators/indicator';
  4. import {
  5. changeOrganizationSlug,
  6. removeAndRedirectToRemainingOrganization,
  7. updateOrganization,
  8. } from 'sentry/actionCreators/organizations';
  9. import Button from 'sentry/components/button';
  10. import Confirm from 'sentry/components/confirm';
  11. import Field from 'sentry/components/forms/field';
  12. import List from 'sentry/components/list';
  13. import ListItem from 'sentry/components/list/listItem';
  14. import {Panel, PanelHeader} from 'sentry/components/panels';
  15. import SentryDocumentTitle from 'sentry/components/sentryDocumentTitle';
  16. import {t, tct} from 'sentry/locale';
  17. import {Organization, Project} from 'sentry/types';
  18. import useApi from 'sentry/utils/useApi';
  19. import withOrganization from 'sentry/utils/withOrganization';
  20. import withProjects from 'sentry/utils/withProjects';
  21. import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
  22. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  23. import PermissionAlert from 'sentry/views/settings/organization/permissionAlert';
  24. import OrganizationSettingsForm from './organizationSettingsForm';
  25. type Props = {
  26. organization: Organization;
  27. projects: Project[];
  28. } & RouteComponentProps<{orgId: string}, {}>;
  29. function OrganizationGeneralSettings(props: Props) {
  30. const api = useApi();
  31. const {organization, projects, params} = props;
  32. const {orgId} = params;
  33. const access = new Set(organization.access);
  34. const removeConfirmMessage = (
  35. <Fragment>
  36. <TextBlock>
  37. {tct(
  38. 'Removing the organization, [name] is permanent and cannot be undone! Are you sure you want to continue?',
  39. {
  40. name: organization && <strong>{organization.name}</strong>,
  41. }
  42. )}
  43. </TextBlock>
  44. {!!projects.length && (
  45. <Fragment>
  46. <TextBlock>
  47. {t('This will also remove the following associated projects:')}
  48. </TextBlock>
  49. <List symbol="bullet" data-test-id="removed-projects-list">
  50. {projects.map(project => (
  51. <ListItem key={project.slug}>{project.slug}</ListItem>
  52. ))}
  53. </List>
  54. </Fragment>
  55. )}
  56. </Fragment>
  57. );
  58. const handleSaveForm: React.ComponentProps<
  59. typeof OrganizationSettingsForm
  60. >['onSave'] = (prevData: Organization, data: Partial<Organization>) => {
  61. if (data.slug && data.slug !== prevData.slug) {
  62. changeOrganizationSlug(
  63. prevData,
  64. data as Partial<Organization> & Pick<Organization, 'slug'>
  65. );
  66. browserHistory.replace(`/settings/${data.slug}/`);
  67. } else {
  68. // This will update OrganizationStore (as well as OrganizationsStore
  69. // which is slightly incorrect because it has summaries vs a detailed org)
  70. updateOrganization(data);
  71. }
  72. };
  73. const handleConfirmRemoveOrg = () => {
  74. if (!organization) {
  75. return;
  76. }
  77. addLoadingMessage();
  78. removeAndRedirectToRemainingOrganization(api, {
  79. orgId: params.orgId,
  80. successMessage: `${organization.name} is queued for deletion.`,
  81. errorMessage: `Error removing the ${organization.name} organization`,
  82. });
  83. };
  84. return (
  85. <Fragment>
  86. <SentryDocumentTitle title={t('General Settings')} orgSlug={orgId} />
  87. <div>
  88. <SettingsPageHeader title={t('Organization Settings')} />
  89. <PermissionAlert />
  90. <OrganizationSettingsForm
  91. {...props}
  92. initialData={organization}
  93. access={access}
  94. onSave={handleSaveForm}
  95. />
  96. {access.has('org:admin') && !organization.isDefault && (
  97. <Panel>
  98. <PanelHeader>{t('Remove Organization')}</PanelHeader>
  99. <Field
  100. label={t('Remove Organization')}
  101. help={t(
  102. 'Removing this organization will delete all data including projects and their associated events.'
  103. )}
  104. >
  105. <div>
  106. <Confirm
  107. priority="danger"
  108. confirmText={t('Remove Organization')}
  109. message={removeConfirmMessage}
  110. onConfirm={handleConfirmRemoveOrg}
  111. >
  112. <Button priority="danger">{t('Remove Organization')}</Button>
  113. </Confirm>
  114. </div>
  115. </Field>
  116. </Panel>
  117. )}
  118. </div>
  119. </Fragment>
  120. );
  121. }
  122. export default withProjects(withOrganization(OrganizationGeneralSettings));