index.tsx 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. import {RouteComponentProps} from 'react-router';
  2. import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
  3. import SelectField from 'sentry/components/forms/fields/selectField';
  4. import Form from 'sentry/components/forms/form';
  5. import NarrowLayout from 'sentry/components/narrowLayout';
  6. import {t, tct} from 'sentry/locale';
  7. import {Organization, Project} from 'sentry/types';
  8. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  9. import DeprecatedAsyncView from 'sentry/views/deprecatedAsyncView';
  10. import SettingsPageHeader from 'sentry/views/settings/components/settingsPageHeader';
  11. type Props = RouteComponentProps<{}, {}>;
  12. type TransferDetails = {
  13. organizations: Organization[];
  14. project: Project;
  15. };
  16. type State = {
  17. transferDetails: TransferDetails | null;
  18. } & DeprecatedAsyncView['state'];
  19. class AcceptProjectTransfer extends DeprecatedAsyncView<Props, State> {
  20. disableErrorReport = false;
  21. getEndpoints(): ReturnType<DeprecatedAsyncView['getEndpoints']> {
  22. const query = this.props.location.query;
  23. return [['transferDetails', '/accept-transfer/', {query}]];
  24. }
  25. getTitle() {
  26. return t('Accept Project Transfer');
  27. }
  28. handleSubmit = formData => {
  29. this.api.request('/accept-transfer/', {
  30. method: 'POST',
  31. data: {
  32. data: this.props.location.query.data,
  33. organization: formData.organization,
  34. },
  35. success: () => {
  36. const orgSlug = formData.organization;
  37. this.props.router.push(normalizeUrl(`/organizations/${orgSlug}/projects/`));
  38. addSuccessMessage(t('Project successfully transferred'));
  39. },
  40. error: error => {
  41. const errorMsg =
  42. error && error.responseJSON && typeof error.responseJSON.detail === 'string'
  43. ? error.responseJSON.detail
  44. : '';
  45. addErrorMessage(
  46. t('Unable to transfer project') + errorMsg ? `: ${errorMsg}` : ''
  47. );
  48. },
  49. });
  50. };
  51. renderError(error) {
  52. let disableLog = false;
  53. // Check if there is an error message with `transferDetails` endpoint
  54. // If so, show as toast and ignore, otherwise log to sentry
  55. if (error && error.responseJSON && typeof error.responseJSON.detail === 'string') {
  56. addErrorMessage(error.responseJSON.detail);
  57. disableLog = true;
  58. }
  59. return super.renderError(error, disableLog);
  60. }
  61. renderBody() {
  62. const {transferDetails} = this.state;
  63. const options = transferDetails?.organizations.map(org => ({
  64. label: org.slug,
  65. value: org.slug,
  66. }));
  67. const organization = options?.[0]?.value;
  68. return (
  69. <NarrowLayout>
  70. <SettingsPageHeader title={t('Approve Transfer Project Request')} />
  71. <p>
  72. {tct(
  73. 'Projects must be transferred to a specific [organization]. You can grant specific teams access to the project later under the [projectSettings]. (Note that granting access to at least one team is necessary for the project to appear in all parts of the UI.)',
  74. {
  75. organization: <strong>{t('Organization')}</strong>,
  76. projectSettings: <strong>{t('Project Settings')}</strong>,
  77. }
  78. )}
  79. </p>
  80. {transferDetails && (
  81. <p>
  82. {tct(
  83. 'Please select which [organization] you want for the project [project].',
  84. {
  85. organization: <strong>{t('Organization')}</strong>,
  86. project: transferDetails.project.slug,
  87. }
  88. )}
  89. </p>
  90. )}
  91. <Form
  92. onSubmit={this.handleSubmit}
  93. submitLabel={t('Transfer Project')}
  94. submitPriority="danger"
  95. initialData={organization ? {organization} : undefined}
  96. >
  97. <SelectField
  98. options={options}
  99. label={t('Organization')}
  100. name="organization"
  101. style={{borderBottom: 'none'}}
  102. />
  103. </Form>
  104. </NarrowLayout>
  105. );
  106. }
  107. }
  108. export default AcceptProjectTransfer;