Browse Source

SONAR-21797 Add info message about chart gap for app/portfolio

tags/10.5.0.89998
stanislavh 1 month ago
parent
commit
8d83292a4f

+ 48
- 0
server/sonar-web/src/main/js/apps/projectActivity/components/ProjectActivityGraphs.tsx View File

@@ -17,8 +17,10 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { FlagMessage } from 'design-system';
import { debounce, findLast, maxBy, minBy, sortBy } from 'lodash';
import * as React from 'react';
import { FormattedMessage } from 'react-intl';
import GraphsHeader from '../../../components/activity-graph/GraphsHeader';
import GraphsHistory from '../../../components/activity-graph/GraphsHistory';
import GraphsZoom from '../../../components/activity-graph/GraphsZoom';
@@ -31,6 +33,9 @@ import {
saveActivityGraph,
splitSeriesInGraphs,
} from '../../../components/activity-graph/utils';
import DocumentationLink from '../../../components/common/DocumentationLink';
import { CCT_SOFTWARE_QUALITY_METRICS } from '../../../helpers/constants';
import { translate } from '../../../helpers/l10n';
import {
GraphType,
MeasureHistory,
@@ -198,6 +203,48 @@ export default class ProjectActivityGraphs extends React.PureComponent<Props, St
}
};

renderQualitiesMetricInfoMessage = () => {
const { measuresHistory } = this.props;

const qualityMeasuresHistory = measuresHistory.find((history) =>
CCT_SOFTWARE_QUALITY_METRICS.includes(history.metric),
);

const indexOfFirstMeasureWithValue = qualityMeasuresHistory?.history.findIndex(
(item) => item.value,
);

const hasGaps =
indexOfFirstMeasureWithValue === -1
? false
: qualityMeasuresHistory?.history
.slice(indexOfFirstMeasureWithValue)
.some((item) => item.value === undefined);

if (hasGaps) {
return (
<FlagMessage variant="info">
<FormattedMessage
id="project_activity.graphs.data_table.data_gap"
tagName="div"
values={{
learn_more: (
<DocumentationLink
className="sw-whitespace-nowrap"
to="/user-guide/clean-code/code-analysis/"
>
{translate('learn_more')}
</DocumentationLink>
),
}}
/>
</FlagMessage>
);
}

return null;
};

render() {
const { analyses, leakPeriodDate, loading, measuresHistory, metrics, query } = this.props;
const { graphEndDate, graphStartDate, series } = this.state;
@@ -214,6 +261,7 @@ export default class ProjectActivityGraphs extends React.PureComponent<Props, St
selectedMetrics={query.customMetrics}
onUpdateGraph={this.handleUpdateGraph}
/>
{this.renderQualitiesMetricInfoMessage()}
<GraphsHistory
analyses={analyses}
graph={query.graph}

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

@@ -86,12 +86,16 @@ beforeEach(() => {
MetricKey.sqale_rating,
MetricKey.security_hotspots_reviewed,
MetricKey.security_review_rating,
MetricKey.maintainability_issues,
].map((metric) =>
mockMeasureHistory({
metric,
history: projectActivityHandler
.getAnalysesList()
.map(({ date }) => mockHistoryItem({ value: '3', date: parseDate(date) })),
history: projectActivityHandler.getAnalysesList().map(({ date }) =>
mockHistoryItem({
value: '3',
date: parseDate(date),
}),
),
}),
),
);
@@ -241,6 +245,50 @@ describe('rendering', () => {
).not.toBeInTheDocument();
},
);

it('should render graph gap info message', async () => {
timeMachineHandler.setMeasureHistory([
mockMeasureHistory({
metric: MetricKey.maintainability_issues,
history: projectActivityHandler.getAnalysesList().map(({ date }, index) =>
mockHistoryItem({
// eslint-disable-next-line jest/no-conditional-in-test
value: index === 0 ? '3' : undefined,
date: parseDate(date),
}),
),
}),
]);
const { ui } = getPageObject();
renderProjectActivityAppContainer(
mockComponent({
breadcrumbs: [
{ key: 'breadcrumb', name: 'breadcrumb', qualifier: ComponentQualifier.Application },
],
}),
);

await ui.changeGraphType(GraphType.custom);
await ui.openMetricsDropdown();
await ui.toggleMetric(MetricKey.maintainability_issues);
expect(ui.gapInfoMessage.get()).toBeInTheDocument();
});

it('should not render graph gap info message if no gaps', async () => {
const { ui } = getPageObject();
renderProjectActivityAppContainer(
mockComponent({
breadcrumbs: [
{ key: 'breadcrumb', name: 'breadcrumb', qualifier: ComponentQualifier.Application },
],
}),
);

await ui.changeGraphType(GraphType.custom);
await ui.openMetricsDropdown();
await ui.toggleMetric(MetricKey.maintainability_issues);
expect(ui.gapInfoMessage.query()).not.toBeInTheDocument();
});
});

describe('CRUD', () => {
@@ -512,6 +560,7 @@ function getPageObject() {
// Graphs.
graphs: byLabelText('project_activity.graphs.explanation_x', { exact: false }),
noDataText: byText('project_activity.graphs.custom.no_history'),
gapInfoMessage: byText('project_activity.graphs.data_table.data_gap', { exact: false }),

// Add metrics.
addMetricBtn: byRole('button', { name: 'project_activity.graphs.custom.add' }),
@@ -697,6 +746,7 @@ function renderProjectActivityAppContainer(
{
metrics: keyBy(
[
mockMetric({ key: MetricKey.maintainability_issues, type: MetricType.Data }),
mockMetric({ key: MetricKey.bugs, type: MetricType.Integer }),
mockMetric({ key: MetricKey.code_smells, type: MetricType.Integer }),
mockMetric({ key: MetricKey.security_hotspots_reviewed }),

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

@@ -1950,6 +1950,7 @@ project_activity.graphs.data_table.no_data_warning=There is no data for the sele
project_activity.graphs.data_table.no_data_warning_check_dates_x=There is no data for the selected date range (everything after {start}). Try modifying the date filters on the main page.
project_activity.graphs.data_table.no_data_warning_check_dates_y=There is no data for the selected date range (everything before {end}). Try modifying the date filters on the main page.
project_activity.graphs.data_table.no_data_warning_check_dates_x_y=There is no data for the selected date range ({start} to {end}). Try modifying the date filters on the main page.
project_activity.graphs.data_table.data_gap=The chart history for issues related to software qualities may contain gaps while information is not available for one or more projects. {learn_more}

project_activity.custom_metric.covered_lines=Covered Lines


Loading…
Cancel
Save