index.tsx 4.5 KB

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