Bladeren bron

SONAR-13075 Show a legend for the New Code period on the activity graph

tags/8.4.0.35506
Wouter Admiraal 4 jaren geleden
bovenliggende
commit
ae807c088e

+ 14
- 0
server/sonar-web/src/main/js/apps/overview/styles.css Bestand weergeven

@@ -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);
}

+ 7
- 2
server/sonar-web/src/main/js/components/activity-graph/GraphHistory.tsx Bestand weergeven

@@ -85,10 +85,15 @@ export default class GraphHistory extends React.PureComponent<Props, State> {
return (
<div className="activity-graph-container flex-grow display-flex-column display-flex-stretch display-flex-justify-center">
{isCustom && this.props.removeCustomMetric ? (
<GraphsLegendCustom removeMetric={this.props.removeCustomMetric} series={series} />
<GraphsLegendCustom
removeMetric={this.props.removeCustomMetric}
series={series}
showLeakLegend={Boolean(leakPeriodDate)}
/>
) : (
<GraphsLegendStatic series={series} />
<GraphsLegendStatic series={series} showLeakLegend={Boolean(leakPeriodDate)} />
)}

<div className="flex-1">
<AutoSizer>
{({ height, width }) => (

+ 34
- 27
server/sonar-web/src/main/js/components/activity-graph/GraphsLegendCustom.tsx Bestand weergeven

@@ -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 (
<div className="activity-graph-legends">
{series.map((serie, idx) => {
const hasData = hasDataValues(serie);
const legendItem = (
<GraphsLegendItem
index={idx}
metric={serie.name}
name={serie.translatedName}
removeMetric={removeMetric}
showWarning={!hasData}
/>
);
if (!hasData) {
<div className="activity-graph-legends display-flex-center">
<div className="flex-1">
{series.map((serie, idx) => {
const hasData = hasDataValues(serie);
const legendItem = (
<GraphsLegendItem
index={idx}
metric={serie.name}
name={serie.translatedName}
removeMetric={props.removeMetric}
showWarning={!hasData}
/>
);
if (!hasData) {
return (
<Tooltip
key={serie.name}
overlay={translate('project_activity.graphs.custom.metric_no_history')}>
<span className="spacer-left spacer-right">{legendItem}</span>
</Tooltip>
);
}
return (
<Tooltip
key={serie.name}
overlay={translate('project_activity.graphs.custom.metric_no_history')}>
<span className="spacer-left spacer-right">{legendItem}</span>
</Tooltip>
<span className="spacer-left spacer-right" key={serie.name}>
{legendItem}
</span>
);
}
return (
<span className="spacer-left spacer-right" key={serie.name}>
{legendItem}
</span>
);
})}
})}
</div>

{showLeakLegend && <GraphsLegendNewCode />}
</div>
);
}

+ 34
- 0
server/sonar-web/src/main/js/components/activity-graph/GraphsLegendNewCode.tsx Bestand weergeven

@@ -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 (
<Tooltip overlay={translate('project_activity.graphs.new_code_long')}>
<span
aria-label={translate('project_activity.graphs.new_code_long')}
className="activity-graph-new-code-legend display-flex-center pull-right note">
{translate('project_activity.graphs.new_code')}
</span>
</Tooltip>
);
}

+ 6
- 2
server/sonar-web/src/main/js/components/activity-graph/GraphsLegendStatic.tsx Bestand weergeven

@@ -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<Pick<Serie, 'name' | 'translatedName'>>;
showLeakLegend: boolean;
}

export default function GraphsLegendStatic({ series }: Props) {
export default function GraphsLegendStatic({ series, showLeakLegend }: GraphsLegendStaticProps) {
return (
<div className="activity-graph-legends">
{series.map((serie, idx) => (
@@ -37,6 +39,8 @@ export default function GraphsLegendStatic({ series }: Props) {
name={serie.translatedName}
/>
))}

{showLeakLegend && <GraphsLegendNewCode />}
</div>
);
}

+ 34
- 24
server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendCustom-test.tsx Bestand weergeven

@@ -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(<GraphsLegendCustom removeMetric={() => {}} series={SERIES} />)).toMatchSnapshot();
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ showLeakLegend: true })).toMatchSnapshot('with leak legend');
});

function shallowRender(props: Partial<GraphsLegendCustomProps> = {}) {
return shallow<GraphsLegendCustomProps>(
<GraphsLegendCustom
removeMetric={jest.fn()}
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'
}
]}
showLeakLegend={false}
{...props}
/>
);
}

+ 31
- 0
server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendNewCode-test.tsx Bestand weergeven

@@ -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(<GraphsLegendNewCode />);
}

+ 17
- 8
server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsLegendStatic-test.tsx Bestand weergeven

@@ -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(<GraphsLegendStatic series={SERIES} />)).toMatchSnapshot();
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
expect(shallowRender({ showLeakLegend: true })).toMatchSnapshot('with leak legend');
});

function shallowRender(props: Partial<GraphsLegendStaticProps> = {}) {
return shallow<GraphsLegendStaticProps>(
<GraphsLegendStatic
series={[
{ name: 'bugs', translatedName: 'Bugs' },
{ name: 'code_smells', translatedName: 'Code Smells' }
]}
showLeakLegend={false}
{...props}
/>
);
}

+ 1
- 0
server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphHistory-test.tsx.snap Bestand weergeven

@@ -28,6 +28,7 @@ exports[`should correctly render a graph 1`] = `
},
]
}
showLeakLegend={true}
/>
<div
className="flex-1"

+ 90
- 34
server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendCustom-test.tsx.snap Bestand weergeven

@@ -1,48 +1,104 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly the list of series 1`] = `
exports[`should render correctly: default 1`] = `
<div
className="activity-graph-legends"
className="activity-graph-legends display-flex-center"
>
<span
className="spacer-left spacer-right"
key="bugs"
<div
className="flex-1"
>
<GraphsLegendItem
index={0}
metric="bugs"
name="Bugs"
removeMetric={[Function]}
showWarning={false}
/>
</span>
<span
className="spacer-left spacer-right"
key="my_metric"
>
<GraphsLegendItem
index={1}
metric="my_metric"
name="My Metric"
removeMetric={[Function]}
showWarning={false}
/>
</span>
<Tooltip
key="foo"
overlay="project_activity.graphs.custom.metric_no_history"
<span
className="spacer-left spacer-right"
key="bugs"
>
<GraphsLegendItem
index={0}
metric="bugs"
name="Bugs"
removeMetric={[MockFunction]}
showWarning={false}
/>
</span>
<span
className="spacer-left spacer-right"
key="my_metric"
>
<GraphsLegendItem
index={1}
metric="my_metric"
name="My Metric"
removeMetric={[MockFunction]}
showWarning={false}
/>
</span>
<Tooltip
key="foo"
overlay="project_activity.graphs.custom.metric_no_history"
>
<span
className="spacer-left spacer-right"
>
<GraphsLegendItem
index={2}
metric="foo"
name="Foo"
removeMetric={[MockFunction]}
showWarning={true}
/>
</span>
</Tooltip>
</div>
</div>
`;

exports[`should render correctly: with leak legend 1`] = `
<div
className="activity-graph-legends display-flex-center"
>
<div
className="flex-1"
>
<span
className="spacer-left spacer-right"
key="bugs"
>
<GraphsLegendItem
index={2}
metric="foo"
name="Foo"
removeMetric={[Function]}
showWarning={true}
index={0}
metric="bugs"
name="Bugs"
removeMetric={[MockFunction]}
showWarning={false}
/>
</span>
</Tooltip>
<span
className="spacer-left spacer-right"
key="my_metric"
>
<GraphsLegendItem
index={1}
metric="my_metric"
name="My Metric"
removeMetric={[MockFunction]}
showWarning={false}
/>
</span>
<Tooltip
key="foo"
overlay="project_activity.graphs.custom.metric_no_history"
>
<span
className="spacer-left spacer-right"
>
<GraphsLegendItem
index={2}
metric="foo"
name="Foo"
removeMetric={[MockFunction]}
showWarning={true}
/>
</span>
</Tooltip>
</div>
<GraphsLegendNewCode />
</div>
`;

+ 14
- 0
server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendNewCode-test.tsx.snap Bestand weergeven

@@ -0,0 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render correctly: default 1`] = `
<Tooltip
overlay="project_activity.graphs.new_code_long"
>
<span
aria-label="project_activity.graphs.new_code_long"
className="activity-graph-new-code-legend display-flex-center pull-right note"
>
project_activity.graphs.new_code
</span>
</Tooltip>
`;

+ 23
- 1
server/sonar-web/src/main/js/components/activity-graph/__tests__/__snapshots__/GraphsLegendStatic-test.tsx.snap Bestand weergeven

@@ -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`] = `
<div
className="activity-graph-legends"
>
@@ -20,3 +20,25 @@ exports[`should render correctly the list of series 1`] = `
/>
</div>
`;

exports[`should render correctly: with leak legend 1`] = `
<div
className="activity-graph-legends"
>
<GraphsLegendItem
className="big-spacer-left big-spacer-right"
index={0}
key="bugs"
metric="bugs"
name="Bugs"
/>
<GraphsLegendItem
className="big-spacer-left big-spacer-right"
index={1}
key="code_smells"
metric="code_smells"
name="Code Smells"
/>
<GraphsLegendNewCode />
</div>
`;

+ 14
- 0
server/sonar-web/src/main/js/components/activity-graph/styles.css Bestand weergeven

@@ -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);
}

+ 2
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties Bestand weergeven

@@ -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

Laden…
Annuleren
Opslaan