Browse Source

rewrite remaining helpers to ts

tags/6.6-RC1
Stas Vilchik 6 years ago
parent
commit
77bd653967

+ 1
- 0
server/sonar-web/package.json View File

@@ -52,6 +52,7 @@
"@types/jest": "20.0.7",
"@types/jquery": "3.2.11",
"@types/lodash": "4.14.73",
"@types/numeral": "0.0.22",
"@types/prop-types": "15.5.1",
"@types/react": "16.0.2",
"@types/react-dom": "15.5.2",

+ 0
- 140
server/sonar-web/src/main/js/components/widgets/barchart.js View File

@@ -1,140 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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 $ from 'jquery';
import { max } from 'd3-array';
import { select } from 'd3-selection';
import { scaleLinear, scaleBand } from 'd3-scale';
import { isSameDay, parseDate, toNotSoISOString } from '../../helpers/dates';

function trans(left, top) {
return `translate(${left}, ${top})`;
}

const defaults = function() {
return {
height: 140,
color: '#1f77b4',

marginLeft: 1,
marginRight: 1,
marginTop: 18,
marginBottom: 1
};
};

/*
* data = [
* { val: '2015-01-30', count: 30 },
* ...
* ]
*/

$.fn.barchart = function(data) {
$(this).each(function() {
const options = { ...defaults(), ...$(this).data() };
Object.assign(options, {
width: options.width || $(this).width(),
endDate: options.endDate ? parseDate(options.endDate) : null
});

const container = select(this);
const svg = container
.append('svg')
.attr('width', options.width + 2)
.attr('height', options.height + 2)
.classed('sonar-d3', true);
const plot = svg.append('g').classed('plot', true);
const xScale = scaleBand().domain(data.map((d, i) => i));
const yScaleMax = max(data, d => d.count);
const yScale = scaleLinear().domain([0, yScaleMax]);

Object.assign(options, {
availableWidth: options.width - options.marginLeft - options.marginRight,
availableHeight: options.height - options.marginTop - options.marginBottom
});

plot.attr('transform', trans(options.marginLeft, options.marginTop));
xScale.rangeRound([0, options.availableWidth]).paddingInner(0.05);
yScale.range([3, options.availableHeight]);

const barWidth = xScale.bandwidth();
const bars = plot.selectAll('g').data(data);

if (barWidth > 0) {
const barsEnter = bars
.enter()
.append('g')
.attr('transform', (d, i) =>
trans(xScale(i), Math.ceil(options.availableHeight - yScale(d.count)))
);

barsEnter
.append('rect')
.style('fill', options.color)
.attr('width', barWidth)
.attr('height', d => Math.floor(yScale(d.count)))
.style('cursor', 'pointer')
.attr('data-period-start', d => toNotSoISOString(d.val))
.attr('data-period-end', (d, i) => {
const ending = i < data.length - 1 ? data[i + 1].val : options.endDate;
if (ending) {
return toNotSoISOString(ending);
} else {
return '';
}
})
.attr('title', (d, i) => {
const beginning = parseDate(d.val);
let ending = options.endDate;
if (i < data.length - 1) {
ending = parseDate(data[i + 1].val);
ending.setDate(ending.getDate() - 1);
}
if (ending) {
return (
d.text +
'<br>' +
beginning.format('LL') +
(isSameDay(ending, beginning) ? '' : ' – ' + ending.format('LL'))
);
} else {
return d.text + '<br>' + beginning.format('LL');
}
})
.attr('data-placement', 'bottom')
.attr('data-toggle', 'tooltip');
const maxValue = max(data, d => d.count);
let isValueShown = false;
barsEnter
.append('text')
.classed('subtitle', true)
.attr('transform', trans(barWidth / 2, -4))
.style('text-anchor', 'middle')
.text(d => {
const text = !isValueShown && d.count === maxValue ? d.text : '';
isValueShown = d.count === maxValue;
return text;
});
$(this)
.find('[data-toggle=tooltip]')
.tooltip({ container: 'body', html: true });
}
});
};

server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.js.snap → server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.ts.snap View File


server/sonar-web/src/main/js/helpers/__tests__/issues-test.js → server/sonar-web/src/main/js/helpers/__tests__/issues-test.ts View File

@@ -17,7 +17,6 @@
* 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 { parseIssueFromResponse } from '../issues';

it('should populate comments data', () => {
@@ -40,7 +39,7 @@ it('should populate comments data', () => {
updatable: true
}
]
};
} as any;
expect(parseIssueFromResponse(issue, undefined, users, undefined).comments).toEqual([
{
author: 'admin',

server/sonar-web/src/main/js/helpers/__tests__/measures-test.js → server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts View File

@@ -160,11 +160,11 @@ describe('#formatMeasure()', () => {
});

it('should return null if value is empty string', () => {
expect(formatMeasure('', 'PERCENT')).toBeNull();
expect(formatMeasure('', 'PERCENT')).toBe('');
});

it('should not fail without parameters', () => {
expect(formatMeasure()).toBeNull();
it('should not fail with undefined', () => {
expect(formatMeasure(undefined, 'INT')).toBe('');
});
});

@@ -252,7 +252,7 @@ describe('#formatMeasureVariation()', () => {
expect(formatMeasureVariation('random value', 'RANDOM_TYPE')).toBe('random value');
});

it('should not fail without parameters', () => {
expect(formatMeasureVariation()).toBeNull();
it('should not fail with undefined', () => {
expect(formatMeasureVariation(undefined, 'INT')).toBe('');
});
});

server/sonar-web/src/main/js/helpers/__tests__/query-test.js → server/sonar-web/src/main/js/helpers/__tests__/query-test.ts View File

@@ -42,7 +42,7 @@ describe('parseAsBoolean', () => {
});

it('should return a default value', () => {
expect(query.parseAsBoolean(1)).toBeTruthy();
expect(query.parseAsBoolean('1')).toBeTruthy();
expect(query.parseAsBoolean('foo')).toBeTruthy();
});
});
@@ -60,7 +60,7 @@ describe('parseAsString', () => {
it('should parse strings correctly', () => {
expect(query.parseAsString('random')).toBe('random');
expect(query.parseAsString('')).toBe('');
expect(query.parseAsString(null)).toBe('');
expect(query.parseAsString(undefined)).toBe('');
});
});

@@ -82,7 +82,6 @@ describe('serializeDate', () => {
const date = parseDate('2016-06-20T13:09:48.256Z');
it('should serialize string correctly', () => {
expect(query.serializeDate(date)).toBe('2016-06-20T13:09:48+0000');
expect(query.serializeDate('')).toBeUndefined();
expect(query.serializeDate()).toBeUndefined();
});
});

server/sonar-web/src/main/js/helpers/issues.js → server/sonar-web/src/main/js/helpers/issues.ts View File

@@ -17,64 +17,71 @@
* 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 { flatten, sortBy } from 'lodash';
import { SEVERITIES } from './constants';
/*:: import type { Issue, FlowLocation } from '../components/issue/types'; */

/*::
type TextRange = {
startLine: number,
endLine: number,
startOffset: number,
endOffset: number
};
*/

/*::
type Comment = {
login: string
};
*/

/*::
type User = {
login: string
};
*/

/*::
type RawIssue = {
assignee?: string,
author: string,
comments?: Array<Comment>,
component: string,

interface TextRange {
startLine: number;
endLine: number;
startOffset: number;
endOffset: number;
}

interface FlowLocation {
msg: string;
textRange?: TextRange;
}

interface Comment {
login: string;
[x: string]: any;
}

interface User {
login: string;
}

interface Rule {}

interface Component {}

interface IssueBase {
severity: string;
[x: string]: any;
}

interface RawIssue extends IssueBase {
assignee?: string;
author?: string;
comments?: Array<Comment>;
component: string;
flows?: Array<{
locations?: Array<{ msg: string, textRange?: TextRange }>
}>,
key: string,
line?: number,
project: string,
rule: string,
status: string,
subProject?: string,
textRange?: TextRange
};
*/

export function sortBySeverity(issues /*: Array<*> */) {
locations?: FlowLocation[];
}>;
key: string;
line?: number;
project: string;
rule: string;
status: string;
subProject?: string;
textRange?: TextRange;
}

interface Issue extends IssueBase {}

export function sortBySeverity(issues: Issue[]): Issue[] {
return sortBy(issues, issue => SEVERITIES.indexOf(issue.severity));
}

function injectRelational(
issue /*: RawIssue | Comment */,
source /*: ?Array<*> */,
baseField /*: string */,
lookupField /*: string */
issue: { [x: string]: any },
source: any[] | undefined,
baseField: string,
lookupField: string
) {
const newFields = {};
const newFields: { [x: string]: any } = {};
const baseValue = issue[baseField];
if (baseValue != null && source != null) {
if (baseValue != undefined && source != undefined) {
const lookupValue = source.find(candidate => candidate[lookupField] === baseValue);
if (lookupValue != null) {
Object.keys(lookupValue).forEach(key => {
@@ -86,7 +93,7 @@ function injectRelational(
return newFields;
}

function injectCommentsRelational(issue /*: RawIssue */, users /*: ?Array<User> */) {
function injectCommentsRelational(issue: RawIssue, users?: User[]) {
if (!issue.comments) {
return {};
}
@@ -100,11 +107,11 @@ function injectCommentsRelational(issue /*: RawIssue */, users /*: ?Array<User>
return { comments };
}

function prepareClosed(issue /*: RawIssue */) {
function prepareClosed(issue: RawIssue): { flows?: undefined } {
return issue.status === 'CLOSED' ? { flows: undefined } : {};
}

function ensureTextRange(issue /*: RawIssue */) {
function ensureTextRange(issue: RawIssue): { textRange?: TextRange } {
return issue.line && !issue.textRange
? {
textRange: {
@@ -117,20 +124,18 @@ function ensureTextRange(issue /*: RawIssue */) {
: {};
}

function reverseLocations(locations /*: Array<*> */) {
function reverseLocations(locations: FlowLocation[]): FlowLocation[] {
const x = [...locations];
x.reverse();
return x;
}

function splitFlows(
issue /*: RawIssue */
// $FlowFixMe textRange is not null
) /*: { secondaryLocations: Array<FlowLocation>, flows: Array<Array<FlowLocation>> } */ {
issue: RawIssue
): { secondaryLocations: Array<FlowLocation>; flows: Array<Array<FlowLocation>> } {
const parsedFlows = (issue.flows || [])
.filter(flow => flow.locations != null)
// $FlowFixMe flow.locations is not null
.map(flow => flow.locations.filter(location => location.textRange != null));
.map(flow => flow.locations!.filter(location => location.textRange != null));

const onlySecondaryLocations = parsedFlows.every(flow => flow.length === 1);

@@ -140,11 +145,11 @@ function splitFlows(
}

export function parseIssueFromResponse(
issue /*: Object */,
components /*: ?Array<*> */,
users /*: ?Array<*> */,
rules /*: ?Array<*> */
) /*: Issue */ {
issue: RawIssue,
components?: Component[],
users?: User[],
rules?: Rule[]
): Issue {
const { secondaryLocations, flows } = splitFlows(issue);
return {
...issue,

server/sonar-web/src/main/js/helpers/measures.js → server/sonar-web/src/main/js/helpers/measures.ts View File

@@ -17,46 +17,55 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import numeral from 'numeral';
import * as numeral from 'numeral';
import { translate, translateWithParameters } from './l10n';

const HOURS_IN_DAY = 8;

/**
* Format a measure value for a given type
* @param {string|number} value
* @param {string} type
*/
export function formatMeasure(value, type, options) {
interface Measure {
metric: string;
periods?: any[];
}

interface EnhancedMeasure {
metric: Metric;
}

interface Metric {
key: string;
}

interface Formatter {
(value: string | number, options?: any): string;
}

/** Format a measure value for a given type */
export function formatMeasure(
value: string | number | undefined,
type: string,
options?: any
): string {
const formatter = getFormatter(type);
return useFormatter(value, formatter, options);
}

/**
* Format a measure variation for a given type
* @param {string|number} value
* @param {string} type
*/
export function formatMeasureVariation(value, type, options) {
/** Format a measure variation for a given type */
export function formatMeasureVariation(
value: string | number | undefined,
type: string,
options?: any
): string {
const formatter = getVariationFormatter(type);
return useFormatter(value, formatter, options);
}

/**
* Return a localized metric name
* @param {string} metricKey
* @returns {string}
*/
export function localizeMetric(metricKey) {
/** Return a localized metric name */
export function localizeMetric(metricKey: string): string {
return translate('metric', metricKey, 'name');
}

/**
* Return corresponding "short" for better display in UI
* @param {string} type
* @returns {string}
*/
export function getShortType(type) {
/** Return corresponding "short" for better display in UI */
export function getShortType(type: string): string {
if (type === 'INT') {
return 'SHORT_INT';
} else if (type === 'WORK_DUR') {
@@ -65,49 +74,38 @@ export function getShortType(type) {
return type;
}

/**
* Map metrics
* @param {Array} measures
* @param {Array} metrics
* @returns {Array}
*/
export function enhanceMeasuresWithMetrics(measures, metrics) {
export function enhanceMeasuresWithMetrics(
measures: Measure[],
metrics: Metric[]
): EnhancedMeasure[] {
return measures.map(measure => {
const metric = metrics.find(metric => metric.key === measure.metric);
const metric = metrics.find(metric => metric.key === measure.metric) as Metric;
return { ...measure, metric };
});
}

/**
* Get period value of a measure
* @param measure
* @param periodIndex
*/
export function getPeriodValue(measure, periodIndex) {
/** Get period value of a measure */
export function getPeriodValue(measure: Measure, periodIndex: number): string | number | undefined {
const { periods } = measure;
const period = periods.find(period => period.index === periodIndex);
return period ? period.value : null;
const period = periods && periods.find(period => period.index === periodIndex);
return period ? period.value : undefined;
}

/**
* Check if metric is differential
* @param {string} metricKey
* @returns {boolean}
*/
export function isDiffMetric(metricKey) {
/** Check if metric is differential */
export function isDiffMetric(metricKey: string): boolean {
return metricKey.indexOf('new_') === 0;
}

/*
* Helpers
*/
function useFormatter(value, formatter, options) {
return value != null && value !== '' && formatter != null ? formatter(value, options) : null;
function useFormatter(
value: string | number | undefined,
formatter: Formatter,
options?: any
): string {
return value != undefined && value !== '' ? formatter(value, options) : '';
}

function getFormatter(type) {
const FORMATTERS = {
function getFormatter(type: string): Formatter {
const FORMATTERS: { [type: string]: Formatter } = {
INT: intFormatter,
SHORT_INT: shortIntFormatter,
FLOAT: floatFormatter,
@@ -121,8 +119,8 @@ function getFormatter(type) {
return FORMATTERS[type] || noFormatter;
}

function getVariationFormatter(type) {
const FORMATTERS = {
function getVariationFormatter(type: string): Formatter {
const FORMATTERS: { [type: string]: Formatter } = {
INT: intVariationFormatter,
SHORT_INT: shortIntVariationFormatter,
FLOAT: floatVariationFormatter,
@@ -136,31 +134,27 @@ function getVariationFormatter(type) {
return FORMATTERS[type] || noFormatter;
}

/*
* Formatters
*/

function genericFormatter(value, formatValue) {
function genericNumberFormatter(value: number, formatValue?: string): string {
return numeral(value).format(formatValue);
}

function noFormatter(value) {
function noFormatter(value: string | number): string | number {
return value;
}

function emptyFormatter() {
return null;
function emptyFormatter(): string {
return '';
}

function intFormatter(value) {
return genericFormatter(value, '0,0');
function intFormatter(value: number): string {
return genericNumberFormatter(value, '0,0');
}

function intVariationFormatter(value) {
return genericFormatter(value, '+0,0');
function intVariationFormatter(value: number): string {
return genericNumberFormatter(value, '+0,0');
}

function shortIntFormatter(value) {
function shortIntFormatter(value: number): string {
let format = '0,0';
if (value >= 1000) {
format = '0.[0]a';
@@ -168,44 +162,53 @@ function shortIntFormatter(value) {
if (value >= 10000) {
format = '0a';
}
return genericFormatter(value, format);
return genericNumberFormatter(value, format);
}

function shortIntVariationFormatter(value) {
function shortIntVariationFormatter(value: number): string {
const formatted = shortIntFormatter(Math.abs(value));
return value < 0 ? `-${formatted}` : `+${formatted}`;
}

function floatFormatter(value) {
return genericFormatter(value, '0,0.0[0000]');
function floatFormatter(value: number): string {
return genericNumberFormatter(value, '0,0.0[0000]');
}

function floatVariationFormatter(value) {
return value === 0 ? '+0.0' : genericFormatter(value, '+0,0.0[0000]');
function floatVariationFormatter(value: number): string {
return value === 0 ? '+0.0' : genericNumberFormatter(value, '+0,0.0[0000]');
}

function percentFormatter(value, options = {}) {
value = parseFloat(value);
function percentFormatter(value: string | number, options: { decimals?: number } = {}): string {
if (typeof value === 'string') {
value = parseFloat(value);
}
if (options.decimals) {
return genericFormatter(value / 100, `0,0.${'0'.repeat(options.decimals)}%`);
return genericNumberFormatter(value / 100, `0,0.${'0'.repeat(options.decimals)}%`);
}
return value === 100 ? '100%' : genericFormatter(value / 100, '0,0.0%');
return value === 100 ? '100%' : genericNumberFormatter(value / 100, '0,0.0%');
}

function percentVariationFormatter(value, options = {}) {
value = parseFloat(value);
function percentVariationFormatter(
value: string | number,
options: { decimals?: number } = {}
): string {
if (typeof value === 'string') {
value = parseFloat(value);
}
if (options.decimals) {
return genericFormatter(value / 100, `+0,0.${'0'.repeat(options.decimals)}%`);
return genericNumberFormatter(value / 100, `+0,0.${'0'.repeat(options.decimals)}%`);
}
return value === 0 ? '+0.0%' : genericFormatter(value / 100, '+0,0.0%');
return value === 0 ? '+0.0%' : genericNumberFormatter(value / 100, '+0,0.0%');
}

function ratingFormatter(value) {
value = parseInt(value, 10);
function ratingFormatter(value: string | number): string {
if (typeof value === 'string') {
value = parseInt(value, 10);
}
return String.fromCharCode(97 + value - 1).toUpperCase();
}

function levelFormatter(value) {
function levelFormatter(value: string): string {
const l10nKey = 'metric.level.' + value;
const result = translate(l10nKey);

@@ -213,7 +216,7 @@ function levelFormatter(value) {
return l10nKey !== result ? result : value;
}

function millisecondsFormatter(value) {
function millisecondsFormatter(value: number): string {
const ONE_SECOND = 1000;
const ONE_MINUTE = 60 * ONE_SECOND;
if (value >= ONE_MINUTE) {
@@ -227,7 +230,7 @@ function millisecondsFormatter(value) {
}
}

function millisecondsVariationFormatter(value) {
function millisecondsVariationFormatter(value: number): string {
const absValue = Math.abs(value);
const formattedValue = millisecondsFormatter(absValue);
return value < 0 ? `-${formattedValue}` : `+${formattedValue}`;
@@ -237,31 +240,31 @@ function millisecondsVariationFormatter(value) {
* Debt Formatters
*/

function shouldDisplayDays(days) {
function shouldDisplayDays(days: number): boolean {
return days > 0;
}

function shouldDisplayDaysInShortFormat(days) {
function shouldDisplayDaysInShortFormat(days: number): boolean {
return days > 0.9;
}

function shouldDisplayHours(days, hours) {
function shouldDisplayHours(days: number, hours: number): boolean {
return hours > 0 && days < 10;
}

function shouldDisplayHoursInShortFormat(hours) {
function shouldDisplayHoursInShortFormat(hours: number): boolean {
return hours > 0.9;
}

function shouldDisplayMinutes(days, hours, minutes) {
function shouldDisplayMinutes(days: number, hours: number, minutes: number): boolean {
return minutes > 0 && hours < 10 && days === 0;
}

function addSpaceIfNeeded(value) {
function addSpaceIfNeeded(value: string): string {
return value.length > 0 ? value + ' ' : value;
}

function formatDuration(isNegative, days, hours, minutes) {
function formatDuration(isNegative: boolean, days: number, hours: number, minutes: number): string {
let formatted = '';
if (shouldDisplayDays(days)) {
formatted += translateWithParameters('work_duration.x_days', isNegative ? -1 * days : days);
@@ -283,7 +286,12 @@ function formatDuration(isNegative, days, hours, minutes) {
return formatted;
}

function formatDurationShort(isNegative, days, hours, minutes) {
function formatDurationShort(
isNegative: boolean,
days: number,
hours: number,
minutes: number
): string {
if (shouldDisplayDaysInShortFormat(days)) {
const roundedDays = Math.round(days);
const formattedDays = formatMeasure(isNegative ? -1 * roundedDays : roundedDays, 'SHORT_INT');
@@ -303,8 +311,11 @@ function formatDurationShort(isNegative, days, hours, minutes) {
return translateWithParameters('work_duration.x_minutes', formattedMinutes);
}

function durationFormatter(value) {
if (value === 0 || value === '0') {
function durationFormatter(value: string | number): string {
if (typeof value === 'string') {
value = parseInt(value);
}
if (value === 0) {
return '0';
}
const hoursInDay = HOURS_IN_DAY;
@@ -317,9 +328,11 @@ function durationFormatter(value) {
return formatDuration(isNegative, days, hours, remainingValue);
}

function shortDurationFormatter(value) {
value = parseInt(value, 10);
if (value === 0 || value === '0') {
function shortDurationFormatter(value: string | number): string {
if (typeof value === 'string') {
value = parseInt(value);
}
if (value === 0) {
return '0';
}
const hoursInDay = HOURS_IN_DAY;
@@ -332,7 +345,7 @@ function shortDurationFormatter(value) {
return formatDurationShort(isNegative, days, hours, remainingValue);
}

function durationVariationFormatter(value) {
function durationVariationFormatter(value: string | number): string {
if (value === 0 || value === '0') {
return '+0';
}
@@ -340,7 +353,7 @@ function durationVariationFormatter(value) {
return formatted[0] !== '-' ? '+' + formatted : formatted;
}

function shortDurationVariationFormatter(value) {
function shortDurationVariationFormatter(value: string | number): string {
if (value === 0 || value === '0') {
return '+0';
}
@@ -348,7 +361,7 @@ function shortDurationVariationFormatter(value) {
return formatted[0] !== '-' ? '+' + formatted : formatted;
}

function getRatingGrid() {
function getRatingGrid(): string {
// workaround cyclic dependencies
const getStore = require('../app/utils/getStore').default;
const { getGlobalSettingValue } = require('../store/rootReducer');
@@ -358,8 +371,8 @@ function getRatingGrid() {
return settingValue ? settingValue.value : '';
}

let maintainabilityRatingGrid;
function getMaintainabilityRatingGrid() {
let maintainabilityRatingGrid: number[];
function getMaintainabilityRatingGrid(): number[] {
if (maintainabilityRatingGrid) {
return maintainabilityRatingGrid;
}
@@ -379,7 +392,7 @@ function getMaintainabilityRatingGrid() {
return maintainabilityRatingGrid;
}

function getMaintainabilityRatingTooltip(rating) {
function getMaintainabilityRatingTooltip(rating: number): string {
const maintainabilityGrid = getMaintainabilityRatingGrid();
const maintainabilityRatingThreshold = maintainabilityGrid[Math.floor(rating) - 2];

@@ -399,7 +412,7 @@ function getMaintainabilityRatingTooltip(rating) {
);
}

export function getRatingTooltip(metricKey, value) {
export function getRatingTooltip(metricKey: string, value: number): string {
const ratingLetter = formatMeasure(value, 'RATING');

const finalMetricKey = metricKey.startsWith('new_') ? metricKey.substr(4) : metricKey;

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

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

export function getPeriod(periods, index) {
interface Period {
date: string;
index: number;
mode: string;
modeParam?: string;
parameter: string;
}

export function getPeriod(periods: Period[] | undefined, index: number): Period | undefined {
if (!Array.isArray(periods)) {
return null;
return undefined;
}

return periods.find(period => period.index === index);
}

export function getLeakPeriod(periods) {
export function getLeakPeriod(periods: Period[] | undefined): Period | undefined {
return getPeriod(periods, 1);
}

export function getPeriodLabel(period) {
export function getPeriodLabel(period: Period | undefined): string | undefined {
if (!period) {
return null;
return undefined;
}

const parameter = period.modeParam || period.parameter;
@@ -46,14 +54,10 @@ export function getPeriodLabel(period) {
return translateWithParameters(`overview.period.${period.mode}`, parameter);
}

export function getPeriodDate(period) {
if (!period) {
return null;
}

return parseDate(period.date);
export function getPeriodDate(period: Period | undefined): Date | undefined {
return period ? parseDate(period.date) : undefined;
}

export function getLeakPeriodLabel(periods) {
export function getLeakPeriodLabel(periods: Period[]): string | undefined {
return getPeriodLabel(getLeakPeriod(periods));
}

server/sonar-web/src/main/js/helpers/query.js → server/sonar-web/src/main/js/helpers/query.ts View File

@@ -17,15 +17,14 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
// @flow
import { isNil, omitBy } from 'lodash';
import { isValidDate, parseDate, toNotSoISOString } from './dates';

/*::
export type RawQuery = { [string]: any };
*/
export interface RawQuery {
[x: string]: any;
}

function arraysEqual(a, b) {
function arraysEqual(a: RawQuery, b: RawQuery): boolean {
if (a.length !== b.length) {
return false;
}
@@ -37,7 +36,7 @@ function arraysEqual(a, b) {
return true;
}

export function queriesEqual(a /*: Object */, b /*: Object */) /*: boolean */ {
export function queriesEqual(a: RawQuery, b: RawQuery): boolean {
const keysA = Object.keys(a);
const keysB = Object.keys(b);

@@ -53,48 +52,50 @@ export function queriesEqual(a /*: Object */, b /*: Object */) /*: boolean */ {
);
}

export function cleanQuery(query /*: { [string]: ?string } */) /*: RawQuery */ {
export function cleanQuery(query: RawQuery): RawQuery {
return omitBy(query, isNil);
}

export function parseAsBoolean(
value /*: ?string */,
defaultValue /*: boolean */ = true
) /*: boolean */ {
export function parseAsBoolean(value: string | undefined, defaultValue: boolean = true): boolean {
return value === 'false' ? false : value === 'true' ? true : defaultValue;
}

export function parseAsDate(value /*: ?string */) /*: Date | void */ {
export function parseAsDate(value?: string): Date | undefined {
if (value) {
const date = parseDate(value);
if (isValidDate(date)) {
return date;
}
}
return undefined;
}

export function parseAsFacetMode(facetMode /*: string */) {
export function parseAsFacetMode(facetMode: string): string {
return facetMode === 'debt' || facetMode === 'effort' ? 'effort' : 'count';
}

export function parseAsString(value /*: ?string */) /*: string */ {
export function parseAsString(value: string | undefined): string {
return value || '';
}

export function parseAsArray(value /*: ?string */, itemParser /*: string => * */) /*: Array<*> */ {
export function parseAsArray(
value: string | undefined,
itemParser: (x: string) => string
): string[] {
return value ? value.split(',').map(itemParser) : [];
}

export function serializeDate(value /*: ?Date */) /*: string | void */ {
export function serializeDate(value?: Date): string | undefined {
if (value != null && value.toISOString) {
return toNotSoISOString(value);
}
return undefined;
}

export function serializeString(value /*: string */) /*: ?string */ {
export function serializeString(value: string): string | undefined {
return value || undefined;
}

export function serializeStringArray(value /*: ?Array<string> */) /*: ?string */ {
export function serializeStringArray(value: string[] | undefined[]): string | undefined {
return value && value.length ? value.join() : undefined;
}

+ 4
- 0
server/sonar-web/yarn.lock View File

@@ -54,6 +54,10 @@
version "8.0.22"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.22.tgz#9c6bfee1f45f5e9952ff6b487e657ecca48c7777"

"@types/numeral@0.0.22":
version "0.0.22"
resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-0.0.22.tgz#86bef1f0a2d743afdc2ef3168d45f2905e1a0b93"

"@types/prop-types@15.5.1":
version "15.5.1"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.1.tgz#1ecf52621299e65b855374337fb11fd2d1066fc1"

Loading…
Cancel
Save