|
@@ -1,6 +1,5 @@
|
|
|
-import {RouteComponentProps} from 'react-router';
|
|
|
+import {useMemo} from 'react';
|
|
|
import styled from '@emotion/styled';
|
|
|
-import {Location} from 'history';
|
|
|
import cloneDeep from 'lodash/cloneDeep';
|
|
|
|
|
|
import {addErrorMessage} from 'sentry/actionCreators/indicator';
|
|
@@ -8,9 +7,6 @@ import {updateOrganization} from 'sentry/actionCreators/organizations';
|
|
|
import Feature from 'sentry/components/acl/feature';
|
|
|
import FeatureDisabled from 'sentry/components/acl/featureDisabled';
|
|
|
import AvatarChooser from 'sentry/components/avatarChooser';
|
|
|
-import DeprecatedAsyncComponent, {
|
|
|
- AsyncComponentState,
|
|
|
-} from 'sentry/components/deprecatedAsyncComponent';
|
|
|
import Form from 'sentry/components/forms/form';
|
|
|
import JsonForm from 'sentry/components/forms/jsonForm';
|
|
|
import HookOrDefault from 'sentry/components/hookOrDefault';
|
|
@@ -20,47 +16,40 @@ import organizationSettingsFields from 'sentry/data/forms/organizationGeneralSet
|
|
|
import {IconCodecov, IconLock} from 'sentry/icons';
|
|
|
import {t} from 'sentry/locale';
|
|
|
import {space} from 'sentry/styles/space';
|
|
|
-import type {Organization, OrganizationAuthProvider, Scope} from 'sentry/types';
|
|
|
-import withOrganization from 'sentry/utils/withOrganization';
|
|
|
+import type {Organization} from 'sentry/types';
|
|
|
+import {useLocation} from 'sentry/utils/useLocation';
|
|
|
+import useOrganization from 'sentry/utils/useOrganization';
|
|
|
|
|
|
const HookCodecovSettingsLink = HookOrDefault({
|
|
|
hookName: 'component:codecov-integration-settings-link',
|
|
|
});
|
|
|
|
|
|
-interface Props extends RouteComponentProps<{}, {}> {
|
|
|
- access: Set<Scope>;
|
|
|
+interface Props {
|
|
|
initialData: Organization;
|
|
|
- location: Location;
|
|
|
onSave: (previous: Organization, updated: Organization) => void;
|
|
|
- organization: Organization;
|
|
|
}
|
|
|
|
|
|
-interface State extends AsyncComponentState {
|
|
|
- authProvider: OrganizationAuthProvider;
|
|
|
-}
|
|
|
-
|
|
|
-class OrganizationSettingsForm extends DeprecatedAsyncComponent<Props, State> {
|
|
|
- getEndpoints(): ReturnType<DeprecatedAsyncComponent['getEndpoints']> {
|
|
|
- const {organization} = this.props;
|
|
|
- return [['authProvider', `/organizations/${organization.slug}/auth-provider/`]];
|
|
|
- }
|
|
|
+function OrganizationSettingsForm({initialData, onSave}: Props) {
|
|
|
+ const location = useLocation();
|
|
|
+ const organization = useOrganization();
|
|
|
+ const endpoint = `/organizations/${organization.slug}/`;
|
|
|
|
|
|
- render() {
|
|
|
- const {initialData, organization, onSave, access} = this.props;
|
|
|
- const {authProvider} = this.state;
|
|
|
- const endpoint = `/organizations/${organization.slug}/`;
|
|
|
+ const access = useMemo(() => new Set(organization.access), [organization]);
|
|
|
|
|
|
- const jsonFormSettings = {
|
|
|
- additionalFieldProps: {hasSsoEnabled: !!authProvider},
|
|
|
+ const jsonFormSettings = useMemo(
|
|
|
+ () => ({
|
|
|
features: new Set(organization.features),
|
|
|
access,
|
|
|
- location: this.props.location,
|
|
|
+ location,
|
|
|
disabled: !access.has('org:write'),
|
|
|
- };
|
|
|
+ }),
|
|
|
+ [access, location, organization]
|
|
|
+ );
|
|
|
|
|
|
- const forms = cloneDeep(organizationSettingsFields);
|
|
|
- forms[0].fields = [
|
|
|
- ...forms[0].fields,
|
|
|
+ const forms = useMemo(() => {
|
|
|
+ const formsConfig = cloneDeep(organizationSettingsFields);
|
|
|
+ formsConfig[0].fields = [
|
|
|
+ ...formsConfig[0].fields,
|
|
|
{
|
|
|
name: 'codecovAccess',
|
|
|
type: 'boolean',
|
|
@@ -103,38 +92,39 @@ class OrganizationSettingsForm extends DeprecatedAsyncComponent<Props, State> {
|
|
|
),
|
|
|
},
|
|
|
];
|
|
|
+ return formsConfig;
|
|
|
+ }, [organization]);
|
|
|
|
|
|
- return (
|
|
|
- <Form
|
|
|
- data-test-id="organization-settings"
|
|
|
- apiMethod="PUT"
|
|
|
- apiEndpoint={endpoint}
|
|
|
- saveOnBlur
|
|
|
- allowUndo
|
|
|
- initialData={initialData}
|
|
|
- onSubmitSuccess={(updated, _model) => {
|
|
|
- // Special case for slug, need to forward to new slug
|
|
|
- if (typeof onSave === 'function') {
|
|
|
- onSave(initialData, updated);
|
|
|
- }
|
|
|
- }}
|
|
|
- onSubmitError={() => addErrorMessage('Unable to save change')}
|
|
|
- >
|
|
|
- <JsonForm {...jsonFormSettings} forms={forms} />
|
|
|
- <AvatarChooser
|
|
|
- type="organization"
|
|
|
- allowGravatar={false}
|
|
|
- endpoint={`${endpoint}avatar/`}
|
|
|
- model={initialData}
|
|
|
- onSave={updateOrganization}
|
|
|
- disabled={!access.has('org:write')}
|
|
|
- />
|
|
|
- </Form>
|
|
|
- );
|
|
|
- }
|
|
|
+ return (
|
|
|
+ <Form
|
|
|
+ data-test-id="organization-settings"
|
|
|
+ apiMethod="PUT"
|
|
|
+ apiEndpoint={endpoint}
|
|
|
+ saveOnBlur
|
|
|
+ allowUndo
|
|
|
+ initialData={initialData}
|
|
|
+ onSubmitSuccess={(updated, _model) => {
|
|
|
+ // Special case for slug, need to forward to new slug
|
|
|
+ if (typeof onSave === 'function') {
|
|
|
+ onSave(initialData, updated);
|
|
|
+ }
|
|
|
+ }}
|
|
|
+ onSubmitError={() => addErrorMessage('Unable to save change')}
|
|
|
+ >
|
|
|
+ <JsonForm {...jsonFormSettings} forms={forms} />
|
|
|
+ <AvatarChooser
|
|
|
+ type="organization"
|
|
|
+ allowGravatar={false}
|
|
|
+ endpoint={`${endpoint}avatar/`}
|
|
|
+ model={initialData}
|
|
|
+ onSave={updateOrganization}
|
|
|
+ disabled={!access.has('org:write')}
|
|
|
+ />
|
|
|
+ </Form>
|
|
|
+ );
|
|
|
}
|
|
|
|
|
|
-export default withOrganization(OrganizationSettingsForm);
|
|
|
+export default OrganizationSettingsForm;
|
|
|
|
|
|
const PoweredByCodecov = styled('div')`
|
|
|
display: flex;
|