From ae807c088ed8910660af642766692feb62bfdab0 Mon Sep 17 00:00:00 2001 From: Wouter Admiraal Date: Mon, 15 Jun 2020 17:46:06 +0200 Subject: [PATCH] SONAR-13075 Show a legend for the New Code period on the activity graph --- .../src/main/js/apps/overview/styles.css | 14 ++ .../activity-graph/GraphHistory.tsx | 9 +- .../activity-graph/GraphsLegendCustom.tsx | 61 +++++---- .../activity-graph/GraphsLegendNewCode.tsx | 34 +++++ .../activity-graph/GraphsLegendStatic.tsx | 8 +- .../__tests__/GraphsLegendCustom-test.tsx | 58 ++++---- .../__tests__/GraphsLegendNewCode-test.tsx | 31 +++++ .../__tests__/GraphsLegendStatic-test.tsx | 25 ++-- .../__snapshots__/GraphHistory-test.tsx.snap | 1 + .../GraphsLegendCustom-test.tsx.snap | 124 +++++++++++++----- .../GraphsLegendNewCode-test.tsx.snap | 14 ++ .../GraphsLegendStatic-test.tsx.snap | 24 +++- .../js/components/activity-graph/styles.css | 14 ++ .../resources/org/sonar/l10n/core.properties | 2 + 14 files changed, 321 insertions(+), 98 deletions(-) create mode 100644 server/sonar-web/src/main/js/components/activity-graph/GraphsLegendNewCode.tsx create mode 100644 server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendNewCode-test.tsx create mode 100644 server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendNewCode-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/overview/styles.css b/server/sonar-web/src/main/js/apps/overview/styles.css index d07c641e950..ccdaeb8c740 100644 --- a/server/sonar-web/src/main/js/apps/overview/styles.css +++ b/server/sonar-web/src/main/js/apps/overview/styles.css @@ -272,6 +272,20 @@ margin-top: -30px; } +.overview-panel .activity-graph-new-code-legend { + position: relative; + z-index: var(--aboveNormalZIndex); + width: 12px; + overflow: hidden; + margin-top: 1px; + margin-left: calc(2 * var(--gridSize)); + text-indent: -9999px; +} + +.overview-panel .activity-graph-new-code-legend::after { + margin: 0; +} + .overview-analysis { color: var(--secondFontColor); } diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx index da94b4e0a08..366cc3aac76 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx @@ -85,10 +85,15 @@ export default class GraphHistory extends React.PureComponent { return (
{isCustom && this.props.removeCustomMetric ? ( - + ) : ( - + )} +
{({ height, width }) => ( diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendCustom.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendCustom.tsx index aaf71573351..0e120067944 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendCustom.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendCustom.tsx @@ -22,42 +22,49 @@ import Tooltip from 'sonar-ui-common/components/controls/Tooltip'; import { translate } from 'sonar-ui-common/helpers/l10n'; import { Serie } from '../../types/project-activity'; import GraphsLegendItem from './GraphsLegendItem'; +import GraphsLegendNewCode from './GraphsLegendNewCode'; import { hasDataValues } from './utils'; -interface Props { +export interface GraphsLegendCustomProps { removeMetric: (metric: string) => void; series: Serie[]; + showLeakLegend: boolean; } -export default function GraphsLegendCustom({ removeMetric, series }: Props) { +export default function GraphsLegendCustom(props: GraphsLegendCustomProps) { + const { series, showLeakLegend } = props; return ( -
- {series.map((serie, idx) => { - const hasData = hasDataValues(serie); - const legendItem = ( - - ); - if (!hasData) { +
+
+ {series.map((serie, idx) => { + const hasData = hasDataValues(serie); + const legendItem = ( + + ); + if (!hasData) { + return ( + + {legendItem} + + ); + } return ( - - {legendItem} - + + {legendItem} + ); - } - return ( - - {legendItem} - - ); - })} + })} +
+ + {showLeakLegend && }
); } diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendNewCode.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendNewCode.tsx new file mode 100644 index 00000000000..d128f685a74 --- /dev/null +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendNewCode.tsx @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 Tooltip from 'sonar-ui-common/components/controls/Tooltip'; +import { translate } from 'sonar-ui-common/helpers/l10n'; + +export default function GraphsLegendNewCode() { + return ( + + + {translate('project_activity.graphs.new_code')} + + + ); +} diff --git a/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendStatic.tsx b/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendStatic.tsx index 9d723ad7071..54349d2a99d 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendStatic.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/GraphsLegendStatic.tsx @@ -20,12 +20,14 @@ import * as React from 'react'; import { Serie } from '../../types/project-activity'; import GraphsLegendItem from './GraphsLegendItem'; +import GraphsLegendNewCode from './GraphsLegendNewCode'; -interface Props { +export interface GraphsLegendStaticProps { series: Array>; + showLeakLegend: boolean; } -export default function GraphsLegendStatic({ series }: Props) { +export default function GraphsLegendStatic({ series, showLeakLegend }: GraphsLegendStaticProps) { return (
{series.map((serie, idx) => ( @@ -37,6 +39,8 @@ export default function GraphsLegendStatic({ series }: Props) { name={serie.translatedName} /> ))} + + {showLeakLegend && }
); } diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendCustom-test.tsx b/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendCustom-test.tsx index 5b213e8141f..9d437a7a0f1 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendCustom-test.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendCustom-test.tsx @@ -20,29 +20,39 @@ import { shallow } from 'enzyme'; import * as React from 'react'; import { parseDate } from 'sonar-ui-common/helpers/dates'; -import GraphsLegendCustom from '../GraphsLegendCustom'; +import GraphsLegendCustom, { GraphsLegendCustomProps } from '../GraphsLegendCustom'; -const SERIES = [ - { - name: 'bugs', - translatedName: 'Bugs', - data: [{ x: parseDate('2017-05-16T13:50:02+0200'), y: 1 }], - type: 'INT' - }, - { - name: 'my_metric', - translatedName: 'My Metric', - data: [{ x: parseDate('2017-05-16T13:50:02+0200'), y: 1 }], - type: 'INT' - }, - { - name: 'foo', - translatedName: 'Foo', - data: [], - type: 'INT' - } -]; - -it('should render correctly the list of series', () => { - expect(shallow( {}} series={SERIES} />)).toMatchSnapshot(); +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender({ showLeakLegend: true })).toMatchSnapshot('with leak legend'); }); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendNewCode-test.tsx b/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendNewCode-test.tsx new file mode 100644 index 00000000000..7f74bf22117 --- /dev/null +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendNewCode-test.tsx @@ -0,0 +1,31 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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 GraphsLegendNewCode from '../GraphsLegendNewCode'; + +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('default'); +}); + +function shallowRender() { + return shallow(); +} diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendStatic-test.tsx b/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendStatic-test.tsx index a0492576ddf..4fa8d55ed7a 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendStatic-test.tsx +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendStatic-test.tsx @@ -19,13 +19,22 @@ */ import { shallow } from 'enzyme'; import * as React from 'react'; -import GraphsLegendStatic from '../GraphsLegendStatic'; +import GraphsLegendStatic, { GraphsLegendStaticProps } from '../GraphsLegendStatic'; -const SERIES = [ - { name: 'bugs', translatedName: 'Bugs', data: [] }, - { name: 'code_smells', translatedName: 'Code Smells', data: [] } -]; - -it('should render correctly the list of series', () => { - expect(shallow()).toMatchSnapshot(); +it('should render correctly', () => { + expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender({ showLeakLegend: true })).toMatchSnapshot('with leak legend'); }); + +function shallowRender(props: Partial = {}) { + return shallow( + + ); +} diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphHistory-test.tsx.snap b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphHistory-test.tsx.snap index cb92ba1524d..d3f064bbe89 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphHistory-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphHistory-test.tsx.snap @@ -28,6 +28,7 @@ exports[`should correctly render a graph 1`] = ` }, ] } + showLeakLegend={true} />
- - - - - - - + + + + + + + + + + +
+
+`; + +exports[`should render correctly: with leak legend 1`] = ` +
+
- + + + + + + + + +
+
`; diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendNewCode-test.tsx.snap b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendNewCode-test.tsx.snap new file mode 100644 index 00000000000..e6c7707ef39 --- /dev/null +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendNewCode-test.tsx.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: default 1`] = ` + + + project_activity.graphs.new_code + + +`; diff --git a/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendStatic-test.tsx.snap b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendStatic-test.tsx.snap index d1198d5f498..cb0be89ef40 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendStatic-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendStatic-test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`should render correctly the list of series 1`] = ` +exports[`should render correctly: default 1`] = `
@@ -20,3 +20,25 @@ exports[`should render correctly the list of series 1`] = ` />
`; + +exports[`should render correctly: with leak legend 1`] = ` +
+ + + +
+`; diff --git a/server/sonar-web/src/main/js/components/activity-graph/styles.css b/server/sonar-web/src/main/js/components/activity-graph/styles.css index 277d3084262..61d2759ce79 100644 --- a/server/sonar-web/src/main/js/components/activity-graph/styles.css +++ b/server/sonar-web/src/main/js/components/activity-graph/styles.css @@ -67,3 +67,17 @@ border-style: solid; border-radius: calc(1.5 * var(--gridSize)); } + +.activity-graph-new-code-legend { + margin-right: 10px; /* padding of activity graph */ +} + +.activity-graph-new-code-legend::after { + content: ''; + display: inline-block; + margin-left: calc(var(--gridSize) / 2); + width: var(--gridSize); + height: var(--gridSize); + background-color: var(--leakPrimaryColor); + border: 2px solid var(--leakSecondaryColor); +} diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index bb781d111ba..789b8cf6718 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -1301,6 +1301,8 @@ project_activity.events.tooltip.delete=Delete this event project_activity.new_code_period_start=New Code Period starts here project_activity.new_code_period_start.help=The analysis before this mark is the baseline for New Code comparison +project_activity.graphs.new_code=New Code +project_activity.graphs.new_code_long=New Code is indicated in yellow on the graph. project_activity.graphs.issues=Issues project_activity.graphs.coverage=Coverage project_activity.graphs.duplications=Duplications -- 2.39.5