From 49391d2eff65209068acc31e41393b9617fb2458 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Tue, 16 Jan 2018 13:49:10 +0100 Subject: [PATCH] Migrate App to tsx and clean up measures related types --- server/sonar-web/src/main/js/api/measures.ts | 26 +++-- .../sonar-web/src/main/js/api/time-machine.ts | 22 +++- server/sonar-web/src/main/js/app/types.ts | 2 +- .../sonar-web/src/main/js/apps/code/types.ts | 10 +- .../main/js/apps/overview/components/App.js | 104 ------------------ .../overview/components/__tests__/App-test.js | 51 --------- .../js/apps/portfolio/components/Summary.tsx | 3 +- .../main/js/components/measure/Measure.tsx | 6 +- .../src/main/js/components/measure/utils.ts | 21 +--- server/sonar-web/src/main/js/helpers/l10n.ts | 9 +- .../sonar-web/src/main/js/helpers/measures.ts | 23 ++-- .../sonar-web/src/main/js/helpers/periods.ts | 2 +- 12 files changed, 64 insertions(+), 215 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/overview/components/App.js delete mode 100644 server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js diff --git a/server/sonar-web/src/main/js/api/measures.ts b/server/sonar-web/src/main/js/api/measures.ts index c423492abde..2f5ae506503 100644 --- a/server/sonar-web/src/main/js/api/measures.ts +++ b/server/sonar-web/src/main/js/api/measures.ts @@ -19,42 +19,48 @@ */ import { getJSON, RequestData } from '../helpers/request'; import throwGlobalError from '../app/utils/throwGlobalError'; +import { Measure, MeasurePeriod } from '../helpers/measures'; +import { Metric } from '../app/types'; +import { Period } from '../helpers/periods'; export function getMeasures( componentKey: string, metrics: string[], branch?: string -): Promise> { +): Promise<{ metric: string; value?: string }[]> { const url = '/api/measures/component'; const data = { componentKey, metricKeys: metrics.join(','), branch }; return getJSON(url, data).then(r => r.component.measures, throwGlobalError); } +interface MeasureComponent { + key: string; + description?: string; + measures: Measure[]; + name: string; + qualifier: string; +} + export function getMeasuresAndMeta( componentKey: string, metrics: string[], additional: RequestData = {} -): Promise { +): Promise<{ component: MeasureComponent; metrics?: Metric[]; periods?: Period[] }> { const data = { ...additional, componentKey, metricKeys: metrics.join(',') }; return getJSON('/api/measures/component', data); } -export interface Period { - index: number; - value: string; -} - -export interface Measure { +interface MeasuresForProjects { component: string; metric: string; - periods?: Period[]; + periods?: MeasurePeriod[]; value?: string; } export function getMeasuresForProjects( projectKeys: string[], metricKeys: string[] -): Promise { +): Promise { return getJSON('/api/measures/search', { projectKeys: projectKeys.join(), metricKeys: metricKeys.join() diff --git a/server/sonar-web/src/main/js/api/time-machine.ts b/server/sonar-web/src/main/js/api/time-machine.ts index 31f3b0681ec..e6c01eba852 100644 --- a/server/sonar-web/src/main/js/api/time-machine.ts +++ b/server/sonar-web/src/main/js/api/time-machine.ts @@ -18,19 +18,29 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { getJSON } from '../helpers/request'; +import { Paging } from '../app/types'; + +export interface HistoryItem { + date: Date; + value: string; +} + +export interface History { + [metric: string]: HistoryItem[]; +} interface TimeMachineResponse { - measures: Array<{ + measures: { metric: string; - history: Array<{ date: string; value: string }>; - }>; - paging: { pageIndex: number; pageSize: number; total: number }; + history: HistoryItem[]; + }[]; + paging: Paging; } export function getTimeMachineData( component: string, metrics: string[], - other?: { p?: number; ps?: number; from?: string; to?: string } + other?: { branch?: string; p?: number; ps?: number; from?: string; to?: string } ): Promise { return getJSON('/api/measures/search_history', { component, @@ -43,7 +53,7 @@ export function getTimeMachineData( export function getAllTimeMachineData( component: string, metrics: Array, - other?: { p?: number; from?: string; to?: string }, + other?: { branch?: string; p?: number; from?: string; to?: string }, prev?: TimeMachineResponse ): Promise { return getTimeMachineData(component, metrics, { ...other, ps: 1000 }).then(r => { diff --git a/server/sonar-web/src/main/js/app/types.ts b/server/sonar-web/src/main/js/app/types.ts index 11394b158ad..7a2a64d4e26 100644 --- a/server/sonar-web/src/main/js/app/types.ts +++ b/server/sonar-web/src/main/js/app/types.ts @@ -105,7 +105,7 @@ export interface Metric { domain?: string; hidden?: boolean; key: string; - name: string; + name?: string; qualitative?: boolean; type: string; } diff --git a/server/sonar-web/src/main/js/apps/code/types.ts b/server/sonar-web/src/main/js/apps/code/types.ts index 0c7040622e8..3a226f8127d 100644 --- a/server/sonar-web/src/main/js/apps/code/types.ts +++ b/server/sonar-web/src/main/js/apps/code/types.ts @@ -17,16 +17,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -interface Measure { - metric: string; - value: string; - periods?: Period[]; -} -interface Period { - index: number; - value: string; -} +import { Measure } from '../../helpers/measures'; export interface Component extends Breadcrumb { measures?: Measure[]; diff --git a/server/sonar-web/src/main/js/apps/overview/components/App.js b/server/sonar-web/src/main/js/apps/overview/components/App.js deleted file mode 100644 index 2d4067baa60..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/components/App.js +++ /dev/null @@ -1,104 +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. - */ -// @flow -import React from 'react'; -import PropTypes from 'prop-types'; -import OverviewApp from './OverviewApp'; -import EmptyOverview from './EmptyOverview'; -import { getBranchName, isShortLivingBranch } from '../../../helpers/branches'; -import { getProjectBranchUrl, getCodeUrl } from '../../../helpers/urls'; - -/*:: -type Props = { - branch?: { name: string }, - component: { - analysisDate?: string, - breadcrumbs: Array<{ key: string }>, - id: string, - key: string, - qualifier: string, - tags: Array, - organization?: string - }, - isInProgress?: bool, - isPending?: bool, - onComponentChange: {} => void, - router: Object -}; -*/ - -export default class App extends React.PureComponent { - /*:: props: Props; */ - /*:: state: Object; */ - - static contextTypes = { - router: PropTypes.object - }; - - componentDidMount() { - const { branch, component } = this.props; - - if (this.isPortfolio()) { - this.context.router.replace({ - pathname: '/portfolio', - query: { id: component.key } - }); - } else if (this.isFile()) { - this.context.router.replace( - getCodeUrl(component.breadcrumbs[0].key, getBranchName(branch), component.key) - ); - } else if (isShortLivingBranch(branch)) { - this.context.router.replace(getProjectBranchUrl(component.key, branch)); - } - } - - isPortfolio() { - return ['VW', 'SVW'].includes(this.props.component.qualifier); - } - - isFile() { - return ['FIL', 'UTS'].includes(this.props.component.qualifier); - } - - render() { - const { branch, component } = this.props; - - if (this.isPortfolio() || this.isFile() || isShortLivingBranch(branch)) { - return null; - } - - if (!component.analysisDate) { - return ( - - ); - } - - return ( - - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js b/server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js deleted file mode 100644 index 09c4aea0151..00000000000 --- a/server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js +++ /dev/null @@ -1,51 +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 React from 'react'; -import { mount, shallow } from 'enzyme'; -import App from '../App'; -import OverviewApp from '../OverviewApp'; -import EmptyOverview from '../EmptyOverview'; - -it('should render OverviewApp', () => { - const component = { key: 'foo', analysisDate: '2016-01-01' }; - const output = shallow(); - expect(output.type()).toBe(OverviewApp); -}); - -it('should render EmptyOverview', () => { - const component = { key: 'foo' }; - const output = shallow(); - expect(output.type()).toBe(EmptyOverview); -}); - -it('redirects on Code page for files', () => { - const branch = { isMain: false, name: 'b' }; - const component = { - breadcrumbs: [{ key: 'project' }, { key: 'foo' }], - key: 'foo', - qualifier: 'FIL' - }; - const replace = jest.fn(); - mount(, { context: { router: { replace } } }); - expect(replace).toBeCalledWith({ - pathname: '/code', - query: { branch: 'b', id: 'project', selected: 'foo' } - }); -}); diff --git a/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx b/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx index a19cd99b2a4..3279b530d70 100644 --- a/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx +++ b/server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx @@ -30,8 +30,7 @@ interface Props { } export default function Summary({ component, measures }: Props) { - const projects = measures['projects']; - const ncloc = measures['ncloc']; + const { projects, ncloc } = measures; const nclocDistribution = measures['ncloc_language_distribution']; return ( diff --git a/server/sonar-web/src/main/js/components/measure/Measure.tsx b/server/sonar-web/src/main/js/components/measure/Measure.tsx index 7836b86e1d6..200035f8016 100644 --- a/server/sonar-web/src/main/js/components/measure/Measure.tsx +++ b/server/sonar-web/src/main/js/components/measure/Measure.tsx @@ -21,8 +21,8 @@ import * as React from 'react'; import Rating from '../ui/Rating'; import Level from '../ui/Level'; import Tooltips from '../controls/Tooltip'; -import { formatMeasure, isDiffMetric } from '../../helpers/measures'; -import { formatLeak, getRatingTooltip, MeasureEnhanced } from './utils'; +import { formatMeasure, isDiffMetric, MeasureEnhanced } from '../../helpers/measures'; +import { formatLeak, getRatingTooltip } from './utils'; interface Props { className?: string; @@ -35,7 +35,7 @@ export default function Measure({ className, decimals, measure }: Props) { return {'–'}; } - const metric = measure.metric; + const { metric } = measure; const value = isDiffMetric(metric.key) ? measure.leak : measure.value; if (value === undefined) { diff --git a/server/sonar-web/src/main/js/components/measure/utils.ts b/server/sonar-web/src/main/js/components/measure/utils.ts index a526a8443c4..8e932892152 100644 --- a/server/sonar-web/src/main/js/components/measure/utils.ts +++ b/server/sonar-web/src/main/js/components/measure/utils.ts @@ -21,33 +21,20 @@ import { formatMeasure, formatMeasureVariation, getRatingTooltip as nextGetRatingTooltip, - isDiffMetric + isDiffMetric, + Measure, + MeasureEnhanced } from '../../helpers/measures'; import { Metric } from '../../app/types'; const KNOWN_RATINGS = ['sqale_rating', 'reliability_rating', 'security_rating']; -export interface MeasureIntern { - value?: string; - periods?: Array<{ index: number; value: string }>; -} - -export interface Measure extends MeasureIntern { - metric: string; -} - -export interface MeasureEnhanced extends MeasureIntern { - metric: { key: string; type: string }; - leak?: string | undefined | undefined; -} - export function enhanceMeasure( measure: Measure, metrics: { [key: string]: Metric } ): MeasureEnhanced { return { - value: measure.value, - periods: measure.periods, + ...measure, metric: metrics[measure.metric], leak: getLeakValue(measure) }; diff --git a/server/sonar-web/src/main/js/helpers/l10n.ts b/server/sonar-web/src/main/js/helpers/l10n.ts index 522bffcc922..df95089855f 100644 --- a/server/sonar-web/src/main/js/helpers/l10n.ts +++ b/server/sonar-web/src/main/js/helpers/l10n.ts @@ -153,18 +153,21 @@ export function getLocalizedDashboardName(baseName: string) { } export function getLocalizedMetricName( - metric: { key: string; name: string }, + metric: { key: string; name?: string }, short?: boolean ): string { const bundleKey = `metric.${metric.key}.${short ? 'short_name' : 'name'}`; const fromBundle = translate(bundleKey); if (fromBundle === bundleKey) { - return short ? getLocalizedMetricName(metric) : metric.name; + if (short) { + return getLocalizedMetricName(metric); + } + return metric.name || metric.key; } return fromBundle; } -export function getLocalizedCategoryMetricName(metric: { key: string; name: string }) { +export function getLocalizedCategoryMetricName(metric: { key: string; name?: string }) { const bundleKey = `metric.${metric.key}.extra_short_name`; const fromBundle = translate(bundleKey); return fromBundle === bundleKey ? getLocalizedMetricName(metric, true) : fromBundle; diff --git a/server/sonar-web/src/main/js/helpers/measures.ts b/server/sonar-web/src/main/js/helpers/measures.ts index a12d45dbd42..edb05d8ce85 100644 --- a/server/sonar-web/src/main/js/helpers/measures.ts +++ b/server/sonar-web/src/main/js/helpers/measures.ts @@ -18,20 +18,27 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import { translate, translateWithParameters, getCurrentLocale } from './l10n'; +import { Metric } from '../app/types'; const HOURS_IN_DAY = 8; -interface Measure { - metric: string; - periods?: any[]; +export interface MeasurePeriod { + index: number; + value: string; } -interface EnhancedMeasure { - metric: Metric; +export interface MeasureIntern { + value?: string; + periods?: MeasurePeriod[]; +} + +export interface Measure extends MeasureIntern { + metric: string; } -interface Metric { - key: string; +export interface MeasureEnhanced extends MeasureIntern { + metric: Metric; + leak?: string; } interface Formatter { @@ -76,7 +83,7 @@ export function getShortType(type: string): string { export function enhanceMeasuresWithMetrics( measures: Measure[], metrics: Metric[] -): EnhancedMeasure[] { +): MeasureEnhanced[] { return measures.map(measure => { const metric = metrics.find(metric => metric.key === measure.metric) as Metric; return { ...measure, metric }; diff --git a/server/sonar-web/src/main/js/helpers/periods.ts b/server/sonar-web/src/main/js/helpers/periods.ts index 53a5435256d..110eb67cf2a 100644 --- a/server/sonar-web/src/main/js/helpers/periods.ts +++ b/server/sonar-web/src/main/js/helpers/periods.ts @@ -20,7 +20,7 @@ import { translate, translateWithParameters } from './l10n'; import { parseDate } from './dates'; -interface Period { +export interface Period { date: string; index: number; mode: string; -- 2.39.5