From: 7PH Date: Tue, 19 Dec 2023 14:57:05 +0000 (+0100) Subject: SONAR-21259 SONAR-21273 Introduce issue measures card for accepted and fixed issues X-Git-Tag: 10.4.0.87286~183 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=2e8c1c2eb0969605048e36b29f0660f6887935ef;p=sonarqube.git SONAR-21259 SONAR-21273 Introduce issue measures card for accepted and fixed issues --- diff --git a/server/sonar-web/design-system/src/components/Text.tsx b/server/sonar-web/design-system/src/components/Text.tsx index c0e122e83b5..d10fdc61ba1 100644 --- a/server/sonar-web/design-system/src/components/Text.tsx +++ b/server/sonar-web/design-system/src/components/Text.tsx @@ -67,12 +67,21 @@ export function PageTitle({ ); } -export function TextError({ text, className }: { className?: string; text: string }) { - return ( - - {text} - - ); +export function TextError({ + text, + className, +}: Readonly<{ + className?: string; + text: string | React.ReactNode; +}>) { + if (typeof text === 'string') { + return ( + + {text} + + ); + } + return {text}; } export function TextSuccess({ text, className }: Readonly<{ className?: string; text: string }>) { diff --git a/server/sonar-web/design-system/src/components/icons/HelperHintIcon.tsx b/server/sonar-web/design-system/src/components/icons/HelperHintIcon.tsx index 3cbe2bf70d6..7da2fc7a275 100644 --- a/server/sonar-web/design-system/src/components/icons/HelperHintIcon.tsx +++ b/server/sonar-web/design-system/src/components/icons/HelperHintIcon.tsx @@ -18,18 +18,37 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { useTheme } from '@emotion/react'; +import { Fragment } from 'react'; import { themeColor, themeContrast } from '../../helpers/theme'; import { CustomIcon, IconProps } from './Icon'; -export function HelperHintIcon(iconProps: IconProps) { +type Props = IconProps & { + raised?: boolean; +}; + +export function HelperHintIcon({ raised, ...iconProps }: Props) { const theme = useTheme(); return ( - - + {raised ? ( + // eslint-disable-next-line react/jsx-fragments + + + + + ) : ( + // eslint-disable-next-line react/jsx-fragments + + + + + )} ); } diff --git a/server/sonar-web/design-system/src/components/icons/Icon.tsx b/server/sonar-web/design-system/src/components/icons/Icon.tsx index ff2d4379a0f..d4c68fd7a64 100644 --- a/server/sonar-web/design-system/src/components/icons/Icon.tsx +++ b/server/sonar-web/design-system/src/components/icons/Icon.tsx @@ -37,6 +37,7 @@ export interface IconProps extends Omit { fill?: ThemeColors | CSSColor; height?: number; transform?: string; + viewBox?: string; width?: number; } diff --git a/server/sonar-web/design-system/src/components/icons/SnoozeCircleIcon.tsx b/server/sonar-web/design-system/src/components/icons/SnoozeCircleIcon.tsx new file mode 100644 index 00000000000..a43b4afb71d --- /dev/null +++ b/server/sonar-web/design-system/src/components/icons/SnoozeCircleIcon.tsx @@ -0,0 +1,39 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 { useTheme } from '@emotion/react'; +import { themeColor, themeContrast } from '../../helpers'; +import { CustomIcon, IconProps } from './Icon'; + +export function SnoozeCircleIcon(props: Readonly<{ neutral?: boolean } & IconProps>) { + const theme = useTheme(); + + const bgColor = themeColor('overviewCardWarningIcon')({ theme }); + const iconColor = themeContrast('overviewCardWarningIcon')({ theme }); + + return ( + + + + + ); +} diff --git a/server/sonar-web/design-system/src/components/icons/TrendDownCircleIcon.tsx b/server/sonar-web/design-system/src/components/icons/TrendDownCircleIcon.tsx new file mode 100644 index 00000000000..c65c312d7d2 --- /dev/null +++ b/server/sonar-web/design-system/src/components/icons/TrendDownCircleIcon.tsx @@ -0,0 +1,39 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 { useTheme } from '@emotion/react'; +import { themeColor, themeContrast } from '../../helpers'; +import { CustomIcon, IconProps } from './Icon'; + +export function TrendDownCircleIcon(props: Readonly) { + const theme = useTheme(); + + const bgColor = themeColor('overviewCardSuccessIcon')({ theme }); + const iconColor = themeContrast('overviewCardSuccessIcon')({ theme }); + + return ( + + + + + ); +} diff --git a/server/sonar-web/design-system/src/components/icons/TrendUpCircleIcon.tsx b/server/sonar-web/design-system/src/components/icons/TrendUpCircleIcon.tsx new file mode 100644 index 00000000000..6113b9cfcf7 --- /dev/null +++ b/server/sonar-web/design-system/src/components/icons/TrendUpCircleIcon.tsx @@ -0,0 +1,46 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 { useTheme } from '@emotion/react'; +import { themeColor, themeContrast } from '../../helpers'; +import { CustomIcon, IconProps } from './Icon'; + +export function TrendUpCircleIcon(props: Readonly) { + const theme = useTheme(); + + const bgColor = themeColor('overviewCardErrorIcon')({ theme }); + const iconColor = themeContrast('overviewCardErrorIcon')({ theme }); + + return ( + + + + + + + + + + + + ); +} diff --git a/server/sonar-web/design-system/src/components/icons/index.ts b/server/sonar-web/design-system/src/components/icons/index.ts index 2498237a78d..0efa2dea06c 100644 --- a/server/sonar-web/design-system/src/components/icons/index.ts +++ b/server/sonar-web/design-system/src/components/icons/index.ts @@ -70,6 +70,7 @@ export { SeverityCriticalIcon } from './SeverityCriticalIcon'; export { SeverityInfoIcon } from './SeverityInfoIcon'; export { SeverityMajorIcon } from './SeverityMajorIcon'; export { SeverityMinorIcon } from './SeverityMinorIcon'; +export { SnoozeCircleIcon } from './SnoozeCircleIcon'; export { SoftwareImpactSeverityHighIcon } from './SoftwareImpactSeverityHighIcon'; export { SoftwareImpactSeverityLowIcon } from './SoftwareImpactSeverityLowIcon'; export { SoftwareImpactSeverityMediumIcon } from './SoftwareImpactSeverityMediumIcon'; @@ -83,7 +84,9 @@ export { StatusReopenedIcon } from './StatusReopenedIcon'; export { StatusResolvedIcon } from './StatusResolvedIcon'; export { TestFileIcon } from './TestFileIcon'; export { TrashIcon } from './TrashIcon'; +export { TrendDownCircleIcon } from './TrendDownCircleIcon'; export { TrendDirection, TrendIcon, TrendType } from './TrendIcon'; +export { TrendUpCircleIcon } from './TrendUpCircleIcon'; export { TriangleDownIcon } from './TriangleDownIcon'; export { TriangleLeftIcon } from './TriangleLeftIcon'; export { TriangleRightIcon } from './TriangleRightIcon'; diff --git a/server/sonar-web/design-system/src/theme/light.ts b/server/sonar-web/design-system/src/theme/light.ts index 604f2bf044b..1534f0adb1d 100644 --- a/server/sonar-web/design-system/src/theme/light.ts +++ b/server/sonar-web/design-system/src/theme/light.ts @@ -390,6 +390,7 @@ export const lightTheme = { iconStatusResolved: secondary.dark, iconNotificationsOn: COLORS.indigo[300], iconHelperHint: COLORS.blueGrey[100], + iconHelperHintRaised: COLORS.blueGrey[400], iconRuleInheritanceOverride: danger.light, // numbered list @@ -516,6 +517,9 @@ export const lightTheme = { // overview iconOverviewIssue: COLORS.blueGrey[400], + overviewCardWarningIcon: COLORS.yellow[50], + overviewCardErrorIcon: COLORS.red[100], + overviewCardSuccessIcon: COLORS.green[200], // graph - chart graphPointCircleColor: COLORS.white, @@ -710,6 +714,11 @@ export const lightTheme = { pillInfoIcon: COLORS.blue[700], pillAccent: COLORS.indigo[500], + // project cards + overviewCardWarningIcon: COLORS.yellow[700], + overviewCardErrorIcon: COLORS.red[500], + overviewCardSuccessIcon: COLORS.green[500], + // breadcrumbs breadcrumb: secondary.dark, @@ -731,6 +740,7 @@ export const lightTheme = { iconSeverityInfo: COLORS.white, iconStatusResolved: COLORS.white, iconHelperHint: secondary.darker, + iconHelperHintRaised: COLORS.white, // numbered list numberedList: COLORS.indigo[800], diff --git a/server/sonar-web/src/main/js/api/measures.ts b/server/sonar-web/src/main/js/api/measures.ts index 58389491d5d..8df28f012e0 100644 --- a/server/sonar-web/src/main/js/api/measures.ts +++ b/server/sonar-web/src/main/js/api/measures.ts @@ -44,7 +44,7 @@ export async function getMeasuresWithMetrics( // TODO: Remove this mock (SONAR-21259) const mockedMetrics = metrics.filter( (metric) => - metric !== MetricKey.pullrequest_addressed_issues && metric !== MetricKey.new_accepted_issues, + metric !== MetricKey.pull_request_fixed_issues && metric !== MetricKey.new_accepted_issues, ); const result = (await getJSON(COMPONENT_URL, { additionalFields: 'metrics', @@ -52,9 +52,9 @@ export async function getMeasuresWithMetrics( metricKeys: mockedMetrics.join(','), ...branchParameters, }).catch(throwGlobalError)) as MeasuresAndMetaWithMetrics; - if (metrics.includes(MetricKey.pullrequest_addressed_issues)) { + if (metrics.includes(MetricKey.pull_request_fixed_issues)) { result.metrics.push({ - key: MetricKey.pullrequest_addressed_issues, + key: MetricKey.pull_request_fixed_issues, name: 'Addressed Issues', description: 'Addressed Issues', domain: 'Reliability', @@ -65,7 +65,7 @@ export async function getMeasuresWithMetrics( bestValue: '0', }); result.component.measures?.push({ - metric: MetricKey.pullrequest_addressed_issues, + metric: MetricKey.pull_request_fixed_issues, period: { index: 0, value: '11', diff --git a/server/sonar-web/src/main/js/apps/component-measures/__tests__/__snapshots__/utils-test.ts.snap b/server/sonar-web/src/main/js/apps/component-measures/__tests__/__snapshots__/utils-test.ts.snap index 2085725441f..139ac8c11c3 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/__tests__/__snapshots__/utils-test.ts.snap +++ b/server/sonar-web/src/main/js/apps/component-measures/__tests__/__snapshots__/utils-test.ts.snap @@ -64,34 +64,30 @@ exports[`sortMeasures should sort based on the config 1`] = ` [ { "metric": { - "id": "3", "key": "new_bugs", - "name": "new_bugs", + "name": "New bugs", "type": "INT", }, }, { "metric": { - "id": "2", "key": "new_reliability_remediation_effort", - "name": "bugs", + "name": "Bugs", "type": "INT", }, }, "overall_category", { "metric": { - "id": "4", "key": "bugs", - "name": "bugs", + "name": "Bugs", "type": "INT", }, }, { "metric": { - "id": "1", "key": "reliability_remediation_effort", - "name": "new_bugs", + "name": "New bugs", "type": "INT", }, }, diff --git a/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts b/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts index da7d8b130d1..af7563afcc9 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts +++ b/server/sonar-web/src/main/js/apps/component-measures/__tests__/utils-test.ts @@ -19,7 +19,7 @@ */ import { ComponentQualifier } from '../../../types/component'; import { MeasurePageView } from '../../../types/measures'; -import { MetricKey } from '../../../types/metrics'; +import { MetricKey, MetricType } from '../../../types/metrics'; import { ComponentMeasure } from '../../../types/types'; import * as utils from '../utils'; @@ -28,7 +28,7 @@ const MEASURES = [ metric: { id: '1', key: MetricKey.lines_to_cover, - type: 'INT', + type: MetricType.Integer, name: 'Lines to Cover', domain: 'Coverage', }, @@ -40,7 +40,7 @@ const MEASURES = [ metric: { id: '2', key: MetricKey.coverage, - type: 'PERCENT', + type: MetricType.Percent, name: 'Coverage', domain: 'Coverage', }, @@ -52,7 +52,7 @@ const MEASURES = [ metric: { id: '3', key: MetricKey.duplicated_lines_density, - type: 'PERCENT', + type: MetricType.Percent, name: 'Duplicated Lines (%)', domain: 'Duplications', }, @@ -66,13 +66,12 @@ describe('filterMeasures', () => { it('should exclude banned measures', () => { expect( utils.filterMeasures([ - { metric: { id: '1', key: MetricKey.open_issues, name: 'Bugs', type: 'INT' } }, + { metric: { key: MetricKey.open_issues, name: 'Bugs', type: MetricType.Integer } }, { metric: { - id: '2', key: MetricKey.critical_violations, name: 'Critical Violations', - type: 'INT', + type: MetricType.Integer, }, }, ]), @@ -86,22 +85,20 @@ describe('sortMeasures', () => { utils.sortMeasures('Reliability', [ { metric: { - id: '1', key: MetricKey.reliability_remediation_effort, - name: 'new_bugs', - type: 'INT', + name: 'New bugs', + type: MetricType.Integer, }, }, { metric: { - id: '2', key: MetricKey.new_reliability_remediation_effort, - name: 'bugs', - type: 'INT', + name: 'Bugs', + type: MetricType.Integer, }, }, - { metric: { id: '3', key: MetricKey.new_bugs, name: 'new_bugs', type: 'INT' } }, - { metric: { id: '4', key: MetricKey.bugs, name: 'bugs', type: 'INT' } }, + { metric: { key: MetricKey.new_bugs, name: 'New bugs', type: MetricType.Integer } }, + { metric: { key: MetricKey.bugs, name: 'Bugs', type: MetricType.Integer } }, 'overall_category', ]), ).toMatchSnapshot(); @@ -168,17 +165,17 @@ describe('extract measure', () => { name: 'TEST', measures: [ { - metric: 'alert_status', + metric: MetricKey.alert_status, value: '3.2', period: { index: 1, value: '0.0' }, }, { - metric: 'releasability_rating', + metric: MetricKey.releasability_rating, value: '3.2', period: { index: 1, value: '0.0' }, }, { - metric: 'releasability_effort', + metric: MetricKey.releasability_effort, value: '3.2', period: { index: 1, value: '0.0' }, }, @@ -199,7 +196,7 @@ describe('extract measure', () => { const measure = utils.banQualityGateMeasure(componentBuilder(ComponentQualifier.File)); expect(measure).toHaveLength(2); measure.forEach(({ metric }) => { - expect(['releasability_rating', 'releasability_effort']).toContain(metric); + expect([MetricKey.releasability_rating, MetricKey.releasability_effort]).toContain(metric); }); }); }); diff --git a/server/sonar-web/src/main/js/apps/overview/components/App.tsx b/server/sonar-web/src/main/js/apps/overview/components/App.tsx index 182ca35881b..661321fea7a 100644 --- a/server/sonar-web/src/main/js/apps/overview/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/overview/components/App.tsx @@ -55,7 +55,7 @@ export function App(props: AppProps) { {isPullRequest(branchLike) ? (
- +
) : (
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCard.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCard.tsx new file mode 100644 index 00000000000..99225368fcf --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCard.tsx @@ -0,0 +1,159 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 styled from '@emotion/styled'; +import { + Card, + HelperHintIcon, + LightLabel, + PopupPlacement, + SnoozeCircleIcon, + TextError, + TextSubdued, + themeColor, + Tooltip, + TrendDownCircleIcon, + TrendUpCircleIcon, +} from 'design-system'; +import * as React from 'react'; +import { useIntl } from 'react-intl'; +import { getLeakValue } from '../../../components/measure/utils'; +import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils'; +import { getBranchLikeQuery } from '../../../helpers/branch-like'; +import { findMeasure, formatMeasure } from '../../../helpers/measures'; +import { getComponentIssuesUrl } from '../../../helpers/urls'; +import { PullRequest } from '../../../types/branch-like'; +import { MetricKey, MetricType } from '../../../types/metrics'; +import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates'; +import { Component, MeasureEnhanced } from '../../../types/types'; +import { getConditionRequiredLabel, Status } from '../utils'; +import { IssueMeasuresCardInner } from './IssueMeasuresCardInner'; + +interface Props { + conditions: QualityGateStatusConditionEnhanced[]; + measures: MeasureEnhanced[]; + component: Component; + pullRequest: PullRequest; +} + +export default function IssueMeasuresCard( + props: React.PropsWithChildren>, +) { + const { measures, conditions, component, pullRequest, ...rest } = props; + + const intl = useIntl(); + + const issuesCount = getLeakValue(findMeasure(measures, MetricKey.new_violations)); + const issuesCondition = conditions.find((c) => c.metric === MetricKey.new_violations); + const issuesConditionFailed = issuesCondition?.level === Status.ERROR; + const fixedCount = findMeasure(measures, MetricKey.pull_request_fixed_issues)?.value; + const acceptedCount = getLeakValue(findMeasure(measures, MetricKey.new_accepted_issues)); + + const issuesUrl = getComponentIssuesUrl(component.key, { + ...getBranchLikeQuery(pullRequest), + ...DEFAULT_ISSUES_QUERY, + }); + const fixedUrl = getComponentIssuesUrl(component.key, { + branch: pullRequest.target, + fixedInPR: pullRequest.key, + }); + const acceptedUrl = getComponentIssuesUrl(component.key, { + ...getBranchLikeQuery(pullRequest), + ...DEFAULT_ISSUES_QUERY, + issueStatuses: 'ACCEPTED', + }); + + return ( + + } + footer={ + issuesCondition && + (issuesConditionFailed ? ( + + ) : ( + + {getConditionRequiredLabel(issuesCondition, intl)} + + )) + } + /> + + } + footer={ + + {intl.formatMessage({ id: 'overview.pull_request.accepted_issues.help' })} + + } + /> + + + {intl.formatMessage({ id: 'overview.pull_request.fixed_issues' })} + + + {intl.formatMessage({ id: 'overview.pull_request.fixed_issues.disclaimer' })} + + + {intl.formatMessage({ id: 'overview.pull_request.fixed_issues.disclaimer.2' })} + + + } + placement={PopupPlacement.Top} + > + + + + } + metric={MetricKey.pull_request_fixed_issues} + value={formatMeasure(fixedCount, MetricType.ShortInteger)} + url={fixedUrl} + icon={fixedCount !== '0' && } + footer={ + + {intl.formatMessage({ id: 'overview.pull_request.fixed_issues.help' })} + + } + /> + + ); +} + +const StyledCardSeparator = styled.div` + width: 1px; + background-color: ${themeColor('projectCardBorder')}; +`; diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCardInner.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCardInner.tsx new file mode 100644 index 00000000000..ccdf8c965f3 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/IssueMeasuresCardInner.tsx @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2023 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 { Badge, ContentLink } from 'design-system'; +import * as React from 'react'; +import { Path } from 'react-router-dom'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; +import { localizeMetric } from '../../../helpers/measures'; +import { MetricKey } from '../../../types/metrics'; + +interface IssueMeasuresCardInnerProps extends React.HTMLAttributes { + metric: MetricKey; + value?: string; + header: React.ReactNode; + url: Path; + failed?: boolean; + icon?: React.ReactNode; + footer?: React.ReactNode; +} + +export function IssueMeasuresCardInner(props: Readonly) { + const { header, metric, icon, value, url, failed, footer, ...rest } = props; + + return ( +
+
+
+ {header} + + {failed && ( + + {translate('overview.measures.failed_badge')} + + )} +
+
+
+ + {value ?? '0'} + +
+ + {icon} +
+
+ {footer} +
+ ); +} diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardNumber.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardNumber.tsx index e53f315fee1..d451fc0711e 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardNumber.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardNumber.tsx @@ -24,7 +24,7 @@ import { To } from 'react-router-dom'; import { formatMeasure } from '../../../helpers/measures'; import { MetricKey, MetricType } from '../../../types/metrics'; import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates'; -import { Status } from '../utils'; +import { Status, getConditionRequiredLabel } from '../utils'; import MeasuresCard from './MeasuresCard'; interface Props { @@ -33,13 +33,12 @@ interface Props { url: To; value: string; conditionMetric: MetricKey; - guidingKeyOnError?: string; } export default function MeasuresCardNumber( props: React.PropsWithChildren>, ) { - const { label, value, conditions, url, conditionMetric, guidingKeyOnError, ...rest } = props; + const { label, value, conditions, url, conditionMetric, ...rest } = props; const intl = useIntl(); @@ -47,16 +46,6 @@ export default function MeasuresCardNumber( const conditionFailed = condition?.level === Status.ERROR; - const requireLabel = - condition && - intl.formatMessage( - { id: 'overview.quality_gate.required_x' }, - { - operator: condition.op === 'GT' ? '≤' : '≥', - value: formatMeasure(condition.error, MetricType.Integer), - }, - ); - return ( - {requireLabel && + {condition && (conditionFailed ? ( - + ) : ( - {requireLabel} + {getConditionRequiredLabel(condition, intl)} ))} diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx index f0bdfb46e1a..2df727a1abe 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPanel.tsx @@ -20,106 +20,95 @@ import classNames from 'classnames'; import * as React from 'react'; import { getLeakValue } from '../../../components/measure/utils'; -import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils'; import { getBranchLikeQuery } from '../../../helpers/branch-like'; import { findMeasure } from '../../../helpers/measures'; -import { - getComponentDrilldownUrl, - getComponentIssuesUrl, - getComponentSecurityHotspotsUrl, -} from '../../../helpers/urls'; -import { BranchLike } from '../../../types/branch-like'; +import { getComponentDrilldownUrl, getComponentSecurityHotspotsUrl } from '../../../helpers/urls'; +import { PullRequest } from '../../../types/branch-like'; import { MetricKey } from '../../../types/metrics'; import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates'; import { Component, MeasureEnhanced } from '../../../types/types'; import { MeasurementType, getMeasurementMetricKey } from '../utils'; +import IssueMeasuresCard from './IssueMeasuresCard'; import MeasuresCardNumber from './MeasuresCardNumber'; import MeasuresCardPercent from './MeasuresCardPercent'; interface Props { className?: string; - branchLike?: BranchLike; + pullRequest: PullRequest; component: Component; measures: MeasureEnhanced[]; conditions: QualityGateStatusConditionEnhanced[]; } export default function MeasuresCardPanel(props: React.PropsWithChildren) { - const { branchLike, component, measures, conditions, className } = props; + const { pullRequest, component, measures, conditions, className } = props; - const newViolations = getLeakValue(findMeasure(measures, MetricKey.new_violations)) as string; const newSecurityHotspots = getLeakValue( findMeasure(measures, MetricKey.new_security_hotspots), ) as string; return ( -
-
- + <> + - -
+
+
+ -
- + +
- +
+ +
-
+ ); } diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPercent.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPercent.tsx index a65760c0563..ab71e1e579b 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPercent.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/MeasuresCardPercent.tsx @@ -35,7 +35,12 @@ import { BranchLike } from '../../../types/branch-like'; import { MetricKey, MetricType } from '../../../types/metrics'; import { QualityGateStatusConditionEnhanced } from '../../../types/quality-gates'; import { MeasureEnhanced } from '../../../types/types'; -import { MeasurementType, Status, getMeasurementMetricKey } from '../utils'; +import { + MeasurementType, + Status, + getConditionRequiredLabel, + getMeasurementMetricKey, +} from '../utils'; import MeasuresCard from './MeasuresCard'; interface Props { @@ -48,7 +53,6 @@ interface Props { conditions: QualityGateStatusConditionEnhanced[]; conditionMetric: MetricKey; newLinesMetric: MetricKey; - afterMergeMetric: MetricKey; } export default function MeasuresCardPercent( @@ -64,7 +68,6 @@ export default function MeasuresCardPercent( conditions, conditionMetric, newLinesMetric, - afterMergeMetric, } = props; const intl = useIntl(); @@ -85,24 +88,9 @@ export default function MeasuresCardPercent( listView: true, }); - const afterMergeValue = findMeasure(measures, afterMergeMetric)?.value; - const condition = conditions.find((c) => c.metric === conditionMetric); const conditionFailed = condition?.level === Status.ERROR; - const requireLabel = - condition && - intl.formatMessage( - { id: 'overview.quality_gate.required_x' }, - { - operator: condition.op === 'GT' ? '≤' : '≥', - value: formatMeasure(condition.error, MetricType.Percent, { - decimals: 2, - omitExtraDecimalZeros: true, - }), - }, - ); - return ( <> - {requireLabel && + {condition && (conditionFailed ? ( - + ) : ( - {requireLabel} + {getConditionRequiredLabel(condition, intl)} ))} -
+
- - {afterMergeValue && ( - {formatMeasure(afterMergeValue, MetricType.Percent)}, - }} - /> - )} -
diff --git a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx index d5c82848bbf..3de4a392362 100644 --- a/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx +++ b/server/sonar-web/src/main/js/apps/overview/pullRequests/PullRequestOverview.tsx @@ -38,12 +38,12 @@ import MeasuresCardPanel from './MeasuresCardPanel'; import SonarLintAd from './SonarLintAd'; interface Props { - branchLike: PullRequest; + pullRequest: PullRequest; component: Component; } -export default function PullRequestOverview(props: Readonly) { - const { component, branchLike } = props; +export default function PullRequestOverview(props: Readonly>) { + const { component, pullRequest } = props; const { data: { conditions, ignoredConditions, status } = {}, @@ -58,7 +58,7 @@ export default function PullRequestOverview(props: Readonly) { useComponentMeasuresWithMetricsQuery( component.key, uniq([...PR_METRICS, ...(conditions?.map((c) => c.metric) ?? [])]), - getBranchLikeQuery(branchLike), + getBranchLikeQuery(pullRequest), !isLoadingBranchStatusesData, ); @@ -97,14 +97,14 @@ export default function PullRequestOverview(props: Readonly) {
- + {ignoredConditions && } {status && ( ) { { mockMeasure({ metric: MetricKey.new_violations, }), + mockMeasure({ + metric: MetricKey.pull_request_fixed_issues, + }), ], }, metrics: [ @@ -70,6 +73,7 @@ jest.mock('../../../../api/measures', () => { mockMetric({ key: MetricKey.new_lines, type: MetricType.ShortInteger }), mockMetric({ key: MetricKey.new_bugs, type: MetricType.Integer }), mockMetric({ key: MetricKey.new_violations }), + mockMetric({ key: MetricKey.pull_request_fixed_issues }), ], }), }; @@ -117,6 +121,36 @@ jest.mock('../../../../api/quality-gates', () => { }; }); +it('should render links correctly', async () => { + jest.mocked(getQualityGateProjectStatus).mockResolvedValueOnce({ + status: 'OK', + conditions: [], + caycStatus: CaycStatus.Compliant, + ignoredConditions: false, + }); + renderPullRequestOverview(); + + await waitFor(async () => expect(await screen.findByText('metric.level.OK')).toBeInTheDocument()); + expect(screen.getByLabelText('overview.quality_gate_x.overview.gate.OK')).toBeInTheDocument(); + + expect( + byRole('link', { + name: 'overview.see_more_details_on_x_of_y.1.metric.new_violations.name', + }).get(), + ).toHaveAttribute( + 'href', + '/project/issues?pullRequest=1001&issueStatuses=OPEN%2CCONFIRMED&id=foo', + ); + + expect( + byRole('link', { + name: 'overview.see_more_details_on_x_of_y.1.metric.pull_request_fixed_issues.name', + }).get(), + ).toHaveAttribute('href', '/project/issues?branch=master&fixedInPullRequest=1001&id=foo'); + + expect(screen.getByLabelText('no_data')).toBeInTheDocument(); +}); + it('should render correctly for a passed QG', async () => { jest.mocked(getQualityGateProjectStatus).mockResolvedValueOnce({ status: 'OK', @@ -283,7 +317,7 @@ function renderPullRequestOverview( renderComponent( = { - [MetricKey.reliability_rating]: IssueType.Bug, - [MetricKey.new_reliability_rating]: IssueType.Bug, - [MetricKey.security_rating]: IssueType.Vulnerability, - [MetricKey.new_security_rating]: IssueType.Vulnerability, - [MetricKey.sqale_rating]: IssueType.CodeSmell, - [MetricKey.new_maintainability_rating]: IssueType.CodeSmell, - [MetricKey.security_review_rating]: IssueType.SecurityHotspot, - [MetricKey.new_security_review_rating]: IssueType.SecurityHotspot, -}; - -export const METRICS_REPORTED_IN_OVERVIEW_CARDS = [ - MetricKey.new_violations, - MetricKey.violations, - MetricKey.new_coverage, - MetricKey.coverage, - MetricKey.new_security_hotspots_reviewed, - MetricKey.security_hotspots_reviewed, - MetricKey.new_duplicated_lines_density, - MetricKey.duplicated_lines_density, -]; - -export function getIssueRatingName(type: IssueType) { - return translate('metric_domain', ISSUETYPE_METRIC_KEYS_MAP[type].ratingName); -} - -export function getIssueIconClass(type: IssueType) { - return ISSUETYPE_METRIC_KEYS_MAP[type].iconClass; -} - -export function getIssueMetricKey(type: IssueType, useDiffMetric: boolean) { - return useDiffMetric - ? ISSUETYPE_METRIC_KEYS_MAP[type].newMetric - : ISSUETYPE_METRIC_KEYS_MAP[type].metric; -} - -export function getIssueRatingMetricKey(type: IssueType, useDiffMetric: boolean) { - return useDiffMetric - ? ISSUETYPE_METRIC_KEYS_MAP[type].newRating - : ISSUETYPE_METRIC_KEYS_MAP[type].rating; -} - -export function getMeasurementIconClass(type: MeasurementType) { - return MEASUREMENTS_MAP[type].iconClass; -} - -export function getMeasurementMetricKey(type: MeasurementType, useDiffMetric: boolean) { - return useDiffMetric ? MEASUREMENTS_MAP[type].newMetric : MEASUREMENTS_MAP[type].metric; -} - -export function getMeasurementAfterMergeMetricKey(type: MeasurementType) { - return MEASUREMENTS_MAP[type].afterMergeMetric; -} - -export function getMeasurementLinesMetricKey(type: MeasurementType, useDiffMetric: boolean) { - return useDiffMetric ? MEASUREMENTS_MAP[type].newLinesMetric : MEASUREMENTS_MAP[type].linesMetric; -} - -export function getMeasurementLabelKeys(type: MeasurementType, useDiffMetric: boolean) { - return { - expandedLabelKey: useDiffMetric - ? MEASUREMENTS_MAP[type].newLinesExpandedLabelKey - : MEASUREMENTS_MAP[type].expandedLabelKey, - labelKey: MEASUREMENTS_MAP[type].labelKey, - }; -} - -export const parseQuery = memoize((urlQuery: RawQuery): { codeScope: string } => { - return { - codeScope: parseAsString(urlQuery['code_scope']), - }; -}); - -export function getAnalysisVariations(measures: MeasureHistory[], analysesCount: number) { - if (analysesCount === 0) { - return []; - } - - const emptyVariations: AnalysisMeasuresVariations[] = Array.from( - { length: analysesCount }, - () => ({}), - ); - - return measures.reduce((variations, { metric, history }) => { - if (!MEASURES_VARIATIONS_METRICS.includes(metric)) { - return variations; - } - - history.slice(-analysesCount).forEach(({ value = '' }, index, analysesHistory) => { - if (index === 0) { - variations[index][metric] = parseFloat(value) || 0; - return; - } - - const previousValue = parseFloat(analysesHistory[index - 1].value ?? '') || 0; - const numericValue = parseFloat(value) || 0; - const variation = numericValue - previousValue; - - if (variation === 0) { - return; - } - - variations[index][metric] = variation; - }); - - return variations; - }, emptyVariations); -} diff --git a/server/sonar-web/src/main/js/apps/overview/utils.tsx b/server/sonar-web/src/main/js/apps/overview/utils.tsx new file mode 100644 index 00000000000..a3816df71a4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/overview/utils.tsx @@ -0,0 +1,299 @@ +/* + * 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 { memoize } from 'lodash'; +import React from 'react'; +import { IntlShape } from 'react-intl'; +import CoverageRating from '../../components/ui/CoverageRating'; +import DuplicationsRating from '../../components/ui/DuplicationsRating'; +import { ISSUETYPE_METRIC_KEYS_MAP } from '../../helpers/issues'; +import { translate } from '../../helpers/l10n'; +import { formatMeasure } from '../../helpers/measures'; +import { parseAsString } from '../../helpers/query'; +import { IssueType } from '../../types/issues'; +import { MetricKey } from '../../types/metrics'; +import { AnalysisMeasuresVariations, MeasureHistory } from '../../types/project-activity'; +import { QualityGateStatusConditionEnhanced } from '../../types/quality-gates'; +import { Dict, RawQuery } from '../../types/types'; + +export const METRICS: string[] = [ + // quality gate + MetricKey.alert_status, + MetricKey.quality_gate_details, // TODO: still relevant? + + // bugs + MetricKey.bugs, + MetricKey.new_bugs, + MetricKey.reliability_rating, + MetricKey.new_reliability_rating, + + // vulnerabilities + MetricKey.vulnerabilities, + MetricKey.new_vulnerabilities, + MetricKey.security_rating, + MetricKey.new_security_rating, + + // hotspots + MetricKey.security_hotspots, + MetricKey.new_security_hotspots, + MetricKey.security_hotspots_reviewed, + MetricKey.new_security_hotspots_reviewed, + MetricKey.security_review_rating, + MetricKey.new_security_review_rating, + + // code smells + MetricKey.code_smells, + MetricKey.new_code_smells, + MetricKey.sqale_rating, + MetricKey.new_maintainability_rating, + MetricKey.sqale_index, + MetricKey.new_technical_debt, + + // coverage + MetricKey.coverage, + MetricKey.new_coverage, + MetricKey.lines_to_cover, + MetricKey.new_lines_to_cover, + MetricKey.tests, + + // duplications + MetricKey.duplicated_lines_density, + MetricKey.new_duplicated_lines_density, + MetricKey.duplicated_blocks, + + // size + MetricKey.ncloc, + MetricKey.ncloc_language_distribution, + MetricKey.projects, + MetricKey.lines, + MetricKey.new_lines, +]; + +export const PR_METRICS: string[] = [ + MetricKey.coverage, + MetricKey.new_coverage, + MetricKey.new_lines_to_cover, + + MetricKey.new_accepted_issues, + MetricKey.new_violations, + MetricKey.duplicated_lines_density, + MetricKey.new_duplicated_lines_density, + MetricKey.new_lines, + MetricKey.new_code_smells, + MetricKey.new_maintainability_rating, + MetricKey.new_bugs, + MetricKey.new_reliability_rating, + MetricKey.new_vulnerabilities, + MetricKey.new_security_hotspots, + MetricKey.new_security_review_rating, + MetricKey.new_security_rating, + + MetricKey.pull_request_fixed_issues, +]; + +export const HISTORY_METRICS_LIST: string[] = [ + MetricKey.bugs, + MetricKey.vulnerabilities, + MetricKey.sqale_index, + MetricKey.duplicated_lines_density, + MetricKey.ncloc, + MetricKey.coverage, + MetricKey.alert_status, +]; + +const MEASURES_VARIATIONS_METRICS = [ + MetricKey.bugs, + MetricKey.code_smells, + MetricKey.coverage, + MetricKey.duplicated_lines_density, + MetricKey.vulnerabilities, +]; + +export enum MeasurementType { + Coverage = 'COVERAGE', + Duplication = 'DUPLICATION', +} + +export enum Status { + OK = 'OK', + ERROR = 'ERROR', +} + +const MEASUREMENTS_MAP = { + [MeasurementType.Coverage]: { + metric: MetricKey.coverage, + newMetric: MetricKey.new_coverage, + linesMetric: MetricKey.lines_to_cover, + newLinesMetric: MetricKey.new_lines_to_cover, + afterMergeMetric: MetricKey.coverage, + labelKey: 'metric.coverage.name', + expandedLabelKey: 'overview.coverage_on_X_lines', + newLinesExpandedLabelKey: 'overview.coverage_on_X_new_lines', + iconClass: CoverageRating, + }, + [MeasurementType.Duplication]: { + metric: MetricKey.duplicated_lines_density, + newMetric: MetricKey.new_duplicated_lines_density, + linesMetric: MetricKey.ncloc, + newLinesMetric: MetricKey.new_lines, + afterMergeMetric: MetricKey.duplicated_lines_density, + labelKey: 'metric.duplicated_lines_density.short_name', + expandedLabelKey: 'overview.duplications_on_X_lines', + newLinesExpandedLabelKey: 'overview.duplications_on_X_new_lines', + iconClass: DuplicationsRating, + }, +}; + +export const RATING_TO_SEVERITIES_MAPPING = [ + 'BLOCKER,CRITICAL,MAJOR,MINOR', + 'BLOCKER,CRITICAL,MAJOR', + 'BLOCKER,CRITICAL', + 'BLOCKER', +]; + +export const RATING_METRICS_MAPPING: Dict = { + [MetricKey.reliability_rating]: IssueType.Bug, + [MetricKey.new_reliability_rating]: IssueType.Bug, + [MetricKey.security_rating]: IssueType.Vulnerability, + [MetricKey.new_security_rating]: IssueType.Vulnerability, + [MetricKey.sqale_rating]: IssueType.CodeSmell, + [MetricKey.new_maintainability_rating]: IssueType.CodeSmell, + [MetricKey.security_review_rating]: IssueType.SecurityHotspot, + [MetricKey.new_security_review_rating]: IssueType.SecurityHotspot, +}; + +export const METRICS_REPORTED_IN_OVERVIEW_CARDS = [ + MetricKey.new_violations, + MetricKey.violations, + MetricKey.new_coverage, + MetricKey.coverage, + MetricKey.new_security_hotspots_reviewed, + MetricKey.security_hotspots_reviewed, + MetricKey.new_duplicated_lines_density, + MetricKey.duplicated_lines_density, +]; + +export function getIssueRatingName(type: IssueType) { + return translate('metric_domain', ISSUETYPE_METRIC_KEYS_MAP[type].ratingName); +} + +export function getIssueIconClass(type: IssueType) { + return ISSUETYPE_METRIC_KEYS_MAP[type].iconClass; +} + +export function getIssueMetricKey(type: IssueType, useDiffMetric: boolean) { + return useDiffMetric + ? ISSUETYPE_METRIC_KEYS_MAP[type].newMetric + : ISSUETYPE_METRIC_KEYS_MAP[type].metric; +} + +export function getIssueRatingMetricKey(type: IssueType, useDiffMetric: boolean) { + return useDiffMetric + ? ISSUETYPE_METRIC_KEYS_MAP[type].newRating + : ISSUETYPE_METRIC_KEYS_MAP[type].rating; +} + +export function getMeasurementIconClass(type: MeasurementType) { + return MEASUREMENTS_MAP[type].iconClass; +} + +export function getMeasurementMetricKey(type: MeasurementType, useDiffMetric: boolean) { + return useDiffMetric ? MEASUREMENTS_MAP[type].newMetric : MEASUREMENTS_MAP[type].metric; +} + +export function getMeasurementAfterMergeMetricKey(type: MeasurementType) { + return MEASUREMENTS_MAP[type].afterMergeMetric; +} + +export function getMeasurementLinesMetricKey(type: MeasurementType, useDiffMetric: boolean) { + return useDiffMetric ? MEASUREMENTS_MAP[type].newLinesMetric : MEASUREMENTS_MAP[type].linesMetric; +} + +export function getMeasurementLabelKeys(type: MeasurementType, useDiffMetric: boolean) { + return { + expandedLabelKey: useDiffMetric + ? MEASUREMENTS_MAP[type].newLinesExpandedLabelKey + : MEASUREMENTS_MAP[type].expandedLabelKey, + labelKey: MEASUREMENTS_MAP[type].labelKey, + }; +} + +export const parseQuery = memoize((urlQuery: RawQuery): { codeScope: string } => { + return { + codeScope: parseAsString(urlQuery['code_scope']), + }; +}); + +export function getAnalysisVariations(measures: MeasureHistory[], analysesCount: number) { + if (analysesCount === 0) { + return []; + } + + const emptyVariations: AnalysisMeasuresVariations[] = Array.from( + { length: analysesCount }, + () => ({}), + ); + + return measures.reduce((variations, { metric, history }) => { + if (!MEASURES_VARIATIONS_METRICS.includes(metric)) { + return variations; + } + + history.slice(-analysesCount).forEach(({ value = '' }, index, analysesHistory) => { + if (index === 0) { + variations[index][metric] = parseFloat(value) || 0; + return; + } + + const previousValue = parseFloat(analysesHistory[index - 1].value ?? '') || 0; + const numericValue = parseFloat(value) || 0; + const variation = numericValue - previousValue; + + if (variation === 0) { + return; + } + + variations[index][metric] = variation; + }); + + return variations; + }, emptyVariations); +} + +export function getConditionRequiredLabel( + condition: QualityGateStatusConditionEnhanced, + intl: IntlShape, + failed = false, +) { + const conditionEl = ( + <> + {condition.op === 'GT' ? '≤' : '≥'}{' '} + {formatMeasure(condition.error, condition.measure.metric.type, { + decimals: 2, + omitExtraDecimalZeros: true, + })} + + ); + return intl.formatMessage( + { id: 'overview.quality_gate.required_x' }, + { + requirement: failed ? {conditionEl} : conditionEl, + }, + ); +} diff --git a/server/sonar-web/src/main/js/helpers/mocks/metrics.ts b/server/sonar-web/src/main/js/helpers/mocks/metrics.ts index 2d7e20c2615..1134b4e62b7 100644 --- a/server/sonar-web/src/main/js/helpers/mocks/metrics.ts +++ b/server/sonar-web/src/main/js/helpers/mocks/metrics.ts @@ -21,7 +21,6 @@ import { Dict, Metric } from '../../types/types'; export const DEFAULT_METRICS: Dict = { new_technical_debt: { - id: 'AXJMbIl_PAOIsUIE3guE', key: 'new_technical_debt', type: 'WORK_DUR', name: 'Added Technical Debt', @@ -32,7 +31,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, blocker_violations: { - id: 'AXJMbIl_PAOIsUIE3gtt', key: 'blocker_violations', type: 'INT', name: 'Blocker Issues', @@ -43,7 +41,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, bugs: { - id: 'AXJMbIl_PAOIsUIE3gt_', key: 'bugs', type: 'INT', name: 'Bugs', @@ -54,7 +51,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, classes: { - id: 'AXJMbImPPAOIsUIE3gu5', key: 'classes', type: 'INT', name: 'Classes', @@ -65,7 +61,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, code_smells: { - id: 'AXJMbIl_PAOIsUIE3gt9', key: 'code_smells', type: 'INT', name: 'Code Smells', @@ -76,7 +71,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, cognitive_complexity: { - id: 'AXJMbIl9PAOIsUIE3gtZ', key: 'cognitive_complexity', type: 'INT', name: 'Cognitive Complexity', @@ -87,7 +81,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, comment_lines: { - id: 'AXJMbImPPAOIsUIE3gup', key: 'comment_lines', type: 'INT', name: 'Comment Lines', @@ -98,7 +91,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, comment_lines_data: { - id: 'AXJMbImPPAOIsUIE3guV', key: 'comment_lines_data', type: 'DATA', name: 'comment_lines_data', @@ -108,7 +100,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, comment_lines_density: { - id: 'AXJMbImPPAOIsUIE3guq', key: 'comment_lines_density', type: 'PERCENT', name: 'Comments (%)', @@ -120,7 +111,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, class_complexity: { - id: 'AXJMbImPPAOIsUIE3guw', key: 'class_complexity', type: 'FLOAT', name: 'Complexity / Class', @@ -132,7 +122,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, file_complexity: { - id: 'AXJMbImPPAOIsUIE3guu', key: 'file_complexity', type: 'FLOAT', name: 'Complexity / File', @@ -144,7 +133,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, function_complexity: { - id: 'AXJMbImPPAOIsUIE3guy', key: 'function_complexity', type: 'FLOAT', name: 'Complexity / Function', @@ -156,7 +144,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, complexity_in_classes: { - id: 'AXJMbImPPAOIsUIE3guv', key: 'complexity_in_classes', type: 'INT', name: 'Complexity in Classes', @@ -167,7 +154,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, complexity_in_functions: { - id: 'AXJMbImPPAOIsUIE3gux', key: 'complexity_in_functions', type: 'INT', name: 'Complexity in Functions', @@ -178,7 +164,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, branch_coverage: { - id: 'AXJMbIl9PAOIsUIE3gs-', key: 'branch_coverage', type: 'PERCENT', name: 'Condition Coverage', @@ -190,7 +175,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, new_branch_coverage: { - id: 'AXJMbIl9PAOIsUIE3gs_', key: 'new_branch_coverage', type: 'PERCENT', name: 'Condition Coverage on New Code', @@ -202,7 +186,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, conditions_to_cover: { - id: 'AXJMbIl9PAOIsUIE3gqt', key: 'conditions_to_cover', type: 'INT', name: 'Conditions to Cover', @@ -213,7 +196,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_conditions_to_cover: { - id: 'AXJMbIl9PAOIsUIE3gs7', key: 'new_conditions_to_cover', type: 'INT', name: 'Conditions to Cover on New Code', @@ -224,7 +206,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, confirmed_issues: { - id: 'AXJMbIl_PAOIsUIE3gt8', key: 'confirmed_issues', type: 'INT', name: 'Confirmed Issues', @@ -235,7 +216,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, coverage: { - id: 'AXJMbIl9PAOIsUIE3gtg', key: 'coverage', type: 'PERCENT', name: 'Coverage', @@ -247,7 +227,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, new_coverage: { - id: 'AXJMbIl_PAOIsUIE3gth', key: 'new_coverage', type: 'PERCENT', name: 'Coverage on New Code', @@ -259,7 +238,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, critical_violations: { - id: 'AXJMbIl_PAOIsUIE3gtu', key: 'critical_violations', type: 'INT', name: 'Critical Issues', @@ -270,7 +248,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, complexity: { - id: 'AXJMbImPPAOIsUIE3gut', key: 'complexity', type: 'INT', name: 'Cyclomatic Complexity', @@ -281,7 +258,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, last_commit_date: { - id: 'AXJMbImPPAOIsUIE3gua', key: 'last_commit_date', type: 'MILLISEC', name: 'Date of Last Commit', @@ -291,7 +267,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, development_cost: { - id: 'AXJMbIl_PAOIsUIE3guI', key: 'development_cost', type: 'STRING', name: 'Development Cost', @@ -302,7 +277,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_development_cost: { - id: 'AXJMbIl_PAOIsUIE3guJ', key: 'new_development_cost', type: 'FLOAT', name: 'Development Cost on New Code', @@ -314,7 +288,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, directories: { - id: 'AXJMbImPPAOIsUIE3gu9', key: 'directories', type: 'INT', name: 'Directories', @@ -325,7 +298,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, duplicated_blocks: { - id: 'AXJMbIl9PAOIsUIE3gsu', key: 'duplicated_blocks', type: 'INT', name: 'Duplicated Blocks', @@ -336,7 +308,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_duplicated_blocks: { - id: 'AXJMbIl_PAOIsUIE3gto', key: 'new_duplicated_blocks', type: 'INT', name: 'Duplicated Blocks on New Code', @@ -347,7 +318,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, duplicated_files: { - id: 'AXJMbImPPAOIsUIE3gvA', key: 'duplicated_files', type: 'INT', name: 'Duplicated Files', @@ -358,7 +328,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, duplicated_lines: { - id: 'AXJMbIl9PAOIsUIE3gss', key: 'duplicated_lines', type: 'INT', name: 'Duplicated Lines', @@ -369,7 +338,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, duplicated_lines_density: { - id: 'AXJMbIl_PAOIsUIE3gtp', key: 'duplicated_lines_density', type: 'PERCENT', name: 'Duplicated Lines (%)', @@ -381,7 +349,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, new_duplicated_lines_density: { - id: 'AXJMbIl_PAOIsUIE3gtq', key: 'new_duplicated_lines_density', type: 'PERCENT', name: 'Duplicated Lines (%) on New Code', @@ -393,7 +360,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, new_duplicated_lines: { - id: 'AXJMbIl9PAOIsUIE3gst', key: 'new_duplicated_lines', type: 'INT', name: 'Duplicated Lines on New Code', @@ -404,7 +370,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, duplications_data: { - id: 'AXJMbIl_PAOIsUIE3gtr', key: 'duplications_data', type: 'DATA', name: 'Duplication Details', @@ -415,7 +380,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, effort_to_reach_maintainability_rating_a: { - id: 'AXJMbIl_PAOIsUIE3guM', key: 'effort_to_reach_maintainability_rating_a', type: 'WORK_DUR', name: 'Effort to Reach Maintainability Rating A', @@ -426,7 +390,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, executable_lines_data: { - id: 'AXJMbImPPAOIsUIE3guW', key: 'executable_lines_data', type: 'DATA', name: 'executable_lines_data', @@ -436,7 +399,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, false_positive_issues: { - id: 'AXJMbIl_PAOIsUIE3gt4', key: 'false_positive_issues', type: 'INT', name: 'False Positive Issues', @@ -447,7 +409,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, file_complexity_distribution: { - id: 'AXJMbIl9PAOIsUIE3gtY', key: 'file_complexity_distribution', type: 'DISTRIB', name: 'File Distribution / Complexity', @@ -458,7 +419,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, files: { - id: 'AXJMbImPPAOIsUIE3gu6', key: 'files', type: 'INT', name: 'Files', @@ -469,7 +429,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, function_complexity_distribution: { - id: 'AXJMbIl9PAOIsUIE3gtX', key: 'function_complexity_distribution', type: 'DISTRIB', name: 'Function Distribution / Complexity', @@ -480,7 +439,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, functions: { - id: 'AXJMbImPPAOIsUIE3gu-', key: 'functions', type: 'INT', name: 'Functions', @@ -491,7 +449,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, generated_lines: { - id: 'AXJMbImPPAOIsUIE3gu0', key: 'generated_lines', type: 'INT', name: 'Generated Lines', @@ -502,7 +459,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, generated_ncloc: { - id: 'AXJMbImPPAOIsUIE3gu4', key: 'generated_ncloc', type: 'INT', name: 'Generated Lines of Code', @@ -513,7 +469,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, info_violations: { - id: 'AXJMbIl_PAOIsUIE3gtx', key: 'info_violations', type: 'INT', name: 'Info Issues', @@ -524,7 +479,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, violations: { - id: 'AXJMbImPPAOIsUIE3gul', key: 'violations', type: 'INT', name: 'Issues', @@ -535,7 +489,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, last_change_on_maintainability_rating: { - id: 'AXJMbImPPAOIsUIE3gud', key: 'last_change_on_maintainability_rating', type: 'DATA', name: 'Last Change on Maintainability Rating', @@ -545,7 +498,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, last_change_on_releasability_rating: { - id: 'AXJMbImPPAOIsUIE3gue', key: 'last_change_on_releasability_rating', type: 'DATA', name: 'Last Change on Releasability Rating', @@ -555,7 +507,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, last_change_on_reliability_rating: { - id: 'AXJMbImPPAOIsUIE3guf', key: 'last_change_on_reliability_rating', type: 'DATA', name: 'Last Change on Reliability Rating', @@ -565,7 +516,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, last_change_on_security_rating: { - id: 'AXJMbImPPAOIsUIE3gug', key: 'last_change_on_security_rating', type: 'DATA', name: 'Last Change on Security Rating', @@ -575,7 +525,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, last_change_on_security_review_rating: { - id: 'AXJMbIl9PAOIsUIE3gs4', key: 'last_change_on_security_review_rating', type: 'DATA', name: 'Last Change on Security Review Rating', @@ -585,7 +534,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, line_coverage: { - id: 'AXJMbIl_PAOIsUIE3gtl', key: 'line_coverage', type: 'PERCENT', name: 'Line Coverage', @@ -597,7 +545,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, new_line_coverage: { - id: 'AXJMbIl_PAOIsUIE3gtm', key: 'new_line_coverage', type: 'PERCENT', name: 'Line Coverage on New Code', @@ -609,7 +556,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, lines: { - id: 'AXJMbImPPAOIsUIE3guz', key: 'lines', type: 'INT', name: 'Lines', @@ -620,7 +566,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, ncloc: { - id: 'AXJMbImPPAOIsUIE3gu1', key: 'ncloc', type: 'INT', name: 'Lines of Code', @@ -631,7 +576,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, ncloc_language_distribution: { - id: 'AXJMbImPPAOIsUIE3gu3', key: 'ncloc_language_distribution', type: 'DATA', name: 'Lines of Code Per Language', @@ -642,7 +586,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, lines_to_cover: { - id: 'AXJMbImPPAOIsUIE3gu_', key: 'lines_to_cover', type: 'INT', name: 'Lines to Cover', @@ -653,7 +596,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_lines_to_cover: { - id: 'AXJMbIl_PAOIsUIE3gti', key: 'new_lines_to_cover', type: 'INT', name: 'Lines to Cover on New Code', @@ -664,7 +606,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, leak_projects: { - id: 'AXJMbImPPAOIsUIE3gvE', key: 'leak_projects', type: 'DATA', name: 'List of technical projects with their leaks', @@ -673,7 +614,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, sqale_rating: { - id: 'AXJMbIl_PAOIsUIE3guF', key: 'sqale_rating', type: 'RATING', name: 'Maintainability Rating', @@ -684,7 +624,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, maintainability_rating_distribution: { - id: 'AX6QkqP7zEziun0YBqmh', key: 'maintainability_rating_distribution', type: 'DATA', name: 'Maintainability Rating Distribution', @@ -695,7 +634,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_maintainability_rating_distribution: { - id: 'AX6QkqP8zEziun0YBqml', key: 'new_maintainability_rating_distribution', type: 'DATA', name: 'Maintainability Rating Distribution on New Code', @@ -706,7 +644,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_maintainability_rating: { - id: 'AXJMbIl_PAOIsUIE3guH', key: 'new_maintainability_rating', type: 'RATING', name: 'Maintainability Rating on New Code', @@ -717,7 +654,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, major_violations: { - id: 'AXJMbIl_PAOIsUIE3gtv', key: 'major_violations', type: 'INT', name: 'Major Issues', @@ -728,7 +664,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, minor_violations: { - id: 'AXJMbIl_PAOIsUIE3gtw', key: 'minor_violations', type: 'INT', name: 'Minor Issues', @@ -739,7 +674,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, ncloc_data: { - id: 'AXJMbImPPAOIsUIE3guU', key: 'ncloc_data', type: 'DATA', name: 'ncloc_data', @@ -749,7 +683,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_blocker_violations: { - id: 'AXJMbIl_PAOIsUIE3gtz', key: 'new_blocker_violations', type: 'INT', name: 'New Blocker Issues', @@ -760,7 +693,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_bugs: { - id: 'AXJMbIl_PAOIsUIE3guA', key: 'new_bugs', type: 'INT', name: 'New Bugs', @@ -771,7 +703,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_code_smells: { - id: 'AXJMbIl_PAOIsUIE3gt-', key: 'new_code_smells', type: 'INT', name: 'New Code Smells', @@ -782,7 +713,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_critical_violations: { - id: 'AXJMbIl_PAOIsUIE3gt0', key: 'new_critical_violations', type: 'INT', name: 'New Critical Issues', @@ -793,7 +723,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_info_violations: { - id: 'AXJMbIl_PAOIsUIE3gt3', key: 'new_info_violations', type: 'INT', name: 'New Info Issues', @@ -804,7 +733,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_violations: { - id: 'AXJMbIl_PAOIsUIE3gty', key: 'new_violations', type: 'INT', name: 'New Issues', @@ -815,7 +743,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_lines: { - id: 'AXJMbImPPAOIsUIE3gu2', key: 'new_lines', type: 'INT', name: 'New Lines', @@ -826,7 +753,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_major_violations: { - id: 'AXJMbIl_PAOIsUIE3gt1', key: 'new_major_violations', type: 'INT', name: 'New Major Issues', @@ -837,7 +763,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_minor_violations: { - id: 'AXJMbIl_PAOIsUIE3gt2', key: 'new_minor_violations', type: 'INT', name: 'New Minor Issues', @@ -848,7 +773,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_security_hotspots: { - id: 'AXJMbIl9PAOIsUIE3gsw', key: 'new_security_hotspots', type: 'INT', name: 'New Security Hotspots', @@ -859,7 +783,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_vulnerabilities: { - id: 'AXJMbIl_PAOIsUIE3guC', key: 'new_vulnerabilities', type: 'INT', name: 'New Vulnerabilities', @@ -870,7 +793,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, unanalyzed_c: { - id: 'AXTb6RMqLLQlB5osv3xN', key: 'unanalyzed_c', type: 'INT', name: 'Number of unanalyzed c files', @@ -880,7 +802,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, unanalyzed_cpp: { - id: 'AXTb6RMtLLQlB5osv3xO', key: 'unanalyzed_cpp', type: 'INT', name: 'Number of unanalyzed c++ files', @@ -890,7 +811,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, open_issues: { - id: 'AXJMbIl_PAOIsUIE3gt6', key: 'open_issues', type: 'INT', name: 'Open Issues', @@ -901,7 +821,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, quality_profiles: { - id: 'AXJMbImPPAOIsUIE3guZ', key: 'quality_profiles', type: 'DATA', name: 'Profiles', @@ -912,7 +831,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, projects: { - id: 'AXJMbImPPAOIsUIE3guo', key: 'projects', type: 'INT', name: 'Project branches', @@ -923,7 +841,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, public_api: { - id: 'AXJMbImPPAOIsUIE3gun', key: 'public_api', type: 'INT', name: 'Public API', @@ -934,7 +851,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, public_documented_api_density: { - id: 'AXJMbImPPAOIsUIE3gur', key: 'public_documented_api_density', type: 'PERCENT', name: 'Public Documented API (%)', @@ -946,7 +862,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, public_undocumented_api: { - id: 'AXJMbImPPAOIsUIE3gus', key: 'public_undocumented_api', type: 'INT', name: 'Public Undocumented API', @@ -957,7 +872,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, quality_gate_details: { - id: 'AXJMbImPPAOIsUIE3guY', key: 'quality_gate_details', type: 'DATA', name: 'Quality Gate Details', @@ -968,7 +882,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, alert_status: { - id: 'AXJMbImPPAOIsUIE3guX', key: 'alert_status', type: 'LEVEL', name: 'Quality Gate Status', @@ -979,7 +892,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, releasability_rating: { - id: 'AXJMbImPPAOIsUIE3guc', key: 'releasability_rating', type: 'RATING', name: 'Releasability rating', @@ -989,7 +901,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, releasability_rating_distribution: { - id: 'AX6QkqP7zEziun0YBqmg', key: 'releasability_rating_distribution', type: 'DATA', name: 'Releasability Rating Distribution', @@ -1000,7 +911,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, reliability_rating: { - id: 'AXJMbIl_PAOIsUIE3guP', key: 'reliability_rating', type: 'RATING', name: 'Reliability Rating', @@ -1011,7 +921,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, reliability_rating_distribution: { - id: 'AX6QkqP7zEziun0YBqmi', key: 'reliability_rating_distribution', type: 'DATA', name: 'Reliability Rating Distribution', @@ -1022,7 +931,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_reliability_rating_distribution: { - id: 'AX6QkqP8zEziun0YBqmm', key: 'new_reliability_rating_distribution', type: 'DATA', name: 'Reliability Rating Distribution on New Code', @@ -1033,7 +941,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_reliability_rating: { - id: 'AXJMbIl_PAOIsUIE3guQ', key: 'new_reliability_rating', type: 'RATING', name: 'Reliability Rating on New Code', @@ -1044,7 +951,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, reliability_remediation_effort: { - id: 'AXJMbIl_PAOIsUIE3guN', key: 'reliability_remediation_effort', type: 'WORK_DUR', name: 'Reliability Remediation Effort', @@ -1055,7 +961,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_reliability_remediation_effort: { - id: 'AXJMbIl_PAOIsUIE3guO', key: 'new_reliability_remediation_effort', type: 'WORK_DUR', name: 'Reliability Remediation Effort on New Code', @@ -1066,7 +971,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, reopened_issues: { - id: 'AXJMbIl_PAOIsUIE3gt7', key: 'reopened_issues', type: 'INT', name: 'Reopened Issues', @@ -1077,7 +981,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, security_hotspots: { - id: 'AXJMbIl9PAOIsUIE3gsv', key: 'security_hotspots', type: 'INT', name: 'Security Hotspots', @@ -1088,7 +991,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, security_hotspots_reviewed: { - id: 'AXJMbIl9PAOIsUIE3gs0', key: 'security_hotspots_reviewed', type: 'PERCENT', name: 'Security Hotspots Reviewed', @@ -1100,7 +1002,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, new_security_hotspots_reviewed: { - id: 'AXJMbIl9PAOIsUIE3gs1', key: 'new_security_hotspots_reviewed', type: 'PERCENT', name: 'Security Hotspots Reviewed on New Code', @@ -1112,7 +1013,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, security_rating: { - id: 'AXJMbIl_PAOIsUIE3guS', key: 'security_rating', type: 'RATING', name: 'Security Rating', @@ -1123,7 +1023,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, security_rating_distribution: { - id: 'AX6QkqP7zEziun0YBqmj', key: 'security_rating_distribution', type: 'DATA', name: 'Security Rating Distribution', @@ -1134,7 +1033,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_security_rating_distribution: { - id: 'AX6QkqP8zEziun0YBqmn', key: 'new_security_rating_distribution', type: 'DATA', name: 'Security Rating Distribution on New Code', @@ -1145,7 +1043,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_security_rating: { - id: 'AXJMbImPPAOIsUIE3guT', key: 'new_security_rating', type: 'RATING', name: 'Security Rating on New Code', @@ -1156,7 +1053,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, security_remediation_effort: { - id: 'AXJMbIl_PAOIsUIE3guG', key: 'security_remediation_effort', type: 'WORK_DUR', name: 'Security Remediation Effort', @@ -1167,7 +1063,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_security_remediation_effort: { - id: 'AXJMbIl_PAOIsUIE3guR', key: 'new_security_remediation_effort', type: 'WORK_DUR', name: 'Security Remediation Effort on New Code', @@ -1178,7 +1073,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, security_review_rating: { - id: 'AXJMbIl9PAOIsUIE3gsx', key: 'security_review_rating', type: 'RATING', name: 'Security Review Rating', @@ -1189,7 +1083,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, security_review_rating_distribution: { - id: 'AX6QkqP8zEziun0YBqmk', key: 'security_review_rating_distribution', type: 'DATA', name: 'Security Review Rating Distribution', @@ -1200,7 +1093,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_security_review_rating_distribution: { - id: 'AX6QkqP8zEziun0YBqmo', key: 'new_security_review_rating_distribution', type: 'DATA', name: 'Security Review Rating Distribution on New Code', @@ -1211,7 +1103,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_security_review_rating: { - id: 'AXJMbIl9PAOIsUIE3gtA', key: 'new_security_review_rating', type: 'RATING', name: 'Security Review Rating on New Code', @@ -1222,7 +1113,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, security_hotspots_reviewed_status: { - id: 'AXJMbIl9PAOIsUIE3gs2', key: 'security_hotspots_reviewed_status', type: 'INT', name: 'Security Review Reviewed Status', @@ -1233,7 +1123,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_security_hotspots_reviewed_status: { - id: 'AXJMbIl9PAOIsUIE3gtB', key: 'new_security_hotspots_reviewed_status', type: 'INT', name: 'Security Review Reviewed Status on New Code', @@ -1244,7 +1133,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, security_hotspots_to_review_status: { - id: 'AXJMbIl9PAOIsUIE3gs3', key: 'security_hotspots_to_review_status', type: 'INT', name: 'Security Review To Review Status', @@ -1255,7 +1143,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, new_security_hotspots_to_review_status: { - id: 'AXJMbIl9PAOIsUIE3gs5', key: 'new_security_hotspots_to_review_status', type: 'INT', name: 'Security Review To Review Status on New Code', @@ -1266,7 +1153,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, skipped_tests: { - id: 'AXJMbIl9PAOIsUIE3gtd', key: 'skipped_tests', type: 'INT', name: 'Skipped Unit Tests', @@ -1277,7 +1163,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, statements: { - id: 'AXJMbImPPAOIsUIE3gum', key: 'statements', type: 'INT', name: 'Statements', @@ -1288,7 +1173,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, sqale_index: { - id: 'AXJMbIl_PAOIsUIE3guD', key: 'sqale_index', type: 'WORK_DUR', name: 'Technical Debt', @@ -1300,7 +1184,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, sqale_debt_ratio: { - id: 'AXJMbIl_PAOIsUIE3guK', key: 'sqale_debt_ratio', type: 'PERCENT', name: 'Technical Debt Ratio', @@ -1313,7 +1196,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, new_sqale_debt_ratio: { - id: 'AXJMbIl_PAOIsUIE3guL', key: 'new_sqale_debt_ratio', type: 'PERCENT', name: 'Technical Debt Ratio on New Code', @@ -1325,7 +1207,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, maintainability_rating_effort: { - id: 'AXJMbImPPAOIsUIE3gvD', key: 'maintainability_rating_effort', type: 'DATA', name: 'Total number of projects having worst maintainability rating', @@ -1335,7 +1216,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, reliability_rating_effort: { - id: 'AXJMbImPPAOIsUIE3gvC', key: 'reliability_rating_effort', type: 'DATA', name: 'Total number of projects having worst reliability rating', @@ -1345,7 +1225,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, security_rating_effort: { - id: 'AXJMbImPPAOIsUIE3gvB', key: 'security_rating_effort', type: 'DATA', name: 'Total number of projects having worst security rating', @@ -1355,7 +1234,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, security_review_rating_effort: { - id: 'AXJMbIl9PAOIsUIE3gs6', key: 'security_review_rating_effort', type: 'DATA', name: 'Total number of projects having worst security review rating', @@ -1365,7 +1243,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, releasability_effort: { - id: 'AXJMbImPPAOIsUIE3gub', key: 'releasability_effort', type: 'INT', name: 'Total number of projects not production ready', @@ -1375,7 +1252,6 @@ export const DEFAULT_METRICS: Dict = { hidden: true, }, uncovered_conditions: { - id: 'AXJMbIl9PAOIsUIE3gs8', key: 'uncovered_conditions', type: 'INT', name: 'Uncovered Conditions', @@ -1386,7 +1262,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_uncovered_conditions: { - id: 'AXJMbIl9PAOIsUIE3gs9', key: 'new_uncovered_conditions', type: 'INT', name: 'Uncovered Conditions on New Code', @@ -1397,7 +1272,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, uncovered_lines: { - id: 'AXJMbIl_PAOIsUIE3gtj', key: 'uncovered_lines', type: 'INT', name: 'Uncovered Lines', @@ -1408,7 +1282,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, new_uncovered_lines: { - id: 'AXJMbIl_PAOIsUIE3gtk', key: 'new_uncovered_lines', type: 'INT', name: 'Uncovered Lines on New Code', @@ -1419,7 +1292,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, test_execution_time: { - id: 'AXJMbIl9PAOIsUIE3gtb', key: 'test_execution_time', type: 'MILLISEC', name: 'Unit Test Duration', @@ -1430,7 +1302,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, test_errors: { - id: 'AXJMbIl9PAOIsUIE3gtc', key: 'test_errors', type: 'INT', name: 'Unit Test Errors', @@ -1441,7 +1312,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, test_failures: { - id: 'AXJMbIl9PAOIsUIE3gte', key: 'test_failures', type: 'INT', name: 'Unit Test Failures', @@ -1452,7 +1322,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, tests: { - id: 'AXJMbIl9PAOIsUIE3gta', key: 'tests', type: 'INT', name: 'Unit Tests', @@ -1463,7 +1332,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, test_success_density: { - id: 'AXJMbIl9PAOIsUIE3gtf', key: 'test_success_density', type: 'PERCENT', name: 'Unit Test Success (%)', @@ -1475,7 +1343,6 @@ export const DEFAULT_METRICS: Dict = { decimalScale: 1, }, vulnerabilities: { - id: 'AXJMbIl_PAOIsUIE3guB', key: 'vulnerabilities', type: 'INT', name: 'Vulnerabilities', @@ -1486,7 +1353,6 @@ export const DEFAULT_METRICS: Dict = { hidden: false, }, accepted_issues: { - id: 'AXJMbIl_PAOIsUIE3ga7', key: 'accepted_issues', type: 'INT', name: 'Accepted Issues', diff --git a/server/sonar-web/src/main/js/helpers/testMocks.ts b/server/sonar-web/src/main/js/helpers/testMocks.ts index 0a4b5e9f32e..0ef2c641c7c 100644 --- a/server/sonar-web/src/main/js/helpers/testMocks.ts +++ b/server/sonar-web/src/main/js/helpers/testMocks.ts @@ -426,7 +426,6 @@ export function mockMetric( const type = overrides.type || MetricType.Percent; return { ...overrides, - id: key, key, name, type, diff --git a/server/sonar-web/src/main/js/types/metrics.ts b/server/sonar-web/src/main/js/types/metrics.ts index 43e1cc79d95..f1b6edd1f0d 100644 --- a/server/sonar-web/src/main/js/types/metrics.ts +++ b/server/sonar-web/src/main/js/types/metrics.ts @@ -117,7 +117,7 @@ export enum MetricKey { public_api = 'public_api', public_documented_api_density = 'public_documented_api_density', public_undocumented_api = 'public_undocumented_api', - pullrequest_addressed_issues = 'pullrequest_addressed_issues', + pull_request_fixed_issues = 'pull_request_fixed_issues', quality_gate_details = 'quality_gate_details', quality_profiles = 'quality_profiles', releasability_effort = 'releasability_effort', diff --git a/server/sonar-web/src/main/js/types/types.ts b/server/sonar-web/src/main/js/types/types.ts index 35ee598d76e..416d5c4cd3c 100644 --- a/server/sonar-web/src/main/js/types/types.ts +++ b/server/sonar-web/src/main/js/types/types.ts @@ -393,7 +393,6 @@ export interface Metric { domain?: string; hidden?: boolean; higherValuesAreBetter?: boolean; - id: string; key: string; name: string; qualitative?: boolean; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index f162c8c0c84..f43ef32e670 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3264,6 +3264,10 @@ metric.wont_fix_issues.description=Won't fix issues metric.wont_fix_issues.name=Won't Fix Issues metric.accepted_issues.description=Accepted issues metric.accepted_issues.name=Accepted Issues +metric.pull_request_fixed_issues.name=Fixed issues +metric.pull_request_fixed_issues.description=Fixed issues +metric.new_accepted_issues.name=Accepted issues +metric.new_accepted_issues.description=Accepted issues #------------------------------------------------------------------------------ # @@ -3845,6 +3849,13 @@ overview.X_conditions_failed={0} failed conditions overview.failed_condition.x_rating_required={rating} is {value}. Required {threshold} overview.failed_condition.x_required={metric}. Required {threshold} overview.fix_failed_conditions_with_sonarlint=Fix issues before they fail your Quality Gate with {link} in your IDE. Power up with connected mode! +overview.pull_request.new_issues=New issues +overview.pull_request.fixed_issues=Fixed issues +overview.pull_request.fixed_issues.help=Estimation of issues fixed by this PR +overview.pull_request.fixed_issues.disclaimer=Only issues fixed on the files modified by the pull request are taken into account. Issues incidentally fixed on unmodified files are not counted. +overview.pull_request.fixed_issues.disclaimer.2=When the pull request and the target branch are not synchronized, issues introduced on the target branch may be incorrectly considered fixed by the pull request. Rebasing the pull request would give an updated value. +overview.pull_request.accepted_issues=Accepted issues +overview.pull_request.accepted_issues.help=Valid issues that were not fixed overview.quality_gate.status=Quality Gate Status overview.quality_gate=Quality Gate overview.quality_gate_x=Quality Gate: {0} @@ -3875,7 +3886,7 @@ overview.quality_gate.on_x_new_lines=On {link} New Lines. overview.quality_gate.x_estimated_after_merge={value} Estimated after merge overview.quality_gate.require_fixing={count, plural, one {requires} other {require}} fixing overview.quality_gate.require_reviewing={count, plural, one {requires} other {require}} reviewing -overview.quality_gate.required_x=Required {operator} {value} +overview.quality_gate.required_x=Required {requirement} overview.quality_profiles=Quality Profiles used overview.new_code_period_x=New Code: {0} overview.max_new_code_period_from_x=Max New Code from: {0}