From fbf80ad4a51f1c3c267c0267345a14881bfc614f Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Thu, 20 Sep 2018 11:28:52 +0200 Subject: [PATCH] finish rewriting overview app to ts --- .../main/js/apps/overview/helpers/metrics.js | 24 ------- .../overview/main/BugsAndVulnerabilities.tsx | 2 +- .../main/js/apps/overview/main/CodeSmells.tsx | 2 +- .../main/js/apps/overview/main/Coverage.tsx | 2 +- .../js/apps/overview/main/Duplications.tsx | 2 +- .../main/js/apps/overview/meta/MetaSize.tsx | 2 +- .../src/main/js/apps/overview/propTypes.js | 67 ------------------ ...ptyQualityGate.js => EmptyQualityGate.tsx} | 8 +-- .../{QualityGate.js => QualityGate.tsx} | 37 +++++----- ...eCondition.js => QualityGateCondition.tsx} | 64 ++++++++--------- ...onditions.js => QualityGateConditions.tsx} | 68 ++++++++++++------- ...alityGate-test.js => QualityGate-test.tsx} | 18 +++-- ...-test.js => QualityGateCondition-test.tsx} | 19 +++--- ...test.js.snap => QualityGate-test.tsx.snap} | 0 ...nap => QualityGateCondition-test.tsx.snap} | 9 --- .../src/main/js/apps/overview/types.js | 63 ----------------- .../js/apps/overview/{utils.js => utils.ts} | 22 +++++- .../components/preview-graph/PreviewGraph.js | 15 +++- 18 files changed, 155 insertions(+), 269 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/overview/helpers/metrics.js delete mode 100644 server/sonar-web/src/main/js/apps/overview/propTypes.js rename server/sonar-web/src/main/js/apps/overview/qualityGate/{EmptyQualityGate.js => EmptyQualityGate.tsx} (92%) rename server/sonar-web/src/main/js/apps/overview/qualityGate/{QualityGate.js => QualityGate.tsx} (85%) rename server/sonar-web/src/main/js/apps/overview/qualityGate/{QualityGateCondition.js => QualityGateCondition.tsx} (77%) rename server/sonar-web/src/main/js/apps/overview/qualityGate/{QualityGateConditions.js => QualityGateConditions.tsx} (68%) rename server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/{QualityGate-test.js => QualityGate-test.tsx} (74%) rename server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/{QualityGateCondition-test.js => QualityGateCondition-test.tsx} (91%) rename server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/{QualityGate-test.js.snap => QualityGate-test.tsx.snap} (100%) rename server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/{QualityGateCondition-test.js.snap => QualityGateCondition-test.tsx.snap} (97%) delete mode 100644 server/sonar-web/src/main/js/apps/overview/types.js rename server/sonar-web/src/main/js/apps/overview/{utils.js => utils.ts} (75%) diff --git a/server/sonar-web/src/main/js/apps/overview/helpers/metrics.js b/server/sonar-web/src/main/js/apps/overview/helpers/metrics.js deleted file mode 100644 index 9e74f072c3d..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/helpers/metrics.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 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 { translate } from '../../../helpers/l10n'; - -export function getMetricName(metricKey) { - return translate('overview.metric', metricKey); -} diff --git a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx index 36b6061b3c6..146158a5b61 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx +++ b/server/sonar-web/src/main/js/apps/overview/main/BugsAndVulnerabilities.tsx @@ -25,7 +25,7 @@ import BubblesIcon from '../../../components/icons-components/BubblesIcon'; import BugIcon from '../../../components/icons-components/BugIcon'; import LeakPeriodLegend from '../components/LeakPeriodLegend'; import VulnerabilityIcon from '../../../components/icons-components/VulnerabilityIcon'; -import { getMetricName } from '../helpers/metrics'; +import { getMetricName } from '../utils'; import { getComponentDrilldownUrl } from '../../../helpers/urls'; import { translate } from '../../../helpers/l10n'; import { isLongLivingBranch } from '../../../helpers/branches'; diff --git a/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.tsx b/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.tsx index d4cf0cd784b..c49704368f0 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.tsx +++ b/server/sonar-web/src/main/js/apps/overview/main/CodeSmells.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import enhance, { ComposedProps } from './enhance'; import DateFromNow from '../../../components/intl/DateFromNow'; -import { getMetricName } from '../helpers/metrics'; +import { getMetricName } from '../utils'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; import CodeSmellIcon from '../../../components/icons-components/CodeSmellIcon'; diff --git a/server/sonar-web/src/main/js/apps/overview/main/Coverage.tsx b/server/sonar-web/src/main/js/apps/overview/main/Coverage.tsx index 28e5a141ef7..cc7dba8cbc4 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/Coverage.tsx +++ b/server/sonar-web/src/main/js/apps/overview/main/Coverage.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import enhance, { ComposedProps } from './enhance'; import DrilldownLink from '../../../components/shared/DrilldownLink'; -import { getMetricName } from '../helpers/metrics'; +import { getMetricName } from '../utils'; import { formatMeasure, getPeriodValue } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; import CoverageRating from '../../../components/ui/CoverageRating'; diff --git a/server/sonar-web/src/main/js/apps/overview/main/Duplications.tsx b/server/sonar-web/src/main/js/apps/overview/main/Duplications.tsx index 49db5f74c36..ea9340b0e9b 100644 --- a/server/sonar-web/src/main/js/apps/overview/main/Duplications.tsx +++ b/server/sonar-web/src/main/js/apps/overview/main/Duplications.tsx @@ -20,7 +20,7 @@ import * as React from 'react'; import enhance, { ComposedProps } from './enhance'; import DrilldownLink from '../../../components/shared/DrilldownLink'; -import { getMetricName } from '../helpers/metrics'; +import { getMetricName } from '../utils'; import { formatMeasure, getPeriodValue } from '../../../helpers/measures'; import { translate } from '../../../helpers/l10n'; import DuplicationsRating from '../../../components/ui/DuplicationsRating'; diff --git a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx index 8ef1bc6c4a8..ab902845eb1 100644 --- a/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx +++ b/server/sonar-web/src/main/js/apps/overview/meta/MetaSize.tsx @@ -23,7 +23,7 @@ import DrilldownLink from '../../../components/shared/DrilldownLink'; import LanguageDistributionContainer from '../../../components/charts/LanguageDistributionContainer'; import SizeRating from '../../../components/ui/SizeRating'; import { formatMeasure } from '../../../helpers/measures'; -import { getMetricName } from '../helpers/metrics'; +import { getMetricName } from '../utils'; import { translate } from '../../../helpers/l10n'; import { LightComponent, BranchLike, MeasureEnhanced } from '../../../app/types'; diff --git a/server/sonar-web/src/main/js/apps/overview/propTypes.js b/server/sonar-web/src/main/js/apps/overview/propTypes.js deleted file mode 100644 index 6f27d5553ba..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/propTypes.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 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 { shape, arrayOf, array, string, number, object } from 'prop-types'; - -export const ComponentType = shape({ - id: string.isRequired -}); - -export const MetricType = shape({ - key: string.isRequired, - name: string.isRequired, - type: string.isRequired -}); - -export const MeasureType = shape({ - metric: MetricType.isRequired, - value: string, - periods: array -}); - -export const MeasuresListType = arrayOf(MeasureType); - -export const ConditionType = shape({ - metric: string.isRequired -}); - -export const EnhancedConditionType = shape({ - measure: MeasureType.isRequired -}); - -export const ConditionsListType = arrayOf(ConditionType); - -export const EnhancedConditionsListType = arrayOf(EnhancedConditionType); - -export const PeriodType = shape({ - index: number.isRequired, - date: string.isRequired, - mode: string.isRequired, - parameter: string -}); - -export const PeriodsListType = arrayOf(PeriodType); - -export const EventType = shape({ - id: string.isRequired, - date: object.isRequired, - type: string.isRequired, - name: string.isRequired, - text: string -}); diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/EmptyQualityGate.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/EmptyQualityGate.tsx similarity index 92% rename from server/sonar-web/src/main/js/apps/overview/qualityGate/EmptyQualityGate.js rename to server/sonar-web/src/main/js/apps/overview/qualityGate/EmptyQualityGate.tsx index 1435438f6c3..77a857a03f1 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/EmptyQualityGate.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/EmptyQualityGate.tsx @@ -17,10 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { translate } from '../../../helpers/l10n'; -const EmptyQualityGate = () => { +export default function EmptyQualityGate() { return (

{translate('overview.quality_gate')}

@@ -29,6 +29,4 @@ const EmptyQualityGate = () => {

); -}; - -export default EmptyQualityGate; +} diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx similarity index 85% rename from server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js rename to server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx index 6b68124e23d..6f6c292dcfb 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGate.tsx @@ -17,33 +17,22 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -//@flow -import React from 'react'; +import * as React from 'react'; import QualityGateConditions from './QualityGateConditions'; import EmptyQualityGate from './EmptyQualityGate'; import { translate } from '../../../helpers/l10n'; import Level from '../../../components/ui/Level'; import HelpTooltip from '../../../components/controls/HelpTooltip'; import DocTooltip from '../../../components/docs/DocTooltip'; -/*:: import type { Component, MeasuresList } from '../types'; */ +import { Component, BranchLike, MeasureEnhanced } from '../../../app/types'; -function parseQualityGateDetails(rawDetails /*: string */) { - return JSON.parse(rawDetails); -} - -function isProject(component /*: Component */) { - return component.qualifier === 'TRK'; +interface Props { + branchLike?: BranchLike; + component: Pick; + measures: MeasureEnhanced[]; } -/*:: -type Props = { - branchLike?: {id?: string; name: string }, - component: Component, - measures: MeasuresList -}; -*/ - -export default function QualityGate({ branchLike, component, measures } /*: Props */) { +export default function QualityGate({ branchLike, component, measures }: Props) { const statusMeasure = measures.find(measure => measure.metric.key === 'alert_status'); const detailsMeasure = measures.find(measure => measure.metric.key === 'quality_gate_details'); @@ -58,7 +47,7 @@ export default function QualityGate({ branchLike, component, measures } /*: Prop if (detailsMeasure && detailsMeasure.value) { const details = parseQualityGateDetails(detailsMeasure.value); conditions = details.conditions || []; - ignoredConditions = details.ignoredConditions; + ({ ignoredConditions } = details); } return ( @@ -69,7 +58,7 @@ export default function QualityGate({ branchLike, component, measures } /*: Prop className="spacer-left" doc={import(/* webpackMode: "eager" */ 'Docs/tooltips/quality-gates/project-homepage-quality-gate.md')} /> - + {level && } {ignoredConditions && ( @@ -94,3 +83,11 @@ export default function QualityGate({ branchLike, component, measures } /*: Prop ); } + +function parseQualityGateDetails(rawDetails: string) { + return JSON.parse(rawDetails); +} + +function isProject(component: Pick) { + return component.qualifier === 'TRK'; +} diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.tsx similarity index 77% rename from server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js rename to server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.tsx index 8e0f66767ef..2946c0c3ca9 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateCondition.tsx @@ -17,10 +17,10 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -// @flow -import React from 'react'; -import classNames from 'classnames'; +import * as React from 'react'; +import * as classNames from 'classnames'; import { Link } from 'react-router'; +import { QualityGateStatusConditionEnhanced } from '../utils'; import DrilldownLink from '../../../components/shared/DrilldownLink'; import Measure from '../../../components/measure/Measure'; import IssueTypeIcon from '../../../components/ui/IssueTypeIcon'; @@ -28,35 +28,27 @@ import { getPeriodValue, isDiffMetric, formatMeasure } from '../../../helpers/me import { translate } from '../../../helpers/l10n'; import { getComponentIssuesUrl } from '../../../helpers/urls'; import { getBranchLikeQuery } from '../../../helpers/branches'; -import { IssueType } from '../../../app/types'; -/*:: import type { Component } from '../types'; */ -/*:: import type { MeasureEnhanced } from '../../../components/measure/types'; */ - -export default class QualityGateCondition extends React.PureComponent { - /*:: props: { - branchLike?: { id?: string; name: string }, - component: Component, - condition: { - level: string, - measure: MeasureEnhanced, - op: string, - period: number, - error: string, - warning: string - } - }; -*/ +import { IssueType, BranchLike, Component } from '../../../app/types'; - getDecimalsNumber(threshold /*: number */, value /*: number */) /*: ?number */ { +interface Props { + branchLike?: BranchLike; + component: Pick; + condition: QualityGateStatusConditionEnhanced; +} + +export default class QualityGateCondition extends React.PureComponent { + getDecimalsNumber(threshold: number, value: number) { const delta = Math.abs(threshold - value); if (delta < 0.1 && delta > 0) { - //$FlowFixMe The matching result can't be null because of the previous check - return delta.toFixed(20).match('[^0.]').index - 1; + const match = delta.toFixed(20).match('[^0.]'); + return match && match.index ? match.index - 1 : undefined; + } else { + return undefined; } } - getIssuesUrl = (sinceLeakPeriod /*: boolean */, customQuery /*: {} */) => { - const query /*: Object */ = { + getIssuesUrl = (sinceLeakPeriod: boolean, customQuery: { [x: string]: string }) => { + const query: { [x: string]: string | undefined } = { resolved: 'false', ...getBranchLikeQuery(this.props.branchLike), ...customQuery @@ -67,11 +59,11 @@ export default class QualityGateCondition extends React.PureComponent { return getComponentIssuesUrl(this.props.component.key, query); }; - getUrlForCodeSmells(sinceLeakPeriod /*: boolean */) { + getUrlForCodeSmells(sinceLeakPeriod: boolean) { return this.getIssuesUrl(sinceLeakPeriod, { types: IssueType.CodeSmell }); } - getUrlForBugsOrVulnerabilities(type /*: string */, sinceLeakPeriod /*: boolean */) { + getUrlForBugsOrVulnerabilities(type: string, sinceLeakPeriod: boolean) { const RATING_TO_SEVERITIES_MAPPING = [ 'BLOCKER,CRITICAL,MAJOR,MINOR', 'BLOCKER,CRITICAL,MAJOR', @@ -88,13 +80,13 @@ export default class QualityGateCondition extends React.PureComponent { }); } - getUrlForType(type /*: string */, sinceLeakPeriod /*: boolean */) { + getUrlForType(type: string, sinceLeakPeriod: boolean) { return type === IssueType.CodeSmell ? this.getUrlForCodeSmells(sinceLeakPeriod) : this.getUrlForBugsOrVulnerabilities(type, sinceLeakPeriod); } - wrapWithLink(children /*: React.Element<*> */) { + wrapWithLink(children: React.ReactNode) { const { branchLike, component, condition } = this.props; const className = classNames( @@ -106,7 +98,7 @@ export default class QualityGateCondition extends React.PureComponent { const metricKey = condition.measure.metric.key; /* eslint-disable camelcase */ - const RATING_METRICS_MAPPING = { + const RATING_METRICS_MAPPING: { [metric: string]: [string, boolean] } = { reliability_rating: [IssueType.Bug, false], new_reliability_rating: [IssueType.Bug, true], security_rating: [IssueType.Vulnerability, false], @@ -139,16 +131,18 @@ export default class QualityGateCondition extends React.PureComponent { const isDiff = isDiffMetric(metric.key); - const threshold = condition.level === 'ERROR' ? condition.error : condition.warning; - const actual = condition.period ? getPeriodValue(measure, condition.period) : measure.value; + const threshold = (condition.level === 'ERROR' ? condition.error : condition.warning) as string; + const actual = (condition.period + ? getPeriodValue(measure, condition.period) + : measure.value) as string; let operator = translate('quality_gates.operator', condition.op); - let decimals = null; + let decimals: number | undefined = undefined; if (metric.type === 'RATING') { operator = translate('quality_gates.operator', condition.op, 'rating'); } else if (metric.type === 'PERCENT') { - decimals = this.getDecimalsNumber(parseFloat(condition.error), parseFloat(actual)); + decimals = this.getDecimalsNumber(parseFloat(threshold), parseFloat(actual)); } return this.wrapWithLink( diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.tsx similarity index 68% rename from server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js rename to server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.tsx index 704825459cc..32762196d54 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/QualityGateConditions.tsx @@ -17,32 +17,31 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { sortBy } from 'lodash'; -import PropTypes from 'prop-types'; import QualityGateCondition from './QualityGateCondition'; -import { ComponentType, ConditionsListType } from '../propTypes'; +import { QualityGateStatusCondition, QualityGateStatusConditionEnhanced } from '../utils'; import { getMeasuresAndMeta } from '../../../api/measures'; import { enhanceMeasuresWithMetrics } from '../../../helpers/measures'; import { isSameBranchLike, getBranchLikeQuery } from '../../../helpers/branches'; +import { BranchLike, Component, MeasureEnhanced } from '../../../app/types'; const LEVEL_ORDER = ['ERROR', 'WARN']; -function enhanceConditions(conditions, measures) { - return conditions.map(c => { - const measure = measures.find(measure => measure.metric.key === c.metric); - return { ...c, measure }; - }); +interface Props { + branchLike?: BranchLike; + component: Pick; + conditions: QualityGateStatusCondition[]; } -export default class QualityGateConditions extends React.PureComponent { - static propTypes = { - branchLike: PropTypes.object, - component: ComponentType.isRequired, - conditions: ConditionsListType.isRequired - }; +interface State { + conditions?: QualityGateStatusConditionEnhanced[]; + loading: boolean; +} - state = { +export default class QualityGateConditions extends React.PureComponent { + mounted = false; + state: State = { loading: true }; @@ -51,7 +50,7 @@ export default class QualityGateConditions extends React.PureComponent { this.loadFailedMeasures(); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps: Props) { if ( !isSameBranchLike(prevProps.branchLike, this.props.branchLike) || prevProps.conditions !== this.props.conditions || @@ -73,15 +72,22 @@ export default class QualityGateConditions extends React.PureComponent { getMeasuresAndMeta(component.key, metrics, { additionalFields: 'metrics', ...getBranchLikeQuery(branchLike) - }).then(r => { - if (this.mounted) { - const measures = enhanceMeasuresWithMetrics(r.component.measures, r.metrics); - this.setState({ - conditions: enhanceConditions(failedConditions, measures), - loading: false - }); + }).then( + ({ component, metrics }) => { + if (this.mounted) { + const measures = enhanceMeasuresWithMetrics(component.measures || [], metrics || []); + this.setState({ + conditions: enhanceConditions(failedConditions, measures), + loading: false + }); + } + }, + () => { + if (this.mounted) { + this.setState({ loading: false }); + } } - }); + ); } else { this.setState({ loading: false }); } @@ -91,14 +97,14 @@ export default class QualityGateConditions extends React.PureComponent { const { branchLike, component } = this.props; const { loading, conditions } = this.state; - if (loading) { + if (loading || !conditions) { return null; } const sortedConditions = sortBy( conditions, condition => LEVEL_ORDER.indexOf(condition.level), - condition => condition.metric.name + condition => condition.measure.metric.name ); return ( @@ -117,3 +123,13 @@ export default class QualityGateConditions extends React.PureComponent { ); } } + +function enhanceConditions( + conditions: QualityGateStatusCondition[], + measures: MeasureEnhanced[] +): QualityGateStatusConditionEnhanced[] { + return conditions.map(condition => { + const measure = measures.find(measure => measure.metric.key === condition.metric)!; + return { ...condition, measure }; + }); +} diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGate-test.js b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGate-test.tsx similarity index 74% rename from server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGate-test.js rename to server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGate-test.tsx index ab0b75b5f9a..5fe6f8eb9eb 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGate-test.js +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/QualityGate-test.tsx @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import React from 'react'; +import * as React from 'react'; import { shallow } from 'enzyme'; import QualityGate from '../QualityGate'; @@ -25,14 +25,24 @@ it('renders message about ignored conditions', () => { expect( shallow( ({ - actual: '3', +const mockRatingCondition = (metric: string): QualityGateStatusConditionEnhanced => ({ error: '1', level: 'ERROR', measure: { metric: { + id: '100', key: metric, type: 'RATING', name: metric @@ -40,12 +41,12 @@ const mockRatingCondition = metric => ({ const periods = [{ value: '3', index: 1 }]; it('open_issues', () => { - const condition = { - actual: '10', + const condition: QualityGateStatusConditionEnhanced = { error: '0', level: 'ERROR', measure: { metric: { + id: '1', key: 'open_issues', type: 'INT', name: 'Open open_issues' @@ -61,12 +62,12 @@ it('open_issues', () => { }); it('new_open_issues', () => { - const condition = { - actual: '10', + const condition: QualityGateStatusConditionEnhanced = { error: '0', level: 'ERROR', measure: { metric: { + id: '1', key: 'new_open_issues', type: 'INT', name: 'new_open_issues' @@ -135,7 +136,7 @@ it('should be able to correctly decide how much decimals to show', () => { const condition = mockRatingCondition('new_maintainability_rating'); const instance = shallow( - ).instance(); + ).instance() as QualityGateCondition; expect(instance.getDecimalsNumber(85, 80)).toBe(undefined); expect(instance.getDecimalsNumber(85, 85)).toBe(undefined); expect(instance.getDecimalsNumber(85, 85.01)).toBe(2); @@ -150,7 +151,7 @@ it('should work with branch', () => { expect( shallow( diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.js.snap b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.tsx.snap similarity index 100% rename from server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.js.snap rename to server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGate-test.tsx.snap diff --git a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGateCondition-test.js.snap b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGateCondition-test.tsx.snap similarity index 97% rename from server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGateCondition-test.js.snap rename to server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGateCondition-test.tsx.snap index 900cc34dce2..e94361e063d 100644 --- a/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGateCondition-test.js.snap +++ b/server/sonar-web/src/main/js/apps/overview/qualityGate/__tests__/__snapshots__/QualityGateCondition-test.tsx.snap @@ -24,7 +24,6 @@ exports[`new_maintainability_rating 1`] = ` className="overview-quality-gate-condition-value" > }; -*/ - -/*:: -export type Metric = { - custom?: boolean, - hidden?: boolean, - key: string, - name: string, - type: string -}; -*/ - -/*:: -export type Measure = { - metric: Metric, - value?: string, - periods?: Array -}; -*/ - -/*:: -export type Period = { - index: number, - date: string, - mode: string, - parameter?: string -}; -*/ - -/*:: -export type MeasuresList = Array; */ diff --git a/server/sonar-web/src/main/js/apps/overview/utils.js b/server/sonar-web/src/main/js/apps/overview/utils.ts similarity index 75% rename from server/sonar-web/src/main/js/apps/overview/utils.js rename to server/sonar-web/src/main/js/apps/overview/utils.ts index 08e128b8cc7..cb0923876ef 100644 --- a/server/sonar-web/src/main/js/apps/overview/utils.js +++ b/server/sonar-web/src/main/js/apps/overview/utils.ts @@ -17,7 +17,23 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -//@flow +import { MeasureEnhanced } from '../../app/types'; +import { translate } from '../../helpers/l10n'; + +export interface QualityGateStatusCondition { + actual?: string; + error?: string; + level: string; + metric: string; + op: string; + period?: number; + warning?: string; +} + +// long name to not mix with Condition from /app/types.ts +export interface QualityGateStatusConditionEnhanced extends QualityGateStatusCondition { + measure: MeasureEnhanced; +} export const METRICS = [ // quality gate @@ -68,3 +84,7 @@ export const HISTORY_METRICS_LIST = [ 'ncloc', 'coverage' ]; + +export function getMetricName(metricKey: string) { + return translate('overview.metric', metricKey); +} diff --git a/server/sonar-web/src/main/js/components/preview-graph/PreviewGraph.js b/server/sonar-web/src/main/js/components/preview-graph/PreviewGraph.js index b98fb9b22ff..64b03d4827c 100644 --- a/server/sonar-web/src/main/js/components/preview-graph/PreviewGraph.js +++ b/server/sonar-web/src/main/js/components/preview-graph/PreviewGraph.js @@ -39,7 +39,20 @@ import { get } from '../../helpers/storage'; import { formatMeasure, getShortType } from '../../helpers/measures'; import { getBranchLikeQuery } from '../../helpers/branches'; /*:: import type { Serie } from '../charts/AdvancedTimeline'; */ -/*:: import type { History, Metric } from '../../apps/overview/types'; */ + +/*:: +type History = { [string]: Array<{ date: Date, value: string }> }; +*/ + +/*:: +type Metric = { + custom?: boolean, + hidden?: boolean, + key: string, + name: string, + type: string +}; +*/ /*:: type Props = { -- 2.39.5