Browse Source

SONAR-19987 Updating new code marker position in project activity's page

tags/10.3.0.82913
Revanshu Paliwal 8 months ago
parent
commit
b433b03043

+ 51
- 9
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysesList.tsx View File

@@ -20,7 +20,7 @@
import styled from '@emotion/styled';
import classNames from 'classnames';
import { isEqual } from 'date-fns';
import { Badge, LightLabel, Spinner, themeColor } from 'design-system';
import { Badge, HelperHintIcon, LightLabel, Spinner, themeColor } from 'design-system';
import * as React from 'react';
import Tooltip from '../../../components/controls/Tooltip';
import DateFormatter from '../../../components/intl/DateFormatter';
@@ -29,8 +29,8 @@ import { translate } from '../../../helpers/l10n';

import { ComponentQualifier } from '../../../types/component';
import { ParsedAnalysis } from '../../../types/project-activity';
import { Query, activityQueryChanged, getAnalysesByVersionByDay } from '../utils';
import ProjectActivityAnalysis from './ProjectActivityAnalysis';
import { AnalysesByDay, Query, activityQueryChanged, getAnalysesByVersionByDay } from '../utils';
import ProjectActivityAnalysis, { BaselineMarker } from './ProjectActivityAnalysis';

interface Props {
onAddCustomEvent: (analysis: string, name: string, category?: string) => Promise<void>;
@@ -72,11 +72,36 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro
this.props.onUpdateQuery({ selectedDate: date });
};

shouldRenderBaselineMarker(analysis: ParsedAnalysis): boolean {
return Boolean(this.props.leakPeriodDate && isEqual(this.props.leakPeriodDate, analysis.date));
getNewCodePeriodStartKey(versionByDay: AnalysesByDay[]): {
firstNewCodeAnalysisKey: string | undefined;
baselineAnalysisKey: string | undefined;
} {
const { leakPeriodDate } = this.props;
if (!leakPeriodDate) {
return { firstNewCodeAnalysisKey: undefined, baselineAnalysisKey: undefined };
}
// In response, the first new code analysis comes before the baseline analysis
// This variable is to track the previous analysis and return when next is baseline analysis
let prevAnalysis;
for (const version of versionByDay) {
const days = Object.keys(version.byDay);
for (const day of days) {
for (const analysis of version.byDay[day]) {
if (isEqual(leakPeriodDate, analysis.date)) {
return {
firstNewCodeAnalysisKey: prevAnalysis?.key,
baselineAnalysisKey: analysis.key,
};
}
prevAnalysis = analysis;
}
}
}

return { firstNewCodeAnalysisKey: undefined, baselineAnalysisKey: undefined };
}

renderAnalysis(analysis: ParsedAnalysis) {
renderAnalysis(analysis: ParsedAnalysis, newCodeKey?: string) {
const firstAnalysisKey = this.props.analyses[0].key;

const selectedDate = this.props.query.selectedDate
@@ -94,7 +119,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro
onChangeEvent={this.props.onChangeEvent}
onDeleteAnalysis={this.props.onDeleteAnalysis}
onDeleteEvent={this.props.onDeleteEvent}
isBaseline={this.shouldRenderBaselineMarker(analysis)}
isBaseline={analysis.key === newCodeKey}
isFirst={analysis.key === firstAnalysisKey}
key={analysis.key}
selected={analysis.date.valueOf() === selectedDate}
@@ -105,6 +130,7 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro

render() {
const byVersionByDay = getAnalysesByVersionByDay(this.props.analyses, this.props.query);
const newCodePeriod = this.getNewCodePeriodStartKey(byVersionByDay);
const hasFilteredData =
byVersionByDay.length > 1 ||
(byVersionByDay.length === 1 && Object.keys(byVersionByDay[0].byDay).length > 0);
@@ -136,6 +162,21 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro
: undefined,
}}
>
{newCodePeriod.baselineAnalysisKey !== undefined &&
newCodePeriod.firstNewCodeAnalysisKey === undefined && (
<BaselineMarker className="sw-body-sm sw-mb-2">
<span className="sw-py-1/2 sw-px-1">
{translate('project_activity.new_code_period_start')}
</span>
<Tooltip
overlay={translate('project_activity.new_code_period_start.help')}
placement="top"
>
<HelperHintIcon className="sw-ml-1" />
</Tooltip>
</BaselineMarker>
)}

{byVersionByDay.map((version, idx) => {
const days = Object.keys(version.byDay);
if (days.length <= 0) {
@@ -172,8 +213,9 @@ export default class ProjectActivityAnalysesList extends React.PureComponent<Pro
<DateFormatter date={Number(day)} long />
</div>
<ul className="it__project-activity-analyses-list">
{version.byDay[day] != null &&
version.byDay[day].map((analysis) => this.renderAnalysis(analysis))}
{version.byDay[day]?.map((analysis) =>
this.renderAnalysis(analysis, newCodePeriod.firstNewCodeAnalysisKey),
)}
</ul>
</li>
))}

+ 14
- 14
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityAnalysis.tsx View File

@@ -101,19 +101,6 @@ function ProjectActivityAnalysis(props: ProjectActivityAnalysisProps) {

return (
<>
{isBaseline && (
<BaselineMarker className="sw-body-sm sw-mt-2">
<span className="sw-py-1/2 sw-px-1">
{translate('project_activity.new_code_period_start')}
</span>
<Tooltip
overlay={translate('project_activity.new_code_period_start.help')}
placement="top"
>
<HelperHintIcon className="sw-ml-1" />
</Tooltip>
</BaselineMarker>
)}
<Tooltip mouseEnterDelay={0.5} overlay={tooltipContent} placement="left">
<ActivityAnalysisListItem
className={classNames(
@@ -213,6 +200,19 @@ function ProjectActivityAnalysis(props: ProjectActivityAnalysisProps) {
)}
</ActivityAnalysisListItem>
</Tooltip>
{isBaseline && (
<BaselineMarker className="sw-body-sm sw-mt-2">
<span className="sw-py-1/2 sw-px-1">
{translate('project_activity.new_code_period_start')}
</span>
<Tooltip
overlay={translate('project_activity.new_code_period_start.help')}
placement="top"
>
<HelperHintIcon className="sw-ml-1" />
</Tooltip>
</BaselineMarker>
)}
</>
);
}
@@ -245,7 +245,7 @@ const ActivityAnalysisListItem = styled.li`
}
`;

const BaselineMarker = styled.li`
export const BaselineMarker = styled.li`
display: flex;
align-items: center;
border-bottom: ${themeBorder('default', 'newCodeHighlight')};

+ 34
- 0
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityApp-it.tsx View File

@@ -163,6 +163,40 @@ describe('rendering', () => {
expect(ui.baseline.get()).toBeInTheDocument();
});

it('should correctly show the baseline marker when first new code analysis is not present but baseline analysis is present', async () => {
const { ui } = getPageObject();

renderProjectActivityAppContainer(
mockComponent({
leakPeriodDate: parseDate('2017-03-03T22:00:00.000Z').toDateString(),
breadcrumbs: [
{ key: 'breadcrumb', name: 'breadcrumb', qualifier: ComponentQualifier.Project },
],
}),
);

await ui.appLoaded();

expect(ui.baseline.get()).toBeInTheDocument();
});

it('should not show the baseline marker when first new code analysis and baseline analysis is not present', async () => {
const { ui } = getPageObject();

renderProjectActivityAppContainer(
mockComponent({
leakPeriodDate: parseDate('2017-03-10T22:00:00.000Z').toDateString(),
breadcrumbs: [
{ key: 'breadcrumb', name: 'breadcrumb', qualifier: ComponentQualifier.Project },
],
}),
);

await ui.appLoaded();

expect(ui.baseline.query()).not.toBeInTheDocument();
});

it('should only show certain security hotspot-related metrics for a project', async () => {
const { ui } = getPageObject();


+ 1
- 1
server/sonar-web/src/main/js/apps/projectActivity/utils.ts View File

@@ -59,7 +59,7 @@ export function historyQueryChanged(prevQuery: Query, nextQuery: Query) {
return prevQuery.graph !== nextQuery.graph;
}

interface AnalysesByDay {
export interface AnalysesByDay {
byDay: Dict<ParsedAnalysis[]>;
version: string | null;
key: string | null;

+ 2
- 2
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -1847,8 +1847,8 @@ project_activity.delete_analysis.question=Are you sure you want to delete this a
project_activity.filter_events=Filter events
project_activity.events.tooltip.edit=Edit this event
project_activity.events.tooltip.delete=Delete this event
project_activity.new_code_period_start=New Code starts here
project_activity.new_code_period_start.help=The analysis before this mark is the baseline for New Code comparison
project_activity.new_code_period_start=Everything above this line is New Code
project_activity.new_code_period_start.help=The analysis below this mark is the baseline for New Code comparison

project_activity.graphs.choose_type=Choose graph type
project_activity.graphs.explanation_x=This interactive graph shows data for the following project measures over time: {0}

Loading…
Cancel
Save