From: Viktor Vorona Date: Mon, 12 Aug 2024 14:11:38 +0000 (+0200) Subject: SONAR-22719 Some fixes to measures X-Git-Tag: 10.7.0.96327~194 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=428ec45595e130c7702d4a2555ed67c6141cfbc3;p=sonarqube.git SONAR-22719 Some fixes to measures --- diff --git a/server/sonar-web/design-system/src/components/__tests__/BubbleChart-test.tsx b/server/sonar-web/design-system/src/components/__tests__/BubbleChart-test.tsx index 125ee7f7192..f1530542972 100644 --- a/server/sonar-web/design-system/src/components/__tests__/BubbleChart-test.tsx +++ b/server/sonar-web/design-system/src/components/__tests__/BubbleChart-test.tsx @@ -81,7 +81,7 @@ function renderBubbleChart(props: Partial> = {}) { height={100} items={[ { x: 1, y: 10, size: 7, data: 'foo' }, - { x: 2, y: 30, size: 5, color: 3, data: 'bar' }, + { x: 2, y: 30, size: 5, data: 'bar' }, ]} padding={[0, 0, 0, 0]} {...props} diff --git a/server/sonar-web/src/main/js/api/mocks/data/measures.ts b/server/sonar-web/src/main/js/api/mocks/data/measures.ts index 5d85c59f327..a08c608b4ed 100644 --- a/server/sonar-web/src/main/js/api/mocks/data/measures.ts +++ b/server/sonar-web/src/main/js/api/mocks/data/measures.ts @@ -218,6 +218,13 @@ function mockComponentMeasure(tree: ComponentTree, issueList: IssueData[], metri ...computeRating(issues, IssueType.Bug), }); + case MetricKey.software_quality_reliability_rating: + return mockMeasure({ + metric: metricKey, + period: undefined, + ...computeRating(issues, IssueType.Bug), + }); + case MetricKey.new_reliability_rating: return mockMeasure({ metric: metricKey, @@ -228,6 +235,16 @@ function mockComponentMeasure(tree: ComponentTree, issueList: IssueData[], metri value: undefined, }); + case MetricKey.new_software_quality_reliability_rating: + return mockMeasure({ + metric: metricKey, + period: { + index: 0, + ...computeRating(issues, IssueType.Bug), + }, + value: undefined, + }); + case MetricKey.sqale_rating: return mockMeasure({ metric: metricKey, @@ -235,6 +252,13 @@ function mockComponentMeasure(tree: ComponentTree, issueList: IssueData[], metri ...computeRating(issues, IssueType.CodeSmell), }); + case MetricKey.software_quality_maintainability_rating: + return mockMeasure({ + metric: metricKey, + period: undefined, + ...computeRating(issues, IssueType.CodeSmell), + }); + case MetricKey.new_maintainability_rating: return mockMeasure({ metric: metricKey, @@ -245,6 +269,16 @@ function mockComponentMeasure(tree: ComponentTree, issueList: IssueData[], metri value: undefined, }); + case MetricKey.new_software_quality_maintainability_rating: + return mockMeasure({ + metric: metricKey, + period: { + index: 0, + ...computeRating(issues, IssueType.CodeSmell), + }, + value: undefined, + }); + case MetricKey.security_rating: return mockMeasure({ metric: metricKey, @@ -252,6 +286,13 @@ function mockComponentMeasure(tree: ComponentTree, issueList: IssueData[], metri ...computeRating(issues, IssueType.Vulnerability), }); + case MetricKey.software_quality_security_rating: + return mockMeasure({ + metric: metricKey, + period: undefined, + ...computeRating(issues, IssueType.Vulnerability), + }); + case MetricKey.new_security_rating: return mockMeasure({ metric: metricKey, @@ -261,6 +302,16 @@ function mockComponentMeasure(tree: ComponentTree, issueList: IssueData[], metri }, value: undefined, }); + + case MetricKey.new_software_quality_security_rating: + return mockMeasure({ + metric: metricKey, + period: { + index: 0, + ...computeRating(issues, IssueType.Vulnerability), + }, + value: undefined, + }); } } @@ -312,11 +363,17 @@ function isIssueType(metricKey: MetricKey) { function isIssueRelatedRating(metricKey: MetricKey) { return [ MetricKey.reliability_rating, + MetricKey.software_quality_reliability_rating, MetricKey.new_reliability_rating, + MetricKey.new_software_quality_reliability_rating, MetricKey.sqale_rating, + MetricKey.software_quality_maintainability_rating, MetricKey.new_maintainability_rating, + MetricKey.new_software_quality_maintainability_rating, MetricKey.security_rating, + MetricKey.software_quality_security_rating, MetricKey.new_security_rating, + MetricKey.new_software_quality_security_rating, ].includes(metricKey); } diff --git a/server/sonar-web/src/main/js/app/components/metrics/RatingComponent.tsx b/server/sonar-web/src/main/js/app/components/metrics/RatingComponent.tsx index 69132914ef8..d5e2a61644a 100644 --- a/server/sonar-web/src/main/js/app/components/metrics/RatingComponent.tsx +++ b/server/sonar-web/src/main/js/app/components/metrics/RatingComponent.tsx @@ -23,6 +23,7 @@ import * as React from 'react'; import { formatMeasure } from '~sonar-aligned/helpers/measures'; import { MetricKey, MetricType } from '~sonar-aligned/types/metrics'; import { getLeakValue } from '../../../components/measure/utils'; +import { SOFTWARE_QUALITY_RATING_METRICS_MAP } from '../../../helpers/constants'; import { isDiffMetric } from '../../../helpers/measures'; import { useMeasureQuery } from '../../../queries/measures'; import { useIsLegacyCCTMode } from '../../../queries/settings'; @@ -46,7 +47,7 @@ type RatingMetricKeys = | MetricKey.releasability_rating; function isNewRatingMetric(metricKey: MetricKey) { - return metricKey.includes('_new'); + return metricKey.includes('software_quality_'); } const useGetMetricKeyForRating = (ratingMetric: RatingMetricKeys): MetricKey | null => { @@ -59,7 +60,7 @@ const useGetMetricKeyForRating = (ratingMetric: RatingMetricKeys): MetricKey | n if (isLoading) { return null; } - return isLegacy ? ratingMetric : ((ratingMetric + '_new') as MetricKey); + return isLegacy ? ratingMetric : SOFTWARE_QUALITY_RATING_METRICS_MAP[ratingMetric]; }; export default function RatingComponent(props: Readonly) { diff --git a/server/sonar-web/src/main/js/apps/code/__tests__/Code-it.ts b/server/sonar-web/src/main/js/apps/code/__tests__/Code-it.ts index b0bdc8c17f6..422930bdf77 100644 --- a/server/sonar-web/src/main/js/apps/code/__tests__/Code-it.ts +++ b/server/sonar-web/src/main/js/apps/code/__tests__/Code-it.ts @@ -34,6 +34,7 @@ import BranchesServiceMock from '../../../api/mocks/BranchesServiceMock'; import ComponentsServiceMock from '../../../api/mocks/ComponentsServiceMock'; import { PARENT_COMPONENT_KEY, RULE_1 } from '../../../api/mocks/data/ids'; import IssuesServiceMock from '../../../api/mocks/IssuesServiceMock'; +import { MeasuresServiceMock } from '../../../api/mocks/MeasuresServiceMock'; import SettingsServiceMock from '../../../api/mocks/SettingsServiceMock'; import SourcesServiceMock from '../../../api/mocks/SourcesServiceMock'; import { CCT_SOFTWARE_QUALITY_METRICS } from '../../../helpers/constants'; @@ -72,6 +73,7 @@ const componentsHandler = new ComponentsServiceMock(); const sourcesHandler = new SourcesServiceMock(); const issuesHandler = new IssuesServiceMock(); const settingsHandler = new SettingsServiceMock(); +const measuresHandler = new MeasuresServiceMock(); const JUPYTER_ISSUE = { issue: mockRawIssue(false, { @@ -129,6 +131,7 @@ beforeEach(() => { sourcesHandler.reset(); issuesHandler.reset(); settingsHandler.reset(); + measuresHandler.reset(); }); it('should allow navigating through the tree', async () => { diff --git a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx index 46c6385554f..8e5142fee57 100644 --- a/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/CodeApp.tsx @@ -26,11 +26,8 @@ import withComponentContext from '../../../app/components/componentContext/withC import withMetricsContext from '../../../app/components/metrics/withMetricsContext'; import { CodeScope, getCodeUrl, getProjectUrl } from '../../../helpers/urls'; import { WithBranchLikesProps, useBranchesQuery } from '../../../queries/branch'; -import { - useComponentBreadcrumbsQuery, - useComponentChildrenQuery, - useComponentQuery, -} from '../../../queries/component'; +import { useComponentBreadcrumbsQuery, useComponentQuery } from '../../../queries/component'; +import { useComponentTreeQuery } from '../../../queries/measures'; import { getBranchLikeQuery } from '../../../sonar-aligned/helpers/branch-like'; import { Component, ComponentMeasure, Dict, Metric } from '../../../types/types'; import { getCodeMetrics } from '../utils'; @@ -69,7 +66,7 @@ function CodeApp(props: Readonly) { data: componentWithChildren, isLoading: isChildrenLoading, fetchNextPage, - } = useComponentChildrenQuery({ + } = useComponentTreeQuery({ strategy: 'children', component: location.query.selected ?? component.key, metrics: getCodeMetrics(component.qualifier, branchLike, { diff --git a/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx b/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx index 96efad19434..021f688d401 100644 --- a/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx +++ b/server/sonar-web/src/main/js/apps/code/components/CodeAppRenderer.tsx @@ -36,10 +36,19 @@ import { Breadcrumb } from '~sonar-aligned/types/component'; import { Location } from '~sonar-aligned/types/router'; import ListFooter from '../../../components/controls/ListFooter'; import AnalysisMissingInfoMessage from '../../../components/shared/AnalysisMissingInfoMessage'; -import { CCT_SOFTWARE_QUALITY_METRICS, OLD_TAXONOMY_METRICS } from '../../../helpers/constants'; +import { + CCT_SOFTWARE_QUALITY_METRICS, + LEAK_OLD_TAXONOMY_RATINGS, + OLD_TAXONOMY_METRICS, + OLD_TAXONOMY_RATINGS, + SOFTWARE_QUALITY_RATING_METRICS, +} from '../../../helpers/constants'; import { KeyboardKeys } from '../../../helpers/keycodes'; import { translate } from '../../../helpers/l10n'; -import { areCCTMeasuresComputed } from '../../../helpers/measures'; +import { + areCCTMeasuresComputed, + areSoftwareQualityRatingsComputed, +} from '../../../helpers/measures'; import { BranchLike } from '../../../types/branch-like'; import { isApplication } from '../../../types/component'; import { Component, ComponentMeasure, Dict, Metric } from '../../../types/types'; @@ -107,11 +116,18 @@ export default function CodeAppRenderer(props: Readonly) { const allComponentsHaveSoftwareQualityMeasures = components.every((component) => areCCTMeasuresComputed(component.measures), ); + const allComponentsHaveRatings = components.every((component) => + areSoftwareQualityRatingsComputed(component.measures), + ); - const filteredMetrics = difference( - metricKeys, - allComponentsHaveSoftwareQualityMeasures ? OLD_TAXONOMY_METRICS : CCT_SOFTWARE_QUALITY_METRICS, - ).map((key) => metrics[key]); + const filteredMetrics = difference(metricKeys, [ + ...(allComponentsHaveSoftwareQualityMeasures + ? OLD_TAXONOMY_METRICS + : CCT_SOFTWARE_QUALITY_METRICS), + ...(allComponentsHaveRatings + ? [...OLD_TAXONOMY_RATINGS, ...LEAK_OLD_TAXONOMY_RATINGS] + : SOFTWARE_QUALITY_RATING_METRICS), + ]).map((key) => metrics[key]); let defaultTitle = translate('code.page'); if (isApplication(baseComponent?.qualifier)) { diff --git a/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx b/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx index 50046f5f08d..6da61a2b489 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/__tests__/ComponentMeasures-it.tsx @@ -452,6 +452,7 @@ describe('navigation', () => { within(ui.measuresRow('folderA').get()).getByRole('cell', { name: '2' }), ).toBeInTheDocument(); + await ui.arrowDown(); // Select the 1st element ("folderA") await ui.arrowRight(); // Open "folderA" await ui.arrowDown(); // Select the 1st element ("out.tsx") diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts b/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts index a8e55997174..b5fedf2ce56 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts +++ b/server/sonar-web/src/main/js/apps/component-measures/config/bubbles.ts @@ -35,19 +35,19 @@ export const newTaxonomyBubbles: BubblesByDomain = { x: MetricKey.ncloc, y: MetricKey.reliability_remediation_effort, size: MetricKey.reliability_issues, - colors: [MetricKey.reliability_rating_new], + colors: [MetricKey.software_quality_reliability_rating], }, Security: { x: MetricKey.ncloc, y: MetricKey.security_remediation_effort, size: MetricKey.security_issues, - colors: [MetricKey.security_rating_new], + colors: [MetricKey.software_quality_security_rating], }, Maintainability: { x: MetricKey.ncloc, y: MetricKey.sqale_index, size: MetricKey.maintainability_issues, - colors: [MetricKey.sqale_rating_new], + colors: [MetricKey.software_quality_maintainability_rating], }, Coverage: { x: MetricKey.complexity, @@ -64,7 +64,10 @@ export const newTaxonomyBubbles: BubblesByDomain = { x: MetricKey.sqale_index, y: MetricKey.coverage, size: MetricKey.ncloc, - colors: [MetricKey.reliability_rating_new, MetricKey.security_rating_new], + colors: [ + MetricKey.software_quality_reliability_rating, + MetricKey.software_quality_security_rating, + ], yDomain: [100, 0], }, }; diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts b/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts index a98910ded13..63a5e81c842 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts +++ b/server/sonar-web/src/main/js/apps/component-measures/config/domains.ts @@ -18,6 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { MetricKey } from '~sonar-aligned/types/metrics'; +import { SOFTWARE_QUALITY_RATING_METRICS_MAP } from '../../../helpers/constants'; interface Domains { [domain: string]: { categories?: string[]; order: string[] }; @@ -34,17 +35,17 @@ export const domains: Domains = { MetricKey.new_reliability_issues, MetricKey.new_bugs, MetricKey.new_reliability_rating, - MetricKey.new_reliability_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_reliability_rating], MetricKey.new_reliability_remediation_effort, - MetricKey.new_reliability_remediation_effort_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_reliability_remediation_effort], OVERALL_CATEGORY, MetricKey.reliability_issues, MetricKey.bugs, MetricKey.reliability_rating, - MetricKey.reliability_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.reliability_rating], MetricKey.reliability_remediation_effort, - MetricKey.reliability_remediation_effort_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.reliability_remediation_effort], ], }, @@ -55,17 +56,17 @@ export const domains: Domains = { MetricKey.new_security_issues, MetricKey.new_vulnerabilities, MetricKey.new_security_rating, - MetricKey.new_security_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_security_rating], MetricKey.new_security_remediation_effort, - MetricKey.new_security_remediation_effort_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_security_remediation_effort], OVERALL_CATEGORY, MetricKey.security_issues, MetricKey.vulnerabilities, MetricKey.security_rating, - MetricKey.security_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.security_rating], MetricKey.security_remediation_effort, - MetricKey.security_remediation_effort_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.security_remediation_effort], ], }, @@ -75,13 +76,13 @@ export const domains: Domains = { NEW_CODE_CATEGORY, MetricKey.new_security_hotspots, MetricKey.new_security_review_rating, - MetricKey.new_security_review_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_security_review_rating], MetricKey.new_security_hotspots_reviewed, OVERALL_CATEGORY, MetricKey.security_hotspots, MetricKey.security_review_rating, - MetricKey.security_review_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.security_review_rating], MetricKey.security_hotspots_reviewed, ], }, @@ -93,19 +94,23 @@ export const domains: Domains = { MetricKey.new_maintainability_issues, MetricKey.new_code_smells, MetricKey.new_technical_debt, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_technical_debt], MetricKey.new_sqale_debt_ratio, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_sqale_debt_ratio], MetricKey.new_maintainability_rating, - MetricKey.new_maintainability_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.new_maintainability_rating], OVERALL_CATEGORY, MetricKey.maintainability_issues, MetricKey.code_smells, MetricKey.sqale_index, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.sqale_index], MetricKey.sqale_debt_ratio, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.sqale_debt_ratio], MetricKey.sqale_rating, - MetricKey.sqale_rating_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.sqale_rating], MetricKey.effort_to_reach_maintainability_rating_a, - MetricKey.effort_to_reach_maintainability_rating_a_new, + SOFTWARE_QUALITY_RATING_METRICS_MAP[MetricKey.effort_to_reach_maintainability_rating_a], ], }, diff --git a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx index d3df6b22d57..ea39cb9d6d4 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx +++ b/server/sonar-web/src/main/js/apps/component-measures/sidebar/Sidebar.tsx @@ -32,6 +32,7 @@ import * as React from 'react'; import A11ySkipTarget from '~sonar-aligned/components/a11y/A11ySkipTarget'; import { translate } from '../../../helpers/l10n'; import useFollowScroll from '../../../hooks/useFollowScroll'; +import { useIsLegacyCCTMode } from '../../../queries/settings'; import { Domain } from '../../../types/measures'; import { MeasureEnhanced } from '../../../types/types'; import { PROJECT_OVERVEW, Query, isProjectOverview, populateDomainsFromMeasures } from '../utils'; @@ -48,7 +49,8 @@ interface Props { export default function Sidebar(props: Readonly) { const { showFullMeasures, updateQuery, componentKey, selectedMetric, measures } = props; const { top: topScroll, scrolledOnce } = useFollowScroll(); - const domains = populateDomainsFromMeasures(measures); + const { data: isLegacy } = useIsLegacyCCTMode(); + const domains = populateDomainsFromMeasures(measures, isLegacy); const handleChangeMetric = React.useCallback( (metric: string) => { diff --git a/server/sonar-web/src/main/js/apps/component-measures/utils.ts b/server/sonar-web/src/main/js/apps/component-measures/utils.ts index 3e1177c38f1..5e639f5fa11 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/utils.ts +++ b/server/sonar-web/src/main/js/apps/component-measures/utils.ts @@ -101,45 +101,59 @@ const ISSUES_METRICS = [ MetricKey.new_violations, ]; -export const populateDomainsFromMeasures = memoize((measures: MeasureEnhanced[]): Domain[] => { - let populatedMeasures = measures - .filter((measure) => !DEPRECATED_METRICS.includes(measure.metric.key as MetricKey)) - .map((measure) => { - const isDiff = isDiffMetric(measure.metric.key); - const calculatedValue = getCCTMeasureValue( - measure.metric.key, - isDiff ? measure.leak : measure.value, +export const populateDomainsFromMeasures = memoize( + (measures: MeasureEnhanced[], isLegacy?: boolean): Domain[] => { + let populatedMeasures = measures + .filter((measure) => !DEPRECATED_METRICS.includes(measure.metric.key as MetricKey)) + .map((measure) => { + const isDiff = isDiffMetric(measure.metric.key); + const calculatedValue = getCCTMeasureValue( + measure.metric.key, + isDiff ? measure.leak : measure.value, + ); + + return { + ...measure, + ...{ [isDiff ? 'leak' : 'value']: calculatedValue }, + }; + }); + + if (!isLegacy && areLeakCCTMeasuresComputed(measures)) { + populatedMeasures = populatedMeasures.filter( + (measure) => !LEAK_OLD_TAXONOMY_METRICS.includes(measure.metric.key as MetricKey), ); + } else { + populatedMeasures = populatedMeasures.filter( + (measure) => !LEAK_CCT_SOFTWARE_QUALITY_METRICS.includes(measure.metric.key as MetricKey), + ); + } + + // Both new and overall code will exist after next analysis + if (!isLegacy && areSoftwareQualityRatingsComputed(measures)) { + populatedMeasures = populatedMeasures.filter( + (measure) => + !OLD_TAXONOMY_RATINGS.includes(measure.metric.key as MetricKey) && + !LEAK_OLD_TAXONOMY_RATINGS.includes(measure.metric.key as MetricKey), + ); + } else { + populatedMeasures = populatedMeasures.filter( + (measure) => !SOFTWARE_QUALITY_RATING_METRICS.includes(measure.metric.key as MetricKey), + ); + } - return { - ...measure, - ...{ [isDiff ? 'leak' : 'value']: calculatedValue }, - }; - }); - - if (areLeakCCTMeasuresComputed(measures)) { - populatedMeasures = populatedMeasures.filter( - (measure) => !LEAK_OLD_TAXONOMY_METRICS.includes(measure.metric.key as MetricKey), - ); - } - - // Both new and overall code will exist after next analysis - if (areSoftwareQualityRatingsComputed(measures)) { - populatedMeasures = populatedMeasures.filter( - (measure) => - !OLD_TAXONOMY_RATINGS.includes(measure.metric.key as MetricKey) && - !LEAK_OLD_TAXONOMY_RATINGS.includes(measure.metric.key as MetricKey), - ); - } - - if (areCCTMeasuresComputed(measures)) { - populatedMeasures = populatedMeasures.filter( - (measure) => !OLD_TAXONOMY_METRICS.includes(measure.metric.key as MetricKey), - ); - } + if (!isLegacy && areCCTMeasuresComputed(measures)) { + populatedMeasures = populatedMeasures.filter( + (measure) => !OLD_TAXONOMY_METRICS.includes(measure.metric.key as MetricKey), + ); + } else { + populatedMeasures = populatedMeasures.filter( + (measure) => !CCT_SOFTWARE_QUALITY_METRICS.includes(measure.metric.key as MetricKey), + ); + } - return groupByDomains(populatedMeasures); -}); + return groupByDomains(populatedMeasures); + }, +); export function getMetricSubnavigationName( metric: Metric, diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx index 8e897786551..5aecfd6063b 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-it.tsx @@ -42,7 +42,7 @@ import PullRequestOverview from '../PullRequestOverview'; jest.mock('../../../../api/measures', () => { return { ...jest.requireActual('../../../../sonar-aligned/types/metrics'), - getMeasuresWithMetrics: jest.fn().mockResolvedValue({ + getMeasuresWithPeriodAndMetrics: jest.fn().mockResolvedValue({ component: { key: '', name: '', diff --git a/server/sonar-web/src/main/js/apps/projects/components/project-card/ProjectCard.tsx b/server/sonar-web/src/main/js/apps/projects/components/project-card/ProjectCard.tsx index 2ee4a4d6881..6b0bce72200 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/project-card/ProjectCard.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/project-card/ProjectCard.tsx @@ -74,9 +74,9 @@ function renderFirstLine( MetricKey.security_issues, ].every((key) => measures[key] === undefined); const noRatingMetrics = [ - MetricKey.reliability_rating_new, - MetricKey.sqale_rating_new, - MetricKey.security_rating_new, + MetricKey.software_quality_reliability_rating, + MetricKey.software_quality_maintainability_rating, + MetricKey.software_quality_security_rating, ].every((key) => measures[key] === undefined); const awaitingScan = (noSoftwareQualityMetrics || noRatingMetrics) && diff --git a/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx b/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx index 3fb06f240d5..26d8ae6558d 100644 --- a/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx +++ b/server/sonar-web/src/main/js/apps/projects/components/project-card/__tests__/ProjectCard-test.tsx @@ -127,20 +127,20 @@ describe('upgrade scenario (awaiting scan)', () => { }; const newRatings = { - [MetricKey.reliability_rating_new]: mockMeasure({ - metric: MetricKey.reliability_rating_new, + [MetricKey.software_quality_reliability_rating]: mockMeasure({ + metric: MetricKey.software_quality_reliability_rating, value: '2', }), - [MetricKey.sqale_rating_new]: mockMeasure({ - metric: MetricKey.sqale_rating_new, + [MetricKey.software_quality_maintainability_rating]: mockMeasure({ + metric: MetricKey.software_quality_maintainability_rating, value: '2', }), - [MetricKey.security_rating_new]: mockMeasure({ - metric: MetricKey.security_rating_new, + [MetricKey.software_quality_security_rating]: mockMeasure({ + metric: MetricKey.software_quality_security_rating, value: '2', }), - [MetricKey.security_review_rating_new]: mockMeasure({ - metric: MetricKey.security_review_rating_new, + [MetricKey.software_quality_security_review_rating]: mockMeasure({ + metric: MetricKey.software_quality_security_review_rating, value: '2', }), }; @@ -170,10 +170,10 @@ describe('upgrade scenario (awaiting scan)', () => { HIGH: 0, total: 3, }), - [MetricKey.sqale_rating_new]: '2', - [MetricKey.reliability_rating_new]: '2', - [MetricKey.security_rating_new]: '2', - [MetricKey.security_review_rating_new]: '2', + [MetricKey.software_quality_maintainability_rating]: '2', + [MetricKey.software_quality_reliability_rating]: '2', + [MetricKey.software_quality_security_rating]: '2', + [MetricKey.software_quality_security_review_rating]: '2', [MetricKey.code_smells]: '4', [MetricKey.bugs]: '5', [MetricKey.vulnerabilities]: '6', @@ -319,10 +319,10 @@ describe('upgrade scenario (awaiting scan)', () => { HIGH: 0, total: 3, }), - [MetricKey.sqale_rating_new]: '2', - [MetricKey.reliability_rating_new]: '2', - [MetricKey.security_rating_new]: '2', - [MetricKey.security_review_rating_new]: '2', + [MetricKey.software_quality_maintainability_rating]: '2', + [MetricKey.software_quality_reliability_rating]: '2', + [MetricKey.software_quality_security_rating]: '2', + [MetricKey.software_quality_security_review_rating]: '2', [MetricKey.code_smells]: '4', [MetricKey.bugs]: '5', [MetricKey.vulnerabilities]: '6', diff --git a/server/sonar-web/src/main/js/helpers/constants.ts b/server/sonar-web/src/main/js/helpers/constants.ts index 96df373e57c..82c0fd1ca6e 100644 --- a/server/sonar-web/src/main/js/helpers/constants.ts +++ b/server/sonar-web/src/main/js/helpers/constants.ts @@ -112,10 +112,16 @@ export const LEAK_OLD_TAXONOMY_METRICS = [ ]; export const OLD_TAXONOMY_RATINGS = [ + MetricKey.releasability_rating, MetricKey.sqale_rating, MetricKey.security_rating, MetricKey.reliability_rating, MetricKey.security_review_rating, + MetricKey.sqale_index, + MetricKey.reliability_remediation_effort, + MetricKey.security_remediation_effort, + MetricKey.sqale_debt_ratio, + MetricKey.effort_to_reach_maintainability_rating_a, ]; export const LEAK_OLD_TAXONOMY_RATINGS = [ @@ -123,6 +129,10 @@ export const LEAK_OLD_TAXONOMY_RATINGS = [ MetricKey.new_security_rating, MetricKey.new_reliability_rating, MetricKey.new_security_review_rating, + MetricKey.new_technical_debt, + MetricKey.new_security_remediation_effort, + MetricKey.new_reliability_remediation_effort, + MetricKey.new_sqale_debt_ratio, ]; export const OLD_TO_NEW_TAXONOMY_METRICS_MAP: { [key in MetricKey]?: MetricKey } = { @@ -181,27 +191,49 @@ export const DEPRECATED_ACTIVITY_METRICS = [ ]; export const SOFTWARE_QUALITY_RATING_METRICS_MAP: Record = { - [MetricKey.sqale_rating]: MetricKey.sqale_rating_new, - [MetricKey.security_rating]: MetricKey.security_rating_new, - [MetricKey.reliability_rating]: MetricKey.reliability_rating_new, - [MetricKey.security_review_rating]: MetricKey.security_review_rating_new, - [MetricKey.releasability_rating]: MetricKey.releasability_rating_new, - [MetricKey.new_maintainability_rating]: MetricKey.new_maintainability_rating_new, - [MetricKey.new_security_rating]: MetricKey.new_security_rating_new, - [MetricKey.new_reliability_rating]: MetricKey.new_reliability_rating_new, - [MetricKey.new_security_review_rating]: MetricKey.new_security_review_rating_new, + [MetricKey.releasability_rating]: MetricKey.software_quality_releasability_rating, + [MetricKey.sqale_rating]: MetricKey.software_quality_maintainability_rating, + [MetricKey.security_rating]: MetricKey.software_quality_security_rating, + [MetricKey.reliability_rating]: MetricKey.software_quality_reliability_rating, + [MetricKey.security_review_rating]: MetricKey.software_quality_security_review_rating, + [MetricKey.reliability_remediation_effort]: + MetricKey.software_quality_reliability_remediation_effort, + [MetricKey.security_remediation_effort]: MetricKey.software_quality_security_remediation_effort, + [MetricKey.sqale_index]: MetricKey.software_quality_maintainability_remediation_effort, + [MetricKey.sqale_debt_ratio]: MetricKey.software_quality_maintainability_debt_ratio, + [MetricKey.effort_to_reach_maintainability_rating_a]: + MetricKey.effort_to_reach_software_quality_maintainability_rating_a, + [MetricKey.new_maintainability_rating]: MetricKey.new_software_quality_maintainability_rating, + [MetricKey.new_security_rating]: MetricKey.new_software_quality_security_rating, + [MetricKey.new_reliability_rating]: MetricKey.new_software_quality_reliability_rating, + [MetricKey.new_security_review_rating]: MetricKey.new_software_quality_security_review_rating, + [MetricKey.new_technical_debt]: MetricKey.new_software_quality_maintainability_remediation_effort, + [MetricKey.new_reliability_remediation_effort]: + MetricKey.new_software_quality_reliability_remediation_effort, + [MetricKey.new_security_remediation_effort]: + MetricKey.new_software_quality_security_remediation_effort, + [MetricKey.new_sqale_debt_ratio]: MetricKey.new_software_quality_maintainability_debt_ratio, }; export const SOFTWARE_QUALITY_RATING_METRICS = [ - MetricKey.sqale_rating_new, - MetricKey.security_rating_new, - MetricKey.reliability_rating_new, - MetricKey.security_review_rating_new, - MetricKey.releasability_rating_new, - MetricKey.new_maintainability_rating_new, - MetricKey.new_security_rating_new, - MetricKey.new_reliability_rating_new, - MetricKey.new_security_review_rating_new, + MetricKey.software_quality_releasability_rating, + MetricKey.software_quality_maintainability_rating, + MetricKey.software_quality_security_rating, + MetricKey.software_quality_reliability_rating, + MetricKey.software_quality_security_review_rating, + MetricKey.software_quality_maintainability_remediation_effort, + MetricKey.software_quality_reliability_remediation_effort, + MetricKey.software_quality_security_remediation_effort, + MetricKey.software_quality_maintainability_debt_ratio, + MetricKey.effort_to_reach_software_quality_maintainability_rating_a, + MetricKey.new_software_quality_maintainability_rating, + MetricKey.new_software_quality_security_rating, + MetricKey.new_software_quality_reliability_rating, + MetricKey.new_software_quality_security_review_rating, + MetricKey.new_software_quality_maintainability_remediation_effort, + MetricKey.new_software_quality_reliability_remediation_effort, + MetricKey.new_software_quality_security_remediation_effort, + MetricKey.new_software_quality_maintainability_debt_ratio, ]; export const PROJECT_KEY_MAX_LEN = 400; diff --git a/server/sonar-web/src/main/js/helpers/measures.ts b/server/sonar-web/src/main/js/helpers/measures.ts index 6b0d5cb0687..315faee7fad 100644 --- a/server/sonar-web/src/main/js/helpers/measures.ts +++ b/server/sonar-web/src/main/js/helpers/measures.ts @@ -27,7 +27,6 @@ import { CCT_SOFTWARE_QUALITY_METRICS, LEAK_CCT_SOFTWARE_QUALITY_METRICS, LEAK_OLD_TAXONOMY_METRICS, - SOFTWARE_QUALITY_RATING_METRICS, } from './constants'; import { translate } from './l10n'; import { isDefined } from './types'; @@ -116,7 +115,11 @@ export function areCCTMeasuresComputed(measures?: Measure[] | MeasureEnhanced[]) ); } export function areSoftwareQualityRatingsComputed(measures?: Measure[] | MeasureEnhanced[]) { - return SOFTWARE_QUALITY_RATING_METRICS.every((metric) => + return [ + MetricKey.software_quality_security_rating, + MetricKey.software_quality_security_rating, + MetricKey.software_quality_maintainability_rating, + ].every((metric) => measures?.find((measure) => isMeasureEnhanced(measure) ? measure.metric.key === metric : measure.metric === metric, ), diff --git a/server/sonar-web/src/main/js/queries/component.ts b/server/sonar-web/src/main/js/queries/component.ts index 31596b4fcd8..0034d72d883 100644 --- a/server/sonar-web/src/main/js/queries/component.ts +++ b/server/sonar-web/src/main/js/queries/component.ts @@ -17,25 +17,14 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { - infiniteQueryOptions, - queryOptions, - useQuery, - useQueryClient, -} from '@tanstack/react-query'; +import { queryOptions, useQuery, useQueryClient } from '@tanstack/react-query'; import { groupBy, omit } from 'lodash'; import { BranchParameters } from '~sonar-aligned/types/branch-like'; import { getTasksForComponent } from '../api/ce'; -import { - getBreadcrumbs, - getComponent, - getComponentData, - getComponentTree, -} from '../api/components'; -import { getNextPageParam, getPreviousPageParam } from '../helpers/react-query'; +import { getBreadcrumbs, getComponent, getComponentData } from '../api/components'; import { MetricKey } from '../sonar-aligned/types/metrics'; import { Component, Measure } from '../types/types'; -import { StaleTime, createInfiniteQueryHook, createQueryHook } from './common'; +import { StaleTime, createQueryHook } from './common'; const NEW_METRICS = [ MetricKey.software_quality_maintainability_rating, @@ -112,63 +101,6 @@ export const useComponentBreadcrumbsQuery = createQueryHook( }, ); -export const useComponentChildrenQuery = createInfiniteQueryHook( - ({ - strategy, - component, - metrics, - additionalData, - }: { - additionalData: Parameters[3]; - component: Parameters[1]; - metrics: Parameters[2]; - strategy: 'children' | 'leaves'; - }) => { - const queryClient = useQueryClient(); - return infiniteQueryOptions({ - queryKey: ['component', component, 'tree', strategy, { metrics, additionalData }], - queryFn: async ({ pageParam }) => { - const result = await getComponentTree( - strategy, - component, - metrics?.filter((m) => !NEW_METRICS.includes(m as MetricKey)), - { ...additionalData, p: pageParam }, - ); - const measuresMapByMetricKeyForBaseComponent = groupBy( - result.baseComponent.measures, - 'metric', - ); - metrics?.forEach((metricKey) => { - const measure = measuresMapByMetricKeyForBaseComponent[metricKey]?.[0] ?? null; - queryClient.setQueryData( - ['measures', 'details', result.baseComponent.key, metricKey], - measure, - ); - }); - - result.components.forEach((childComponent) => { - const measuresMapByMetricKeyForChildComponent = groupBy( - childComponent.measures, - 'metric', - ); - metrics?.forEach((metricKey) => { - const measure = measuresMapByMetricKeyForChildComponent[metricKey]?.[0] ?? null; - queryClient.setQueryData( - ['measures', 'details', childComponent.key, metricKey], - measure, - ); - }); - }); - return result; - }, - getNextPageParam: (data) => getNextPageParam({ page: data.paging }), - getPreviousPageParam: (data) => getPreviousPageParam({ page: data.paging }), - initialPageParam: 1, - staleTime: 60_000, - }); - }, -); - export const useComponentDataQuery = createQueryHook( (data: Parameters[0]) => { return queryOptions({ diff --git a/server/sonar-web/src/main/js/queries/measures.ts b/server/sonar-web/src/main/js/queries/measures.ts index b7274ac555e..90522111df9 100644 --- a/server/sonar-web/src/main/js/queries/measures.ts +++ b/server/sonar-web/src/main/js/queries/measures.ts @@ -39,7 +39,7 @@ import { getBranchLikeQuery } from '../sonar-aligned/helpers/branch-like'; import { MetricKey } from '../sonar-aligned/types/metrics'; import { BranchLike } from '../types/branch-like'; import { Measure } from '../types/types'; -import {createInfiniteQueryHook, createQueryHook} from './common'; +import { createInfiniteQueryHook, createQueryHook } from './common'; const NEW_METRICS = [ MetricKey.software_quality_maintainability_rating, @@ -140,24 +140,27 @@ export const useComponentTreeQuery = createInfiniteQueryHook( { ...additionalData, p: pageParam, ...branchLikeQuery }, ); - // const measuresMapByMetricKeyForBaseComponent = groupBy( - // result.baseComponent.measures, - // 'metric', - // ); - // metrics?.forEach((metricKey) => { - // const measure = measuresMapByMetricKeyForBaseComponent[metricKey]?.[0] ?? null; - // queryClient.setQueryData( - // [ - // 'measures', - // 'details', - // result.baseComponent.key, - // 'branchLike', - // branchLikeQuery, - // metricKey, - // ], - // measure, - // ); - // }); + if (result.baseComponent.measures && result.baseComponent.measures.length > 0) { + const measuresMapByMetricKeyForBaseComponent = groupBy( + result.baseComponent.measures, + 'metric', + ); + metrics?.forEach((metricKey) => { + const measure = measuresMapByMetricKeyForBaseComponent[metricKey]?.[0] ?? null; + queryClient.setQueryData( + [ + 'measures', + 'details', + result.baseComponent.key, + 'branchLike', + branchLikeQuery, + metricKey, + ], + measure, + ); + }); + } + result.components.forEach((childComponent) => { const measuresMapByMetricKeyForChildComponent = groupBy( childComponent.measures, diff --git a/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts b/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts index 9a3677b6aa6..cb25b06904b 100644 --- a/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts +++ b/server/sonar-web/src/main/js/sonar-aligned/types/metrics.ts @@ -112,7 +112,7 @@ export enum MetricKey { new_reliability_rating_distribution = 'new_reliability_rating_distribution', new_software_quality_reliability_rating_distribution = 'new_software_quality_reliability_rating_distribution', new_reliability_remediation_effort = 'new_reliability_remediation_effort', - new_reliability_remediation_effort_new = 'new_reliability_remediation_effort_new', + new_software_quality_reliability_remediation_effort = 'new_software_quality_reliability_remediation_effort', new_security_hotspots = 'new_security_hotspots', new_security_hotspots_reviewed = 'new_security_hotspots_reviewed', new_security_issues = 'new_security_issues', @@ -121,13 +121,15 @@ export enum MetricKey { new_security_rating_distribution = 'new_security_rating_distribution', new_software_quality_security_rating_distribution = 'new_software_quality_security_rating_distribution', new_security_remediation_effort = 'new_security_remediation_effort', - new_security_remediation_effort_new = 'new_security_remediation_effort_new', + new_software_quality_security_remediation_effort = 'new_software_quality_security_remediation_effort', new_security_review_rating = 'new_security_review_rating', new_software_quality_security_review_rating = 'new_software_quality_security_review_rating', new_security_review_rating_distribution = 'new_security_review_rating_distribution', new_software_quality_security_review_rating_distribution = 'new_software_quality_security_review_rating_distribution', new_sqale_debt_ratio = 'new_sqale_debt_ratio', + new_software_quality_maintainability_debt_ratio = 'new_software_quality_maintainability_debt_ratio', new_technical_debt = 'new_technical_debt', + new_software_quality_maintainability_remediation_effort = 'new_software_quality_maintainability_remediation_effort', new_uncovered_conditions = 'new_uncovered_conditions', new_uncovered_lines = 'new_uncovered_lines', new_violations = 'new_violations', @@ -154,7 +156,7 @@ export enum MetricKey { software_quality_reliability_rating_distribution = 'software_quality_reliability_rating_distribution', reliability_rating_effort = 'reliability_rating_effort', reliability_remediation_effort = 'reliability_remediation_effort', - reliability_remediation_effort_new = 'reliability_remediation_effort_new', + software_quality_reliability_remediation_effort = 'software_quality_reliability_remediation_effort', reopened_issues = 'reopened_issues', security_hotspots = 'security_hotspots', security_hotspots_reviewed = 'security_hotspots_reviewed', @@ -165,7 +167,7 @@ export enum MetricKey { software_quality_security_rating_distribution = 'software_quality_security_rating_distribution', security_rating_effort = 'security_rating_effort', security_remediation_effort = 'security_remediation_effort', - security_remediation_effort_new = 'security_remediation_effort_new', + software_quality_security_remediation_effort = 'software_quality_security_remediation_effort', security_review_rating = 'security_review_rating', software_quality_security_review_rating = 'software_quality_security_review_rating', security_review_rating_distribution = 'security_review_rating_distribution', @@ -174,7 +176,9 @@ export enum MetricKey { skipped_tests = 'skipped_tests', sonarjava_feedback = 'sonarjava_feedback', sqale_debt_ratio = 'sqale_debt_ratio', + software_quality_maintainability_debt_ratio = 'software_quality_maintainability_debt_ratio', sqale_index = 'sqale_index', + software_quality_maintainability_remediation_effort = 'software_quality_maintainability_remediation_effort', sqale_rating = 'sqale_rating', software_quality_maintainability_rating = 'software_quality_maintainability_rating', statements = 'statements',