"@types/classnames": "2.2.3",
"@types/clipboard": "2.0.0",
"@types/d3-array": "1.2.1",
+ "@types/d3-hierarchy": "1.1.1",
"@types/d3-scale": "2.0.0",
+ "@types/d3-shape": "1.2.2",
"@types/enzyme": "3.1.10",
"@types/jest": "22.2.3",
"@types/keymaster": "1.6.28",
--- /dev/null
+/*
+ * 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.
+ */
+declare module '*.json' {
+ const value: any;
+ export default value;
+}
/*:: import type { Component, More, Results } from './utils'; */
import RecentHistory from '../../components/RecentHistory';
import DeferredSpinner from '../../../components/common/DeferredSpinner';
-import ClockIcon from '../../../components/common/ClockIcon';
+import ClockIcon from '../../../components/icons-components/ClockIcon';
import OutsideClickHandler from '../../../components/controls/OutsideClickHandler';
import SearchBox from '../../../components/controls/SearchBox';
import { getSuggestions } from '../../../api/components';
/*:: import type { Component } from './utils'; */
import FavoriteIcon from '../../../components/icons-components/FavoriteIcon';
import QualifierIcon from '../../../components/shared/QualifierIcon';
-import ClockIcon from '../../../components/common/ClockIcon';
+import ClockIcon from '../../../components/icons-components/ClockIcon';
import Tooltip from '../../../components/controls/Tooltip';
import { getProjectUrl } from '../../../helpers/urls';
import * as PropTypes from 'prop-types';
import { Component } from '../types';
import { BranchLike } from '../../../app/types';
-import PinIcon from '../../../components/shared/pin-icon';
+import PinIcon from '../../../components/icons-components/PinIcon';
import { WorkspaceContext } from '../../../components/workspace/context';
import { translate } from '../../../helpers/l10n';
<AutoSizer disableHeight={true}>
{({ width }) => (
<TreeMap
+ height={HEIGHT}
items={treemapItems}
onRectangleClick={this.props.handleSelect}
- height={HEIGHT}
width={width}
/>
)}
import { longFormatterOption } from '../../../components/intl/DateFormatter';
import DateFromNow from '../../../components/intl/DateFromNow';
import DateTimeFormatter from '../../../components/intl/DateTimeFormatter';
-import { BarChart } from '../../../components/charts/bar-chart';
+import BarChart from '../../../components/charts/BarChart';
import DateRangeInput from '../../../components/controls/DateRangeInput';
import { isSameDay, parseDate } from '../../../helpers/dates';
import { translate } from '../../../helpers/l10n';
*/
import * as React from 'react';
import { max } from 'd3-array';
-import { LineChart } from '../../../components/charts/line-chart';
+import LineChart from '../../../components/charts/LineChart';
import { HistoryItem } from '../../../api/time-machine';
const HEIGHT = 80;
}
const data = snapshots.map((snapshot, index) => {
- return { x: index, y: snapshot.value };
+ return { x: index, y: Number(snapshot.value) };
});
- const domain = [0, max(this.props.history, d => parseFloat(d.value))];
+ const domain = [0, max(this.props.history, d => parseFloat(d.value))] as [number, number];
return (
<LineChart
data={data}
- domain={domain}
- interpolate="basis"
displayBackdrop={true}
displayPoints={false}
displayVerticalGrid={false}
+ domain={domain}
height={HEIGHT}
padding={[0, 0, 0, 0]}
/>
Array [
Object {
"x": 0,
- "y": "29.6",
+ "y": 29.6,
},
Object {
"x": 1,
- "y": "170.8",
+ "y": 170.8,
},
]
}
]
}
height={80}
- interpolate="basis"
padding={
Array [
0,
0,
]
}
- xTicks={Array []}
- xValues={Array []}
/>
`;
Array [
Object {
"x": 0,
- "y": "360",
+ "y": 360,
},
Object {
"x": 1,
- "y": "39",
+ "y": 39,
},
]
}
]
}
height={80}
- interpolate="basis"
padding={
Array [
0,
0,
]
}
- xTicks={Array []}
- xValues={Array []}
/>
`;
import { isProvided, getLinkName } from '../../project-admin/links/utils';
import { ProjectLink } from '../../../app/types';
import DetachIcon from '../../../components/icons-components/DetachIcon';
-import BugTrackerIcon from '../../../components/ui/BugTrackerIcon';
+import BugTrackerIcon from '../../../components/icons-components/BugTrackerIcon';
interface Props {
link: ProjectLink;
import { ProjectLink } from '../../../app/types';
import ConfirmButton from '../../../components/controls/ConfirmButton';
import DetachIcon from '../../../components/icons-components/DetachIcon';
-import BugTrackerIcon from '../../../components/ui/BugTrackerIcon';
+import BugTrackerIcon from '../../../components/icons-components/BugTrackerIcon';
import { Button } from '../../../components/ui/buttons';
import { translate, translateWithParameters } from '../../../helpers/l10n';
children: React.ReactElement<any>;
languages: Languages;
onRequestFail: (reasong: any) => void;
- organization: { name: string; key: string } | null;
+ organization: { name: string; key: string } | undefined;
}
interface State {
<div className="page page-limited">
<Suggestions suggestions="quality_profiles" />
<OrganizationHelmet
- title={translate('quality_profiles.page')}
organization={this.props.organization}
+ title={translate('quality_profiles.page')}
/>
{this.renderChild()}
interface StateProps {
languages: Languages;
- organization: { name: string; key: string } | null;
+ organization: { name: string; key: string } | undefined;
}
interface DispatchProps {
languages: getLanguages(state),
organization: ownProps.params.organizationKey
? getOrganizationByKey(state, ownProps.params.organizationKey)
- : null
+ : undefined
});
const mapDispatchToProps = (dispatch: any) => ({
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { max } from 'd3-array';
+import { scaleLinear, scaleBand, ScaleLinear, ScaleBand } from 'd3-scale';
+import Tooltip from '../controls/Tooltip';
+
+interface DataPoint {
+ tooltip?: React.ReactNode;
+ x: number;
+ y: number;
+}
+
+interface Props<T> {
+ barsWidth: number;
+ data: Array<DataPoint & T>;
+ height: number;
+ onBarClick?: (point: DataPoint & T) => void;
+ padding?: [number, number, number, number];
+ width: number;
+ xTicks?: string[];
+ xValues?: string[];
+}
+
+export default class BarChart<T> extends React.PureComponent<Props<T>> {
+ handleClick = (point: DataPoint & T) => {
+ if (this.props.onBarClick) {
+ this.props.onBarClick(point);
+ }
+ };
+
+ renderXTicks = (xScale: ScaleBand<number>, yScale: ScaleLinear<number, number>) => {
+ const { data, xTicks = [] } = this.props;
+
+ if (!xTicks.length) {
+ return null;
+ }
+
+ const ticks = xTicks.map((tick, index) => {
+ const point = data[index];
+ const x = Math.round((xScale(point.x) as number) + xScale.bandwidth() / 2);
+ const y = yScale.range()[0];
+ const d = data[index];
+ const text = (
+ <text
+ className="bar-chart-tick"
+ dy="1.5em"
+ key={index}
+ onClick={() => this.handleClick(point)}
+ style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
+ x={x}
+ y={y}>
+ {tick}
+ </text>
+ );
+ return (
+ <Tooltip key={index} overlay={d.tooltip || undefined}>
+ {text}
+ </Tooltip>
+ );
+ });
+ return <g>{ticks}</g>;
+ };
+
+ renderXValues = (xScale: ScaleBand<number>, yScale: ScaleLinear<number, number>) => {
+ const { data, xValues = [] } = this.props;
+
+ if (!xValues.length) {
+ return null;
+ }
+
+ const ticks = xValues.map((value, index) => {
+ const point = data[index];
+ const x = Math.round((xScale(point.x) as number) + xScale.bandwidth() / 2);
+ const y = yScale(point.y);
+ const text = (
+ <text
+ className="bar-chart-tick"
+ dy="-1em"
+ key={index}
+ onClick={() => this.handleClick(point)}
+ style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
+ x={x}
+ y={y}>
+ {value}
+ </text>
+ );
+ return (
+ <Tooltip key={index} overlay={point.tooltip || undefined}>
+ {text}
+ </Tooltip>
+ );
+ });
+ return <g>{ticks}</g>;
+ };
+
+ renderBars = (xScale: ScaleBand<number>, yScale: ScaleLinear<number, number>) => {
+ const bars = this.props.data.map((point, index) => {
+ const x = Math.round(xScale(point.x) as number);
+ const maxY = yScale.range()[0];
+ const y = Math.round(yScale(point.y)) - /* minimum bar height */ 1;
+ const height = maxY - y;
+ const rect = (
+ <rect
+ className="bar-chart-bar"
+ height={height}
+ key={index}
+ onClick={() => this.handleClick(point)}
+ style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
+ width={this.props.barsWidth}
+ x={x}
+ y={y}
+ />
+ );
+ return (
+ <Tooltip key={index} overlay={point.tooltip || undefined}>
+ {rect}
+ </Tooltip>
+ );
+ });
+ return <g>{bars}</g>;
+ };
+
+ render() {
+ const { barsWidth, data, width, height, padding = [10, 10, 10, 10] } = this.props;
+
+ const availableWidth = width - padding[1] - padding[3];
+ const availableHeight = height - padding[0] - padding[2];
+
+ const innerPadding = (availableWidth - barsWidth * data.length) / (data.length - 1);
+ const relativeInnerPadding = innerPadding / (innerPadding + barsWidth);
+
+ const maxY = max(data, d => d.y) as number;
+ const xScale = scaleBand<number>()
+ .domain(data.map(d => d.x))
+ .range([0, availableWidth])
+ .paddingInner(relativeInnerPadding);
+ const yScale = scaleLinear()
+ .domain([0, maxY])
+ .range([availableHeight, 0]);
+
+ return (
+ <svg className="bar-chart" height={height} width={width}>
+ <g transform={`translate(${padding[3]}, ${padding[0]})`}>
+ {this.renderXTicks(xScale, yScale)}
+ {this.renderXValues(xScale, yScale)}
+ {this.renderBars(xScale, yScale)}
+ </g>
+ </svg>
+ );
+ }
+}
displayXTicks?: boolean;
displayYGrid?: boolean;
displayYTicks?: boolean;
- formatXTick: (tick: number) => string;
- formatYTick: (tick: number) => string;
+ formatXTick?: (tick: number) => string;
+ formatYTick?: (tick: number) => string;
height: number;
items: Item[];
onBubbleClick?: (link?: string) => void;
- padding: [number, number, number, number];
+ padding?: [number, number, number, number];
sizeDomain?: [number, number];
sizeRange?: [number, number];
xDomain?: [number, number];
displayXTicks: true,
displayYGrid: true,
displayYTicks: true,
- formatXTick: (d: number) => d,
- formatYTick: (d: number) => d,
- padding: [10, 10, 10, 10],
sizeRange: [5, 45]
};
document.removeEventListener('mousemove', this.updateZoomCenter);
}
+ get formatXTick() {
+ return this.props.formatXTick || ((d: number) => String(d));
+ }
+
+ get formatYTick() {
+ return this.props.formatYTick || ((d: number) => String(d));
+ }
+
+ get padding() {
+ return this.props.padding || [10, 10, 10, 10];
+ }
+
startMoving = (event: React.MouseEvent<SVGSVGElement>) => {
if (this.node && this.state.zoom > 1) {
const rect = this.node.getBoundingClientRect();
event.preventDefault();
const rect = this.node.getBoundingClientRect();
- const mouseX = event.clientX - rect.left - this.props.padding[1];
- const mouseY = event.clientY - rect.top - this.props.padding[0];
+ const mouseX = event.clientX - rect.left - this.padding[1];
+ const mouseY = event.clientY - rect.top - this.padding[0];
let delta = event.deltaY;
if ((event as any).webkitDirectionInvertedFromDevice) {
const ticks = xTicks.map((tick, index) => {
const x = xScale(tick);
const y = yScale.range()[0];
- const innerText = this.props.formatXTick(tick);
+ const innerText = this.formatXTick(tick);
return (
<text
className="bubble-chart-tick"
const ticks = yTicks.map((tick, index) => {
const x = xScale.range()[0];
const y = yScale(tick);
- const innerText = this.props.formatYTick(tick);
+ const innerText = this.formatYTick(tick);
return (
<text
className="bubble-chart-tick bubble-chart-tick-y"
};
renderChart = (width: number) => {
- const availableWidth = width - this.props.padding[1] - this.props.padding[3];
- const availableHeight = this.props.height - this.props.padding[0] - this.props.padding[2];
+ const availableWidth = width - this.padding[1] - this.padding[3];
+ const availableHeight = this.props.height - this.padding[0] - this.padding[2];
const xScale = scaleLinear()
.domain(this.props.xDomain || [0, max(this.props.items, d => d.x) || 0])
);
});
- const xTicks = this.getTicks(xScale, this.props.formatXTick);
- const yTicks = this.getTicks(yScale, this.props.formatYTick);
+ const xTicks = this.getTicks(xScale, this.formatXTick);
+ const yTicks = this.getTicks(yScale, this.formatYTick);
return (
<svg
onWheel={this.onWheel}
ref={node => (this.node = node)}
width={width}>
- <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0]})`}>
+ <g transform={`translate(${this.padding[3]}, ${this.padding[0]})`}>
<svg
- height={this.props.height - this.props.padding[0] - this.props.padding[2]}
+ height={this.props.height - this.padding[0] - this.padding[2]}
style={{ overflow: 'hidden' }}
width={width}>
{this.renderXGrid(xTicks, xScale, yScale, centerXDelta)}
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-import { formatMeasure } from '../../helpers/measures';
-
-/*:: type Props = {
- className?: string,
- colorScale: Object,
- colorNA?: string,
- metricType: string
-}; */
-
-export default function ColorBoxLegend(
- { className, colorScale, colorNA, metricType } /*: Props */
-) {
- const colorDomain = colorScale.domain();
- const colorRange = colorScale.range();
- return (
- <div className={classNames('color-box-legend', className)}>
- {colorDomain.map((value, idx) => (
- <div key={value}>
- <span className="color-box-legend-rect" style={{ borderColor: colorRange[idx] }}>
- <span
- className="color-box-legend-rect-inner"
- style={{ backgroundColor: colorRange[idx] }}
- />
- </span>
- {formatMeasure(value, metricType)}
- </div>
- ))}
- {colorNA && (
- <div>
- <span className="color-box-legend-rect" style={{ borderColor: colorNA }}>
- <span className="color-box-legend-rect-inner" style={{ backgroundColor: colorNA }} />
- </span>
- N/A
- </div>
- )}
- </div>
- );
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+import { ScaleLinear, ScaleOrdinal } from 'd3-scale';
+import { formatMeasure } from '../../helpers/measures';
+
+interface Props {
+ className?: string;
+ colorNA?: string;
+ colorScale:
+ | ScaleOrdinal<string, string> // used for LEVEL type
+ | ScaleLinear<number, string | number>; // used for RATING or PERCENT type
+ metricType: string;
+}
+
+export default function ColorBoxLegend({ className, colorScale, colorNA, metricType }: Props) {
+ const colorDomain: Array<number | string> = colorScale.domain();
+ const colorRange = colorScale.range();
+ return (
+ <div className={classNames('color-box-legend', className)}>
+ {colorDomain.map((value, idx) => (
+ <div key={value}>
+ <span className="color-box-legend-rect" style={{ borderColor: colorRange[idx] }}>
+ <span
+ className="color-box-legend-rect-inner"
+ style={{ backgroundColor: colorRange[idx] }}
+ />
+ </span>
+ {formatMeasure(value, metricType)}
+ </div>
+ ))}
+ {colorNA && (
+ <div>
+ <span className="color-box-legend-rect" style={{ borderColor: colorNA }}>
+ <span className="color-box-legend-rect-inner" style={{ backgroundColor: colorNA }} />
+ </span>
+ N/A
+ </div>
+ )}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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';
-
-/*:: type Props = {
- className?: string,
- colorScale: Object,
- colorNA?: string,
- direction?: number,
- padding?: Array<number>,
- height: number,
- width: number
-}; */
-
-const NA_SPACING = 4;
-
-export default function ColorGradientLegend(
- {
- className,
- colorScale,
- colorNA,
- direction,
- padding = [12, 24, 0, 0],
- height,
- width
- } /*: Props */
-) {
- const colorRange = colorScale.range();
- if (direction === 1) {
- colorRange.reverse();
- }
-
- const colorDomain = colorScale.domain();
- const lastColorIdx = colorRange.length - 1;
- const lastDomainIdx = colorDomain.length - 1;
- const widthNoPadding = width - padding[1];
- const rectHeight = height - padding[0];
- return (
- <svg className={className} width={width} height={height}>
- <defs>
- <linearGradient id="gradient-legend">
- {colorRange.map((color, idx) => (
- <stop key={idx} offset={idx / lastColorIdx} stopColor={color} />
- ))}
- </linearGradient>
- </defs>
- <g transform={`translate(${padding[3]}, ${padding[0]})`}>
- <rect fill="url(#gradient-legend)" x={0} y={0} height={rectHeight} width={widthNoPadding} />
- {colorDomain.map((d, idx) => (
- <text
- className="gradient-legend-text"
- key={idx}
- x={widthNoPadding * (idx / lastDomainIdx)}
- y={0}
- dy="-2px">
- {d}
- </text>
- ))}
- </g>
- {colorNA && (
- <g transform={`translate(${widthNoPadding}, ${padding[0]})`}>
- <rect
- fill={colorNA}
- x={NA_SPACING}
- y={0}
- height={rectHeight}
- width={padding[1] - NA_SPACING}
- />
- <text
- className="gradient-legend-na"
- x={NA_SPACING + (padding[1] - NA_SPACING) / 2}
- y={0}
- dy="-2px">
- N/A
- </text>
- </g>
- )}
- </svg>
- );
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { ScaleLinear, ScaleOrdinal } from 'd3-scale';
+
+interface Props {
+ className?: string;
+ colorNA?: string;
+ colorScale:
+ | ScaleOrdinal<string, string> // used for LEVEL type
+ | ScaleLinear<number, string | number>; // used for RATING or PERCENT type
+ direction?: number;
+ height: number;
+ padding?: [number, number, number, number];
+ width: number;
+}
+
+const NA_SPACING = 4;
+
+export default function ColorGradientLegend({
+ className,
+ colorScale,
+ colorNA,
+ direction,
+ padding = [12, 24, 0, 0],
+ height,
+ width
+}: Props) {
+ const colorRange: Array<string | number> = colorScale.range();
+ if (direction === 1) {
+ colorRange.reverse();
+ }
+
+ const colorDomain: Array<string | number> = colorScale.domain();
+ const lastColorIdx = colorRange.length - 1;
+ const lastDomainIdx = colorDomain.length - 1;
+ const widthNoPadding = width - padding[1];
+ const rectHeight = height - padding[0];
+ return (
+ <svg className={className} height={height} width={width}>
+ <defs>
+ <linearGradient id="gradient-legend">
+ {colorRange.map((color, idx) => (
+ <stop key={idx} offset={idx / lastColorIdx} stopColor={String(color)} />
+ ))}
+ </linearGradient>
+ </defs>
+ <g transform={`translate(${padding[3]}, ${padding[0]})`}>
+ <rect fill="url(#gradient-legend)" height={rectHeight} width={widthNoPadding} x={0} y={0} />
+ {colorDomain.map((d, idx) => (
+ <text
+ className="gradient-legend-text"
+ dy="-2px"
+ key={idx}
+ x={widthNoPadding * (idx / lastDomainIdx)}
+ y={0}>
+ {d}
+ </text>
+ ))}
+ </g>
+ {colorNA && (
+ <g transform={`translate(${widthNoPadding}, ${padding[0]})`}>
+ <rect
+ fill={colorNA}
+ height={rectHeight}
+ width={padding[1] - NA_SPACING}
+ x={NA_SPACING}
+ y={0}
+ />
+ <text
+ className="gradient-legend-na"
+ dy="-2px"
+ x={NA_SPACING + (padding[1] - NA_SPACING) / 2}
+ y={0}>
+ N/A
+ </text>
+ </g>
+ )}
+ </svg>
+ );
+}
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-import { formatMeasure } from '../../helpers/measures';
-import { RATING_COLORS } from '../../helpers/constants';
-
-export default function ColorRatingsLegend({ className } /*: { className?: string } */) {
- return (
- <div className={classNames('color-box-legend', className)}>
- {[1, 2, 3, 4, 5].map(rating => (
- <div key={rating}>
- <span
- className="color-box-legend-rect"
- style={{ borderColor: RATING_COLORS[rating - 1] }}>
- <span
- className="color-box-legend-rect-inner"
- style={{ backgroundColor: RATING_COLORS[rating - 1] }}
- />
- </span>
- {formatMeasure(rating, 'RATING')}
- </div>
- ))}
- </div>
- );
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+import { formatMeasure } from '../../helpers/measures';
+import { RATING_COLORS } from '../../helpers/constants';
+
+interface Props {
+ className?: string;
+}
+
+export default function ColorRatingsLegend({ className }: Props) {
+ return (
+ <div className={classNames('color-box-legend', className)}>
+ {[1, 2, 3, 4, 5].map(rating => (
+ <div key={rating}>
+ <span
+ className="color-box-legend-rect"
+ style={{ borderColor: RATING_COLORS[rating - 1] }}>
+ <span
+ className="color-box-legend-rect-inner"
+ style={{ backgroundColor: RATING_COLORS[rating - 1] }}
+ />
+ </span>
+ {formatMeasure(rating, 'RATING')}
+ </div>
+ ))}
+ </div>
+ );
+}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { arc as d3Arc, pie as d3Pie, PieArcDatum } from 'd3-shape';
+
+interface DataPoint {
+ fill: string;
+ value: number;
+}
+
+interface Props {
+ data: DataPoint[];
+ height: number;
+ thickness: number;
+ padding?: [number, number, number, number];
+ width: number;
+}
+
+export default function DonutChart(props: Props) {
+ const { height, padding = [0, 0, 0, 0], width } = props;
+
+ const availableWidth = width - padding[1] - padding[3];
+ const availableHeight = height - padding[0] - padding[2];
+
+ const size = Math.min(availableWidth, availableHeight);
+ const radius = Math.floor(size / 2);
+
+ const pie = d3Pie<any, DataPoint>()
+ .sort(null)
+ .value(d => d.value);
+
+ const sectors = pie(props.data).map((d, i) => {
+ return (
+ <Sector
+ data={d}
+ fill={props.data[i].fill}
+ key={i}
+ radius={radius}
+ thickness={props.thickness}
+ />
+ );
+ });
+
+ return (
+ <svg className="donut-chart" height={height} width={width}>
+ <g transform={`translate(${padding[3]}, ${padding[0]})`}>
+ <g transform={`translate(${radius}, ${radius})`}>{sectors}</g>
+ </g>
+ </svg>
+ );
+}
+
+interface SectorProps {
+ data: PieArcDatum<DataPoint>;
+ fill: string;
+ radius: number;
+ thickness: number;
+}
+
+function Sector(props: SectorProps) {
+ const arc = d3Arc<any, PieArcDatum<DataPoint>>()
+ .outerRadius(props.radius)
+ .innerRadius(props.radius - props.thickness);
+ const d = arc(props.data) as string;
+ return <path d={d} style={{ fill: props.fill }} />;
+}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { extent, max } from 'd3-array';
+import { scaleLinear, ScaleLinear } from 'd3-scale';
+import { area as d3Area, line as d3Line, curveBasis } from 'd3-shape';
+import { AutoSizer } from 'react-virtualized/dist/commonjs/AutoSizer';
+
+interface DataPoint {
+ x: number;
+ y: number;
+}
+
+interface Props {
+ backdropConstraints?: [number, number];
+ data: DataPoint[];
+ displayBackdrop?: boolean;
+ displayPoints?: boolean;
+ displayVerticalGrid?: boolean;
+ domain?: [number, number];
+ height: number;
+ padding?: [number, number, number, number];
+ width?: number;
+ xTicks?: {}[];
+ xValues?: {}[];
+}
+
+export default class LineChart extends React.PureComponent<Props> {
+ renderBackdrop(xScale: ScaleLinear<number, number>, yScale: ScaleLinear<number, number>) {
+ const { displayBackdrop = true } = this.props;
+
+ if (!displayBackdrop) {
+ return null;
+ }
+
+ const area = d3Area<DataPoint>()
+ .x(d => xScale(d.x))
+ .y0(yScale.range()[0])
+ .y1(d => yScale(d.y))
+ .defined(d => d.y != null)
+ .curve(curveBasis);
+
+ let { data } = this.props;
+ if (this.props.backdropConstraints) {
+ const c = this.props.backdropConstraints;
+ data = data.filter(d => c[0] <= d.x && d.x <= c[1]);
+ }
+
+ return <path className="line-chart-backdrop" d={area(data) as string} />;
+ }
+
+ renderPoints(xScale: ScaleLinear<number, number>, yScale: ScaleLinear<number, number>) {
+ const { displayPoints = true } = this.props;
+
+ if (!displayPoints) {
+ return null;
+ }
+
+ const points = this.props.data.filter(point => point.y != null).map((point, index) => {
+ const x = xScale(point.x);
+ const y = yScale(point.y);
+ return <circle className="line-chart-point" cx={x} cy={y} key={index} r="3" />;
+ });
+ return <g>{points}</g>;
+ }
+
+ renderVerticalGrid(xScale: ScaleLinear<number, number>, yScale: ScaleLinear<number, number>) {
+ const { displayVerticalGrid = true } = this.props;
+
+ if (!displayVerticalGrid) {
+ return null;
+ }
+
+ const lines = this.props.data.map((point, index) => {
+ const x = xScale(point.x);
+ const y1 = yScale.range()[0];
+ const y2 = yScale(point.y);
+ return <line className="line-chart-grid" key={index} x1={x} x2={x} y1={y1} y2={y2} />;
+ });
+ return <g>{lines}</g>;
+ }
+
+ renderXTicks(xScale: ScaleLinear<number, number>, yScale: ScaleLinear<number, number>) {
+ const { xTicks = [] } = this.props;
+
+ if (!xTicks.length) {
+ return null;
+ }
+
+ const ticks = xTicks.map((tick, index) => {
+ const point = this.props.data[index];
+ const x = xScale(point.x);
+ const y = yScale.range()[0];
+ return (
+ <text className="line-chart-tick" dy="1.5em" key={index} x={x} y={y}>
+ {tick}
+ </text>
+ );
+ });
+ return <g>{ticks}</g>;
+ }
+
+ renderXValues(xScale: ScaleLinear<number, number>, yScale: ScaleLinear<number, number>) {
+ const { xValues = [] } = this.props;
+
+ if (!xValues.length) {
+ return null;
+ }
+
+ const ticks = xValues.map((value, index) => {
+ const point = this.props.data[index];
+ const x = xScale(point.x);
+ const y = yScale(point.y);
+ return (
+ <text className="line-chart-tick" dy="-1em" key={index} x={x} y={y}>
+ {value}
+ </text>
+ );
+ });
+ return <g>{ticks}</g>;
+ }
+
+ renderLine(xScale: ScaleLinear<number, number>, yScale: ScaleLinear<number, number>) {
+ const p = d3Line<DataPoint>()
+ .x(d => xScale(d.x))
+ .y(d => yScale(d.y))
+ .defined(d => d.y != null)
+ .curve(curveBasis);
+ return <path className="line-chart-path" d={p(this.props.data) as string} />;
+ }
+
+ renderChart = (width: number) => {
+ const { height, padding = [10, 10, 10, 10] } = this.props;
+
+ if (!width || !height) {
+ return <div />;
+ }
+
+ const availableWidth = width - padding[1] - padding[3];
+ const availableHeight = height - padding[0] - padding[2];
+
+ const xScale = scaleLinear()
+ .domain(extent(this.props.data, d => d.x) as [number, number])
+ .range([0, availableWidth]);
+ const yScale = scaleLinear().range([availableHeight, 0]);
+
+ if (this.props.domain) {
+ yScale.domain(this.props.domain);
+ } else {
+ const maxY = max(this.props.data, d => d.y) as number;
+ yScale.domain([0, maxY]);
+ }
+
+ return (
+ <svg className="line-chart" height={height} width={width}>
+ <g transform={`translate(${padding[3]}, ${padding[0]})`}>
+ {this.renderVerticalGrid(xScale, yScale)}
+ {this.renderBackdrop(xScale, yScale)}
+ {this.renderLine(xScale, yScale)}
+ {this.renderPoints(xScale, yScale)}
+ {this.renderXTicks(xScale, yScale)}
+ {this.renderXValues(xScale, yScale)}
+ </g>
+ </svg>
+ );
+ };
+
+ render() {
+ return this.props.width !== undefined ? (
+ this.renderChart(this.props.width)
+ ) : (
+ <AutoSizer disableHeight={true}>{size => this.renderChart(size.width)}</AutoSizer>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { treemap as d3Treemap, hierarchy as d3Hierarchy } from 'd3-hierarchy';
-import TreeMapRect from './TreeMapRect';
-import { translate } from '../../helpers/l10n';
-
-/*:: export type TreeMapItem = {
- key: string,
- size: number,
- color: string,
- icon?: React.Element<*>,
- tooltip?: string | React.Element<*>,
- label: string,
- link?: string
-}; */
-
-/*:: type Props = {|
- items: Array<TreeMapItem>,
- onRectangleClick?: string => void,
- height: number,
- width: number
-|}; */
-
-export default class TreeMap extends React.PureComponent {
- /*:: props: Props; */
-
- mostCommitPrefix = (labels /*: Array<string> */) => {
- const sortedLabels = labels.slice(0).sort();
- const firstLabel = sortedLabels[0];
- const firstLabelLength = firstLabel.length;
- const lastLabel = sortedLabels[sortedLabels.length - 1];
- let i = 0;
- while (i < firstLabelLength && firstLabel.charAt(i) === lastLabel.charAt(i)) {
- i++;
- }
- const prefix = firstLabel.substr(0, i);
- const prefixTokens = prefix.split(/[\s\\/]/);
- const lastPrefixPart = prefixTokens[prefixTokens.length - 1];
- return prefix.substr(0, prefix.length - lastPrefixPart.length);
- };
-
- renderNoData() {
- return (
- <div className="sonar-d3">
- <div
- className="treemap-container"
- style={{ width: this.props.width, height: this.props.height }}>
- {translate('no_data')}
- </div>
- </div>
- );
- }
-
- render() {
- const { items, height, width } = this.props;
- if (items.length <= 0) {
- return this.renderNoData();
- }
-
- const hierarchy = d3Hierarchy({ children: items })
- .sum(d => d.size)
- .sort((a, b) => b.value - a.value);
-
- const treemap = d3Treemap()
- .round(true)
- .size([width, height]);
-
- const nodes = treemap(hierarchy).leaves();
- const prefix = this.mostCommitPrefix(items.map(item => item.label));
- const halfWidth = width / 2;
- return (
- <div className="sonar-d3">
- <div className="treemap-container" style={{ width, height }}>
- {nodes.map(node => (
- <TreeMapRect
- key={node.data.key}
- x={node.x0}
- y={node.y0}
- width={node.x1 - node.x0}
- height={node.y1 - node.y0}
- fill={node.data.color}
- label={node.data.label}
- prefix={prefix}
- itemKey={node.data.key}
- icon={node.data.icon}
- tooltip={node.data.tooltip}
- link={node.data.link}
- onClick={this.props.onRectangleClick}
- placement={node.x0 === 0 || node.x1 < halfWidth ? 'right' : 'left'}
- />
- ))}
- </div>
- </div>
- );
- }
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { treemap as d3Treemap, hierarchy as d3Hierarchy } from 'd3-hierarchy';
+import TreeMapRect from './TreeMapRect';
+import { translate } from '../../helpers/l10n';
+
+interface TreeMapItem {
+ color: string;
+ icon?: React.ReactNode;
+ key: string;
+ label: string;
+ link?: string;
+ size: number;
+ tooltip?: React.ReactNode;
+}
+
+interface HierarchicalTreemapItem extends TreeMapItem {
+ children?: TreeMapItem[];
+}
+
+interface Props {
+ height: number;
+ items: TreeMapItem[];
+ onRectangleClick?: (item: string) => void;
+ width: number;
+}
+
+export default class TreeMap extends React.PureComponent<Props> {
+ mostCommitPrefix = (labels: string[]) => {
+ const sortedLabels = labels.slice(0).sort();
+ const firstLabel = sortedLabels[0];
+ const firstLabelLength = firstLabel.length;
+ const lastLabel = sortedLabels[sortedLabels.length - 1];
+ let i = 0;
+ while (i < firstLabelLength && firstLabel.charAt(i) === lastLabel.charAt(i)) {
+ i++;
+ }
+ const prefix = firstLabel.substr(0, i);
+ const prefixTokens = prefix.split(/[\s\\/]/);
+ const lastPrefixPart = prefixTokens[prefixTokens.length - 1];
+ return prefix.substr(0, prefix.length - lastPrefixPart.length);
+ };
+
+ renderNoData() {
+ return (
+ <div className="sonar-d3">
+ <div
+ className="treemap-container"
+ style={{ width: this.props.width, height: this.props.height }}>
+ {translate('no_data')}
+ </div>
+ </div>
+ );
+ }
+
+ render() {
+ const { items, height, width } = this.props;
+ if (items.length <= 0) {
+ return this.renderNoData();
+ }
+
+ const hierarchy = d3Hierarchy({ children: items } as HierarchicalTreemapItem)
+ .sum(d => d.size)
+ .sort((a, b) => (b.value || 0) - (a.value || 0));
+
+ const treemap = d3Treemap<TreeMapItem>()
+ .round(true)
+ .size([width, height]);
+
+ const nodes = treemap(hierarchy).leaves();
+ const prefix = this.mostCommitPrefix(items.map(item => item.label));
+ const halfWidth = width / 2;
+ return (
+ <div className="sonar-d3">
+ <div className="treemap-container" style={{ width, height }}>
+ {nodes.map(node => (
+ <TreeMapRect
+ fill={node.data.color}
+ height={node.y1 - node.y0}
+ icon={node.data.icon}
+ itemKey={node.data.key}
+ key={node.data.key}
+ label={node.data.label}
+ link={node.data.link}
+ onClick={this.props.onRectangleClick}
+ placement={node.x0 === 0 || node.x1 < halfWidth ? 'right' : 'left'}
+ prefix={prefix}
+ tooltip={node.data.tooltip}
+ width={node.x1 - node.x0}
+ x={node.x0}
+ y={node.y0}
+ />
+ ))}
+ </div>
+ </div>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { Link } from 'react-router';
-import classNames from 'classnames';
-import { scaleLinear } from 'd3-scale';
-import LinkIcon from '../icons-components/LinkIcon';
-import Tooltip from '../controls/Tooltip';
-
-const SIZE_SCALE = scaleLinear()
- .domain([3, 15])
- .range([11, 18])
- .clamp(true);
-
-/*:: type Props = {|
- x: number,
- y: number,
- width: number,
- height: number,
- fill: string,
- label: string,
- prefix: string,
- icon?: React.Element<*>,
- tooltip?: string | React.Element<*>,
- itemKey: string,
- link?: string,
- onClick?: string => void,
- placement?: string
-|}; */
-
-export default class TreeMapRect extends React.PureComponent {
- /*:: props: Props; */
-
- handleLinkClick = (e /*: Event */) => e.stopPropagation();
-
- handleRectClick = () => {
- if (this.props.onClick != null) {
- this.props.onClick(this.props.itemKey);
- }
- };
-
- renderLink = () => {
- const { link, height, width } = this.props;
- const hasMinSize = width >= 24 && height >= 24 && (width >= 48 || height >= 50);
- if (!hasMinSize || link == null) {
- return null;
- }
- return (
- <Link className="treemap-link" to={link} onClick={this.handleLinkClick}>
- <LinkIcon />
- </Link>
- );
- };
-
- renderCell = () => {
- const cellStyles = {
- left: this.props.x,
- top: this.props.y,
- width: this.props.width,
- height: this.props.height,
- backgroundColor: this.props.fill,
- fontSize: SIZE_SCALE(this.props.width / this.props.label.length),
- lineHeight: `${this.props.height}px`,
- cursor: this.props.onClick != null ? 'pointer' : 'default'
- };
- const isTextVisible = this.props.width >= 40 && this.props.height >= 45;
- const isIconVisible = this.props.width >= 24 && this.props.height >= 26;
-
- const label = this.props.prefix
- ? `${this.props.prefix}<br>${this.props.label.substr(this.props.prefix.length)}`
- : this.props.label;
-
- return (
- <div
- className="treemap-cell"
- style={cellStyles}
- onClick={this.handleRectClick}
- role="treeitem"
- tabIndex={0}>
- <div className="treemap-inner" style={{ maxWidth: this.props.width }}>
- {isIconVisible && (
- <span className={classNames('treemap-icon', { 'spacer-right': isTextVisible })}>
- {this.props.icon}
- </span>
- )}
- {isTextVisible && (
- <span className="treemap-text" dangerouslySetInnerHTML={{ __html: label }} />
- )}
- </div>
- {this.renderLink()}
- </div>
- );
- };
-
- render() {
- const { placement, tooltip } = this.props;
- return (
- <Tooltip overlay={tooltip || undefined} placement={placement || 'left'}>
- {this.renderCell()}
- </Tooltip>
- );
- }
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { Link } from 'react-router';
+import * as classNames from 'classnames';
+import { scaleLinear } from 'd3-scale';
+import LinkIcon from '../icons-components/LinkIcon';
+import Tooltip, { Placement } from '../controls/Tooltip';
+
+const SIZE_SCALE = scaleLinear()
+ .domain([3, 15])
+ .range([11, 18])
+ .clamp(true);
+
+interface Props {
+ fill: string;
+ height: number;
+ icon?: React.ReactNode;
+ itemKey: string;
+ label: string;
+ link?: string;
+ onClick?: (item: string) => void;
+ placement?: Placement;
+ prefix: string;
+ tooltip?: React.ReactNode;
+ width: number;
+ x: number;
+ y: number;
+}
+
+export default class TreeMapRect extends React.PureComponent<Props> {
+ handleLinkClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
+ event.stopPropagation();
+ };
+
+ handleRectClick = () => {
+ if (this.props.onClick) {
+ this.props.onClick(this.props.itemKey);
+ }
+ };
+
+ renderLink = () => {
+ const { link, height, width } = this.props;
+ const hasMinSize = width >= 24 && height >= 24 && (width >= 48 || height >= 50);
+ if (!hasMinSize || link == null) {
+ return null;
+ }
+ return (
+ <Link className="treemap-link" onClick={this.handleLinkClick} to={link}>
+ <LinkIcon />
+ </Link>
+ );
+ };
+
+ renderCell = () => {
+ const cellStyles = {
+ left: this.props.x,
+ top: this.props.y,
+ width: this.props.width,
+ height: this.props.height,
+ backgroundColor: this.props.fill,
+ fontSize: SIZE_SCALE(this.props.width / this.props.label.length),
+ lineHeight: `${this.props.height}px`,
+ cursor: this.props.onClick != null ? 'pointer' : 'default'
+ };
+ const isTextVisible = this.props.width >= 40 && this.props.height >= 45;
+ const isIconVisible = this.props.width >= 24 && this.props.height >= 26;
+
+ const label = this.props.prefix
+ ? `${this.props.prefix}<br>${this.props.label.substr(this.props.prefix.length)}`
+ : this.props.label;
+
+ return (
+ <div
+ className="treemap-cell"
+ onClick={this.handleRectClick}
+ role="treeitem"
+ style={cellStyles}
+ tabIndex={0}>
+ <div className="treemap-inner" style={{ maxWidth: this.props.width }}>
+ {isIconVisible && (
+ <span className={classNames('treemap-icon', { 'spacer-right': isTextVisible })}>
+ {this.props.icon}
+ </span>
+ )}
+ {isTextVisible && (
+ <span className="treemap-text" dangerouslySetInnerHTML={{ __html: label }} />
+ )}
+ </div>
+ {this.renderLink()}
+ </div>
+ );
+ };
+
+ render() {
+ const { placement, tooltip } = this.props;
+ return (
+ <Tooltip overlay={tooltip || undefined} placement={placement || 'left'}>
+ {this.renderCell()}
+ </Tooltip>
+ );
+ }
+}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import BarChart from '../BarChart';
+
+it('should display bars', () => {
+ const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
+ const chart = shallow(<BarChart barsWidth={20} data={data} height={100} width={100} />);
+ expect(chart.find('.bar-chart-bar').length).toBe(3);
+});
+
+it('should display ticks', () => {
+ const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
+ const ticks = ['A', 'B', 'C'];
+ const chart = shallow(
+ <BarChart barsWidth={20} data={data} height={100} width={100} xTicks={ticks} />
+ );
+ expect(chart.find('.bar-chart-tick').length).toBe(3);
+});
+
+it('should display values', () => {
+ const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
+ const values = ['A', 'B', 'C'];
+ const chart = shallow(
+ <BarChart barsWidth={20} data={data} height={100} width={100} xValues={values} />
+ );
+ expect(chart.find('.bar-chart-tick').length).toBe(3);
+});
+
+it('should display bars, ticks and values', () => {
+ const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
+ const ticks = ['A', 'B', 'C'];
+ const values = ['A', 'B', 'C'];
+ const chart = shallow(
+ <BarChart barsWidth={20} data={data} height={100} width={100} xTicks={ticks} xValues={values} />
+ );
+ expect(chart.find('.bar-chart-bar').length).toBe(3);
+ expect(chart.find('.bar-chart-tick').length).toBe(6);
+});
+++ /dev/null
-/*
- * 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 } from 'enzyme';
-import BubbleChart, { Bubble } from '../BubbleChart';
-
-it('should display bubbles', () => {
- const items = [{ x: 1, y: 10, size: 7 }, { x: 2, y: 30, size: 5 }];
- const chart = mount(<BubbleChart items={items} height={100} />);
- chart.find(Bubble).forEach(bubble => expect(bubble).toMatchSnapshot());
-});
-
-it('should render bubble links', () => {
- const items = [{ x: 1, y: 10, size: 7, link: 'foo' }, { x: 2, y: 30, size: 5, link: 'bar' }];
- const chart = mount(<BubbleChart items={items} height={100} />);
- chart.find(Bubble).forEach(bubble => expect(bubble).toMatchSnapshot());
-});
-
-it('should render bubbles with click handlers', () => {
- const onClick = jest.fn();
- const items = [{ x: 1, y: 10, size: 7, link: 'foo' }, { x: 2, y: 30, size: 5, link: 'bar' }];
- const chart = mount(<BubbleChart items={items} height={100} onBubbleClick={onClick} />);
- chart.find(Bubble).forEach(bubble => expect(bubble).toMatchSnapshot());
-});
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { mount } from 'enzyme';
+import BubbleChart, { Bubble } from '../BubbleChart';
+
+it('should display bubbles', () => {
+ const items = [{ x: 1, y: 10, size: 7 }, { x: 2, y: 30, size: 5 }];
+ const chart = mount(<BubbleChart height={100} items={items} />);
+ chart.find(Bubble).forEach(bubble => expect(bubble).toMatchSnapshot());
+});
+
+it('should render bubble links', () => {
+ const items = [{ x: 1, y: 10, size: 7, link: 'foo' }, { x: 2, y: 30, size: 5, link: 'bar' }];
+ const chart = mount(<BubbleChart height={100} items={items} />);
+ chart.find(Bubble).forEach(bubble => expect(bubble).toMatchSnapshot());
+});
+
+it('should render bubbles with click handlers', () => {
+ const onClick = jest.fn();
+ const items = [{ x: 1, y: 10, size: 7, link: 'foo' }, { x: 2, y: 30, size: 5, link: 'bar' }];
+ const chart = mount(<BubbleChart height={100} items={items} onBubbleClick={onClick} />);
+ chart.find(Bubble).forEach(bubble => expect(bubble).toMatchSnapshot());
+});
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import LineChart from '../LineChart';
+
+it('should display line', () => {
+ const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
+ const chart = shallow(<LineChart data={data} height={100} width={100} />);
+ expect(chart.find('.line-chart-path').length).toBe(1);
+});
+
+it('should display ticks', () => {
+ const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
+ const ticks = ['A', 'B', 'C'];
+ const chart = shallow(<LineChart data={data} height={100} width={100} xTicks={ticks} />);
+ expect(chart.find('.line-chart-tick').length).toBe(3);
+});
+
+it('should display values', () => {
+ const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
+ const values = ['A', 'B', 'C'];
+ const chart = shallow(<LineChart data={data} height={100} width={100} xValues={values} />);
+ expect(chart.find('.line-chart-tick').length).toBe(3);
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import TreeMap from '../TreeMap';
-
-it('should display', () => {
- const items = [
- { key: '1', size: 10, color: '#777', label: 'SonarQube :: Server' },
- { key: '2', size: 30, color: '#777', label: 'SonarQube :: Web' },
- { key: '3', size: 20, color: '#777', label: 'SonarQube :: Search' }
- ];
- const chart = shallow(
- <TreeMap items={items} width={100} height={100} onRectangleClick={() => {}} />
- );
- expect(chart.find('TreeMapRect')).toHaveLength(3);
-});
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import TreeMap from '../TreeMap';
+
+it('should display', () => {
+ const items = [
+ { key: '1', size: 10, color: '#777', label: 'SonarQube :: Server' },
+ { key: '2', size: 30, color: '#777', label: 'SonarQube :: Web' },
+ { key: '3', size: 20, color: '#777', label: 'SonarQube :: Search' }
+ ];
+ const chart = shallow(
+ <TreeMap height={100} items={items} onRectangleClick={() => {}} width={100} />
+ );
+ expect(chart.find('TreeMapRect')).toHaveLength(3);
+});
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should display bubbles 1`] = `
-<Bubble
- key="0"
- r={45}
- x={-10}
- y={52.3015873015873}
->
- <Tooltip>
- <g>
- <circle
- className="bubble-chart-bubble"
- r={45}
- style={
- Object {
- "fill": undefined,
- "stroke": undefined,
- }
- }
- transform="translate(-10, 52.3015873015873)"
- />
- </g>
- </Tooltip>
-</Bubble>
-`;
-
-exports[`should display bubbles 2`] = `
-<Bubble
- key="1"
- r={33.57142857142857}
- x={-75}
- y={33.57142857142857}
->
- <Tooltip>
- <g>
- <circle
- className="bubble-chart-bubble"
- r={33.57142857142857}
- style={
- Object {
- "fill": undefined,
- "stroke": undefined,
- }
- }
- transform="translate(-75, 33.57142857142857)"
- />
- </g>
- </Tooltip>
-</Bubble>
-`;
-
-exports[`should render bubble links 1`] = `
-<Bubble
- key="0"
- link="foo"
- r={45}
- x={-10}
- y={52.3015873015873}
->
- <Tooltip>
- <g>
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="foo"
- >
- <a
- onClick={[Function]}
- style={Object {}}
- >
- <circle
- className="bubble-chart-bubble"
- r={45}
- style={
- Object {
- "fill": undefined,
- "stroke": undefined,
- }
- }
- transform="translate(-10, 52.3015873015873)"
- />
- </a>
- </Link>
- </g>
- </Tooltip>
-</Bubble>
-`;
-
-exports[`should render bubble links 2`] = `
-<Bubble
- key="1"
- link="bar"
- r={33.57142857142857}
- x={-75}
- y={33.57142857142857}
->
- <Tooltip>
- <g>
- <Link
- onlyActiveOnIndex={false}
- style={Object {}}
- to="bar"
- >
- <a
- onClick={[Function]}
- style={Object {}}
- >
- <circle
- className="bubble-chart-bubble"
- r={33.57142857142857}
- style={
- Object {
- "fill": undefined,
- "stroke": undefined,
- }
- }
- transform="translate(-75, 33.57142857142857)"
- />
- </a>
- </Link>
- </g>
- </Tooltip>
-</Bubble>
-`;
-
-exports[`should render bubbles with click handlers 1`] = `
-<Bubble
- key="0"
- link="foo"
- onClick={[MockFunction]}
- r={45}
- x={-10}
- y={52.3015873015873}
->
- <Tooltip>
- <g>
- <circle
- className="bubble-chart-bubble"
- onClick={[Function]}
- r={45}
- style={
- Object {
- "fill": undefined,
- "stroke": undefined,
- }
- }
- transform="translate(-10, 52.3015873015873)"
- />
- </g>
- </Tooltip>
-</Bubble>
-`;
-
-exports[`should render bubbles with click handlers 2`] = `
-<Bubble
- key="1"
- link="bar"
- onClick={[MockFunction]}
- r={33.57142857142857}
- x={-75}
- y={33.57142857142857}
->
- <Tooltip>
- <g>
- <circle
- className="bubble-chart-bubble"
- onClick={[Function]}
- r={33.57142857142857}
- style={
- Object {
- "fill": undefined,
- "stroke": undefined,
- }
- }
- transform="translate(-75, 33.57142857142857)"
- />
- </g>
- </Tooltip>
-</Bubble>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should display bubbles 1`] = `
+<Bubble
+ key="0"
+ r={45}
+ x={-10}
+ y={52.3015873015873}
+>
+ <Tooltip>
+ <g>
+ <circle
+ className="bubble-chart-bubble"
+ r={45}
+ style={
+ Object {
+ "fill": undefined,
+ "stroke": undefined,
+ }
+ }
+ transform="translate(-10, 52.3015873015873)"
+ />
+ </g>
+ </Tooltip>
+</Bubble>
+`;
+
+exports[`should display bubbles 2`] = `
+<Bubble
+ key="1"
+ r={33.57142857142857}
+ x={-75}
+ y={33.57142857142857}
+>
+ <Tooltip>
+ <g>
+ <circle
+ className="bubble-chart-bubble"
+ r={33.57142857142857}
+ style={
+ Object {
+ "fill": undefined,
+ "stroke": undefined,
+ }
+ }
+ transform="translate(-75, 33.57142857142857)"
+ />
+ </g>
+ </Tooltip>
+</Bubble>
+`;
+
+exports[`should render bubble links 1`] = `
+<Bubble
+ key="0"
+ link="foo"
+ r={45}
+ x={-10}
+ y={52.3015873015873}
+>
+ <Tooltip>
+ <g>
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="foo"
+ >
+ <a
+ onClick={[Function]}
+ style={Object {}}
+ >
+ <circle
+ className="bubble-chart-bubble"
+ r={45}
+ style={
+ Object {
+ "fill": undefined,
+ "stroke": undefined,
+ }
+ }
+ transform="translate(-10, 52.3015873015873)"
+ />
+ </a>
+ </Link>
+ </g>
+ </Tooltip>
+</Bubble>
+`;
+
+exports[`should render bubble links 2`] = `
+<Bubble
+ key="1"
+ link="bar"
+ r={33.57142857142857}
+ x={-75}
+ y={33.57142857142857}
+>
+ <Tooltip>
+ <g>
+ <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ to="bar"
+ >
+ <a
+ onClick={[Function]}
+ style={Object {}}
+ >
+ <circle
+ className="bubble-chart-bubble"
+ r={33.57142857142857}
+ style={
+ Object {
+ "fill": undefined,
+ "stroke": undefined,
+ }
+ }
+ transform="translate(-75, 33.57142857142857)"
+ />
+ </a>
+ </Link>
+ </g>
+ </Tooltip>
+</Bubble>
+`;
+
+exports[`should render bubbles with click handlers 1`] = `
+<Bubble
+ key="0"
+ link="foo"
+ onClick={[MockFunction]}
+ r={45}
+ x={-10}
+ y={52.3015873015873}
+>
+ <Tooltip>
+ <g>
+ <circle
+ className="bubble-chart-bubble"
+ onClick={[Function]}
+ r={45}
+ style={
+ Object {
+ "fill": undefined,
+ "stroke": undefined,
+ }
+ }
+ transform="translate(-10, 52.3015873015873)"
+ />
+ </g>
+ </Tooltip>
+</Bubble>
+`;
+
+exports[`should render bubbles with click handlers 2`] = `
+<Bubble
+ key="1"
+ link="bar"
+ onClick={[MockFunction]}
+ r={33.57142857142857}
+ x={-75}
+ y={33.57142857142857}
+>
+ <Tooltip>
+ <g>
+ <circle
+ className="bubble-chart-bubble"
+ onClick={[Function]}
+ r={33.57142857142857}
+ style={
+ Object {
+ "fill": undefined,
+ "stroke": undefined,
+ }
+ }
+ transform="translate(-75, 33.57142857142857)"
+ />
+ </g>
+ </Tooltip>
+</Bubble>
+`;
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import { BarChart } from '../bar-chart';
-
-it('should display bars', () => {
- const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
- const chart = shallow(<BarChart data={data} width={100} height={100} barsWidth={20} />);
- expect(chart.find('.bar-chart-bar').length).toBe(3);
-});
-
-it('should display ticks', () => {
- const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
- const ticks = ['A', 'B', 'C'];
- const chart = shallow(
- <BarChart data={data} xTicks={ticks} width={100} height={100} barsWidth={20} />
- );
- expect(chart.find('.bar-chart-tick').length).toBe(3);
-});
-
-it('should display values', () => {
- const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
- const values = ['A', 'B', 'C'];
- const chart = shallow(
- <BarChart data={data} xValues={values} width={100} height={100} barsWidth={20} />
- );
- expect(chart.find('.bar-chart-tick').length).toBe(3);
-});
-
-it('should display bars, ticks and values', () => {
- const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
- const ticks = ['A', 'B', 'C'];
- const values = ['A', 'B', 'C'];
- const chart = shallow(
- <BarChart data={data} xTicks={ticks} xValues={values} width={100} height={100} barsWidth={20} />
- );
- expect(chart.find('.bar-chart-bar').length).toBe(3);
- expect(chart.find('.bar-chart-tick').length).toBe(6);
-});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import { LineChart } from '../line-chart';
-
-it('should display line', () => {
- const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
- const chart = shallow(<LineChart data={data} width={100} height={100} />);
- expect(chart.find('.line-chart-path').length).toBe(1);
-});
-
-it('should display ticks', () => {
- const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
- const ticks = ['A', 'B', 'C'];
- const chart = shallow(<LineChart data={data} xTicks={ticks} width={100} height={100} />);
- expect(chart.find('.line-chart-tick').length).toBe(3);
-});
-
-it('should display values', () => {
- const data = [{ x: 1, y: 10 }, { x: 2, y: 30 }, { x: 3, y: 20 }];
- const values = ['A', 'B', 'C'];
- const chart = shallow(<LineChart data={data} xValues={values} width={100} height={100} />);
- expect(chart.find('.line-chart-tick').length).toBe(3);
-});
+++ /dev/null
-/*
- * 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 createReactClass from 'create-react-class';
-import PropTypes from 'prop-types';
-import { max } from 'd3-array';
-import { scaleLinear, scaleBand } from 'd3-scale';
-import Tooltip from '../controls/Tooltip';
-import { ResizeMixin } from '../mixins/resize-mixin';
-
-export const BarChart = createReactClass({
- displayName: 'BarChart',
-
- propTypes: {
- data: PropTypes.arrayOf(PropTypes.object).isRequired,
- xTicks: PropTypes.arrayOf(PropTypes.any),
- xValues: PropTypes.arrayOf(PropTypes.any),
- height: PropTypes.number,
- padding: PropTypes.arrayOf(PropTypes.number),
- barsWidth: PropTypes.number.isRequired,
- onBarClick: PropTypes.func
- },
-
- mixins: [ResizeMixin],
-
- getDefaultProps() {
- return {
- xTicks: [],
- xValues: [],
- padding: [10, 10, 10, 10]
- };
- },
-
- getInitialState() {
- return { width: this.props.width, height: this.props.height };
- },
-
- componentDidUpdate(prevProps) {
- if (this.props.width && prevProps.width !== this.props.width) {
- this.setState({ width: this.props.width });
- }
- if (this.props.height && prevProps.height !== this.props.height) {
- this.setState({ height: this.props.height });
- }
- },
-
- handleClick(point) {
- this.props.onBarClick(point);
- },
-
- renderXTicks(xScale, yScale) {
- if (!this.props.xTicks.length) {
- return null;
- }
- const ticks = this.props.xTicks.map((tick, index) => {
- const point = this.props.data[index];
- const x = Math.round(xScale(point.x) + xScale.bandwidth() / 2);
- const y = yScale.range()[0];
- const d = this.props.data[index];
- const text = (
- <text
- className="bar-chart-tick"
- dy="1.5em"
- key={index}
- onClick={this.props.onBarClick && this.handleClick.bind(this, point)}
- style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
- x={x}
- y={y}>
- {tick}
- </text>
- );
- return (
- <Tooltip key={index} overlay={d.tooltip || undefined}>
- {text}
- </Tooltip>
- );
- });
- return <g>{ticks}</g>;
- },
-
- renderXValues(xScale, yScale) {
- if (!this.props.xValues.length) {
- return null;
- }
- const ticks = this.props.xValues.map((value, index) => {
- const point = this.props.data[index];
- const x = Math.round(xScale(point.x) + xScale.bandwidth() / 2);
- const y = yScale(point.y);
- const d = this.props.data[index];
- const text = (
- <text
- className="bar-chart-tick"
- dy="-1em"
- key={index}
- onClick={this.props.onBarClick && this.handleClick.bind(this, point)}
- style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
- x={x}
- y={y}>
- {value}
- </text>
- );
- return (
- <Tooltip key={index} overlay={d.tooltip || undefined}>
- {text}
- </Tooltip>
- );
- });
- return <g>{ticks}</g>;
- },
-
- renderBars(xScale, yScale) {
- const bars = this.props.data.map((d, index) => {
- const x = Math.round(xScale(d.x));
- const maxY = yScale.range()[0];
- const y = Math.round(yScale(d.y)) - /* minimum bar height */ 1;
- const height = maxY - y;
- const rect = (
- <rect
- className="bar-chart-bar"
- height={height}
- key={index}
- onClick={this.props.onBarClick && this.handleClick.bind(this, d)}
- style={{ cursor: this.props.onBarClick ? 'pointer' : 'default' }}
- width={this.props.barsWidth}
- x={x}
- y={y}
- />
- );
- return (
- <Tooltip key={index} overlay={d.tooltip || undefined}>
- {rect}
- </Tooltip>
- );
- });
- return <g>{bars}</g>;
- },
-
- render() {
- if (!this.state.width || !this.state.height) {
- return <div />;
- }
-
- const availableWidth = this.state.width - this.props.padding[1] - this.props.padding[3];
- const availableHeight = this.state.height - this.props.padding[0] - this.props.padding[2];
-
- const innerPadding =
- (availableWidth - this.props.barsWidth * this.props.data.length) /
- (this.props.data.length - 1);
- const relativeInnerPadding = innerPadding / (innerPadding + this.props.barsWidth);
-
- const maxY = max(this.props.data, d => d.y);
- const xScale = scaleBand()
- .domain(this.props.data.map(d => d.x))
- .range([0, availableWidth])
- .paddingInner(relativeInnerPadding);
- const yScale = scaleLinear()
- .domain([0, maxY])
- .range([availableHeight, 0]);
-
- return (
- <svg className="bar-chart" height={this.state.height} width={this.state.width}>
- <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0]})`}>
- {this.renderXTicks(xScale, yScale)}
- {this.renderXValues(xScale, yScale)}
- {this.renderBars(xScale, yScale)}
- </g>
- </svg>
- );
- }
-});
+++ /dev/null
-/*
- * 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 createReactClass from 'create-react-class';
-import PropTypes from 'prop-types';
-import { arc as d3Arc, pie as d3Pie } from 'd3-shape';
-import { ResizeMixin } from './../mixins/resize-mixin';
-
-function Sector(props) {
- const arc = d3Arc()
- .outerRadius(props.radius)
- .innerRadius(props.radius - props.thickness);
- return <path d={arc(props.data)} style={{ fill: props.fill }} />;
-}
-
-export const DonutChart = createReactClass({
- displayName: 'DonutChart',
-
- propTypes: {
- data: PropTypes.arrayOf(PropTypes.object).isRequired
- },
-
- mixins: [ResizeMixin],
-
- getDefaultProps() {
- return { thickness: 6, padding: [0, 0, 0, 0] };
- },
-
- getInitialState() {
- return { width: this.props.width, height: this.props.height };
- },
-
- render() {
- if (!this.state.width || !this.state.height) {
- return <div />;
- }
-
- const availableWidth = this.state.width - this.props.padding[1] - this.props.padding[3];
- const availableHeight = this.state.height - this.props.padding[0] - this.props.padding[2];
-
- const size = Math.min(availableWidth, availableHeight);
- const radius = Math.floor(size / 2);
-
- const pie = d3Pie()
- .sort(null)
- .value(d => d.value);
- const sectors = pie(this.props.data).map((d, i) => {
- return (
- <Sector
- data={d}
- fill={this.props.data[i].fill}
- key={i}
- radius={radius}
- thickness={this.props.thickness}
- />
- );
- });
-
- return (
- <svg className="donut-chart" height={this.state.height} width={this.state.width}>
- <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0]})`}>
- <g transform={`translate(${radius}, ${radius})`}>{sectors}</g>
- </g>
- </svg>
- );
- }
-});
+++ /dev/null
-/*
- * 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 createReactClass from 'create-react-class';
-import PropTypes from 'prop-types';
-import { extent, max } from 'd3-array';
-import { scaleLinear } from 'd3-scale';
-import { area as d3Area, line as d3Line, curveBasis } from 'd3-shape';
-import { ResizeMixin } from './../mixins/resize-mixin';
-
-export const LineChart = createReactClass({
- displayName: 'LineChart',
-
- propTypes: {
- data: PropTypes.arrayOf(PropTypes.object).isRequired,
- xTicks: PropTypes.arrayOf(PropTypes.any),
- xValues: PropTypes.arrayOf(PropTypes.any),
- padding: PropTypes.arrayOf(PropTypes.number),
- backdropConstraints: PropTypes.arrayOf(PropTypes.number),
- displayBackdrop: PropTypes.bool,
- displayPoints: PropTypes.bool,
- displayVerticalGrid: PropTypes.bool,
- height: PropTypes.number
- },
-
- mixins: [ResizeMixin],
-
- getDefaultProps() {
- return {
- displayBackdrop: true,
- displayPoints: true,
- displayVerticalGrid: true,
- xTicks: [],
- xValues: [],
- padding: [10, 10, 10, 10]
- };
- },
-
- getInitialState() {
- return { width: this.props.width, height: this.props.height };
- },
-
- renderBackdrop(xScale, yScale) {
- if (!this.props.displayBackdrop) {
- return null;
- }
-
- const area = d3Area()
- .x(d => xScale(d.x))
- .y0(yScale.range()[0])
- .y1(d => yScale(d.y))
- .defined(d => d.y != null)
- .curve(curveBasis);
-
- let data = this.props.data;
- if (this.props.backdropConstraints) {
- const c = this.props.backdropConstraints;
- data = data.filter(d => c[0] <= d.x && d.x <= c[1]);
- }
- return <path className="line-chart-backdrop" d={area(data)} />;
- },
-
- renderPoints(xScale, yScale) {
- if (!this.props.displayPoints) {
- return null;
- }
- const points = this.props.data.filter(point => point.y != null).map((point, index) => {
- const x = xScale(point.x);
- const y = yScale(point.y);
- return <circle key={index} className="line-chart-point" r="3" cx={x} cy={y} />;
- });
- return <g>{points}</g>;
- },
-
- renderVerticalGrid(xScale, yScale) {
- if (!this.props.displayVerticalGrid) {
- return null;
- }
- const lines = this.props.data.map((point, index) => {
- const x = xScale(point.x);
- const y1 = yScale.range()[0];
- const y2 = yScale(point.y);
- return <line key={index} className="line-chart-grid" x1={x} x2={x} y1={y1} y2={y2} />;
- });
- return <g>{lines}</g>;
- },
-
- renderXTicks(xScale, yScale) {
- if (!this.props.xTicks.length) {
- return null;
- }
- const ticks = this.props.xTicks.map((tick, index) => {
- const point = this.props.data[index];
- const x = xScale(point.x);
- const y = yScale.range()[0];
- return (
- <text key={index} className="line-chart-tick" x={x} y={y} dy="1.5em">
- {tick}
- </text>
- );
- });
- return <g>{ticks}</g>;
- },
-
- renderXValues(xScale, yScale) {
- if (!this.props.xValues.length) {
- return null;
- }
- const ticks = this.props.xValues.map((value, index) => {
- const point = this.props.data[index];
- const x = xScale(point.x);
- const y = yScale(point.y);
- return (
- <text key={index} className="line-chart-tick" x={x} y={y} dy="-1em">
- {value}
- </text>
- );
- });
- return <g>{ticks}</g>;
- },
-
- renderLine(xScale, yScale) {
- const p = d3Line()
- .x(d => xScale(d.x))
- .y(d => yScale(d.y))
- .defined(d => d.y != null)
- .curve(curveBasis);
- return <path className="line-chart-path" d={p(this.props.data)} />;
- },
-
- render() {
- if (!this.state.width || !this.state.height) {
- return <div />;
- }
-
- const availableWidth = this.state.width - this.props.padding[1] - this.props.padding[3];
- const availableHeight = this.state.height - this.props.padding[0] - this.props.padding[2];
-
- let maxY;
- const xScale = scaleLinear()
- .domain(extent(this.props.data, d => d.x))
- .range([0, availableWidth]);
- const yScale = scaleLinear().range([availableHeight, 0]);
-
- if (this.props.domain) {
- maxY = this.props.domain[1];
- yScale.domain(this.props.domain);
- } else {
- maxY = max(this.props.data, d => d.y);
- yScale.domain([0, maxY]);
- }
-
- return (
- <svg className="line-chart" width={this.state.width} height={this.state.height}>
- <g transform={`translate(${this.props.padding[3]}, ${this.props.padding[0]})`}>
- {this.renderVerticalGrid(xScale, yScale, maxY)}
- {this.renderBackdrop(xScale, yScale)}
- {this.renderLine(xScale, yScale)}
- {this.renderPoints(xScale, yScale)}
- {this.renderXTicks(xScale, yScale)}
- {this.renderXValues(xScale, yScale)}
- </g>
- </svg>
- );
- }
-});
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-
-/*::
-type Props = {
- className?: string,
- size?: number
-};
-*/
-
-export default function ClockIcon(props /*: Props */) {
- /* eslint max-len: 0 */
- return (
- <svg
- className={classNames('icon-clock', props.className)}
- viewBox="0 0 16 16"
- width={props.size}
- height={props.size}>
- <g fill="#fff" stroke="#ADADAD" transform="matrix(1.4 0 0 1.4 .3 .7)">
- <circle cx="5.5" cy="5.2" r="5" />
- <path fillRule="nonzero" d="M5.6 2.9v2.7l2-.5" />
- </g>
- </svg>
- );
-}
-
-ClockIcon.defaultProps = {
- size: 16
-};
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-import './LocationIndex.css';
-
-/*::
-type Props = {
- children?: React.Element<*>,
- leading?: boolean,
- onClick?: () => void,
- selected?: boolean
-};
-*/
-
-export default function LocationIndex(props /*: Props */) {
- const { children, leading, onClick, selected, ...other } = props;
- const clickAttributes = onClick ? { onClick, role: 'button', tabIndex: 0 } : {};
-
- // put {...others} because Tooltip sets some event handlers
- return (
- <div
- className={classNames('location-index', { 'is-leading': leading, selected })}
- {...clickAttributes}
- {...other}>
- {children}
- </div>
- );
-}
-
-LocationIndex.defaultProps = {
- selected: false
-};
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+import './LocationIndex.css';
+
+interface Props {
+ children?: React.ReactNode;
+ leading?: boolean;
+ onClick?: () => void;
+ selected?: boolean;
+ [x: string]: any;
+}
+
+export default function LocationIndex(props: Props) {
+ const { children, leading, onClick, selected, ...other } = props;
+ const clickAttributes = onClick ? { onClick, role: 'button', tabIndex: 0 } : {};
+ // put {...others} because Tooltip sets some event handlers
+ return (
+ <div
+ className={classNames('location-index', {
+ 'is-leading': leading,
+ selected
+ })}
+ {...clickAttributes}
+ {...other}>
+ {children}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-import './LocationMessage.css';
-
-/*::
-type Props = {
- children?: React.Element<*>,
- selected: boolean
-};
-*/
-
-export default function LocationMessage(props /*: Props */) {
- return (
- <div className={classNames('location-message', { selected: props.selected })}>
- {props.children}
- </div>
- );
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+import './LocationMessage.css';
+
+interface Props {
+ children?: React.ReactNode;
+ selected: boolean;
+}
+
+export default function LocationMessage(props: Props) {
+ return (
+ <div className={classNames('location-message', { selected: props.selected })}>
+ {props.children}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 Helmet from 'react-helmet';
-
-/*::
-type Props = {
- title: string,
- organization?: ?{ name: string }
-};
-*/
-
-export default function OrganizationHelmet({ title, organization } /*: Props */) {
- const defaultTitle = title + (organization ? ' - ' + organization.name : '');
- return <Helmet defaultTitle={defaultTitle} titleTemplate={'%s - ' + defaultTitle} />;
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import Helmet from 'react-helmet';
+
+interface Props {
+ organization?: { name: string };
+ title: string;
+}
+
+export default function OrganizationHelmet({ title, organization }: Props) {
+ const defaultTitle = title + (organization ? ' - ' + organization.name : '');
+ return <Helmet defaultTitle={defaultTitle} titleTemplate={'%s - ' + defaultTitle} />;
+}
+++ /dev/null
-/*
- * 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 { Link } from 'react-router';
-import { translate, hasMessage } from '../../helpers/l10n';
-import './UpgradeOrganizationBox.css';
-
-/*::
-type Props = {
- organization: string
-};
-*/
-
-export default function UpgradeOrganizationBox(props /*: Props */) {
- return (
- <div className="boxed-group boxed-group-inner upgrade-organization-box">
- <h3 className="spacer-bottom">{translate('billing.upgrade_box.header')}</h3>
-
- <p>{translate('billing.upgrade_box.text')}</p>
-
- {hasMessage('billing.upgrade_box.button') && (
- <div className="big-spacer-top">
- <Link
- className="button"
- to={{
- pathname: `organizations/${props.organization}/extension/billing/billing`,
- query: { page: 'upgrade' }
- }}>
- {translate('billing.upgrade_box.button')}
- </Link>
- </div>
- )}
- </div>
- );
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { Link } from 'react-router';
+import { translate, hasMessage } from '../../helpers/l10n';
+import './UpgradeOrganizationBox.css';
+
+interface Props {
+ organization: string;
+}
+
+export default function UpgradeOrganizationBox({ organization }: Props) {
+ return (
+ <div className="boxed-group boxed-group-inner upgrade-organization-box">
+ <h3 className="spacer-bottom">{translate('billing.upgrade_box.header')}</h3>
+
+ <p>{translate('billing.upgrade_box.text')}</p>
+
+ {hasMessage('billing.upgrade_box.button') && (
+ <div className="big-spacer-top">
+ <Link
+ className="button"
+ to={{
+ pathname: `organizations/${organization}/extension/billing/billing`,
+ query: { page: 'upgrade' }
+ }}>
+ {translate('billing.upgrade_box.button')}
+ </Link>
+ </div>
+ )}
+ </div>
+ );
+}
+++ /dev/null
-/*
- * 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 PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { ERROR, SUCCESS } from '../../store/globalMessages/duck';
-import { Button } from '../ui/buttons';
-
-export default class GlobalMessages extends React.PureComponent {
- static propTypes = {
- messages: PropTypes.arrayOf(
- PropTypes.shape({
- id: PropTypes.string.isRequired,
- message: PropTypes.string.isRequired,
- level: PropTypes.oneOf([ERROR, SUCCESS])
- })
- ),
- closeGlobalMessage: PropTypes.func.isRequired
- };
-
- renderMessage = message => {
- const className = classNames('process-spinner', 'shown', {
- 'process-spinner-failed': message.level === ERROR,
- 'process-spinner-success': message.level === SUCCESS
- });
- return (
- <div className={className} key={message.id}>
- {message.message}
- <Button
- className="process-spinner-close"
- onClick={() => this.props.closeGlobalMessage(message.id)}>
- <i className="icon-close" />
- </Button>
- </div>
- );
- };
-
- render() {
- const { messages } = this.props;
-
- if (messages.length === 0) {
- return null;
- }
-
- return <div className="processes-container">{messages.map(this.renderMessage)}</div>;
- }
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+import { Button } from '../ui/buttons';
+
+interface Message {
+ id: string;
+ level: 'ERROR' | 'SUCCESS';
+ message: string;
+}
+
+interface Props {
+ closeGlobalMessage: (id: string) => void;
+ messages: Message[];
+}
+
+export default class GlobalMessages extends React.PureComponent<Props> {
+ renderMessage = (message: Message) => {
+ const className = classNames('process-spinner', 'shown', {
+ 'process-spinner-failed': message.level === 'ERROR',
+ 'process-spinner-success': message.level === 'SUCCESS'
+ });
+ return (
+ <div className={className} key={message.id}>
+ {message.message}
+ <Button
+ className="process-spinner-close"
+ onClick={() => this.props.closeGlobalMessage(message.id)}>
+ <i className="icon-close" />
+ </Button>
+ </div>
+ );
+ };
+
+ render() {
+ const { messages } = this.props;
+
+ if (messages.length === 0) {
+ return null;
+ }
+
+ return <div className="processes-container">{messages.map(this.renderMessage)}</div>;
+ }
+}
+++ /dev/null
-/*
- * 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 PropTypes from 'prop-types';
-import classNames from 'classnames';
-import { Button } from '../ui/buttons';
-import './styles.css';
-
-export default class Toggle extends React.PureComponent {
- static propTypes = {
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]).isRequired,
- name: PropTypes.string,
- onChange: PropTypes.func
- };
-
- handleClick = value => {
- if (this.props.onChange) {
- this.props.onChange(!value);
- }
- };
-
- render() {
- const { value } = this.props;
- const booleanValue = typeof value === 'string' ? value === 'true' : value;
-
- const className = classNames('boolean-toggle', { 'boolean-toggle-on': booleanValue });
-
- return (
- <Button
- className={className}
- name={this.props.name}
- onClick={() => this.handleClick(booleanValue)}>
- <div className="boolean-toggle-handle" />
- </Button>
- );
- }
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+import { Button } from '../ui/buttons';
+import './styles.css';
+
+export interface Props {
+ name?: string;
+ onChange?: (value: boolean) => void;
+ value: boolean | string;
+}
+
+export default class Toggle extends React.PureComponent<Props> {
+ getValue = () => {
+ const { value } = this.props;
+ return typeof value === 'string' ? value === 'true' : value;
+ };
+
+ handleClick = () => {
+ if (this.props.onChange) {
+ const value = this.getValue();
+ this.props.onChange(!value);
+ }
+ };
+
+ render() {
+ const value = this.getValue();
+ const className = classNames('boolean-toggle', { 'boolean-toggle-on': value });
+
+ return (
+ <Button className={className} name={this.props.name} onClick={this.handleClick}>
+ <div className="boolean-toggle-handle" />
+ </Button>
+ );
+ }
+}
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import ListFooter from '../ListFooter';
-import { click } from '../../../helpers/testUtils';
-
-it('should render "3 of 5 shown"', () => {
- const listFooter = shallow(<ListFooter count={3} total={5} />);
- expect(listFooter.text()).toContain('x_of_y_shown.3.5');
-});
-
-it('should not render "show more"', () => {
- const listFooter = shallow(<ListFooter count={3} total={5} />);
- expect(listFooter.find('a').length).toBe(0);
-});
-
-it('should not render "show more"', () => {
- const listFooter = shallow(<ListFooter count={5} total={5} loadMore={jest.fn()} />);
- expect(listFooter.find('a').length).toBe(0);
-});
-
-it('should "show more"', () => {
- const loadMore = jest.fn();
- const listFooter = shallow(<ListFooter count={3} total={5} loadMore={loadMore} />);
- const link = listFooter.find('a');
- expect(link.length).toBe(1);
- click(link);
- expect(loadMore).toBeCalled();
-});
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import ListFooter from '../ListFooter';
+import { click } from '../../../helpers/testUtils';
+
+it('should render "3 of 5 shown"', () => {
+ const listFooter = shallow(<ListFooter count={3} total={5} />);
+ expect(listFooter.text()).toContain('x_of_y_shown.3.5');
+});
+
+it('should not render "show more"', () => {
+ const listFooter = shallow(<ListFooter count={3} total={5} />);
+ expect(listFooter.find('a').length).toBe(0);
+});
+
+it('should not render "show more"', () => {
+ const listFooter = shallow(<ListFooter count={5} loadMore={jest.fn()} total={5} />);
+ expect(listFooter.find('a').length).toBe(0);
+});
+
+it('should "show more"', () => {
+ const loadMore = jest.fn();
+ const listFooter = shallow(<ListFooter count={3} loadMore={loadMore} total={5} />);
+ const link = listFooter.find('a');
+ expect(link.length).toBe(1);
+ click(link);
+ expect(loadMore).toBeCalled();
+});
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import Toggle from '../Toggle';
-import { click } from '../../../helpers/testUtils';
-
-function getSample(props) {
- return <Toggle onChange={() => true} value={true} {...props} />;
-}
-
-it('should render', () => {
- const Toggle = shallow(getSample());
- expect(Toggle.is('Button')).toBe(true);
-});
-
-it('should call onChange', () => {
- const onChange = jest.fn();
- const Toggle = shallow(getSample({ onChange }));
- click(Toggle);
- expect(onChange).toBeCalledWith(false);
-});
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import Toggle, { Props } from '../Toggle';
+import { click } from '../../../helpers/testUtils';
+
+it('should render', () => {
+ const Toggle = shallowRender();
+ expect(Toggle.is('Button')).toBe(true);
+});
+
+it('should call onChange', () => {
+ const onChange = jest.fn();
+ const Toggle = shallowRender({ onChange });
+ click(Toggle);
+ expect(onChange).toBeCalledWith(false);
+});
+
+function shallowRender(props?: Partial<Props>) {
+ return shallow(<Toggle onChange={() => true} value={true} {...props} />);
+}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { IconProps } from './types';
+
+export default function BugTrackerIcon({ className, fill = 'currentColor', size = 16 }: IconProps) {
+ return (
+ <svg
+ className={className}
+ height={size}
+ version="1.1"
+ viewBox="0 0 16 16"
+ width={size}
+ xmlSpace="preserve"
+ xmlnsXlink="http://www.w3.org/1999/xlink">
+ <path
+ d="M13.5 9.5c1.003.033 1.466 1.952 0 2h-2.618L9.685 9.107 8 14.162 6.096 8.45l-.832 3.05-2.829-.002c-.984-.097-1.369-1.951.065-1.998h1.236l2.168-7.95L8 7.838l1.315-3.945L12.118 9.5H13.5z"
+ style={{ fill }}
+ />
+ </svg>
+ );
+}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+import { IconProps } from './types';
+
+export default function ClockIcon({ className, size = 16 }: IconProps) {
+ return (
+ <svg
+ className={classNames('icon-clock', className)}
+ height={size}
+ version="1.1"
+ viewBox="0 0 16 16"
+ width={size}
+ xmlSpace="preserve"
+ xmlnsXlink="http://www.w3.org/1999/xlink">
+ <g fill="#fff" stroke="#ADADAD" transform="matrix(1.4 0 0 1.4 .3 .7)">
+ <circle cx="5.5" cy="5.2" r="5" />
+ <path d="M5.6 2.9v2.7l2-.5" fillRule="nonzero" />
+ </g>
+ </svg>
+ );
+}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { IconProps } from './types';
+
+export default function PinIcon({ className, fill = 'currentColor', size = 16 }: IconProps) {
+ return (
+ <svg
+ className={className}
+ height={size}
+ version="1.1"
+ viewBox="0 0 16 16"
+ width={size}
+ xmlSpace="preserve"
+ xmlnsXlink="http://www.w3.org/1999/xlink">
+ <path
+ d="M7.25 7.25v-3.5a.243.243 0 0 0-.07-.18A.243.243 0 0 0 7 3.5a.243.243 0 0 0-.18.07.243.243 0 0 0-.07.18v3.5c0 .073.023.133.07.18.047.047.107.07.18.07a.243.243 0 0 0 .18-.07.243.243 0 0 0 .07-.18zM12.5 10a.482.482 0 0 1-.148.352.482.482 0 0 1-.352.148H8.648l-.398 3.773a.29.29 0 0 1-.082.161.219.219 0 0 1-.16.066H8c-.141 0-.224-.07-.25-.211L7.156 10.5H4a.482.482 0 0 1-.352-.148A.482.482 0 0 1 3.5 10c0-.641.204-1.217.613-1.73.409-.513.871-.77 1.387-.77v-4a.96.96 0 0 1-.703-.297A.96.96 0 0 1 4.5 2.5a.96.96 0 0 1 .297-.703A.96.96 0 0 1 5.5 1.5h5a.96.96 0 0 1 .703.297.96.96 0 0 1 .297.703.96.96 0 0 1-.297.703.96.96 0 0 1-.703.297v4c.516 0 .978.257 1.387.77.409.513.613 1.089.613 1.73z"
+ style={{ fill }}
+ />;
+ </svg>
+ );
+}
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should count all code locations 1`] = `
-<LocationIndex
- selected={false}
->
+<LocationIndex>
7
</LocationIndex>
`;
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-
-export default function SeverityIcon(props /*: { severity: ?string, className?: string } */) {
- if (!props.severity) {
- return null;
- }
- const className = classNames('icon-severity-' + props.severity.toLowerCase(), props.className);
- return <i className={className} />;
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+
+interface Props {
+ className?: string;
+ severity: string | null | undefined;
+}
+
+export default function SeverityIcon(props: Props) {
+ if (!props.severity) {
+ return null;
+ }
+ return (
+ <i className={classNames('icon-severity-' + props.severity.toLowerCase(), props.className)} />
+ );
+}
+++ /dev/null
-/*
- * 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 StatusIcon from './StatusIcon';
-import { translate } from '../../helpers/l10n';
-
-export default function StatusHelper(
- props /*: {
- resolution?: string,
- status: string,
- className?: string
-} */
-) {
- const resolution =
- props.resolution != null && ` (${translate('issue.resolution', props.resolution)})`;
- return (
- <span className={props.className}>
- <StatusIcon className="little-spacer-right" status={props.status} />
- {translate('issue.status', props.status)}
- {resolution}
- </span>
- );
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import StatusIcon from './StatusIcon';
+import { translate } from '../../helpers/l10n';
+
+interface Props {
+ className?: string;
+ resolution: string | undefined;
+ status: string;
+}
+
+export default function StatusHelper(props: Props) {
+ const resolution = props.resolution && ` (${translate('issue.resolution', props.resolution)})`;
+ return (
+ <span className={props.className}>
+ <StatusIcon className="little-spacer-right" status={props.status} />
+ {translate('issue.status', props.status)}
+ {resolution}
+ </span>
+ );
+}
+++ /dev/null
-/*
- * 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 classNames from 'classnames';
-
-export default function StatusIcon(props /*: { status: string, className?: string } */) {
- const className = classNames('icon-status-' + props.status.toLowerCase(), props.className);
- return <i className={className} />;
-}
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import * as classNames from 'classnames';
+
+interface Props {
+ className?: string;
+ status: string;
+}
+
+export default function StatusIcon({ className, status }: Props) {
+ return <i className={classNames('icon-status-' + status.toLowerCase(), className)} />;
+}
+++ /dev/null
-/*
- * 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 getStore from '../../app/utils/getStore';
-
-/*::
-type Props = {
- children: React.Element<*>
-};
-*/
-
-export default class WithStore extends React.PureComponent {
- /*:: props: Props; */
- /*:: store: {};
-*/
-
- static childContextTypes = {
- store: PropTypes.object
- };
-
- constructor(props /*: Props */) {
- super(props);
- this.store = getStore();
- }
-
- getChildContext() {
- return { store: this.store };
- }
-
- render() {
- return this.props.children;
- }
-}
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import QualifierIcon from '../QualifierIcon';
-
-it('should render icon', () => {
- expect(shallow(<QualifierIcon qualifier="TRK" />)).toMatchSnapshot();
- expect(shallow(<QualifierIcon qualifier="trk" />)).toMatchSnapshot();
-});
-
-it('should not render icon', () => {
- expect(shallow(<QualifierIcon qualifier={null} />).type()).toBeNull();
-});
-
-it('should render with custom class', () => {
- expect(shallow(<QualifierIcon className="spacer-right" qualifier="TRK" />)).toMatchSnapshot();
-});
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import QualifierIcon from '../QualifierIcon';
+
+it('should render icon', () => {
+ expect(shallow(<QualifierIcon qualifier="TRK" />)).toMatchSnapshot();
+ expect(shallow(<QualifierIcon qualifier="trk" />)).toMatchSnapshot();
+});
+
+it('should not render icon', () => {
+ expect(shallow(<QualifierIcon qualifier={null} />).type()).toBeNull();
+});
+
+it('should render with custom class', () => {
+ expect(shallow(<QualifierIcon className="spacer-right" qualifier="TRK" />)).toMatchSnapshot();
+});
+++ /dev/null
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should render icon 1`] = `
-<i
- className="icon-qualifier-trk"
-/>
-`;
-
-exports[`should render icon 2`] = `
-<i
- className="icon-qualifier-trk"
-/>
-`;
-
-exports[`should render with custom class 1`] = `
-<i
- className="icon-qualifier-trk spacer-right"
-/>
-`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render icon 1`] = `
+<i
+ className="icon-qualifier-trk"
+/>
+`;
+
+exports[`should render icon 2`] = `
+<i
+ className="icon-qualifier-trk"
+/>
+`;
+
+exports[`should render with custom class 1`] = `
+<i
+ className="icon-qualifier-trk spacer-right"
+/>
+`;
+++ /dev/null
-/*
- * 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.
- */
-/* eslint max-len: 0 */
-import React from 'react';
-import * as theme from '../../app/theme';
-
-export default function PinIcon() {
- return (
- <svg width="9" height="14" viewBox="0 0 288 448">
- <path
- fill={theme.darkBlue}
- d="M120 216v-112q0-3.5-2.25-5.75t-5.75-2.25-5.75 2.25-2.25 5.75v112q0 3.5 2.25 5.75t5.75 2.25 5.75-2.25 2.25-5.75zM288 304q0 6.5-4.75 11.25t-11.25 4.75h-107.25l-12.75 120.75q-0.5 3-2.625 5.125t-5.125 2.125h-0.25q-6.75 0-8-6.75l-19-121.25h-101q-6.5 0-11.25-4.75t-4.75-11.25q0-30.75 19.625-55.375t44.375-24.625v-128q-13 0-22.5-9.5t-9.5-22.5 9.5-22.5 22.5-9.5h160q13 0 22.5 9.5t9.5 22.5-9.5 22.5-22.5 9.5v128q24.75 0 44.375 24.625t19.625 55.375z"
- />
- </svg>
- );
-}
+++ /dev/null
-/*
- * 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';
-
-export default function BugTrackerIcon() {
- /* eslint-disable max-len */
- return (
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14" width="14" height="14">
- <g transform="matrix(1,0,0,1,0,1)">
- <path
- style={{
- fill: 'none',
- stroke: 'currentColor',
- strokeWidth: 2,
- strokeLinecap: 'round',
- strokeMiterlimit: '10'
- }}
- d="M12 9h-2L8 5 6.5 9.5l-2-6L3 9H1"
- />
- </g>
- </svg>
- );
-}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { DonutChart } from '../charts/donut-chart';
+import DonutChart from '../charts/DonutChart';
import * as theme from '../../app/theme';
const SIZE_TO_WIDTH_MAPPING = { small: 16, normal: 24, big: 40, huge: 60 };
const width = SIZE_TO_WIDTH_MAPPING[size];
const thickness = SIZE_TO_THICKNESS_MAPPING[size];
- return <DonutChart data={data} width={width} height={width} thickness={thickness} />;
+ return <DonutChart data={data} height={width} thickness={thickness} width={width} />;
}
+++ /dev/null
-/*
- * 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 { shallow } from 'enzyme';
-import React from 'react';
-import Level from '../Level';
-
-it('should render', () => {
- const rating = shallow(<Level level="ERROR" />);
- expect(rating.is('.level-ERROR')).toBe(true);
-});
--- /dev/null
+/*
+ * 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 * as React from 'react';
+import { shallow } from 'enzyme';
+import Level from '../Level';
+
+it('should render', () => {
+ const rating = shallow(<Level level="ERROR" />);
+ expect(rating.is('.level-ERROR')).toBe(true);
+});
disabled?: boolean;
id?: string;
innerRef?: (node: HTMLElement | null) => void;
+ name?: string;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
preventDefault?: boolean;
stopPropagation?: boolean;
+++ /dev/null
-/*
- * 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.
- */
-// Copyright (C) Microsoft Corporation. All rights reserved.
-var XDM, VSS;
-(function(n) {
- function u() {
- return new o();
- }
- function s() {
- return (
- Math.floor(Math.random() * (f - t) + t).toString(36) +
- Math.floor(Math.random() * (f - t) + t).toString(36)
- );
- }
- var i, r, e;
- n.createDeferred = u;
- var o = (function() {
- function n() {
- var n = this;
- this._resolveCallbacks = [];
- this._rejectCallbacks = [];
- this._isResolved = !1;
- this._isRejected = !1;
- this.resolve = function(t) {
- n._resolve(t);
- };
- this.reject = function(t) {
- n._reject(t);
- };
- this.promise = {};
- this.promise.then = function(t, i) {
- return n._then(t, i);
- };
- }
- return (
- (n.prototype._then = function(t, i) {
- var u = this,
- r;
- return (!t && !i) || (this._isResolved && !t) || (this._isRejected && !i)
- ? this.promise
- : ((r = new n()),
- this._resolveCallbacks.push(function(n) {
- u._wrapCallback(t, n, r, !1);
- }),
- this._rejectCallbacks.push(function(n) {
- u._wrapCallback(i, n, r, !0);
- }),
- this._isResolved
- ? this._resolve(this._resolvedValue)
- : this._isRejected && this._reject(this._rejectValue),
- r.promise);
- }),
- (n.prototype._wrapCallback = function(n, t, i, r) {
- if (!n) {
- r ? i.reject(t) : i.resolve(t);
- return;
- }
- var u;
- try {
- u = n(t);
- } catch (f) {
- i.reject(f);
- return;
- }
- u === undefined
- ? i.resolve(t)
- : u && typeof u.then == 'function'
- ? u.then(
- function(n) {
- i.resolve(n);
- },
- function(n) {
- i.reject(n);
- }
- )
- : i.resolve(u);
- }),
- (n.prototype._resolve = function(n) {
- if (
- (this._isRejected ||
- this._isResolved ||
- ((this._isResolved = !0), (this._resolvedValue = n)),
- this._isResolved && this._resolveCallbacks.length > 0)
- ) {
- var t = this._resolveCallbacks.splice(0);
- window.setTimeout(function() {
- for (var i = 0, r = t.length; i < r; i++) t[i](n);
- });
- }
- }),
- (n.prototype._reject = function(n) {
- if (
- (this._isRejected ||
- this._isResolved ||
- ((this._isRejected = !0),
- (this._rejectValue = n),
- this._rejectCallbacks.length === 0 &&
- window.console &&
- window.console.warn &&
- (console.warn('Rejected XDM promise with no reject callbacks'),
- n && console.warn(n))),
- this._isRejected && this._rejectCallbacks.length > 0)
- ) {
- var t = this._rejectCallbacks.splice(0);
- window.setTimeout(function() {
- for (var i = 0, r = t.length; i < r; i++) t[i](n);
- });
- }
- }),
- n
- );
- })(),
- t = parseInt('10000000000', 36),
- f = Number.MAX_SAFE_INTEGER || 9007199254740991;
- i = (function() {
- function n() {
- this._registeredObjects = {};
- }
- return (
- (n.prototype.register = function(n, t) {
- this._registeredObjects[n] = t;
- }),
- (n.prototype.unregister = function(n) {
- delete this._registeredObjects[n];
- }),
- (n.prototype.getInstance = function(n, t) {
- var i = this._registeredObjects[n];
- return i ? (typeof i == 'function' ? i(t) : i) : null;
- }),
- n
- );
- })();
- n.XDMObjectRegistry = i;
- n.globalObjectRegistry = new i();
- r = (function() {
- function t(n, r) {
- r === void 0 && (r = null);
- this._nextMessageId = 1;
- this._deferreds = {};
- this._nextProxyFunctionId = 1;
- this._proxyFunctions = {};
- this._postToWindow = n;
- this._targetOrigin = r;
- this._channelObjectRegistry = new i();
- this._channelId = t._nextChannelId++;
- this._targetOrigin || (this._handshakeToken = s());
- }
- return (
- (t.prototype.getObjectRegistry = function() {
- return this._channelObjectRegistry;
- }),
- (t.prototype.invokeRemoteMethod = function(n, t, i, r, f) {
- var e = {
- id: this._nextMessageId++,
- methodName: n,
- instanceId: t,
- instanceContext: r,
- params: this._customSerializeObject(i, f),
- jsonrpc: '2.0',
- serializationSettings: f
- },
- o;
- return (
- this._targetOrigin || (e.handshakeToken = this._handshakeToken),
- (o = u()),
- (this._deferreds[e.id] = o),
- this._sendRpcMessage(e),
- o.promise
- );
- }),
- (t.prototype.getRemoteObjectProxy = function(n, t) {
- return this.invokeRemoteMethod(null, n, null, t);
- }),
- (t.prototype.invokeMethod = function(n, t) {
- var f = this,
- r,
- u,
- i;
- if (!t.methodName) {
- this._success(t, n, t.handshakeToken);
- return;
- }
- if (((r = n[t.methodName]), typeof r != 'function')) {
- this._error(t, new Error('RPC method not found: ' + t.methodName), t.handshakeToken);
- return;
- }
- try {
- u = [];
- t.params && (u = this._customDeserializeObject(t.params));
- i = r.apply(n, u);
- i && i.then && typeof i.then == 'function'
- ? i.then(
- function(n) {
- f._success(t, n, t.handshakeToken);
- },
- function(n) {
- f._error(t, n, t.handshakeToken);
- }
- )
- : this._success(t, i, t.handshakeToken);
- } catch (e) {
- this._error(t, e, t.handshakeToken);
- }
- }),
- (t.prototype.getRegisteredObject = function(t, i) {
- if (t === '__proxyFunctions') return this._proxyFunctions;
- var r = this._channelObjectRegistry.getInstance(t, i);
- return r || (r = n.globalObjectRegistry.getInstance(t, i)), r;
- }),
- (t.prototype.onMessage = function(n) {
- var u = this,
- t = n,
- i,
- r;
- if (t.instanceId) {
- if (((i = this.getRegisteredObject(t.instanceId, t.instanceContext)), !i)) return !1;
- typeof i.then == 'function'
- ? i.then(
- function(n) {
- u.invokeMethod(n, t);
- },
- function(n) {
- u._error(t, n, t.handshakeToken);
- }
- )
- : this.invokeMethod(i, t);
- } else {
- if (((r = this._deferreds[t.id]), !r)) return !1;
- t.error
- ? r.reject(this._customDeserializeObject([t.error])[0])
- : r.resolve(this._customDeserializeObject([t.result])[0]);
- delete this._deferreds[t.id];
- }
- return !0;
- }),
- (t.prototype.owns = function(n, t, i) {
- var r = i;
- if (this._postToWindow === n) {
- if (this._targetOrigin)
- return t
- ? t.toLowerCase() === 'null' ||
- this._targetOrigin.toLowerCase().indexOf(t.toLowerCase()) === 0
- : !1;
- if (r.handshakeToken && r.handshakeToken === this._handshakeToken)
- return (this._targetOrigin = t), !0;
- }
- return !1;
- }),
- (t.prototype.error = function(n, t) {
- var i = n;
- this._error(i, t, i.handshakeToken);
- }),
- (t.prototype._error = function(n, t, i) {
- var r = {
- id: n.id,
- error: this._customSerializeObject([t], n.serializationSettings)[0],
- jsonrpc: '2.0',
- handshakeToken: i
- };
- this._sendRpcMessage(r);
- }),
- (t.prototype._success = function(n, t, i) {
- var r = {
- id: n.id,
- result: this._customSerializeObject([t], n.serializationSettings)[0],
- jsonrpc: '2.0',
- handshakeToken: i
- };
- this._sendRpcMessage(r);
- }),
- (t.prototype._sendRpcMessage = function(n) {
- var t = JSON.stringify(n);
- this._postToWindow.postMessage(t, '*');
- }),
- (t.prototype._shouldSkipSerialization = function(n) {
- for (var r, i = 0, u = t.WINDOW_TYPES_TO_SKIP_SERIALIZATION.length; i < u; i++)
- if (((r = t.WINDOW_TYPES_TO_SKIP_SERIALIZATION[i]), window[r] && n instanceof window[r]))
- return !0;
- if (window.jQuery)
- for (i = 0, u = t.JQUERY_TYPES_TO_SKIP_SERIALIZATION.length; i < u; i++)
- if (
- ((r = t.JQUERY_TYPES_TO_SKIP_SERIALIZATION[i]),
- window.jQuery[r] && n instanceof window.jQuery[r])
- )
- return !0;
- return !1;
- }),
- (t.prototype._customSerializeObject = function(n, i, r, u, f) {
- var h = this,
- a,
- o,
- l,
- v,
- e,
- c,
- s;
- if (
- (r === void 0 && (r = null),
- u === void 0 && (u = 1),
- f === void 0 && (f = 1),
- !n || f > t.MAX_XDM_DEPTH) ||
- this._shouldSkipSerialization(n)
- )
- return null;
- if (
- ((a = function(t, e, o) {
- var s, c, l, a, v;
- try {
- s = t[o];
- } catch (y) {}
- ((c = typeof s), c !== 'undefined') &&
- ((l = -1),
- c === 'object' && (l = r.originalObjects.indexOf(s)),
- l >= 0
- ? ((a = r.newObjects[l]),
- a.__circularReferenceId || (a.__circularReferenceId = u++),
- (e[o] = { __circularReference: a.__circularReferenceId }))
- : c === 'function'
- ? ((v = h._nextProxyFunctionId++),
- (e[o] = {
- __proxyFunctionId: h._registerProxyFunction(s, n),
- __channelId: h._channelId
- }))
- : c === 'object'
- ? (e[o] =
- s && s instanceof Date
- ? { __proxyDate: s.getTime() }
- : h._customSerializeObject(s, i, r, u, f + 1))
- : o !== '__proxyFunctionId' && (e[o] = s));
- }),
- r || (r = { newObjects: [], originalObjects: [] }),
- r.originalObjects.push(n),
- n instanceof Array)
- )
- for (o = [], r.newObjects.push(o), e = 0, c = n.length; e < c; e++) a(n, o, e);
- else {
- o = {};
- r.newObjects.push(o);
- l = {};
- try {
- for (s in n) l[s] = !0;
- for (v = Object.getOwnPropertyNames(n), e = 0, c = v.length; e < c; e++) l[v[e]] = !0;
- } catch (y) {}
- for (s in l) ((s && s[0] !== '_') || (i && i.includeUnderscoreProperties)) && a(n, o, s);
- }
- return r.originalObjects.pop(), r.newObjects.pop(), o;
- }),
- (t.prototype._registerProxyFunction = function(n, t) {
- var i = this._nextProxyFunctionId++;
- return (
- (this._proxyFunctions['proxy' + i] = function() {
- return n.apply(t, Array.prototype.slice.call(arguments, 0));
- }),
- i
- );
- }),
- (t.prototype._customDeserializeObject = function(n, t) {
- var e = this,
- o = this,
- r,
- i,
- u,
- f;
- if (!n) return null;
- if (
- (t || (t = {}),
- (r = function(n, i) {
- var r = n[i],
- u = typeof r;
- i === '__circularReferenceId' && u === 'number'
- ? ((t[r] = n), delete n[i])
- : u === 'object' &&
- r &&
- (r.__proxyFunctionId
- ? (n[i] = function() {
- return o.invokeRemoteMethod(
- 'proxy' + r.__proxyFunctionId,
- '__proxyFunctions',
- Array.prototype.slice.call(arguments, 0),
- null,
- { includeUnderscoreProperties: !0 }
- );
- })
- : r.__proxyDate
- ? (n[i] = new Date(r.__proxyDate))
- : r.__circularReference
- ? (n[i] = t[r.__circularReference])
- : e._customDeserializeObject(r, t));
- }),
- n instanceof Array)
- )
- for (i = 0, u = n.length; i < u; i++) r(n, i);
- else if (typeof n == 'object') for (f in n) r(n, f);
- return n;
- }),
- (t._nextChannelId = 1),
- (t.MAX_XDM_DEPTH = 100),
- (t.WINDOW_TYPES_TO_SKIP_SERIALIZATION = ['Node', 'Window', 'Event']),
- (t.JQUERY_TYPES_TO_SKIP_SERIALIZATION = ['jQuery']),
- t
- );
- })();
- n.XDMChannel = r;
- e = (function() {
- function n() {
- this._channels = [];
- this._subscribe(window);
- }
- return (
- (n.get = function() {
- return this._default || (this._default = new n()), this._default;
- }),
- (n.prototype.addChannel = function(n, t) {
- var i = new r(n, t);
- return this._channels.push(i), i;
- }),
- (n.prototype.removeChannel = function(n) {
- this._channels = this._channels.filter(function(t) {
- return t !== n;
- });
- }),
- (n.prototype._handleMessageReceived = function(n) {
- var i, e, r, t, u, f;
- if (typeof n.data == 'string')
- try {
- t = JSON.parse(n.data);
- } catch (o) {}
- if (t) {
- for (u = !1, i = 0, e = this._channels.length; i < e; i++)
- (r = this._channels[i]),
- r.owns(n.source, n.origin, t) && ((f = r), (u = r.onMessage(t, n.origin) || u));
- !f ||
- u ||
- (window.console &&
- console.error('No handler found on any channel for message: ' + JSON.stringify(t)),
- t.instanceId &&
- f.error(t, 'The registered object ' + t.instanceId + ' could not be found.'));
- }
- }),
- (n.prototype._subscribe = function(n) {
- var t = this;
- n.addEventListener
- ? n.addEventListener('message', function(n) {
- t._handleMessageReceived(n);
- })
- : n.attachEvent('onmessage', function(n) {
- t._handleMessageReceived(n);
- });
- }),
- n
- );
- })();
- n.XDMChannelManager = e;
-})(XDM || (XDM = {})),
- (function(n) {
- function at() {
- function r() {
- n ||
- (n = setTimeout(function() {
- n = 0;
- tt();
- }, 50));
- }
- var n,
- i = !1,
- t;
- try {
- i = typeof document.cookie == 'string';
- } catch (f) {}
- i ||
- Object.defineProperty(Document.prototype, 'cookie', {
- get: function() {
- return '';
- },
- set: function() {}
- });
- t = !1;
- try {
- t = !!window.localStorage;
- } catch (f) {}
- t ||
- (delete window.localStorage,
- (u = new g(r)),
- Object.defineProperty(window, 'localStorage', { value: u }),
- delete window.sessionStorage,
- Object.defineProperty(window, 'sessionStorage', { value: new g() }));
- }
- function nt(f) {
- r = f || {};
- e = r.usePlatformScripts;
- a = r.usePlatformStyles;
- window.setTimeout(function() {
- var f = {
- notifyLoadSucceeded: !r.explicitNotifyLoaded,
- extensionReusedCallback: r.extensionReusedCallback,
- vssSDKVersion: n.VssSDKVersion
- };
- i.invokeRemoteMethod('initialHandshake', 'VSS.HostControl', [f]).then(function(n) {
- var f, r, o, h, l, s, v, i;
- if (
- ((t = n.pageContext),
- (b = t.webContext),
- (k = n.initialConfig || {}),
- (d = n.contribution),
- (c = n.extensionContext),
- n.sandboxedStorage)
- ) {
- if (((f = !1), u))
- if (n.sandboxedStorage.localStorage) {
- for (
- r = n.sandboxedStorage.localStorage, o = 0, h = Object.keys(u);
- o < h.length;
- o++
- )
- (i = h[o]), (l = u.getItem(i)), l !== r[i] && ((r[i] = l), (f = !0));
- for (s = 0, v = Object.keys(r); s < v.length; s++) (i = v[s]), u.setItem(i, r[i]);
- } else u.length > 0 && (f = !0);
- lt = !0;
- f && tt();
- }
- e || a ? ht() : w();
- });
- }, 0);
- }
- function tt() {
- var n = { localStorage: JSON.stringify(u || {}) };
- i.invokeRemoteMethod('updateSandboxedStorage', 'VSS.HostControl', [n]);
- }
- function pt(n, t) {
- var i;
- i = typeof n == 'string' ? [n] : n;
- t || (t = function() {});
- l
- ? it(i, t)
- : (r ? e || ((e = !0), s && ((s = !1), ht())) : nt({ usePlatformScripts: !0 }),
- rt(function() {
- it(i, t);
- }));
- }
- function it(n, i) {
- t.diagnostics.bundlingEnabled
- ? window.require(['VSS/Bundling'], function(t) {
- t.requireModules(n).spread(function() {
- i.apply(this, arguments);
- });
- })
- : window.require(n, i);
- }
- function rt(n) {
- s ? window.setTimeout(n, 0) : (f || (f = []), f.push(n));
- }
- function wt() {
- i.invokeRemoteMethod('notifyLoadSucceeded', 'VSS.HostControl');
- }
- function ut(n) {
- i.invokeRemoteMethod('notifyLoadFailed', 'VSS.HostControl', [n]);
- }
- function ft() {
- return b;
- }
- function bt() {
- return k;
- }
- function et() {
- return c;
- }
- function kt() {
- return d;
- }
- function dt(n, t) {
- return ot(n).then(function(n) {
- return (
- t || (t = {}),
- t.webContext || (t.webContext = ft()),
- t.extensionContext || (t.extensionContext = et()),
- n.getInstance(n.id, t)
- );
- });
- }
- function ot(t) {
- var r = XDM.createDeferred();
- return (
- n.ready(function() {
- i
- .invokeRemoteMethod('getServiceContribution', 'vss.hostManagement', [t])
- .then(function(n) {
- var t = n;
- t.getInstance = function(t, i) {
- return st(n, t, i);
- };
- r.resolve(t);
- }, r.reject);
- }),
- r.promise
- );
- }
- function gt(t) {
- var r = XDM.createDeferred();
- return (
- n.ready(function() {
- i
- .invokeRemoteMethod('getContributionsForTarget', 'vss.hostManagement', [t])
- .then(function(n) {
- var t = [];
- n.forEach(function(n) {
- var i = n;
- i.getInstance = function(t, i) {
- return st(n, t, i);
- };
- t.push(i);
- });
- r.resolve(t);
- }, r.reject);
- }),
- r.promise
- );
- }
- function st(t, r, u) {
- var f = XDM.createDeferred();
- return (
- n.ready(function() {
- i
- .invokeRemoteMethod('getBackgroundContributionInstance', 'vss.hostManagement', [
- t,
- r,
- u
- ])
- .then(f.resolve, f.reject);
- }),
- f.promise
- );
- }
- function ni(n, t) {
- i.getObjectRegistry().register(n, t);
- }
- function ti(n) {
- i.getObjectRegistry().unregister(n);
- }
- function ii(n, t) {
- return i.getObjectRegistry().getInstance(n, t);
- }
- function ri() {
- return i.invokeRemoteMethod('getAccessToken', 'VSS.HostControl');
- }
- function ui() {
- return i.invokeRemoteMethod('getAppToken', 'VSS.HostControl');
- }
- function fi(n, t) {
- o || (o = document.getElementsByTagName('body').item(0));
- var r = typeof n == 'number' ? n : o.scrollWidth,
- u = typeof t == 'number' ? t : o.scrollHeight;
- i.invokeRemoteMethod('resize', 'VSS.HostControl', [r, u]);
- }
- function ht() {
- var i = si(t.webContext),
- f,
- g,
- n,
- s,
- o,
- b,
- k,
- nt,
- tt,
- d,
- u;
- if (
- ((window.__vssPageContext = t),
- (window.__cultureInfo = t.microsoftAjaxConfig.cultureInfo),
- a !== !1 &&
- t.coreReferences.stylesheets &&
- t.coreReferences.stylesheets.forEach(function(n) {
- if (n.isCoreStylesheet) {
- var t = document.createElement('link');
- t.href = h(n.url, i);
- t.rel = 'stylesheet';
- p(t, 'head');
- }
- }),
- !e)
- ) {
- l = !0;
- w();
- return;
- }
- if (
- ((f = []),
- (g = !1),
- t.coreReferences.scripts &&
- (t.coreReferences.scripts.forEach(function(n) {
- if (n.isCoreModule) {
- var r = !1,
- t = window;
- n.identifier === 'JQuery'
- ? (r = !!t.jQuery)
- : n.identifier === 'JQueryUI'
- ? (r = !!(t.jQuery && t.jQuery.ui && t.jQuery.ui.version))
- : n.identifier === 'AMDLoader' &&
- (r = typeof t.define == 'function' && !!t.define.amd);
- r ? (g = !0) : f.push({ source: h(n.url, i) });
- }
- }),
- t.coreReferences.coreScriptsBundle &&
- !g &&
- (f = [{ source: h(t.coreReferences.coreScriptsBundle.url, i) }]),
- t.coreReferences.extensionCoreReferences &&
- f.push({ source: h(t.coreReferences.extensionCoreReferences.url, i) })),
- (n = { baseUrl: c.baseUri, contributionPaths: null, paths: {}, shim: {} }),
- r.moduleLoaderConfig &&
- (r.moduleLoaderConfig.baseUrl && (n.baseUrl = r.moduleLoaderConfig.baseUrl),
- oi(r.moduleLoaderConfig, n),
- ct(r.moduleLoaderConfig, n)),
- t.moduleLoaderConfig &&
- (ct(t.moduleLoaderConfig, n), (s = t.moduleLoaderConfig.contributionPaths), s))
- )
- for (o in s)
- if (
- s.hasOwnProperty(o) &&
- !n.paths[o] &&
- ((b = s[o].value),
- (n.paths[o] = b.match('^https?://') ? b : i + b),
- (k = t.moduleLoaderConfig.paths),
- k)
- ) {
- nt = o + '/';
- tt = v(i, t.moduleLoaderConfig.baseUrl);
- for (d in k)
- ei(d, nt) &&
- ((u = k[d]),
- u.match('^https?://') || (u = u[0] === '/' ? v(i, u) : v(tt, u)),
- (n.paths[d] = u));
- }
- window.__vssModuleLoaderConfig = n;
- f.push({ content: 'require.config(' + JSON.stringify(n) + ');' });
- y(f, 0, function() {
- l = !0;
- w();
- });
- }
- function ei(n, t) {
- return n && n.length >= t.length ? n.substr(0, t.length).localeCompare(t) === 0 : !1;
- }
- function v(n, t) {
- var i = n || '';
- return i[i.length - 1] !== '/' && (i += '/'), t && (i += t[0] === '/' ? t.substr(1) : t), i;
- }
- function oi(n, t, i) {
- var r, u;
- if (n.paths) {
- t.paths || (t.paths = {});
- for (r in n.paths)
- n.paths.hasOwnProperty(r) &&
- ((u = n.paths[r]), i && (u = i(r, n.paths[r])), u && (t.paths[r] = u));
- }
- }
- function ct(n, t) {
- if (n.shim) {
- t.shim || (t.shim = {});
- for (var i in n.shim) n.shim.hasOwnProperty(i) && (t.shim[i] = n.shim[i]);
- }
- }
- function si(n) {
- var r = n.account || n.host,
- t = r.uri,
- i = r.relativeUri;
- return (
- t &&
- i &&
- (t[t.length - 1] !== '/' && (t += '/'),
- i[i.length - 1] !== '/' && (i += '/'),
- (t = t.substr(0, t.length - i.length))),
- t
- );
- }
- function y(n, t, i) {
- var f = this,
- r,
- u;
- if (t >= n.length) {
- i.call(this);
- return;
- }
- r = document.createElement('script');
- r.type = 'text/javascript';
- n[t].source
- ? ((u = n[t].source),
- (r.src = u),
- r.addEventListener('load', function() {
- y.call(f, n, t + 1, i);
- }),
- r.addEventListener('error', function() {
- ut('Failed to load script: ' + u);
- }),
- p(r, 'head'))
- : n[t].content && ((r.textContent = n[t].content), p(r, 'head'), y.call(this, n, t + 1, i));
- }
- function p(n, t) {
- var i = document.getElementsByTagName(t)[0];
- i || ((i = document.createElement(t)), document.appendChild(i));
- i.appendChild(n);
- }
- function h(n, t) {
- var i = (n || '').toLowerCase();
- return (
- i.substr(0, 2) !== '//' &&
- i.substr(0, 5) !== 'http:' &&
- i.substr(0, 6) !== 'https:' &&
- (n = t + (i[0] === '/' ? '' : '/') + n),
- n
- );
- }
- function w() {
- var t = this,
- n;
- s = !0;
- f &&
- ((n = f),
- (f = null),
- n.forEach(function(n) {
- n.call(t);
- }));
- }
- var yt;
- n.VssSDKVersion = 2;
- n.VssSDKRestVersion = '4.0';
- var o,
- b,
- t,
- c,
- k,
- d,
- r,
- l = !1,
- e,
- a,
- s = !1,
- f,
- i = XDM.XDMChannelManager.get().addChannel(window.parent),
- u,
- lt = !1,
- g = (function() {
- function n() {
- t && t.call(this);
- }
- function i() {}
- var t;
- return (
- Object.defineProperties(i.prototype, {
- getItem: {
- get: function() {
- return function(n) {
- var t = this['' + n];
- return typeof t == 'undefined' ? null : t;
- };
- }
- },
- setItem: {
- get: function() {
- return function(t, i) {
- t = '' + t;
- var u = this[t],
- r = '' + i;
- u !== r && ((this[t] = r), n());
- };
- }
- },
- removeItem: {
- get: function() {
- return function(t) {
- t = '' + t;
- typeof this[t] != 'undefined' && (delete this[t], n());
- };
- }
- },
- clear: {
- get: function() {
- return function() {
- var r = Object.keys(this),
- t,
- i,
- u;
- if (r.length > 0) {
- for (t = 0, i = r; t < i.length; t++) (u = i[t]), delete this[u];
- n();
- }
- };
- }
- },
- key: {
- get: function() {
- return function(n) {
- return Object.keys(this)[n];
- };
- }
- },
- length: {
- get: function() {
- return Object.keys(this).length;
- }
- }
- }),
- i
- );
- })();
- if (!window.__vssNoSandboxShim)
- try {
- at();
- } catch (vt) {
- window.console &&
- window.console.warn &&
- window.console.warn(
- 'Failed to shim support for sandboxed properties: ' +
- vt.message +
- '. Set "window.__vssNoSandboxShim = true" in order to bypass the shim of sandboxed properties.'
- );
- }
- (function(n) {
- n.Dialog = 'ms.vss-web.dialog-service';
- n.Navigation = 'ms.vss-web.navigation-service';
- n.ExtensionData = 'ms.vss-web.data-service';
- })((yt = n.ServiceIds || (n.ServiceIds = {})));
- n.init = nt;
- n.require = pt;
- n.ready = rt;
- n.notifyLoadSucceeded = wt;
- n.notifyLoadFailed = ut;
- n.getWebContext = ft;
- n.getConfiguration = bt;
- n.getExtensionContext = et;
- n.getContribution = kt;
- n.getService = dt;
- n.getServiceContribution = ot;
- n.getServiceContributions = gt;
- n.register = ni;
- n.unregister = ti;
- n.getRegisteredObject = ii;
- n.getAccessToken = ri;
- n.getAppToken = ui;
- n.resize = fi;
- })(VSS || (VSS = {}));
+++ /dev/null
-/*
- * 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.
- */
-declare module '*.json' {
- const value: any;
- export default value;
-}
+++ /dev/null
-/*
- * 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.
- */
-declare module 'rc-tooltip' {
- export type Trigger = 'hover' | 'click' | 'focus';
- export type Placement =
- | 'left'
- | 'right'
- | 'top'
- | 'bottom'
- | 'topLeft'
- | 'topRight'
- | 'bottomLeft'
- | 'bottomRight';
-
- export interface Props extends React.Props<any> {
- overlayClassName?: string;
- trigger?: Trigger[];
- mouseEnterDelay?: number;
- mouseLeaveDelay?: number;
- overlayStyle?: React.CSSProperties;
- prefixCls?: string;
- transitionName?: string;
- onVisibleChange?: () => void;
- visible?: boolean;
- defaultVisible?: boolean;
- placement?: Placement | Object;
- align?: Object;
- onPopupAlign?: (popupDomNode: Element, align: Object) => void;
- overlay: React.ReactNode;
- arrowContent?: React.ReactNode;
- getTooltipContainer?: () => Element;
- destroyTooltipOnHide?: boolean;
- }
-
- // the next line is crucial, it is absent in the original typings
- export default class Tooltip extends React.Component<Props> {}
-}
version "1.2.1"
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-1.2.1.tgz#e489605208d46a1c9d980d2e5772fa9c75d9ec65"
+"@types/d3-hierarchy@1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-1.1.1.tgz#f1b7f4bab0a9ecfb9c372a303ded97d83db3cbbf"
+
+"@types/d3-path@*":
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.6.tgz#c1a7d2dc07b295fdd1c84dabe4404df991b48693"
+
"@types/d3-scale@2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-2.0.0.tgz#d40f2ff137f4fe9b13b45c5a8e14f39edd498dcf"
dependencies:
"@types/d3-time" "*"
+"@types/d3-shape@1.2.2":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-1.2.2.tgz#f8dcdff7772a7ae37858bf04abd43848a78e590e"
+ dependencies:
+ "@types/d3-path" "*"
+
"@types/d3-time@*":
version "1.0.7"
resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-1.0.7.tgz#4266d7c9be15fa81256a88d1d052d61cd8dc572c"