aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web/src')
-rw-r--r--server/sonar-web/src/main/js/components/widgets/barchart.js140
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.ts.snap (renamed from server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.js.snap)0
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/issues-test.ts (renamed from server/sonar-web/src/main/js/helpers/__tests__/issues-test.js)3
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts (renamed from server/sonar-web/src/main/js/helpers/__tests__/measures-test.js)10
-rw-r--r--server/sonar-web/src/main/js/helpers/__tests__/query-test.ts (renamed from server/sonar-web/src/main/js/helpers/__tests__/query-test.js)5
-rw-r--r--server/sonar-web/src/main/js/helpers/issues.ts (renamed from server/sonar-web/src/main/js/helpers/issues.js)131
-rw-r--r--server/sonar-web/src/main/js/helpers/measures.ts (renamed from server/sonar-web/src/main/js/helpers/measures.js)231
-rw-r--r--server/sonar-web/src/main/js/helpers/periods.ts (renamed from server/sonar-web/src/main/js/helpers/periods.js)28
-rw-r--r--server/sonar-web/src/main/js/helpers/query.ts (renamed from server/sonar-web/src/main/js/helpers/query.js)37
9 files changed, 233 insertions, 352 deletions
diff --git a/server/sonar-web/src/main/js/components/widgets/barchart.js b/server/sonar-web/src/main/js/components/widgets/barchart.js
deleted file mode 100644
index ab376ca1a3d..00000000000
--- a/server/sonar-web/src/main/js/components/widgets/barchart.js
+++ /dev/null
@@ -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 });
- }
- });
-};
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.js.snap b/server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.ts.snap
index 4f0b5538ba8..4f0b5538ba8 100644
--- a/server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.js.snap
+++ b/server/sonar-web/src/main/js/helpers/__tests__/__snapshots__/query-test.ts.snap
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/issues-test.js b/server/sonar-web/src/main/js/helpers/__tests__/issues-test.ts
index 49d9a67a68f..034fcb4a916 100644
--- a/server/sonar-web/src/main/js/helpers/__tests__/issues-test.js
+++ b/server/sonar-web/src/main/js/helpers/__tests__/issues-test.ts
@@ -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',
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/measures-test.js b/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts
index d36a63740eb..875b3eb9f75 100644
--- a/server/sonar-web/src/main/js/helpers/__tests__/measures-test.js
+++ b/server/sonar-web/src/main/js/helpers/__tests__/measures-test.ts
@@ -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('');
});
});
diff --git a/server/sonar-web/src/main/js/helpers/__tests__/query-test.js b/server/sonar-web/src/main/js/helpers/__tests__/query-test.ts
index 9c2c8c24b37..09bfc803b71 100644
--- a/server/sonar-web/src/main/js/helpers/__tests__/query-test.js
+++ b/server/sonar-web/src/main/js/helpers/__tests__/query-test.ts
@@ -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();
});
});
diff --git a/server/sonar-web/src/main/js/helpers/issues.js b/server/sonar-web/src/main/js/helpers/issues.ts
index a03d7ac807f..34cef95d7c6 100644
--- a/server/sonar-web/src/main/js/helpers/issues.js
+++ b/server/sonar-web/src/main/js/helpers/issues.ts
@@ -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,
diff --git a/server/sonar-web/src/main/js/helpers/measures.js b/server/sonar-web/src/main/js/helpers/measures.ts
index bdd207a6a28..41dec890089 100644
--- a/server/sonar-web/src/main/js/helpers/measures.js
+++ b/server/sonar-web/src/main/js/helpers/measures.ts
@@ -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;
diff --git a/server/sonar-web/src/main/js/helpers/periods.js b/server/sonar-web/src/main/js/helpers/periods.ts
index d458a1931eb..138e67606d6 100644
--- a/server/sonar-web/src/main/js/helpers/periods.js
+++ b/server/sonar-web/src/main/js/helpers/periods.ts
@@ -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));
}
diff --git a/server/sonar-web/src/main/js/helpers/query.js b/server/sonar-web/src/main/js/helpers/query.ts
index 400390e65b8..8517917de18 100644
--- a/server/sonar-web/src/main/js/helpers/query.js
+++ b/server/sonar-web/src/main/js/helpers/query.ts
@@ -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;
}