From: Grégoire Aubert Date: Fri, 13 Apr 2018 08:51:47 +0000 (+0200) Subject: SONAR-10571 Show background task notifications only on related branch/pr X-Git-Tag: 7.5~1357 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=35cb9ce02600f030954805ca506acf61da6625cc;p=sonarqube.git SONAR-10571 Show background task notifications only on related branch/pr --- diff --git a/server/sonar-web/src/main/js/api/ce.ts b/server/sonar-web/src/main/js/api/ce.ts index 3046f797467..21eaff0990d 100644 --- a/server/sonar-web/src/main/js/api/ce.ts +++ b/server/sonar-web/src/main/js/api/ce.ts @@ -21,12 +21,16 @@ import { getJSON, post, RequestData } from '../helpers/request'; import throwGlobalError from '../app/utils/throwGlobalError'; export interface PendingTask { + branch?: string; + branchType?: string; componentKey: string; componentName: string; componentQualifier: string; id: string; logs: boolean; organization: string; + pullRequest?: string; + pullRequestTitle?: string; status: string; submittedAt: Date; submitterLogin?: string; 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 { @@ -132,17 +137,38 @@ export class ComponentContainer extends React.PureComponent { 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, + 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 { ? 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 (
{component && @@ -182,9 +213,9 @@ export class ComponentContainer extends React.PureComponent { 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 { 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( + + + + ); + + 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 { }; 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 = ( {
- +