aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/app
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-04-13 10:51:47 +0200
committerSonarTech <sonartech@sonarsource.com>2018-04-16 20:20:47 +0200
commit35cb9ce02600f030954805ca506acf61da6625cc (patch)
tree4e3b744811814cba616bf35274bb749858a9d940 /server/sonar-web/src/main/js/app
parent2c36adcf2180253e3cd6832d6fb454e580a42cd2 (diff)
downloadsonarqube-35cb9ce02600f030954805ca506acf61da6625cc.tar.gz
sonarqube-35cb9ce02600f030954805ca506acf61da6625cc.zip
SONAR-10571 Show background task notifications only on related branch/pr
Diffstat (limited to 'server/sonar-web/src/main/js/app')
-rw-r--r--server/sonar-web/src/main/js/app/components/ComponentContainer.tsx61
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx67
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx17
3 files changed, 119 insertions, 26 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 530bb5f63d4..27165885dc5 100644
--- a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
@@ -25,12 +25,18 @@ import ComponentNav from './nav/component/ComponentNav';
import { Component, BranchLike } from '../types';
import handleRequiredAuthorization from '../utils/handleRequiredAuthorization';
import { getBranches, getPullRequests } from '../../api/branches';
-import { Task, getTasksForComponent } from '../../api/ce';
+import { Task, getTasksForComponent, PendingTask } from '../../api/ce';
import { getComponentData } from '../../api/components';
import { getComponentNavigation } from '../../api/nav';
import { fetchOrganizations } from '../../store/rootActions';
import { STATUSES } from '../../apps/background-tasks/constants';
-import { isPullRequest, isBranch } from '../../helpers/branches';
+import {
+ isPullRequest,
+ isBranch,
+ isMainBranch,
+ isLongLivingBranch,
+ isShortLivingBranch
+} from '../../helpers/branches';
interface Props {
children: any;
@@ -42,11 +48,10 @@ interface Props {
interface State {
branchLikes: BranchLike[];
- loading: boolean;
component?: Component;
currentTask?: Task;
- isInProgress?: boolean;
- isPending?: boolean;
+ loading: boolean;
+ pendingTasks?: PendingTask[];
}
export class ComponentContainer extends React.PureComponent<Props, State> {
@@ -132,17 +137,38 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
getTasksForComponent(component.key).then(
({ current, queue }) => {
if (this.mounted) {
- this.setState({
- currentTask: current,
- isInProgress: queue.some(task => task.status === STATUSES.IN_PROGRESS),
- isPending: queue.some(task => task.status === STATUSES.PENDING)
- });
+ this.setState({ currentTask: current, pendingTasks: queue });
}
},
() => {}
);
};
+ getCurrentTask = (branchLike?: BranchLike) => {
+ const { currentTask } = this.state;
+ return currentTask && this.isSameBranch(currentTask, branchLike) ? currentTask : undefined;
+ };
+
+ getPendingTasks = (branchLike?: BranchLike) => {
+ const { pendingTasks = [] } = this.state;
+ return pendingTasks.filter(task => this.isSameBranch(task, branchLike));
+ };
+
+ isSameBranch = (
+ task: Pick<PendingTask, 'branch' | 'branchType' | 'pullRequest'>,
+ branchLike?: BranchLike
+ ) => {
+ if (branchLike && !isMainBranch(branchLike)) {
+ if (isPullRequest(branchLike)) {
+ return branchLike.key === task.pullRequest;
+ }
+ if (isShortLivingBranch(branchLike) || isLongLivingBranch(branchLike)) {
+ return branchLike.type === task.branchType && branchLike.name === task.branch;
+ }
+ }
+ return !task.branch && !task.pullRequest;
+ };
+
handleComponentChange = (changes: {}) => {
if (this.mounted) {
this.setState(state => ({ component: { ...state.component, ...changes } }));
@@ -174,6 +200,11 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
? branchLikes.find(b => isPullRequest(b) && b.key === query.pullRequest)
: branchLikes.find(b => isBranch(b) && (query.branch ? b.name === query.branch : b.isMain));
+ const currentTask = this.getCurrentTask(branchLike);
+ const pendingTasks = this.getPendingTasks(branchLike);
+ const isInProgress = pendingTasks.some(task => task.status === STATUSES.IN_PROGRESS);
+ const isPending = pendingTasks.some(task => task.status === STATUSES.PENDING);
+
return (
<div>
{component &&
@@ -182,9 +213,9 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
branchLikes={branchLikes}
component={component}
currentBranchLike={branchLike}
- currentTask={this.state.currentTask}
- isInProgress={this.state.isInProgress}
- isPending={this.state.isPending}
+ currentTask={currentTask}
+ isInProgress={isInProgress}
+ isPending={isPending}
location={this.props.location}
/>
)}
@@ -197,8 +228,8 @@ export class ComponentContainer extends React.PureComponent<Props, State> {
branchLike,
branchLikes,
component,
- isInProgress: this.state.isInProgress,
- isPending: this.state.isPending,
+ isInProgress,
+ isPending,
onBranchesChange: this.handleBranchesChange,
onComponentChange: this.handleComponentChange
})
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 b0917c9d1c7..1611daa5d00 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
@@ -21,9 +21,16 @@ import * as React from 'react';
import { shallow, mount } from 'enzyme';
import { ComponentContainer } from '../ComponentContainer';
import { getBranches, getPullRequests } from '../../../api/branches';
-import { getTasksForComponent } from '../../../api/ce';
+import { getTasksForComponent, Task } from '../../../api/ce';
import { getComponentData } from '../../../api/components';
import { getComponentNavigation } from '../../../api/nav';
+import {
+ ShortLivingBranch,
+ MainBranch,
+ LongLivingBranch,
+ PullRequest,
+ BranchType
+} from '../../types';
jest.mock('../../../api/branches', () => ({
getBranches: jest.fn(() => Promise.resolve([])),
@@ -170,3 +177,61 @@ it('fetches status', async () => {
await new Promise(setImmediate);
expect(getTasksForComponent).toBeCalledWith('portfolioKey');
});
+
+it('filters correctly the pending tasks for a main branch', () => {
+ const wrapper = shallow(
+ <ComponentContainer fetchOrganizations={jest.fn()} location={{ query: { id: 'foo' } }}>
+ <Inner />
+ </ComponentContainer>
+ );
+
+ const component = wrapper.instance() as ComponentContainer;
+ const mainBranch: MainBranch = { isMain: true, name: 'master' };
+ const shortBranch: ShortLivingBranch = {
+ isMain: false,
+ mergeBranch: 'master',
+ name: 'feature',
+ type: BranchType.SHORT
+ };
+ const longBranch: LongLivingBranch = { isMain: false, name: 'branch-7.2', type: BranchType.LONG };
+ const pullRequest: PullRequest = {
+ base: 'feature',
+ branch: 'feature',
+ key: 'pr-89',
+ title: 'PR Feature'
+ };
+
+ expect(component.isSameBranch({}, undefined)).toBeTruthy();
+ expect(component.isSameBranch({}, mainBranch)).toBeTruthy();
+ expect(component.isSameBranch({}, shortBranch)).toBeFalsy();
+ expect(
+ component.isSameBranch({ branch: 'feature', branchType: 'SHORT' }, shortBranch)
+ ).toBeTruthy();
+ expect(
+ component.isSameBranch({ branch: 'feature', branchType: 'SHORT' }, longBranch)
+ ).toBeFalsy();
+ expect(
+ component.isSameBranch({ branch: 'feature', branchType: 'SHORT' }, longBranch)
+ ).toBeFalsy();
+ expect(
+ component.isSameBranch({ branch: 'branch-7.1', branchType: 'LONG' }, longBranch)
+ ).toBeFalsy();
+ expect(
+ component.isSameBranch({ branch: 'branch-7.2', branchType: 'LONG' }, pullRequest)
+ ).toBeFalsy();
+ expect(component.isSameBranch({ pullRequest: 'pr-89' }, pullRequest)).toBeTruthy();
+
+ const currentTask = { pullRequest: 'pr-89' } as Task;
+ const pendingTasks = [
+ currentTask,
+ { branch: 'feature', branchType: 'SHORT' } as Task,
+ {} as Task
+ ];
+ expect(component.getCurrentTask(undefined)).toBe(undefined);
+ component.setState({ currentTask });
+ expect(component.getCurrentTask(mainBranch)).toBe(undefined);
+ expect(component.getCurrentTask(pullRequest)).toMatchObject(currentTask);
+ component.setState({ pendingTasks });
+ expect(component.getPendingTasks(mainBranch)).toMatchObject([{}]);
+ expect(component.getPendingTasks(pullRequest)).toMatchObject([currentTask]);
+});
diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
index 366b240f357..f5ca55b6f83 100644
--- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
+++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.tsx
@@ -67,12 +67,12 @@ export default class ComponentNav extends React.PureComponent<Props> {
};
render() {
- const { currentTask, isInProgress, isPending } = this.props;
+ const { component, currentBranchLike, currentTask, isInProgress, isPending } = this.props;
let notifComponent;
if (isInProgress || isPending || (currentTask && currentTask.status === STATUSES.FAILED)) {
notifComponent = (
<ComponentNavBgTaskNotif
- component={this.props.component}
+ component={component}
currentTask={currentTask}
isInProgress={isInProgress}
isPending={isPending}
@@ -87,19 +87,16 @@ export default class ComponentNav extends React.PureComponent<Props> {
<div className="navbar-context-justified">
<ComponentNavHeader
branchLikes={this.props.branchLikes}
- component={this.props.component}
- currentBranchLike={this.props.currentBranchLike}
+ component={component}
+ currentBranchLike={currentBranchLike}
// to close dropdown on any location change
location={this.props.location}
/>
- <ComponentNavMeta
- branchLike={this.props.currentBranchLike}
- component={this.props.component}
- />
+ <ComponentNavMeta branchLike={currentBranchLike} component={component} />
</div>
<ComponentNavMenu
- branchLike={this.props.currentBranchLike}
- component={this.props.component}
+ branchLike={currentBranchLike}
+ component={component}
// to re-render selected menu item
location={this.props.location}
/>