organizationSettingsForm.tsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import {RouteComponentProps} from 'react-router';
  2. import {Location} from 'history';
  3. import cloneDeep from 'lodash/cloneDeep';
  4. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  5. import {updateOrganization} from 'sentry/actionCreators/organizations';
  6. import AsyncComponent from 'sentry/components/asyncComponent';
  7. import AvatarChooser from 'sentry/components/avatarChooser';
  8. import Form from 'sentry/components/forms/form';
  9. import JsonForm from 'sentry/components/forms/jsonForm';
  10. import organizationSettingsFields from 'sentry/data/forms/organizationGeneralSettings';
  11. import {t} from 'sentry/locale';
  12. import {Organization, Scope} from 'sentry/types';
  13. import withOrganization from 'sentry/utils/withOrganization';
  14. type Props = {
  15. access: Set<Scope>;
  16. initialData: Organization;
  17. location: Location;
  18. onSave: (previous: Organization, updated: Organization) => void;
  19. organization: Organization;
  20. } & RouteComponentProps<{}, {}>;
  21. type State = AsyncComponent['state'] & {
  22. authProvider: object;
  23. };
  24. class OrganizationSettingsForm extends AsyncComponent<Props, State> {
  25. getEndpoints(): ReturnType<AsyncComponent['getEndpoints']> {
  26. const {organization} = this.props;
  27. return [['authProvider', `/organizations/${organization.slug}/auth-provider/`]];
  28. }
  29. render() {
  30. const {initialData, organization, onSave, access} = this.props;
  31. const {authProvider} = this.state;
  32. const endpoint = `/organizations/${organization.slug}/`;
  33. const jsonFormSettings = {
  34. additionalFieldProps: {hasSsoEnabled: !!authProvider},
  35. features: new Set(organization.features),
  36. access,
  37. location: this.props.location,
  38. disabled: !access.has('org:write'),
  39. };
  40. const forms = cloneDeep(organizationSettingsFields);
  41. if (organization.features.includes('codecov-stacktrace-integration')) {
  42. forms[0].fields = [
  43. ...forms[0].fields,
  44. {
  45. name: 'codecovAccess',
  46. type: 'boolean',
  47. label: t('Enable Code Coverage Insights - powered by Codecov'),
  48. help: t('Opt-in to connect your codecov account'),
  49. },
  50. ];
  51. }
  52. return (
  53. <Form
  54. data-test-id="organization-settings"
  55. apiMethod="PUT"
  56. apiEndpoint={endpoint}
  57. saveOnBlur
  58. allowUndo
  59. initialData={initialData}
  60. onSubmitSuccess={(updated, _model) => {
  61. // Special case for slug, need to forward to new slug
  62. if (typeof onSave === 'function') {
  63. onSave(initialData, updated);
  64. }
  65. }}
  66. onSubmitError={() => addErrorMessage('Unable to save change')}
  67. >
  68. <JsonForm {...jsonFormSettings} forms={forms} />
  69. <AvatarChooser
  70. type="organization"
  71. allowGravatar={false}
  72. endpoint={`${endpoint}avatar/`}
  73. model={initialData}
  74. onSave={updateOrganization}
  75. disabled={!access.has('org:write')}
  76. />
  77. </Form>
  78. );
  79. }
  80. }
  81. export default withOrganization(OrganizationSettingsForm);