Browse Source

ref(ui) Remove more context types. (#25769)

Replace usage of `router.replace` for the more broadly used
`browserHistory.replace` as well.
Mark Story 3 years ago
parent
commit
2accf61ee2

+ 9 - 10
static/app/views/permissionDenied.tsx

@@ -2,27 +2,26 @@ import React from 'react';
 import DocumentTitle from 'react-document-title';
 import {withRouter, WithRouterProps} from 'react-router';
 import * as Sentry from '@sentry/react';
-import PropTypes from 'prop-types';
 
 import ExternalLink from 'app/components/links/externalLink';
 import LoadingError from 'app/components/loadingError';
 import {t, tct} from 'app/locale';
 import {PageContent} from 'app/styles/organization';
+import {LightWeightOrganization, Project} from 'app/types';
 import getRouteStringFromRoutes from 'app/utils/getRouteStringFromRoutes';
+import withOrganization from 'app/utils/withOrganization';
+import withProject from 'app/utils/withProject';
 
 const ERROR_NAME = 'Permission Denied';
 
-type Props = WithRouterProps;
+type Props = WithRouterProps & {
+  organization: LightWeightOrganization;
+  project?: Project;
+};
 
 class PermissionDenied extends React.Component<Props> {
-  static contextTypes = {
-    organization: PropTypes.object,
-    project: PropTypes.object,
-  };
-
   componentDidMount() {
-    const {routes} = this.props;
-    const {organization, project} = this.context;
+    const {organization, project, routes} = this.props;
 
     const route = getRouteStringFromRoutes(routes);
     Sentry.withScope(scope => {
@@ -56,4 +55,4 @@ class PermissionDenied extends React.Component<Props> {
   }
 }
 
-export default withRouter(PermissionDenied);
+export default withRouter(withOrganization(withProject(PermissionDenied)));

+ 7 - 9
static/app/views/routeError.tsx

@@ -2,33 +2,31 @@ import React from 'react';
 import {withRouter, WithRouterProps} from 'react-router';
 import styled from '@emotion/styled';
 import * as Sentry from '@sentry/react';
-import PropTypes from 'prop-types';
 
 import Alert from 'app/components/alert';
 import {IconWarning} from 'app/icons';
 import {t, tct} from 'app/locale';
 import space from 'app/styles/space';
+import {LightWeightOrganization, Project} from 'app/types';
 import getRouteStringFromRoutes from 'app/utils/getRouteStringFromRoutes';
+import withOrganization from 'app/utils/withOrganization';
+import withProject from 'app/utils/withProject';
 
 type Props = WithRouterProps & {
+  organization: LightWeightOrganization;
   error: Error | undefined;
   /**
    * Disable logging to Sentry
    */
   disableLogSentry?: boolean;
   disableReport?: boolean;
+  project?: Project;
 };
 
 class RouteError extends React.Component<Props> {
-  static contextTypes = {
-    organization: PropTypes.object,
-    project: PropTypes.object,
-  };
-
   UNSAFE_componentWillMount() {
     const {error} = this.props;
-    const {disableLogSentry, disableReport, routes} = this.props;
-    const {organization, project} = this.context;
+    const {disableLogSentry, disableReport, organization, project, routes} = this.props;
 
     if (disableLogSentry) {
       return;
@@ -139,5 +137,5 @@ const Heading = styled('h3')`
   margin-bottom: ${space(1.5)};
 `;
 
-export default withRouter(RouteError);
+export default withRouter(withOrganization(withProject(RouteError)));
 export {RouteError};

+ 8 - 10
static/app/views/settings/organizationAuditLog/index.tsx

@@ -1,10 +1,10 @@
 import React from 'react';
 import {browserHistory, RouteComponentProps} from 'react-router';
-import PropTypes from 'prop-types';
 
 import {t} from 'app/locale';
-import SentryTypes from 'app/sentryTypes';
+import {LightWeightOrganization} from 'app/types';
 import routeTitleGen from 'app/utils/routeTitle';
+import withOrganization from 'app/utils/withOrganization';
 import AsyncView from 'app/views/asyncView';
 
 import AuditLogList from './auditLogList';
@@ -63,16 +63,14 @@ const EVENT_TYPES = [
   'plan.cancelled',
 ];
 
-type Props = RouteComponentProps<{orgId: string}, {}> & AsyncView['props'];
+type Props = RouteComponentProps<{orgId: string}, {}> &
+  AsyncView['props'] & {
+    organization: LightWeightOrganization;
+  };
 
 type State = AsyncView['state'];
 
 class OrganizationAuditLog extends AsyncView<Props, State> {
-  static contextTypes = {
-    router: PropTypes.object,
-    organization: SentryTypes.Organization,
-  };
-
   getEndpoints(): ReturnType<AsyncView['getEndpoints']> {
     return [
       [
@@ -86,7 +84,7 @@ class OrganizationAuditLog extends AsyncView<Props, State> {
   }
 
   getTitle() {
-    return routeTitleGen(t('Audit Log'), this.context.organization.slug, false);
+    return routeTitleGen(t('Audit Log'), this.props.organization.slug, false);
   }
 
   handleEventSelect = (value: string) => {
@@ -117,4 +115,4 @@ class OrganizationAuditLog extends AsyncView<Props, State> {
   }
 }
 
-export default OrganizationAuditLog;
+export default withOrganization(OrganizationAuditLog);

+ 11 - 17
static/app/views/settings/organizationTeams/teamSettings/index.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
-import {RouteComponentProps} from 'react-router';
-import PropTypes from 'prop-types';
+import {browserHistory, RouteComponentProps} from 'react-router';
 
 import {addErrorMessage, addSuccessMessage} from 'app/actionCreators/indicator';
 import {removeTeam, updateTeamSuccess} from 'app/actionCreators/teams';
@@ -10,8 +9,8 @@ import {Panel, PanelHeader} from 'app/components/panels';
 import teamSettingsFields from 'app/data/forms/teamSettingsFields';
 import {IconDelete} from 'app/icons';
 import {t, tct} from 'app/locale';
-import SentryTypes from 'app/sentryTypes';
-import {Scope, Team} from 'app/types';
+import {LightWeightOrganization, Scope, Team} from 'app/types';
+import withOrganization from 'app/utils/withOrganization';
 import AsyncView from 'app/views/asyncView';
 import Field from 'app/views/settings/components/forms/field';
 import Form from 'app/views/settings/components/forms/form';
@@ -20,19 +19,14 @@ import FormModel from 'app/views/settings/components/forms/model';
 
 import TeamModel from './model';
 
-type Props = {
+type Props = RouteComponentProps<{orgId: string; teamId: string}, {}> & {
+  organization: LightWeightOrganization;
   team: Team;
-} & RouteComponentProps<{orgId: string; teamId: string}, {}>;
+};
 
 type State = AsyncView['state'];
 
-export default class TeamSettings extends AsyncView<Props, State> {
-  static contextTypes = {
-    router: PropTypes.object,
-    location: PropTypes.object,
-    organization: SentryTypes.Organization,
-  };
-
+class TeamSettings extends AsyncView<Props, State> {
   model = new TeamModel(this.props.params.orgId, this.props.params.teamId);
 
   getTitle() {
@@ -47,7 +41,7 @@ export default class TeamSettings extends AsyncView<Props, State> {
     updateTeamSuccess(resp.slug, resp);
     if (id === 'slug') {
       addSuccessMessage(t('Team name changed'));
-      this.props.router.replace(
+      browserHistory.replace(
         `/settings/${this.props.params.orgId}/teams/${model.getValue(id)}/settings/`
       );
       this.setState({loading: true});
@@ -56,12 +50,11 @@ export default class TeamSettings extends AsyncView<Props, State> {
 
   handleRemoveTeam = async () => {
     await removeTeam(this.api, this.props.params);
-    this.props.router.replace(`/settings/${this.props.params.orgId}/teams/`);
+    browserHistory.replace(`/settings/${this.props.params.orgId}/teams/`);
   };
 
   renderBody() {
-    const {location, organization} = this.context;
-    const {team} = this.props;
+    const {location, organization, team} = this.props;
 
     const access = new Set<Scope>(organization.access);
 
@@ -113,3 +106,4 @@ export default class TeamSettings extends AsyncView<Props, State> {
     );
   }
 }
+export default withOrganization(TeamSettings);

+ 8 - 10
static/app/views/settings/project/projectServiceHooks.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 import {Link, WithRouterProps} from 'react-router';
-import PropTypes from 'prop-types';
 
 import {
   addErrorMessage,
@@ -13,7 +12,8 @@ import Switch from 'app/components/switchButton';
 import Truncate from 'app/components/truncate';
 import {IconAdd, IconFlag} from 'app/icons';
 import {t} from 'app/locale';
-import {ServiceHook} from 'app/types';
+import {LightWeightOrganization, ServiceHook} from 'app/types';
+import withOrganization from 'app/utils/withOrganization';
 import AsyncView from 'app/views/asyncView';
 import EmptyMessage from 'app/views/settings/components/emptyMessage';
 import Field from 'app/views/settings/components/forms/field';
@@ -52,18 +52,15 @@ function ServiceHookRow({orgId, projectId, hook, onToggleActive}: RowProps) {
   );
 }
 
-type Props = WithRouterProps<{orgId: string; projectId: string}, {}>;
+type Props = WithRouterProps<{orgId: string; projectId: string}, {}> & {
+  organization: LightWeightOrganization;
+};
 
 type State = {
   hookList: null | ServiceHook[];
 } & AsyncView['state'];
 
-export default class ProjectServiceHooks extends AsyncView<Props, State> {
-  static contextTypes = {
-    router: PropTypes.object,
-    organization: PropTypes.object.isRequired,
-  };
-
+class ProjectServiceHooks extends AsyncView<Props, State> {
   getEndpoints(): ReturnType<AsyncView['getEndpoints']> {
     const {orgId, projectId} = this.props.params;
     return [['hookList', `/projects/${orgId}/${projectId}/hooks/`]];
@@ -143,7 +140,7 @@ export default class ProjectServiceHooks extends AsyncView<Props, State> {
       hookList && hookList.length > 0 ? this.renderResults() : this.renderEmpty();
 
     const {orgId, projectId} = this.props.params;
-    const access = new Set(this.context.organization.access);
+    const access = new Set(this.props.organization.access);
 
     return (
       <React.Fragment>
@@ -168,3 +165,4 @@ export default class ProjectServiceHooks extends AsyncView<Props, State> {
     );
   }
 }
+export default withOrganization(ProjectServiceHooks);

+ 12 - 12
tests/js/spec/views/teamSettings.spec.jsx

@@ -1,4 +1,5 @@
 import React from 'react';
+import {browserHistory} from 'react-router';
 
 import {mountWithTheme} from 'sentry-test/enzyme';
 import {mountGlobalModal} from 'sentry-test/modal';
@@ -23,15 +24,12 @@ describe('TeamSettings', function () {
       method: 'PUT',
     });
     const mountOptions = TestStubs.routerContext();
-    const {router} = mountOptions.context;
 
     const wrapper = mountWithTheme(
       <TeamSettings
-        routes={[]}
-        router={router}
-        params={{orgId: 'org', teamId: team.slug}}
         team={team}
         onTeamChange={() => {}}
+        params={{orgId: 'org', teamId: team.slug}}
       />,
       mountOptions
     );
@@ -53,7 +51,9 @@ describe('TeamSettings', function () {
     );
 
     await tick();
-    expect(router.replace).toHaveBeenCalledWith('/settings/org/teams/new-slug/settings/');
+    expect(browserHistory.replace).toHaveBeenCalledWith(
+      '/settings/org/teams/new-slug/settings/'
+    );
   });
 
   it('needs team:admin in order to see an enabled Remove Team button', function () {
@@ -61,12 +61,15 @@ describe('TeamSettings', function () {
 
     const wrapper = mountWithTheme(
       <TeamSettings
-        routes={[]}
-        params={{orgId: 'org', teamId: team.slug}}
         team={team}
         onTeamChange={() => {}}
+        params={{orgId: 'org', teamId: team.slug}}
       />,
-      TestStubs.routerContext([{organization: TestStubs.Organization({access: []})}])
+      TestStubs.routerContext([
+        {
+          organization: TestStubs.Organization({access: []}),
+        },
+      ])
     );
     expect(wrapper.find('Panel').last().find('Button').prop('disabled')).toBe(true);
   });
@@ -77,7 +80,6 @@ describe('TeamSettings', function () {
       url: `/teams/org/${team.slug}/`,
       method: 'DELETE',
     });
-    const routerPushMock = jest.fn();
     jest.spyOn(TeamStore, 'trigger');
     TeamStore.loadInitialData([
       {
@@ -88,8 +90,6 @@ describe('TeamSettings', function () {
 
     const wrapper = mountWithTheme(
       <TeamSettings
-        router={{replace: routerPushMock}}
-        routes={[]}
         params={{orgId: 'org', teamId: team.slug}}
         team={team}
         onTeamChange={() => {}}
@@ -115,7 +115,7 @@ describe('TeamSettings', function () {
 
     await tick();
     await tick();
-    expect(routerPushMock).toHaveBeenCalledWith('/settings/org/teams/');
+    expect(browserHistory.replace).toHaveBeenCalledWith('/settings/org/teams/');
 
     expect(TeamStore.getAll()).toEqual([]);