aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-07-10 17:49:11 +0200
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-07-13 14:34:17 +0200
commitd9f1651b8dba7756edf2eb1fce0c0d607e46f05f (patch)
tree9cf5990469f8cff26c1ab2246e2e4189f883859e
parentfaaee054e871a3aac2167063e411d1373956e082 (diff)
downloadsonarqube-d9f1651b8dba7756edf2eb1fce0c0d607e46f05f.tar.gz
sonarqube-d9f1651b8dba7756edf2eb1fce0c0d607e46f05f.zip
Fix a bug with the version badges when filtering on an event category
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/__tests__/__snapshots__/utils-test.js.snap102
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/__tests__/utils-test.js29
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js168
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js41
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js116
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js20
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityAnalysesList-test.js.snap336
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap46
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/utils.js25
9 files changed, 698 insertions, 185 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/__tests__/__snapshots__/utils-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/__tests__/__snapshots__/utils-test.js.snap
index e9144bf2e16..14647a21294 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/__tests__/__snapshots__/utils-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/projectActivity/__tests__/__snapshots__/utils-test.js.snap
@@ -53,6 +53,108 @@ Array [
]
`;
+exports[`getAnalysesByVersionByDay should also filter analysis based on the query 1`] = `
+Array [
+ Object {
+ "byDay": Object {
+ "2017-4-16": Array [
+ Object {
+ "date": 2017-05-16T05:09:59.000Z,
+ "events": Array [
+ Object {
+ "category": "VERSION",
+ "key": "AVyM9oI1HjR_PLDzRciU",
+ "name": "1.0",
+ },
+ Object {
+ "category": "QUALITY_PROFILE",
+ "key": "AVwQF7zXl-nNFgFWOJ3W",
+ "name": "Changes in 'Default - SonarSource conventions' (Java)",
+ },
+ ],
+ "key": "AVwQF7kwl-nNFgFWOJ3V",
+ },
+ ],
+ "2017-4-18": Array [
+ Object {
+ "date": 2017-05-18T12:13:07.000Z,
+ "events": Array [
+ Object {
+ "category": "QUALITY_PROFILE",
+ "key": "AVxZtC-N7841nF4RNEMJ",
+ "name": "Changes in 'Default - SonarSource conventions' (Java)",
+ },
+ ],
+ "key": "AVxZtCpH7841nF4RNEMI",
+ },
+ ],
+ },
+ "key": "AVyM9oI1HjR_PLDzRciU",
+ "version": "1.0",
+ },
+ Object {
+ "byDay": Object {},
+ "key": undefined,
+ "version": undefined,
+ },
+]
+`;
+
+exports[`getAnalysesByVersionByDay should also filter analysis based on the query 2`] = `
+Array [
+ Object {
+ "byDay": Object {
+ "2017-5-9": Array [
+ Object {
+ "date": 2017-06-09T09:12:27.000Z,
+ "events": Array [
+ Object {
+ "category": "VERSION",
+ "key": "AVyM9oI1HjR_PLDzRciU",
+ "name": "1.1-SNAPSHOT",
+ },
+ ],
+ "key": "AVyM9n3cHjR_PLDzRciT",
+ },
+ ],
+ },
+ "key": "AVyM9oI1HjR_PLDzRciU",
+ "version": "1.1-SNAPSHOT",
+ },
+ Object {
+ "byDay": Object {
+ "2017-4-18": Array [
+ Object {
+ "date": 2017-05-18T12:13:07.000Z,
+ "events": Array [
+ Object {
+ "category": "QUALITY_PROFILE",
+ "key": "AVxZtC-N7841nF4RNEMJ",
+ "name": "Changes in 'Default - SonarSource conventions' (Java)",
+ },
+ ],
+ "key": "AVxZtCpH7841nF4RNEMI",
+ },
+ ],
+ "2017-5-9": Array [
+ Object {
+ "date": 2017-06-09T09:12:27.000Z,
+ "events": Array [],
+ "key": "AVyMjlK1HjR_PLDzRbB9",
+ },
+ ],
+ },
+ "key": "AVyM9oI1HjR_PLDzRciU",
+ "version": "1.0",
+ },
+ Object {
+ "byDay": Object {},
+ "key": undefined,
+ "version": undefined,
+ },
+]
+`;
+
exports[`getAnalysesByVersionByDay should correctly map analysis by versions and by days 1`] = `
Array [
Object {
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/__tests__/utils-test.js b/server/sonar-web/src/main/js/apps/projectActivity/__tests__/utils-test.js
index c165f9740b8..b3e4f2b28cf 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/__tests__/utils-test.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/__tests__/utils-test.js
@@ -108,7 +108,34 @@ describe('generateSeries', () => {
describe('getAnalysesByVersionByDay', () => {
it('should correctly map analysis by versions and by days', () => {
- expect(utils.getAnalysesByVersionByDay(ANALYSES)).toMatchSnapshot();
+ expect(
+ utils.getAnalysesByVersionByDay(ANALYSES, {
+ category: '',
+ customMetrics: [],
+ graph: 'overview',
+ project: 'foo'
+ })
+ ).toMatchSnapshot();
+ });
+ it('should also filter analysis based on the query', () => {
+ expect(
+ utils.getAnalysesByVersionByDay(ANALYSES, {
+ category: 'QUALITY_PROFILE',
+ customMetrics: [],
+ graph: 'overview',
+ project: 'foo'
+ })
+ ).toMatchSnapshot();
+ expect(
+ utils.getAnalysesByVersionByDay(ANALYSES, {
+ category: '',
+ customMetrics: [],
+ graph: 'overview',
+ project: 'foo',
+ to: new Date('2017-06-09T11:12:27+0200'),
+ from: new Date('2017-05-18T14:13:07+0200')
+ })
+ ).toMatchSnapshot();
});
});
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js
index a0a8a41dd31..2706f9d2b14 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.js
@@ -65,30 +65,48 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
}
componentDidUpdate(prevProps: Props) {
- if (this.scrollContainer) {
- const selectedDateChanged = selectedDateQueryChanged(prevProps.query, this.props.query);
- if (selectedDateChanged || prevProps.analysis !== this.props.analyses) {
- if (selectedDateChanged && this.props.query.selectedDate) {
- const selectedDate = this.props.query.selectedDate.valueOf();
- for (let i = 1; i < this.analyses.length; i++) {
- if (Number(this.analyses[i].getAttribute('data-date')) === selectedDate) {
- const containerHeight = this.scrollContainer.offsetHeight - 100;
- const scrollDiff = Math.abs(
- this.scrollContainer.scrollTop - this.analyses[i].offsetTop
- );
- // Center only the extremities and the ones outside of the container
- if (scrollDiff > containerHeight || scrollDiff < 100) {
- this.resetScrollTop(this.analyses[i].offsetTop - containerHeight / 2);
- }
- break;
- }
- }
- } else if (activityQueryChanged(prevProps.query, this.props.query)) {
- this.resetScrollTop(0, true);
+ if (!this.scrollContainer) {
+ return;
+ }
+ if (
+ this.props.query.selectedDate &&
+ (selectedDateQueryChanged(prevProps.query, this.props.query) ||
+ prevProps.analyses !== this.props.analyses)
+ ) {
+ this.scrollToDate(this.props.query.selectedDate);
+ } else if (activityQueryChanged(prevProps.query, this.props.query)) {
+ this.resetScrollTop(0, true);
+ }
+ }
+
+ handleScroll = () => this.updateStickyBadges(true);
+
+ resetScrollTop = (newScrollTop: number, forceBadgeAlignement?: boolean) => {
+ this.scrollContainer.scrollTop = newScrollTop;
+ for (let i = 1; i < this.badges.length; i++) {
+ this.badges[i].removeAttribute('originOffsetTop');
+ this.badges[i].classList.remove('sticky');
+ }
+ this.updateStickyBadges(forceBadgeAlignement);
+ };
+
+ scrollToDate = (targetDate: ?Date) => {
+ if (!this.scrollContainer || !targetDate) {
+ return;
+ }
+ const date = targetDate.valueOf();
+ for (let i = 1; i < this.analyses.length; i++) {
+ if (Number(this.analyses[i].getAttribute('data-date')) === date) {
+ const containerHeight = this.scrollContainer.offsetHeight - 100;
+ const scrollDiff = Math.abs(this.scrollContainer.scrollTop - this.analyses[i].offsetTop);
+ // Center only the extremities and the ones outside of the container
+ if (scrollDiff > containerHeight || scrollDiff < 100) {
+ this.resetScrollTop(this.analyses[i].offsetTop - containerHeight / 2);
}
+ break;
}
}
- }
+ };
updateStickyBadges = (forceBadgeAlignement?: boolean) => {
if (this.scrollContainer && this.badges) {
@@ -119,23 +137,14 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
}
};
- handleScroll = () => this.updateStickyBadges(true);
-
- resetScrollTop = (newScrollTop: number, forceBadgeAlignement?: boolean) => {
- this.scrollContainer.scrollTop = newScrollTop;
- for (let i = 1; i < this.badges.length; i++) {
- this.badges[i].removeAttribute('originOffsetTop');
- this.badges[i].classList.remove('sticky');
- }
- this.updateStickyBadges(forceBadgeAlignement);
- };
-
- updateSelectedDate = (date: Date) => {
- this.props.updateQuery({ selectedDate: date });
- };
+ updateSelectedDate = (date: Date) => this.props.updateQuery({ selectedDate: date });
render() {
- if (this.props.analyses.length === 0) {
+ const byVersionByDay = getAnalysesByVersionByDay(this.props.analyses, this.props.query);
+ const hasFilteredData =
+ byVersionByDay.length > 1 ||
+ (byVersionByDay.length === 1 && Object.keys(byVersionByDay[0].byDay).length > 0);
+ if (this.props.analyses.length === 0 || !hasFilteredData) {
return (
<div className={this.props.className}>
{this.props.loading
@@ -146,7 +155,6 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
}
const firstAnalysisKey = this.props.analyses[0].key;
- const byVersionByDay = getAnalysesByVersionByDay(this.props.analyses);
const selectedDate = this.props.query.selectedDate
? this.props.query.selectedDate.valueOf()
: null;
@@ -155,46 +163,52 @@ export default class ProjectActivityAnalysesList extends React.PureComponent {
className={classNames('project-activity-versions-list', this.props.className)}
onScroll={this.handleScroll}
ref={element => (this.scrollContainer = element)}>
- {byVersionByDay.map((version, idx) => (
- <li key={version.key || 'noversion'}>
- {version.version &&
- <div className={classNames('project-activity-version-badge', { first: idx === 0 })}>
- <span className="badge">
- {version.version}
- </span>
- </div>}
- <ul className="project-activity-days-list">
- {Object.keys(version.byDay).map(day => (
- <li
- key={day}
- className="project-activity-day"
- data-day={moment(Number(day)).format('YYYY-MM-DD')}>
- <div className="project-activity-date">
- <FormattedDate date={Number(day)} format="LL" />
- </div>
- <ul className="project-activity-analyses-list">
- {version.byDay[day] != null &&
- version.byDay[day].map(analysis => (
- <ProjectActivityAnalysis
- addCustomEvent={this.props.addCustomEvent}
- addVersion={this.props.addVersion}
- analysis={analysis}
- canAdmin={this.props.canAdmin}
- changeEvent={this.props.changeEvent}
- deleteAnalysis={this.props.deleteAnalysis}
- deleteEvent={this.props.deleteEvent}
- isFirst={analysis.key === firstAnalysisKey}
- key={analysis.key}
- selected={analysis.date.valueOf() === selectedDate}
- updateSelectedDate={this.updateSelectedDate}
- />
- ))}
- </ul>
- </li>
- ))}
- </ul>
- </li>
- ))}
+ {byVersionByDay.map((version, idx) => {
+ const days = Object.keys(version.byDay);
+ if (days.length <= 0) {
+ return null;
+ }
+ return (
+ <li key={version.key || 'noversion'}>
+ {version.version &&
+ <div className={classNames('project-activity-version-badge', { first: idx === 0 })}>
+ <span className="badge">
+ {version.version}
+ </span>
+ </div>}
+ <ul className="project-activity-days-list">
+ {days.map(day => (
+ <li
+ key={day}
+ className="project-activity-day"
+ data-day={moment(Number(day)).format('YYYY-MM-DD')}>
+ <div className="project-activity-date">
+ <FormattedDate date={Number(day)} format="LL" />
+ </div>
+ <ul className="project-activity-analyses-list">
+ {version.byDay[day] != null &&
+ version.byDay[day].map(analysis => (
+ <ProjectActivityAnalysis
+ addCustomEvent={this.props.addCustomEvent}
+ addVersion={this.props.addVersion}
+ analysis={analysis}
+ canAdmin={this.props.canAdmin}
+ changeEvent={this.props.changeEvent}
+ deleteAnalysis={this.props.deleteAnalysis}
+ deleteEvent={this.props.deleteEvent}
+ isFirst={analysis.key === firstAnalysisKey}
+ key={analysis.key}
+ selected={analysis.date.valueOf() === selectedDate}
+ updateSelectedDate={this.updateSelectedDate}
+ />
+ ))}
+ </ul>
+ </li>
+ ))}
+ </ul>
+ </li>
+ );
+ })}
{this.props.analysesLoading && <li className="text-center"><i className="spinner" /></li>}
</ul>
);
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js
index 59c9485d937..e3a3b582796 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityApp.js
@@ -24,7 +24,7 @@ import moment from 'moment';
import ProjectActivityPageHeader from './ProjectActivityPageHeader';
import ProjectActivityAnalysesList from './ProjectActivityAnalysesList';
import ProjectActivityGraphs from './ProjectActivityGraphs';
-import { getDisplayedHistoryMetrics, activityQueryChanged } from '../utils';
+import { getDisplayedHistoryMetrics } from '../utils';
import { translate } from '../../../helpers/l10n';
import './projectActivity.css';
import type { Analysis, MeasureHistory, Metric, Query } from '../types';
@@ -46,40 +46,8 @@ type Props = {
updateQuery: (newQuery: Query) => void
};
-type State = {
- filteredAnalyses: Array<Analysis>
-};
-
export default class ProjectActivityApp extends React.PureComponent {
props: Props;
- state: State;
-
- constructor(props: Props) {
- super(props);
- this.state = { filteredAnalyses: this.filterAnalyses(props.analyses, props.query) };
- }
-
- componentWillReceiveProps(nextProps: Props) {
- if (
- nextProps.analyses !== this.props.analyses ||
- activityQueryChanged(this.props.query, nextProps.query)
- ) {
- this.setState({ filteredAnalyses: this.filterAnalyses(nextProps.analyses, nextProps.query) });
- }
- }
-
- filterAnalyses = (analyses: Array<Analysis>, query: Query): Array<Analysis> => {
- if (!query.category && !query.from && !query.to) {
- return analyses;
- }
- return analyses.filter(analysis => {
- const isAfterFrom = !query.from || analysis.date >= query.from;
- const isBeforeTo = !query.to || analysis.date <= query.to;
- const hasSelectedCategoryEvents =
- !query.category || analysis.events.find(event => event.category === query.category) != null;
- return isAfterFrom && isBeforeTo && hasSelectedCategoryEvents;
- });
- };
getMetricType = () => {
const historyMetrics = getDisplayedHistoryMetrics(
@@ -92,8 +60,7 @@ export default class ProjectActivityApp extends React.PureComponent {
};
render() {
- const { measuresHistory, query } = this.props;
- const { filteredAnalyses } = this.state;
+ const { analyses, measuresHistory, query } = this.props;
const { configuration } = this.props.project;
const canAdmin = configuration ? configuration.showHistory : false;
return (
@@ -113,7 +80,7 @@ export default class ProjectActivityApp extends React.PureComponent {
addCustomEvent={this.props.addCustomEvent}
addVersion={this.props.addVersion}
analysesLoading={this.props.analysesLoading}
- analyses={filteredAnalyses}
+ analyses={analyses}
canAdmin={canAdmin}
className="boxed-group-inner"
changeEvent={this.props.changeEvent}
@@ -126,7 +93,7 @@ export default class ProjectActivityApp extends React.PureComponent {
</div>
<div className="project-activity-layout-page-main">
<ProjectActivityGraphs
- analyses={filteredAnalyses}
+ analyses={analyses}
leakPeriodDate={moment(this.props.project.leakPeriodDate).toDate()}
loading={this.props.graphLoading}
measuresHistory={measuresHistory}
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js
new file mode 100644
index 00000000000..762c2d5efe3
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.js
@@ -0,0 +1,116 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 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 React from 'react';
+import { shallow } from 'enzyme';
+import ProjectActivityAnalysesList from '../ProjectActivityAnalysesList';
+
+const ANALYSES = [
+ {
+ key: 'A1',
+ date: new Date('2016-10-27T16:33:50+0000'),
+ events: [
+ {
+ key: 'E1',
+ category: 'VERSION',
+ name: '6.5-SNAPSHOT'
+ }
+ ]
+ },
+ {
+ key: 'A2',
+ date: new Date('2016-10-27T12:21:15+0000'),
+ events: []
+ },
+ {
+ key: 'A3',
+ date: new Date('2016-10-26T12:17:29+0000'),
+ events: [
+ {
+ key: 'E2',
+ category: 'VERSION',
+ name: '6.4'
+ },
+ {
+ key: 'E3',
+ category: 'OTHER',
+ name: 'foo'
+ }
+ ]
+ },
+ {
+ key: 'A4',
+ date: new Date('2016-10-24T16:33:50+0000'),
+ events: [
+ {
+ key: 'E1',
+ category: 'QUALITY_GATE',
+ name: 'Quality gate changed to red...'
+ }
+ ]
+ }
+];
+
+const DEFAULT_PROPS = {
+ addCustomEvent: () => {},
+ addVersion: () => {},
+ analyses: ANALYSES,
+ analysesLoading: false,
+ canAdmin: false,
+ changeEvent: () => {},
+ deleteAnalysis: () => {},
+ deleteEvent: () => {},
+ loading: false,
+ query: { category: '', graph: 'overview', project: 'org.sonarsource.sonarqube:sonarqube' },
+ updateQuery: () => {}
+};
+
+jest.mock('moment', () => date => ({
+ startOf: () => {
+ return {
+ valueOf: () => `${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`
+ };
+ },
+ toDate: () => new Date(date),
+ format: format => `Formated.${format}:${date}`
+}));
+
+window.Number = val => val;
+
+it('should render correctly', () => {
+ expect(shallow(<ProjectActivityAnalysesList {...DEFAULT_PROPS} />)).toMatchSnapshot();
+});
+
+it('should correctly filter analyses by category', () => {
+ const wrapper = shallow(<ProjectActivityAnalysesList {...DEFAULT_PROPS} />);
+ wrapper.setProps({ query: { ...DEFAULT_PROPS.query, category: 'QUALITY_GATE' } });
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should correctly filter analyses by date range', () => {
+ const wrapper = shallow(<ProjectActivityAnalysesList {...DEFAULT_PROPS} />);
+ wrapper.setProps({
+ query: {
+ ...DEFAULT_PROPS.query,
+ from: new Date('2016-10-27T16:33:50+0000'),
+ to: new Date('2016-10-27T16:33:50+0000')
+ }
+ });
+ expect(wrapper).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js
index 22f85b2a28f..21c0a40d10c 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-test.js
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
-import { mount, shallow } from 'enzyme';
+import { shallow } from 'enzyme';
import ProjectActivityApp from '../ProjectActivityApp';
const ANALYSES = [
@@ -87,21 +87,3 @@ const DEFAULT_PROPS = {
it('should render correctly', () => {
expect(shallow(<ProjectActivityApp {...DEFAULT_PROPS} />)).toMatchSnapshot();
});
-
-it('should correctly filter analyses by category', () => {
- const wrapper = mount(<ProjectActivityApp {...DEFAULT_PROPS} />);
- wrapper.setProps({ query: { ...DEFAULT_PROPS.query, category: 'VERSION' } });
- expect(wrapper.state()).toMatchSnapshot();
-});
-
-it('should correctly filter analyses by date range', () => {
- const wrapper = mount(<ProjectActivityApp {...DEFAULT_PROPS} />);
- wrapper.setProps({
- query: {
- ...DEFAULT_PROPS.query,
- from: new Date('2016-10-27T12:21:15+0200'),
- to: new Date('2016-10-27T12:21:15+0200')
- }
- });
- expect(wrapper.state()).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityAnalysesList-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityAnalysesList-test.js.snap
new file mode 100644
index 00000000000..53dc51ec351
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityAnalysesList-test.js.snap
@@ -0,0 +1,336 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should correctly filter analyses by category 1`] = `
+<ul
+ className="project-activity-versions-list"
+ onScroll={[Function]}
+>
+ <li>
+ <div
+ className="project-activity-version-badge first"
+ >
+ <span
+ className="badge"
+ >
+ 6.4
+ </span>
+ </div>
+ <ul
+ className="project-activity-days-list"
+ >
+ <li
+ className="project-activity-day"
+ data-day="Formated.YYYY-MM-DD:2016-9-24"
+ >
+ <div
+ className="project-activity-date"
+ >
+ <FormattedDate
+ date="2016-9-24"
+ format="LL"
+ />
+ </div>
+ <ul
+ className="project-activity-analyses-list"
+ >
+ <ProjectActivityAnalysis
+ addCustomEvent={[Function]}
+ addVersion={[Function]}
+ analysis={
+ Object {
+ "date": 2016-10-24T16:33:50.000Z,
+ "events": Array [
+ Object {
+ "category": "QUALITY_GATE",
+ "key": "E1",
+ "name": "Quality gate changed to red...",
+ },
+ ],
+ "key": "A4",
+ }
+ }
+ canAdmin={false}
+ changeEvent={[Function]}
+ deleteAnalysis={[Function]}
+ deleteEvent={[Function]}
+ isFirst={false}
+ selected={false}
+ updateSelectedDate={[Function]}
+ />
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+`;
+
+exports[`should correctly filter analyses by date range 1`] = `
+<ul
+ className="project-activity-versions-list"
+ onScroll={[Function]}
+>
+ <li>
+ <div
+ className="project-activity-version-badge first"
+ >
+ <span
+ className="badge"
+ >
+ 6.5-SNAPSHOT
+ </span>
+ </div>
+ <ul
+ className="project-activity-days-list"
+ >
+ <li
+ className="project-activity-day"
+ data-day="Formated.YYYY-MM-DD:2016-9-27"
+ >
+ <div
+ className="project-activity-date"
+ >
+ <FormattedDate
+ date="2016-9-27"
+ format="LL"
+ />
+ </div>
+ <ul
+ className="project-activity-analyses-list"
+ >
+ <ProjectActivityAnalysis
+ addCustomEvent={[Function]}
+ addVersion={[Function]}
+ analysis={
+ Object {
+ "date": 2016-10-27T16:33:50.000Z,
+ "events": Array [
+ Object {
+ "category": "VERSION",
+ "key": "E1",
+ "name": "6.5-SNAPSHOT",
+ },
+ ],
+ "key": "A1",
+ }
+ }
+ canAdmin={false}
+ changeEvent={[Function]}
+ deleteAnalysis={[Function]}
+ deleteEvent={[Function]}
+ isFirst={true}
+ selected={false}
+ updateSelectedDate={[Function]}
+ />
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+`;
+
+exports[`should render correctly 1`] = `
+<ul
+ className="project-activity-versions-list"
+ onScroll={[Function]}
+>
+ <li>
+ <div
+ className="project-activity-version-badge first"
+ >
+ <span
+ className="badge"
+ >
+ 6.5-SNAPSHOT
+ </span>
+ </div>
+ <ul
+ className="project-activity-days-list"
+ >
+ <li
+ className="project-activity-day"
+ data-day="Formated.YYYY-MM-DD:2016-9-27"
+ >
+ <div
+ className="project-activity-date"
+ >
+ <FormattedDate
+ date="2016-9-27"
+ format="LL"
+ />
+ </div>
+ <ul
+ className="project-activity-analyses-list"
+ >
+ <ProjectActivityAnalysis
+ addCustomEvent={[Function]}
+ addVersion={[Function]}
+ analysis={
+ Object {
+ "date": 2016-10-27T16:33:50.000Z,
+ "events": Array [
+ Object {
+ "category": "VERSION",
+ "key": "E1",
+ "name": "6.5-SNAPSHOT",
+ },
+ ],
+ "key": "A1",
+ }
+ }
+ canAdmin={false}
+ changeEvent={[Function]}
+ deleteAnalysis={[Function]}
+ deleteEvent={[Function]}
+ isFirst={true}
+ selected={false}
+ updateSelectedDate={[Function]}
+ />
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <div
+ className="project-activity-version-badge"
+ >
+ <span
+ className="badge"
+ >
+ 6.4
+ </span>
+ </div>
+ <ul
+ className="project-activity-days-list"
+ >
+ <li
+ className="project-activity-day"
+ data-day="Formated.YYYY-MM-DD:2016-9-27"
+ >
+ <div
+ className="project-activity-date"
+ >
+ <FormattedDate
+ date="2016-9-27"
+ format="LL"
+ />
+ </div>
+ <ul
+ className="project-activity-analyses-list"
+ >
+ <ProjectActivityAnalysis
+ addCustomEvent={[Function]}
+ addVersion={[Function]}
+ analysis={
+ Object {
+ "date": 2016-10-27T12:21:15.000Z,
+ "events": Array [],
+ "key": "A2",
+ }
+ }
+ canAdmin={false}
+ changeEvent={[Function]}
+ deleteAnalysis={[Function]}
+ deleteEvent={[Function]}
+ isFirst={false}
+ selected={false}
+ updateSelectedDate={[Function]}
+ />
+ </ul>
+ </li>
+ <li
+ className="project-activity-day"
+ data-day="Formated.YYYY-MM-DD:2016-9-26"
+ >
+ <div
+ className="project-activity-date"
+ >
+ <FormattedDate
+ date="2016-9-26"
+ format="LL"
+ />
+ </div>
+ <ul
+ className="project-activity-analyses-list"
+ >
+ <ProjectActivityAnalysis
+ addCustomEvent={[Function]}
+ addVersion={[Function]}
+ analysis={
+ Object {
+ "date": 2016-10-26T12:17:29.000Z,
+ "events": Array [
+ Object {
+ "category": "VERSION",
+ "key": "E2",
+ "name": "6.4",
+ },
+ Object {
+ "category": "OTHER",
+ "key": "E3",
+ "name": "foo",
+ },
+ ],
+ "key": "A3",
+ }
+ }
+ canAdmin={false}
+ changeEvent={[Function]}
+ deleteAnalysis={[Function]}
+ deleteEvent={[Function]}
+ isFirst={false}
+ selected={false}
+ updateSelectedDate={[Function]}
+ />
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <ul
+ className="project-activity-days-list"
+ >
+ <li
+ className="project-activity-day"
+ data-day="Formated.YYYY-MM-DD:2016-9-24"
+ >
+ <div
+ className="project-activity-date"
+ >
+ <FormattedDate
+ date="2016-9-24"
+ format="LL"
+ />
+ </div>
+ <ul
+ className="project-activity-analyses-list"
+ >
+ <ProjectActivityAnalysis
+ addCustomEvent={[Function]}
+ addVersion={[Function]}
+ analysis={
+ Object {
+ "date": 2016-10-24T16:33:50.000Z,
+ "events": Array [
+ Object {
+ "category": "QUALITY_GATE",
+ "key": "E1",
+ "name": "Quality gate changed to red...",
+ },
+ ],
+ "key": "A4",
+ }
+ }
+ canAdmin={false}
+ changeEvent={[Function]}
+ deleteAnalysis={[Function]}
+ deleteEvent={[Function]}
+ isFirst={false}
+ selected={false}
+ updateSelectedDate={[Function]}
+ />
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+`;
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap
index 7fa450f12c8..f966955c248 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/ProjectActivityApp-test.js.snap
@@ -1,51 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should correctly filter analyses by category 1`] = `
-Object {
- "filteredAnalyses": Array [
- Object {
- "date": 2016-10-27T14:33:50.000Z,
- "events": Array [
- Object {
- "category": "VERSION",
- "key": "E1",
- "name": "6.5-SNAPSHOT",
- },
- ],
- "key": "A1",
- },
- Object {
- "date": 2016-10-26T10:17:29.000Z,
- "events": Array [
- Object {
- "category": "VERSION",
- "key": "E2",
- "name": "6.4",
- },
- Object {
- "category": "OTHER",
- "key": "E3",
- "name": "foo",
- },
- ],
- "key": "A3",
- },
- ],
-}
-`;
-
-exports[`should correctly filter analyses by date range 1`] = `
-Object {
- "filteredAnalyses": Array [
- Object {
- "date": 2016-10-27T10:21:15.000Z,
- "events": Array [],
- "key": "A2",
- },
- ],
-}
-`;
-
exports[`should render correctly 1`] = `
<div
className="page page-limited"
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/utils.js b/server/sonar-web/src/main/js/apps/projectActivity/utils.js
index a42c389972c..6ea4c782138 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/utils.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/utils.js
@@ -130,7 +130,8 @@ export const generateSeries = (
};
export const getAnalysesByVersionByDay = (
- analyses: Array<Analysis>
+ analyses: Array<Analysis>,
+ query: Query
): Array<{
version: ?string,
key: ?string,
@@ -142,16 +143,30 @@ export const getAnalysesByVersionByDay = (
}
const currentVersion = acc[acc.length - 1];
const day = moment(analysis.date).startOf('day').valueOf().toString();
- if (!currentVersion.byDay[day]) {
- currentVersion.byDay[day] = [];
+
+ let matchFilters = true;
+ if (query.category || query.from || query.to) {
+ const isAfterFrom = !query.from || analysis.date >= query.from;
+ const isBeforeTo = !query.to || analysis.date <= query.to;
+ const hasSelectedCategoryEvents =
+ !query.category || analysis.events.find(event => event.category === query.category) != null;
+ matchFilters = isAfterFrom && isBeforeTo && hasSelectedCategoryEvents;
+ }
+
+ if (matchFilters) {
+ if (!currentVersion.byDay[day]) {
+ currentVersion.byDay[day] = [];
+ }
+ currentVersion.byDay[day].push(analysis);
}
- currentVersion.byDay[day].push(analysis);
const versionEvent = analysis.events.find(event => event.category === 'VERSION');
if (versionEvent && versionEvent.category === 'VERSION') {
currentVersion.version = versionEvent.name;
currentVersion.key = versionEvent.key;
- acc.push({ version: undefined, key: undefined, byDay: {} });
+ if (Object.keys(currentVersion.byDay).length > 0) {
+ acc.push({ version: undefined, key: undefined, byDay: {} });
+ }
}
return acc;
}, []);