aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/app/components
diff options
context:
space:
mode:
authorJeremy Davis <jeremy.davis@sonarsource.com>2022-03-22 16:24:08 +0100
committersonartech <sonartech@sonarsource.com>2022-03-23 20:02:45 +0000
commita38eda46c2f174efe54e6a584f12895a3d3c7f3c (patch)
treeef05b7691529a4cd77dba965e523469e7e5b7d3b /server/sonar-web/src/main/js/app/components
parent9a35b0e3e65302ee4f6c1b4cc2c5db71df5b0a5d (diff)
downloadsonarqube-a38eda46c2f174efe54e6a584f12895a3d3c7f3c.tar.gz
sonarqube-a38eda46c2f174efe54e6a584f12895a3d3c7f3c.zip
SONAR-15914 Extract branchstatus from redux
Diffstat (limited to 'server/sonar-web/src/main/js/app/components')
-rw-r--r--server/sonar-web/src/main/js/app/components/ComponentContainer.tsx13
-rw-r--r--server/sonar-web/src/main/js/app/components/GlobalContainer.tsx29
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx8
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap54
-rw-r--r--server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContext.tsx46
-rw-r--r--server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContextProvider.tsx100
-rw-r--r--server/sonar-web/src/main/js/app/components/branch-status/__tests__/BranchStatusContextProvider-test.tsx73
-rw-r--r--server/sonar-web/src/main/js/app/components/branch-status/withBranchStatus.tsx59
-rw-r--r--server/sonar-web/src/main/js/app/components/branch-status/withBranchStatusActions.tsx51
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/HeaderMeta.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/HeaderMeta-test.tsx.snap27
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap50
13 files changed, 454 insertions, 60 deletions
diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
index fc98bc60e17..a3d571fcb2e 100644
--- a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
@@ -19,7 +19,6 @@
*/
import { differenceBy } from 'lodash';
import * as React from 'react';
-import { connect } from 'react-redux';
import { getProjectAlmBinding, validateProjectAlmBinding } from '../../api/alm-settings';
import { getBranches, getPullRequests } from '../../api/branches';
import { getAnalysisStatus, getTasksForComponent } from '../../api/ce';
@@ -34,7 +33,6 @@ import {
} from '../../helpers/branch-like';
import { HttpStatus } from '../../helpers/request';
import { getPortfolioUrl } from '../../helpers/urls';
-import { registerBranchStatus } from '../../store/branches';
import {
ProjectAlmBindingConfigurationErrors,
ProjectAlmBindingResponse
@@ -46,6 +44,7 @@ import { Task, TaskStatuses, TaskTypes, TaskWarning } from '../../types/tasks';
import { Component, Status } from '../../types/types';
import handleRequiredAuthorization from '../utils/handleRequiredAuthorization';
import withAppStateContext from './app-state/withAppStateContext';
+import withBranchStatusActions from './branch-status/withBranchStatusActions';
import ComponentContainerNotFound from './ComponentContainerNotFound';
import { ComponentContext } from './ComponentContext';
import PageUnavailableDueToIndexation from './indexation/PageUnavailableDueToIndexation';
@@ -55,7 +54,7 @@ interface Props {
appState: AppState;
children: React.ReactElement;
location: Pick<Location, 'query' | 'pathname'>;
- registerBranchStatus: (branchLike: BranchLike, component: string, status: Status) => void;
+ updateBranchStatus: (branchLike: BranchLike, component: string, status: Status) => void;
router: Pick<Router, 'replace'>;
}
@@ -359,7 +358,7 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
registerBranchStatuses = (branchLikes: BranchLike[], component: Component) => {
branchLikes.forEach(branchLike => {
if (branchLike.status) {
- this.props.registerBranchStatus(
+ this.props.updateBranchStatus(
branchLike,
component.key,
branchLike.status.qualityGateStatus
@@ -467,8 +466,4 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
}
}
-const mapDispatchToProps = { registerBranchStatus };
-
-export default withRouter(
- connect(null, mapDispatchToProps)(withAppStateContext(ComponentContainer))
-);
+export default withRouter(withAppStateContext(withBranchStatusActions(ComponentContainer)));
diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx
index 52a5eccf943..3ee41a0606e 100644
--- a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx
@@ -21,6 +21,7 @@ import * as React from 'react';
import Workspace from '../../components/workspace/Workspace';
import A11yProvider from './a11y/A11yProvider';
import A11ySkipLinks from './a11y/A11ySkipLinks';
+import BranchStatusContextProvider from './branch-status/BranchStatusContextProvider';
import SuggestionsProvider from './embed-docs-modal/SuggestionsProvider';
import GlobalFooter from './GlobalFooter';
import GlobalMessagesContainer from './GlobalMessagesContainer';
@@ -50,19 +51,21 @@ export default function GlobalContainer(props: Props) {
<div className="global-container">
<div className="page-wrapper" id="container">
<div className="page-container">
- <Workspace>
- <IndexationContextProvider>
- <LanguagesContextProvider>
- <MetricsContextProvider>
- <GlobalNav location={props.location} />
- <GlobalMessagesContainer />
- <IndexationNotification />
- <UpdateNotification dismissable={true} />
- {props.children}
- </MetricsContextProvider>
- </LanguagesContextProvider>
- </IndexationContextProvider>
- </Workspace>
+ <BranchStatusContextProvider>
+ <Workspace>
+ <IndexationContextProvider>
+ <LanguagesContextProvider>
+ <MetricsContextProvider>
+ <GlobalNav location={props.location} />
+ <GlobalMessagesContainer />
+ <IndexationNotification />
+ <UpdateNotification dismissable={true} />
+ {props.children}
+ </MetricsContextProvider>
+ </LanguagesContextProvider>
+ </IndexationContextProvider>
+ </Workspace>
+ </BranchStatusContextProvider>
</div>
<PromotionNotification />
</div>
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
index a0bbceabb68..f1c4226abca 100644
--- a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
@@ -144,10 +144,10 @@ it("doesn't load branches portfolio", async () => {
});
it('updates branches on change', async () => {
- const registerBranchStatus = jest.fn();
+ const updateBranchStatus = jest.fn();
const wrapper = shallowRender({
location: mockLocation({ query: { id: 'portfolioKey' } }),
- registerBranchStatus
+ updateBranchStatus
});
wrapper.setState({
branchLikes: [mockMainBranch()],
@@ -160,7 +160,7 @@ it('updates branches on change', async () => {
expect(getBranches).toBeCalledWith('projectKey');
expect(getPullRequests).toBeCalledWith('projectKey');
await waitAndUpdate(wrapper);
- expect(registerBranchStatus).toBeCalledTimes(2);
+ expect(updateBranchStatus).toBeCalledTimes(2);
});
it('fetches status', async () => {
@@ -441,7 +441,7 @@ function shallowRender(props: Partial<ComponentContainer['props']> = {}) {
<ComponentContainer
appState={mockAppState()}
location={mockLocation({ query: { id: 'foo' } })}
- registerBranchStatus={jest.fn()}
+ updateBranchStatus={jest.fn()}
router={mockRouter()}
{...props}>
<Inner />
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap
index ab5e5905229..2f15d0754f4 100644
--- a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap
+++ b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalContainer-test.tsx.snap
@@ -15,33 +15,35 @@ exports[`should render correctly 1`] = `
<div
className="page-container"
>
- <Workspace>
- <withAppStateContext(IndexationContextProvider)>
- <LanguagesContextProvider>
- <MetricsContextProvider>
- <withCurrentUserContext(GlobalNav)
- location={
- Object {
- "action": "PUSH",
- "hash": "",
- "key": "key",
- "pathname": "/path",
- "query": Object {},
- "search": "",
- "state": Object {},
+ <BranchStatusContextProvider>
+ <Workspace>
+ <withAppStateContext(IndexationContextProvider)>
+ <LanguagesContextProvider>
+ <MetricsContextProvider>
+ <withCurrentUserContext(GlobalNav)
+ location={
+ Object {
+ "action": "PUSH",
+ "hash": "",
+ "key": "key",
+ "pathname": "/path",
+ "query": Object {},
+ "search": "",
+ "state": Object {},
+ }
}
- }
- />
- <Connect(GlobalMessages) />
- <withCurrentUserContext(withIndexationContext(IndexationNotification)) />
- <withCurrentUserContext(withAppStateContext(UpdateNotification))
- dismissable={true}
- />
- <ChildComponent />
- </MetricsContextProvider>
- </LanguagesContextProvider>
- </withAppStateContext(IndexationContextProvider)>
- </Workspace>
+ />
+ <Connect(GlobalMessages) />
+ <withCurrentUserContext(withIndexationContext(IndexationNotification)) />
+ <withCurrentUserContext(withAppStateContext(UpdateNotification))
+ dismissable={true}
+ />
+ <ChildComponent />
+ </MetricsContextProvider>
+ </LanguagesContextProvider>
+ </withAppStateContext(IndexationContextProvider)>
+ </Workspace>
+ </BranchStatusContextProvider>
</div>
<withCurrentUserContext(PromotionNotification) />
</div>
diff --git a/server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContext.tsx b/server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContext.tsx
new file mode 100644
index 00000000000..64220f8c13b
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContext.tsx
@@ -0,0 +1,46 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { BranchLike, BranchStatusData } from '../../../types/branch-like';
+import { QualityGateStatusCondition } from '../../../types/quality-gates';
+import { Dict, Status } from '../../../types/types';
+
+export interface BranchStatusContextInterface {
+ branchStatusByComponent: Dict<Dict<BranchStatusData>>;
+ fetchBranchStatus: (branchLike: BranchLike, projectKey: string) => void;
+ updateBranchStatus: (
+ branchLike: BranchLike,
+ projectKey: string,
+ status: Status,
+ conditions?: QualityGateStatusCondition[],
+ ignoredConditions?: boolean
+ ) => void;
+}
+
+export const BranchStatusContext = React.createContext<BranchStatusContextInterface>({
+ branchStatusByComponent: {},
+ fetchBranchStatus: () => {
+ throw Error('BranchStatusContext is not provided');
+ },
+ updateBranchStatus: () => {
+ throw Error('BranchStatusContext is not provided');
+ }
+});
diff --git a/server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContextProvider.tsx b/server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContextProvider.tsx
new file mode 100644
index 00000000000..fc0e828d5a2
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/branch-status/BranchStatusContextProvider.tsx
@@ -0,0 +1,100 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { getQualityGateProjectStatus } from '../../../api/quality-gates';
+import { getBranchLikeKey, getBranchLikeQuery } from '../../../helpers/branch-like';
+import { extractStatusConditionsFromProjectStatus } from '../../../helpers/qualityGates';
+import { BranchLike, BranchStatusData } from '../../../types/branch-like';
+import { QualityGateStatusCondition } from '../../../types/quality-gates';
+import { Dict, Status } from '../../../types/types';
+import { BranchStatusContext } from './BranchStatusContext';
+
+interface State {
+ branchStatusByComponent: Dict<Dict<BranchStatusData>>;
+}
+
+export default class BranchStatusContextProvider extends React.PureComponent<{}, State> {
+ mounted = false;
+ state: State = {
+ branchStatusByComponent: {}
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ fetchBranchStatus = async (branchLike: BranchLike, projectKey: string) => {
+ const projectStatus = await getQualityGateProjectStatus({
+ projectKey,
+ ...getBranchLikeQuery(branchLike)
+ }).catch(() => undefined);
+
+ if (!this.mounted || projectStatus === undefined) {
+ return;
+ }
+
+ const { ignoredConditions, status } = projectStatus;
+ const conditions = extractStatusConditionsFromProjectStatus(projectStatus);
+
+ this.updateBranchStatus(branchLike, projectKey, status, conditions, ignoredConditions);
+ };
+
+ updateBranchStatus = (
+ branchLike: BranchLike,
+ projectKey: string,
+ status: Status,
+ conditions?: QualityGateStatusCondition[],
+ ignoredConditions?: boolean
+ ) => {
+ const branchLikeKey = getBranchLikeKey(branchLike);
+
+ this.setState(({ branchStatusByComponent }) => ({
+ branchStatusByComponent: {
+ ...branchStatusByComponent,
+ [projectKey]: {
+ ...(branchStatusByComponent[projectKey] || {}),
+ [branchLikeKey]: {
+ conditions,
+ ignoredConditions,
+ status
+ }
+ }
+ }
+ }));
+ };
+
+ render() {
+ return (
+ <BranchStatusContext.Provider
+ value={{
+ branchStatusByComponent: this.state.branchStatusByComponent,
+ fetchBranchStatus: this.fetchBranchStatus,
+ updateBranchStatus: this.updateBranchStatus
+ }}>
+ {this.props.children}
+ </BranchStatusContext.Provider>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/app/components/branch-status/__tests__/BranchStatusContextProvider-test.tsx b/server/sonar-web/src/main/js/app/components/branch-status/__tests__/BranchStatusContextProvider-test.tsx
new file mode 100644
index 00000000000..9b9e26dfea3
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/branch-status/__tests__/BranchStatusContextProvider-test.tsx
@@ -0,0 +1,73 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { getQualityGateProjectStatus } from '../../../../api/quality-gates';
+import { mockBranch } from '../../../../helpers/mocks/branch-like';
+import { waitAndUpdate } from '../../../../helpers/testUtils';
+import { QualityGateProjectStatus } from '../../../../types/quality-gates';
+import BranchStatusContextProvider from '../BranchStatusContextProvider';
+
+jest.mock('../../../../api/quality-gates', () => ({
+ getQualityGateProjectStatus: jest.fn().mockResolvedValue({})
+}));
+
+describe('fetchBranchStatus', () => {
+ it('should get the branch status', async () => {
+ const projectKey = 'projectKey';
+ const branchName = 'branch-6.7';
+ const status: QualityGateProjectStatus = {
+ status: 'OK',
+ conditions: [],
+ ignoredConditions: false
+ };
+ (getQualityGateProjectStatus as jest.Mock).mockResolvedValueOnce(status);
+ const wrapper = shallowRender();
+
+ wrapper.instance().fetchBranchStatus(mockBranch({ name: branchName }), projectKey);
+
+ expect(getQualityGateProjectStatus).toBeCalledWith({ projectKey, branch: branchName });
+
+ await waitAndUpdate(wrapper);
+
+ expect(wrapper.state().branchStatusByComponent).toEqual({
+ [projectKey]: { [`branch-${branchName}`]: status }
+ });
+ });
+
+ it('should ignore errors', async () => {
+ (getQualityGateProjectStatus as jest.Mock).mockRejectedValueOnce('error');
+ const wrapper = shallowRender();
+
+ wrapper.instance().fetchBranchStatus(mockBranch(), 'project');
+
+ await waitAndUpdate(wrapper);
+
+ expect(wrapper.state().branchStatusByComponent).toEqual({});
+ });
+});
+
+function shallowRender() {
+ return shallow<BranchStatusContextProvider>(
+ <BranchStatusContextProvider>
+ <div />
+ </BranchStatusContextProvider>
+ );
+}
diff --git a/server/sonar-web/src/main/js/app/components/branch-status/withBranchStatus.tsx b/server/sonar-web/src/main/js/app/components/branch-status/withBranchStatus.tsx
new file mode 100644
index 00000000000..8f1ccf414de
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/branch-status/withBranchStatus.tsx
@@ -0,0 +1,59 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { getWrappedDisplayName } from '../../../components/hoc/utils';
+import { getBranchStatusByBranchLike } from '../../../helpers/branch-like';
+import { BranchLike, BranchStatusData } from '../../../types/branch-like';
+import { Component } from '../../../types/types';
+import { BranchStatusContext } from './BranchStatusContext';
+
+export default function withBranchStatus<
+ P extends { branchLike: BranchLike; component: Component }
+>(WrappedComponent: React.ComponentType<P & BranchStatusData>) {
+ return class WithBranchStatus extends React.PureComponent<Omit<P, keyof BranchStatusData>> {
+ static displayName = getWrappedDisplayName(WrappedComponent, 'withBranchStatus');
+
+ render() {
+ const { branchLike, component } = this.props;
+
+ return (
+ <BranchStatusContext.Consumer>
+ {({ branchStatusByComponent }) => {
+ const { conditions, ignoredConditions, status } = getBranchStatusByBranchLike(
+ branchStatusByComponent,
+ component.key,
+ branchLike
+ );
+
+ return (
+ <WrappedComponent
+ conditions={conditions}
+ ignoredConditions={ignoredConditions}
+ status={status}
+ {...(this.props as P)}
+ />
+ );
+ }}
+ </BranchStatusContext.Consumer>
+ );
+ }
+ };
+}
diff --git a/server/sonar-web/src/main/js/app/components/branch-status/withBranchStatusActions.tsx b/server/sonar-web/src/main/js/app/components/branch-status/withBranchStatusActions.tsx
new file mode 100644
index 00000000000..97ffc3de903
--- /dev/null
+++ b/server/sonar-web/src/main/js/app/components/branch-status/withBranchStatusActions.tsx
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { getWrappedDisplayName } from '../../../components/hoc/utils';
+import { BranchStatusContext, BranchStatusContextInterface } from './BranchStatusContext';
+
+export type WithBranchStatusActionsProps =
+ | Pick<BranchStatusContextInterface, 'fetchBranchStatus'>
+ | Pick<BranchStatusContextInterface, 'updateBranchStatus'>;
+
+export default function withBranchStatusActions<P>(
+ WrappedComponent: React.ComponentType<P & WithBranchStatusActionsProps>
+) {
+ return class WithBranchStatusActions extends React.PureComponent<
+ Omit<P, keyof BranchStatusContextInterface>
+ > {
+ static displayName = getWrappedDisplayName(WrappedComponent, 'withBranchStatusActions');
+
+ render() {
+ return (
+ <BranchStatusContext.Consumer>
+ {({ fetchBranchStatus, updateBranchStatus }) => (
+ <WrappedComponent
+ fetchBranchStatus={fetchBranchStatus}
+ updateBranchStatus={updateBranchStatus}
+ {...(this.props as P)}
+ />
+ )}
+ </BranchStatusContext.Consumer>
+ );
+ }
+ };
+}
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/HeaderMeta.tsx b/server/sonar-web/src/main/js/app/components/nav/component/HeaderMeta.tsx
index f77c4429974..1729155f1a0 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/HeaderMeta.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/HeaderMeta.tsx
@@ -86,7 +86,7 @@ export function HeaderMeta(props: HeaderMetaProps) {
<DetachIcon className="little-spacer-left" size={12} />
</a>
)}
- <BranchStatus branchLike={branchLike} component={component.key} />
+ <BranchStatus branchLike={branchLike} component={component} />
</div>
)}
</>
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/HeaderMeta-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/HeaderMeta-test.tsx.snap
index 14a257a1b3c..110542461d9 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/HeaderMeta-test.tsx.snap
+++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/__snapshots__/HeaderMeta-test.tsx.snap
@@ -196,7 +196,7 @@ exports[`should render correctly for a pull request 1`] = `
size={12}
/>
</a>
- <Connect(BranchStatus)
+ <withBranchStatus(BranchStatus)
branchLike={
Object {
"analysisDate": "2018-01-01",
@@ -208,7 +208,30 @@ exports[`should render correctly for a pull request 1`] = `
"url": "https://example.com/pull/1234",
}
}
- component="my-project"
+ component={
+ Object {
+ "analysisDate": "2017-01-02T00:00:00.000Z",
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ "version": "0.0.1",
+ }
+ }
/>
</div>
</Fragment>
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx
index eeb24400e8a..298ae9448f0 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/MenuItem.tsx
@@ -58,7 +58,7 @@ export function MenuItem(props: MenuItemProps) {
)}
</div>
<div className="spacer-left">
- <BranchStatus branchLike={branchLike} component={component.key} />
+ <BranchStatus branchLike={branchLike} component={component} />
</div>
</div>
</li>
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap
index 393f960966d..e9df1e0578f 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap
+++ b/server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/__snapshots__/MenuItem-test.tsx.snap
@@ -36,7 +36,7 @@ exports[`should render a main branch correctly 1`] = `
<div
className="spacer-left"
>
- <Connect(BranchStatus)
+ <withBranchStatus(BranchStatus)
branchLike={
Object {
"analysisDate": "2018-01-01",
@@ -45,7 +45,28 @@ exports[`should render a main branch correctly 1`] = `
"name": "master",
}
}
- component="my-project"
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
/>
</div>
</div>
@@ -85,7 +106,7 @@ exports[`should render a non-main branch, indented and selected item correctly 1
<div
className="spacer-left"
>
- <Connect(BranchStatus)
+ <withBranchStatus(BranchStatus)
branchLike={
Object {
"analysisDate": "2018-01-01",
@@ -96,7 +117,28 @@ exports[`should render a non-main branch, indented and selected item correctly 1
"title": "Foo Bar feature",
}
}
- component="my-project"
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
/>
</div>
</div>