index.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import {Fragment} from 'react';
  2. import {browserHistory, RouteComponentProps} from 'react-router';
  3. import {addErrorMessage, addSuccessMessage} from 'sentry/actionCreators/indicator';
  4. import {removeTeam, updateTeamSuccess} from 'sentry/actionCreators/teams';
  5. import {hasEveryAccess} from 'sentry/components/acl/access';
  6. import {Button} from 'sentry/components/button';
  7. import Confirm from 'sentry/components/confirm';
  8. import FieldGroup from 'sentry/components/forms/fieldGroup';
  9. import Form, {FormProps} from 'sentry/components/forms/form';
  10. import JsonForm from 'sentry/components/forms/jsonForm';
  11. import Panel from 'sentry/components/panels/panel';
  12. import PanelHeader from 'sentry/components/panels/panelHeader';
  13. import teamSettingsFields from 'sentry/data/forms/teamSettingsFields';
  14. import {IconDelete} from 'sentry/icons';
  15. import {t, tct} from 'sentry/locale';
  16. import {Organization, Team} from 'sentry/types';
  17. import {normalizeUrl} from 'sentry/utils/withDomainRequired';
  18. import withOrganization from 'sentry/utils/withOrganization';
  19. import DeprecatedAsyncView from 'sentry/views/deprecatedAsyncView';
  20. import PermissionAlert from 'sentry/views/settings/project/permissionAlert';
  21. type Props = RouteComponentProps<{teamId: string}, {}> & {
  22. organization: Organization;
  23. team: Team;
  24. };
  25. type State = DeprecatedAsyncView['state'];
  26. class TeamSettings extends DeprecatedAsyncView<Props, State> {
  27. getTitle() {
  28. return 'Team Settings';
  29. }
  30. getEndpoints() {
  31. return [];
  32. }
  33. handleSubmitSuccess: FormProps['onSubmitSuccess'] = (resp, _model, id) => {
  34. const {organization} = this.props;
  35. // Use the old slug when triggering the update so we correctly replace the
  36. // previous team in the store
  37. updateTeamSuccess(this.props.team.slug, resp);
  38. if (id === 'slug') {
  39. addSuccessMessage(t('Team name changed'));
  40. browserHistory.replace(
  41. normalizeUrl(`/settings/${organization.slug}/teams/${resp.slug}/settings/`)
  42. );
  43. this.setState({loading: true});
  44. }
  45. };
  46. handleRemoveTeam = async () => {
  47. const {organization, params} = this.props;
  48. try {
  49. await removeTeam(this.api, {orgId: organization.slug, teamId: params.teamId});
  50. browserHistory.replace(normalizeUrl(`/settings/${organization.slug}/teams/`));
  51. } catch {
  52. // removeTeam already displays an error message
  53. }
  54. };
  55. renderBody() {
  56. const {organization, team} = this.props;
  57. const idpProvisioned = team.flags['idp:provisioned'];
  58. const orgRoleList = organization.orgRoleList;
  59. const hasOrgRoleFlag = organization.features.includes('org-roles-for-teams');
  60. const hasTeamWrite = hasEveryAccess(['team:write'], {organization, team});
  61. const hasTeamAdmin = hasEveryAccess(['team:admin'], {organization, team});
  62. const hasOrgAdmin = hasEveryAccess(['org:admin'], {organization});
  63. return (
  64. <Fragment>
  65. <PermissionAlert access={['team:write']} team={team} />
  66. <Form
  67. apiMethod="PUT"
  68. apiEndpoint={`/teams/${organization.slug}/${team.slug}/`}
  69. saveOnBlur
  70. allowUndo
  71. onSubmitSuccess={this.handleSubmitSuccess}
  72. onSubmitError={() => addErrorMessage(t('Unable to save change'))}
  73. initialData={{
  74. name: team.name,
  75. slug: team.slug,
  76. orgRole: team.orgRole,
  77. }}
  78. >
  79. <JsonForm
  80. additionalFieldProps={{
  81. idpProvisioned,
  82. hasOrgRoleFlag,
  83. hasTeamWrite,
  84. hasOrgAdmin,
  85. orgRoleList,
  86. }}
  87. forms={teamSettingsFields}
  88. />
  89. </Form>
  90. <Panel>
  91. <PanelHeader>{t('Team Administration')}</PanelHeader>
  92. <FieldGroup
  93. label={t('Remove Team')}
  94. help={t(
  95. "This may affect team members' access to projects and associated alert delivery."
  96. )}
  97. >
  98. <div>
  99. <Confirm
  100. disabled={!hasTeamAdmin}
  101. onConfirm={this.handleRemoveTeam}
  102. priority="danger"
  103. message={tct('Are you sure you want to remove the team [team]?', {
  104. team: `#${team.slug}`,
  105. })}
  106. >
  107. <Button
  108. icon={<IconDelete />}
  109. priority="danger"
  110. data-test-id="button-remove-team"
  111. >
  112. {t('Remove Team')}
  113. </Button>
  114. </Confirm>
  115. </div>
  116. </FieldGroup>
  117. </Panel>
  118. </Fragment>
  119. );
  120. }
  121. }
  122. export default withOrganization(TeamSettings);