123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- /*
- * SonarQube
- * Copyright (C) 2009-2024 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 {
- CoverageIndicator,
- DuplicationsIndicator,
- MetricsLabel,
- MetricsRatingBadge,
- Note,
- PageContentFontWrapper,
- } from 'design-system';
- import * as React from 'react';
- import Measure from '../../../../components/measure/Measure';
- import { duplicationRatingConverter } from '../../../../components/measure/utils';
- import { translate } from '../../../../helpers/l10n';
- import { formatRating } from '../../../../helpers/measures';
- import { isDefined } from '../../../../helpers/types';
- import { ComponentQualifier } from '../../../../types/component';
- import { MetricKey, MetricType } from '../../../../types/metrics';
- import { Dict } from '../../../../types/types';
- import ProjectCardMeasure from './ProjectCardMeasure';
-
- export interface ProjectCardMeasuresProps {
- isNewCode: boolean;
- measures: Dict<string | undefined>;
- componentQualifier: ComponentQualifier;
- }
-
- function renderNewIssues(props: ProjectCardMeasuresProps) {
- const { measures, isNewCode } = props;
-
- if (!isNewCode) {
- return null;
- }
-
- return (
- <ProjectCardMeasure
- metricKey={MetricKey.new_violations}
- label={translate(`metric.${MetricKey.new_violations}.description`)}
- >
- <Measure
- metricKey={MetricKey.new_violations}
- metricType={MetricType.ShortInteger}
- value={measures[MetricKey.new_violations]}
- className="sw-ml-2 sw-body-md-highlight"
- />
- </ProjectCardMeasure>
- );
- }
-
- function renderCoverage(props: ProjectCardMeasuresProps) {
- const { measures, isNewCode } = props;
- const coverageMetric = isNewCode ? MetricKey.new_coverage : MetricKey.coverage;
-
- return (
- <ProjectCardMeasure metricKey={coverageMetric} label={translate('metric.coverage.name')}>
- <div>
- {measures[coverageMetric] && <CoverageIndicator value={measures[coverageMetric]} />}
- <Measure
- metricKey={coverageMetric}
- metricType={MetricType.Percent}
- value={measures[coverageMetric]}
- className="sw-ml-2 sw-body-md-highlight"
- />
- </div>
- </ProjectCardMeasure>
- );
- }
-
- function renderDuplication(props: ProjectCardMeasuresProps) {
- const { measures, isNewCode } = props;
- const duplicationMetric = isNewCode
- ? MetricKey.new_duplicated_lines_density
- : MetricKey.duplicated_lines_density;
-
- const rating =
- measures[duplicationMetric] !== undefined
- ? duplicationRatingConverter(Number(measures[duplicationMetric]))
- : undefined;
-
- return (
- <ProjectCardMeasure
- metricKey={duplicationMetric}
- label={translate('metric.duplicated_lines_density.short_name')}
- >
- <div>
- {measures[duplicationMetric] != null && <DuplicationsIndicator rating={rating} />}
- <Measure
- metricKey={duplicationMetric}
- metricType={MetricType.Percent}
- value={measures[duplicationMetric]}
- className="sw-ml-2 sw-body-md-highlight"
- />
- </div>
- </ProjectCardMeasure>
- );
- }
-
- function renderRatings(props: ProjectCardMeasuresProps) {
- const { isNewCode, measures } = props;
-
- const measuresByCodeLeak = isNewCode
- ? []
- : [
- {
- iconLabel: translate(`metric.${MetricKey.security_issues}.short_name`),
- noShrink: true,
- metricKey:
- measures[MetricKey.security_issues] !== undefined
- ? MetricKey.security_issues
- : MetricKey.vulnerabilities,
- metricRatingKey: MetricKey.security_rating,
- metricType: MetricType.ShortInteger,
- },
- {
- iconLabel: translate(`metric.${MetricKey.reliability_issues}.short_name`),
- metricKey:
- measures[MetricKey.reliability_issues] !== undefined
- ? MetricKey.reliability_issues
- : MetricKey.bugs,
- metricRatingKey: MetricKey.reliability_rating,
- metricType: MetricType.ShortInteger,
- },
- {
- iconLabel: translate(`metric.${MetricKey.maintainability_issues}.short_name`),
- metricKey:
- measures[MetricKey.maintainability_issues] !== undefined
- ? MetricKey.maintainability_issues
- : MetricKey.code_smells,
- metricRatingKey: MetricKey.sqale_rating,
- metricType: MetricType.ShortInteger,
- },
- ];
-
- const measureList = [
- ...measuresByCodeLeak,
- {
- iconKey: 'security_hotspots',
- iconLabel: translate('projects.security_hotspots_reviewed'),
- metricKey: isNewCode
- ? MetricKey.new_security_hotspots_reviewed
- : MetricKey.security_hotspots_reviewed,
- metricRatingKey: isNewCode
- ? MetricKey.new_security_review_rating
- : MetricKey.security_review_rating,
- metricType: MetricType.Percent,
- },
- ];
-
- return measureList.map((measure) => {
- const { iconLabel, metricKey, metricRatingKey, metricType } = measure;
- const value = formatRating(measures[metricRatingKey]);
-
- const measureValue =
- [
- MetricKey.security_issues,
- MetricKey.reliability_issues,
- MetricKey.maintainability_issues,
- ].includes(metricKey) && measures[metricKey]
- ? JSON.parse(measures[metricKey] as string)?.total
- : measures[metricKey];
-
- return (
- <ProjectCardMeasure key={metricKey} metricKey={metricKey} label={iconLabel}>
- <MetricsRatingBadge label={metricKey} rating={value as MetricsLabel} />
- <Measure
- metricKey={metricKey}
- metricType={metricType}
- value={measureValue}
- className="sw-ml-2 sw-body-md-highlight"
- />
- </ProjectCardMeasure>
- );
- });
- }
-
- export default function ProjectCardMeasures(props: ProjectCardMeasuresProps) {
- const { isNewCode, measures, componentQualifier } = props;
-
- const { ncloc } = measures;
-
- if (!isNewCode && !ncloc) {
- return (
- <Note className="sw-py-4">
- {componentQualifier === ComponentQualifier.Application
- ? translate('portfolio.app.empty')
- : translate('overview.project.main_branch_empty')}
- </Note>
- );
- }
-
- const measureList = [
- renderNewIssues(props),
- ...renderRatings(props),
- renderCoverage(props),
- renderDuplication(props),
- ].filter(isDefined);
-
- return (
- <PageContentFontWrapper className="sw-flex sw-gap-8">
- {measureList.map((measure, i) => (
- // eslint-disable-next-line react/no-array-index-key
- <React.Fragment key={i}>{measure}</React.Fragment>
- ))}
- </PageContentFontWrapper>
- );
- }
|