Browse Source

Migrate App to tsx and clean up measures related types

tags/7.5
Grégoire Aubert 6 years ago
parent
commit
49391d2eff

+ 16
- 10
server/sonar-web/src/main/js/api/measures.ts View File

@@ -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<Array<{ metric: string; value?: string }>> {
): 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<any> {
): 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<Measure[]> {
): Promise<MeasuresForProjects[]> {
return getJSON('/api/measures/search', {
projectKeys: projectKeys.join(),
metricKeys: metricKeys.join()

+ 16
- 6
server/sonar-web/src/main/js/api/time-machine.ts View File

@@ -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<TimeMachineResponse> {
return getJSON('/api/measures/search_history', {
component,
@@ -43,7 +53,7 @@ export function getTimeMachineData(
export function getAllTimeMachineData(
component: string,
metrics: Array<string>,
other?: { p?: number; from?: string; to?: string },
other?: { branch?: string; p?: number; from?: string; to?: string },
prev?: TimeMachineResponse
): Promise<TimeMachineResponse> {
return getTimeMachineData(component, metrics, { ...other, ps: 1000 }).then(r => {

+ 1
- 1
server/sonar-web/src/main/js/app/types.ts View File

@@ -105,7 +105,7 @@ export interface Metric {
domain?: string;
hidden?: boolean;
key: string;
name: string;
name?: string;
qualitative?: boolean;
type: string;
}

+ 1
- 9
server/sonar-web/src/main/js/apps/code/types.ts View File

@@ -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[];

+ 0
- 104
server/sonar-web/src/main/js/apps/overview/components/App.js View File

@@ -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<string>,
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 (
<EmptyOverview
component={component.key}
showWarning={!this.props.isPending && !this.props.isInProgress}
/>
);
}

return (
<OverviewApp
branch={branch}
component={component}
onComponentChange={this.props.onComponentChange}
/>
);
}
}

+ 0
- 51
server/sonar-web/src/main/js/apps/overview/components/__tests__/App-test.js View File

@@ -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(<App component={component} />);
expect(output.type()).toBe(OverviewApp);
});

it('should render EmptyOverview', () => {
const component = { key: 'foo' };
const output = shallow(<App component={component} />);
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(<App branch={branch} component={component} />, { context: { router: { replace } } });
expect(replace).toBeCalledWith({
pathname: '/code',
query: { branch: 'b', id: 'project', selected: 'foo' }
});
});

+ 1
- 2
server/sonar-web/src/main/js/apps/portfolio/components/Summary.tsx View File

@@ -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 (

+ 3
- 3
server/sonar-web/src/main/js/components/measure/Measure.tsx View File

@@ -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 <span>{'–'}</span>;
}

const metric = measure.metric;
const { metric } = measure;
const value = isDiffMetric(metric.key) ? measure.leak : measure.value;

if (value === undefined) {

+ 4
- 17
server/sonar-web/src/main/js/components/measure/utils.ts View File

@@ -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)
};

+ 6
- 3
server/sonar-web/src/main/js/helpers/l10n.ts View File

@@ -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;

+ 15
- 8
server/sonar-web/src/main/js/helpers/measures.ts View File

@@ -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 };

+ 1
- 1
server/sonar-web/src/main/js/helpers/periods.ts View File

@@ -20,7 +20,7 @@
import { translate, translateWithParameters } from './l10n';
import { parseDate } from './dates';

interface Period {
export interface Period {
date: string;
index: number;
mode: string;

Loading…
Cancel
Save