aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-07-12 14:34:59 +0200
committerGrégoire Aubert <gregoire.aubert@sonarsource.com>2017-07-13 14:34:17 +0200
commit6f1a53f106d2c658996f4b7a6a6e1e493b653c86 (patch)
treed1f6cf82ebf9174268b043abd5e1230d43909e56 /server/sonar-web
parent33c3ac6b2feb1ef97cb16bc949a0840c388cceaf (diff)
downloadsonarqube-6f1a53f106d2c658996f4b7a6a6e1e493b653c86.tar.gz
sonarqube-6f1a53f106d2c658996f4b7a6a6e1e493b653c86.zip
SONAR-9403 Change style of metrics with no historical data in the custom graph legend
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js32
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js27
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendCustom-test.js9
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendItem-test.js8
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendCustom-test.js.snap26
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.js.snap11
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css7
-rw-r--r--server/sonar-web/src/main/js/apps/projectActivity/utils.js2
-rw-r--r--server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js40
9 files changed, 134 insertions, 28 deletions
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js
index e0236cb4e2f..540bb65961a 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendCustom.js
@@ -19,6 +19,9 @@
*/
import React from 'react';
import GraphsLegendItem from './GraphsLegendItem';
+import Tooltip from '../../../components/controls/Tooltip';
+import { hasDataValues } from '../utils';
+import { translate } from '../../../helpers/l10n';
import type { Metric } from '../types';
type Props = {
@@ -32,14 +35,31 @@ export default function GraphsLegendCustom({ metrics, removeMetric, series }: Pr
<div className="project-activity-graph-legends">
{series.map(serie => {
const metric = metrics.find(metric => metric.key === serie.name);
+ const hasData = hasDataValues(serie);
+ const legendItem = (
+ <GraphsLegendItem
+ metric={serie.name}
+ name={metric && metric.custom ? metric.name : serie.translatedName}
+ showWarning={!hasData}
+ style={serie.style}
+ removeMetric={removeMetric}
+ />
+ );
+ if (!hasData) {
+ return (
+ <Tooltip
+ key={serie.name}
+ overlay={translate('project_activity.graphs.custom.metric_no_history')}
+ placement="bottom">
+ <span className="spacer-left spacer-right">
+ {legendItem}
+ </span>
+ </Tooltip>
+ );
+ }
return (
<span className="spacer-left spacer-right" key={serie.name}>
- <GraphsLegendItem
- metric={serie.name}
- name={metric && metric.custom ? metric.name : serie.translatedName}
- style={serie.style}
- removeMetric={removeMetric}
- />
+ {legendItem}
</span>
);
})}
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js
index 79d294505c0..a458455a85c 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/GraphsLegendItem.js
@@ -17,15 +17,18 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+// @flow
import React from 'react';
import classNames from 'classnames';
-import CloseIcon from '../../../components/icons-components/CloseIcon';
+import AlertWarnIcon from '../../../components/icons-components/AlertWarnIcon';
import ChartLegendIcon from '../../../components/icons-components/ChartLegendIcon';
+import CloseIcon from '../../../components/icons-components/CloseIcon';
type Props = {
className?: string,
metric: string,
name: string,
+ showWarning?: boolean,
style: string,
removeMetric?: string => void
};
@@ -35,26 +38,30 @@ export default class GraphsLegendItem extends React.PureComponent {
handleClick = (e: Event) => {
e.preventDefault();
- this.props.removeMetric(this.props.metric);
+ if (this.props.removeMetric) {
+ this.props.removeMetric(this.props.metric);
+ }
};
render() {
const isActionable = this.props.removeMetric != null;
const legendClass = classNames(
{
- 'project-activity-graph-legend-actionable': isActionable
+ 'project-activity-graph-legend-actionable': isActionable,
+ 'alert-warning': this.props.showWarning
},
this.props.className
);
-
return (
<span className={legendClass}>
- <ChartLegendIcon
- className={classNames(
- 'spacer-right line-chart-legend',
- 'line-chart-legend-' + this.props.style
- )}
- />
+ {this.props.showWarning
+ ? <AlertWarnIcon className="spacer-right" />
+ : <ChartLegendIcon
+ className={classNames(
+ 'spacer-right line-chart-legend',
+ 'line-chart-legend-' + this.props.style
+ )}
+ />}
{this.props.name}
{isActionable &&
<a className="spacer-left button-clean text-text-top" href="#" onClick={this.handleClick}>
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendCustom-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendCustom-test.js
index 9b785f2213b..c115f0b5f13 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendCustom-test.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendCustom-test.js
@@ -22,8 +22,13 @@ import { shallow } from 'enzyme';
import GraphsLegendCustom from '../GraphsLegendCustom';
const SERIES = [
- { name: 'bugs', translatedName: 'Bugs', style: '2', data: [] },
- { name: 'my_metric', translatedName: 'metric.my_metric.name', style: '1', data: [] },
+ { name: 'bugs', translatedName: 'Bugs', style: '2', data: [{ x: 1, y: 1 }] },
+ {
+ name: 'my_metric',
+ translatedName: 'metric.my_metric.name',
+ style: '1',
+ data: [{ x: 1, y: 1 }]
+ },
{ name: 'foo', translatedName: 'Foo', style: '0', data: [] }
];
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendItem-test.js b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendItem-test.js
index a000a1dec04..5a0af033764 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendItem-test.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/GraphsLegendItem-test.js
@@ -38,3 +38,11 @@ it('should render correctly an actionable legend', () => {
)
).toMatchSnapshot();
});
+
+it('should render correctly legends with warning', () => {
+ expect(
+ shallow(
+ <GraphsLegendItem className="myclass" metric="foo" name="Foo" showWarning={true} style="1" />
+ )
+ ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendCustom-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendCustom-test.js.snap
index b19b8e8e654..d90f7a6843d 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendCustom-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendCustom-test.js.snap
@@ -11,6 +11,7 @@ exports[`should render correctly the list of series 1`] = `
metric="bugs"
name="Bugs"
removeMetric={[Function]}
+ showWarning={false}
style="2"
/>
</span>
@@ -21,18 +22,25 @@ exports[`should render correctly the list of series 1`] = `
metric="my_metric"
name="My Metric"
removeMetric={[Function]}
+ showWarning={false}
style="1"
/>
</span>
- <span
- className="spacer-left spacer-right"
+ <Tooltip
+ overlay="project_activity.graphs.custom.metric_no_history"
+ placement="bottom"
>
- <GraphsLegendItem
- metric="foo"
- name="Foo"
- removeMetric={[Function]}
- style="0"
- />
- </span>
+ <span
+ className="spacer-left spacer-right"
+ >
+ <GraphsLegendItem
+ metric="foo"
+ name="Foo"
+ removeMetric={[Function]}
+ showWarning={true}
+ style="0"
+ />
+ </span>
+ </Tooltip>
</div>
`;
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.js.snap b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.js.snap
index 84dc737ae03..1c660cd406e 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.js.snap
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/__snapshots__/GraphsLegendItem-test.js.snap
@@ -30,3 +30,14 @@ exports[`should render correctly an actionable legend 1`] = `
</a>
</span>
`;
+
+exports[`should render correctly legends with warning 1`] = `
+<span
+ className="alert-warning myclass"
+>
+ <AlertWarnIcon
+ className="spacer-right"
+ />
+ Foo
+</span>
+`;
diff --git a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css
index 4bec19f63e2..a42cbc13f2e 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css
+++ b/server/sonar-web/src/main/js/apps/projectActivity/components/projectActivity.css
@@ -65,10 +65,15 @@
.project-activity-graph-legend-actionable {
padding: 4px 12px;
- border: 1px solid #e6e6e6;
+ border-width: 1px;
+ border-style: solid;
border-radius: 12px;
}
+.project-activity-graph-legend-actionable:not(.alert-warning) {
+ border-color: #e6e6e6;
+}
+
.project-activity-graph-tooltip {
padding: 8px;
pointer-events: none;
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 6ea4c782138..83f5960b6e7 100644
--- a/server/sonar-web/src/main/js/apps/projectActivity/utils.js
+++ b/server/sonar-web/src/main/js/apps/projectActivity/utils.js
@@ -65,6 +65,8 @@ export const datesQueryChanged = (prevQuery: Query, nextQuery: Query): boolean =
return previousFrom !== nextFrom || previousTo !== nextTo;
};
+export const hasDataValues = (serie: Serie) => serie.data.some(point => point.y || point.y === 0);
+
export const hasHistoryData = (series: Array<Serie>) =>
series.some(serie => serie.data && serie.data.length > 2);
diff --git a/server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js b/server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js
new file mode 100644
index 00000000000..3ecabfa4c5a
--- /dev/null
+++ b/server/sonar-web/src/main/js/components/icons-components/AlertWarnIcon.js
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+// @flow
+import React from 'react';
+
+type Props = { className?: string, size?: number };
+
+export default function AlertWarnIcon({ className, size = 16 }: Props) {
+ /* eslint-disable max-len */
+ return (
+ <svg
+ xmlns="http://www.w3.org/2000/svg"
+ className={className}
+ height={size}
+ width={size}
+ viewBox="0 0 16 16">
+ <path
+ style={{ fill: '#ed7d20' }}
+ d="M8 1.143q1.866 0 3.442.92t2.496 2.496.92 3.442-.92 3.442-2.496 2.496-3.442.92-3.442-.92-2.496-2.496-.92-3.442.92-3.442 2.496-2.496T8 1.143zm1.143 11.134v-1.696q0-.125-.08-.21t-.196-.085H7.153q-.116 0-.205.089t-.089.205v1.696q0 .116.089.205t.205.089h1.714q.116 0 .196-.085t.08-.21zm-.018-3.072l.161-5.545q0-.107-.089-.161-.089-.071-.214-.071H7.019q-.125 0-.214.071-.089.054-.089.161l.152 5.545q0 .089.089.156t.214.067h1.652q.125 0 .21-.067t.094-.156z"
+ />
+ </svg>
+ );
+}