],
"rules": {
- "quotes": [ 2, "single", "avoid-escape" ],
- "react/jsx-uses-react": 1
+ "quotes": [2, "single", "avoid-escape"],
+
+ "react/jsx-closing-bracket-location": [1, "after-props"],
+ "react/jsx-handler-names": 0,
+ "react/jsx-key": 2,
+ "react/jsx-max-props-per-line": [1, { "maximum": 3 }],
+ "react/jsx-no-duplicate-props": 2,
+ "react/jsx-no-undef": 2,
+ "react/jsx-pascal-case": 1,
+ "react/jsx-uses-react": 1,
+ "react/jsx-uses-vars": 2,
+ "react/no-did-mount-set-state": [2, "allow-in-func"],
+ "react/no-did-update-set-state": [2, "allow-in-func"],
+ "react/no-direct-mutation-state": 2,
+ "react/no-multi-comp": 0,
+ "react/no-unknown-property": 2,
+ "react/prop-types": 0,
+ "react/react-in-jsx-scope": 2,
+ "react/self-closing-comp": 2,
+ "react/sort-comp": 1
}
}
import { STATUSES, CURRENTS, DATE, DATE_FORMAT } from './constants';
export default React.createClass({
- componentDidUpdate() {
+ componentDidMount() {
this.attachDatePicker();
},
- componentDidMount() {
+ componentDidUpdate() {
this.attachDatePicker();
},
<button className="search-box-submit button-clean">
<i className="icon-search"></i>
</button>
- <input onChange={this.onSearch} value={this.props.searchQuery} ref="searchInput" className="search-box-input"
- type="search" placeholder="Search"/>
+ <input onChange={this.onSearch}
+ value={this.props.searchQuery}
+ ref="searchInput"
+ className="search-box-input"
+ type="search"
+ placeholder="Search"/>
</form>
);
},
if (this.props.failuresCount > 0) {
return (
<span>
- <a ref="failureCount" onClick={this.onFailuresClick} className="emphasised-measure" data-toggle="tooltip"
+ <a ref="failureCount"
+ onClick={this.onFailuresClick}
+ className="emphasised-measure"
+ data-toggle="tooltip"
title="Count of projects where processing of most recent analysis report failed"
href="#">{this.props.failuresCount}</a>
export default React.createClass({
- mixins: [TooltipsMixin],
-
propTypes: {
tasks: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
},
+ mixins: [TooltipsMixin],
+
onTaskCanceled (task, e) {
e.preventDefault();
this.props.onTaskCanceled(task);
}
metrics = metrics.map(metric => {
- return <DetailedMeasure key={metric.key} {...this.props} {...this.props} metric={metric.key}
+ return <DetailedMeasure key={metric.key}
+ {...this.props}
+ {...this.props}
+ metric={metric.key}
type={metric.type}/>;
});
return <div className="overview-detailed-measures-list">{metrics}</div>;
<div className="overview-detailed-measure-leak">
<span className="overview-detailed-measure-value">
<span className="spacer-right">
- <DonutChart width="30" height="30" thickness="4" data={donutData}/>
+ <DonutChart width="30"
+ height="30"
+ thickness="4"
+ data={donutData}/>
</span>
<DrilldownLink component={this.props.component.key}
metric={newCoverageMetricName}
{ value: coverage, fill: '#85bb43' },
{ value: 100 - coverage, fill: '#d4333f' }
];
- return <DonutChart width="30" height="30" thickness="4" data={donutData}/>;
+ return <DonutChart width="30"
+ height="30"
+ thickness="4"
+ data={donutData}/>;
},
render() {
export const Event = React.createClass({
- mixins: [TooltipsMixin],
-
propTypes: {
event: React.PropTypes.shape({
id: React.PropTypes.string.isRequired,
})
},
+ mixins: [TooltipsMixin],
+
render () {
const { event } = this.props;
return <li className="spacer-top">
export const Timeline = React.createClass({
- mixins: [ResizeMixin, TooltipsMixin],
-
propTypes: {
data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
padding: React.PropTypes.arrayOf(React.PropTypes.number),
interpolate: React.PropTypes.string
},
+ mixins: [ResizeMixin, TooltipsMixin],
+
getDefaultProps() {
return {
padding: [10, 10, 10, 10],
let nextTick = index + 1 < ticks.length ? ticks[index + 1] : xScale.domain()[1];
let x = (xScale(tick) + xScale(nextTick)) / 2;
let y = yScale.range()[0];
- return <text key={index} className="line-chart-tick" x={x} y={y} dy="1.5em">{format(tick)}</text>;
+ return <text key={index}
+ className="line-chart-tick"
+ x={x}
+ y={y}
+ dy="1.5em">{format(tick)}</text>;
});
return <g>{ticks}</g>;
},
},
renderLine (xScale, yScale) {
- let path = d3.svg.line()
+ let p = d3.svg.line()
.x(d => xScale(d.x))
.y(d => yScale(d.y))
.interpolate(this.props.interpolate);
- return <path className="line-chart-path" d={path(this.props.data)}/>;
+ return <path className="line-chart-path" d={p(this.props.data)}/>;
},
renderEvents(xScale, yScale) {
.filter(metric => KNOWN_METRICS.indexOf(metric.key) === -1)
.filter(metric => this.state.measures[metric.key] != null)
.map(metric => {
- return <DetailedMeasure key={metric.key} {...this.props} {...this.state} metric={metric.key}
+ return <DetailedMeasure key={metric.key}
+ {...this.props}
+ {...this.state}
+ metric={metric.key}
type={metric.type}/>;
});
if (!metrics.length) {
let metrics = filterMetricsForDomains(this.props.metrics, ['Duplication'])
.filter(metric => metric.key !== 'duplicated_lines_density')
.map(metric => {
- return <DetailedMeasure key={metric.key} {...this.props} {...this.state} metric={metric.key}
+ return <DetailedMeasure key={metric.key}
+ {...this.props}
+ {...this.state}
+ metric={metric.key}
type={metric.type}/>;
});
return <div>{metrics}</div>;
{ value: duplications, fill: '#f3ca8e' },
{ value: Math.max(0, 20 - duplications), fill: '#e6e6e6' }
];
- return <DonutChart width="30" height="30" thickness="4" data={donutData}/>;
+ return <DonutChart width="30"
+ height="30"
+ thickness="4"
+ data={donutData}/>;
},
renderDuplicationsLeak() {
let metrics = filterMetricsForDomains(this.props.metrics, [domain])
.filter(metric => hiddenMetrics.indexOf(metric.key) === -1)
.map(metric => {
- return <DetailedMeasure key={metric.key} {...this.props} {...this.state} metric={metric.key}
+ return <DetailedMeasure key={metric.key}
+ {...this.props}
+ {...this.state}
+ metric={metric.key}
type={metric.type}/>;
});
return <div>{metrics}</div>;
return <div className="overview-detailed-layout-column">
<div className="overview-detailed-measures-list">
- <DetailedMeasure {...this.props} {...this.state} metric="complexity" type="INT"/>
- <DetailedMeasure {...this.props} {...this.state} metric="function_complexity" type="FLOAT">
+ <DetailedMeasure {...this.props}
+ {...this.state}
+ metric="complexity"
+ type="INT"/>
+ <DetailedMeasure {...this.props}
+ {...this.state}
+ metric="function_complexity"
+ type="FLOAT">
{this.renderComplexityDistribution(this.state.measures['function_complexity_distribution'],
{ of: 'function' })}
</DetailedMeasure>
- <DetailedMeasure {...this.props} {...this.state} metric="file_complexity" type="FLOAT">
+ <DetailedMeasure {...this.props}
+ {...this.state}
+ metric="file_complexity"
+ type="FLOAT">
{this.renderComplexityDistribution(this.state.measures['file_complexity_distribution'],
{ of: 'file' })}
</DetailedMeasure>
- <DetailedMeasure {...this.props} {...this.state} metric="class_complexity" type="FLOAT"/>
+ <DetailedMeasure {...this.props}
+ {...this.state}
+ metric="class_complexity"
+ type="FLOAT"/>
{this.renderOtherComplexityMeasures()}
</div>
</div>;
<div className="overview-detailed-layout-size">
<div className="overview-detailed-layout-column">
<div className="overview-detailed-measures-list">
- <DetailedMeasure {...this.props} {...this.state} metric="ncloc" type="INT">
+ <DetailedMeasure {...this.props}
+ {...this.state}
+ metric="ncloc"
+ type="INT">
{this.renderLanguageDistribution()}
</DetailedMeasure>
{this.renderOtherSizeMeasures()}
export const GeneralCoverage = React.createClass({
- mixins: [TooltipsMixin, DomainMixin],
-
propTypes: {
measures: React.PropTypes.object.isRequired,
leakPeriodLabel: React.PropTypes.string,
coverageMetricPrefix: React.PropTypes.string.isRequired
},
+ mixins: [TooltipsMixin, DomainMixin],
+
getCoverageMetric () {
return this.props.coverageMetricPrefix + 'coverage';
},
<Measure composite={true}>
<div className="display-inline-block text-middle big-spacer-right">
- <DonutChart width="40" height="40" thickness="4" data={donutData}/>
+ <DonutChart width="40"
+ height="40"
+ thickness="4"
+ data={donutData}/>
</div>
<div className="display-inline-block text-middle">
<div className="overview-domain-measure-value">
export const GeneralDuplications = React.createClass({
- mixins: [TooltipsMixin, DomainMixin],
-
propTypes: {
leakPeriodLabel: React.PropTypes.string,
leakPeriodDate: React.PropTypes.object
},
+ mixins: [TooltipsMixin, DomainMixin],
+
renderLeak () {
if (!this.hasLeakPeriod()) {
return null;
<Measure composite={true}>
<div className="display-inline-block text-middle big-spacer-right">
- <DonutChart width="40" height="40" thickness="4" data={donutData}/>
+ <DonutChart width="40"
+ height="40"
+ thickness="4"
+ data={donutData}/>
</div>
<div className="display-inline-block text-middle">
<div className="overview-domain-measure-value">
export const GeneralIssues = React.createClass({
- mixins: [TooltipsMixin, DomainMixin],
-
propTypes: {
leakPeriodLabel: React.PropTypes.string,
leakPeriodDate: React.PropTypes.object
},
+ mixins: [TooltipsMixin, DomainMixin],
+
renderLeak () {
if (!this.hasLeakPeriod()) {
return null;
export default React.createClass({
- mixins: [CoverageSelectionMixin],
-
propTypes: {
leakPeriodIndex: React.PropTypes.string.isRequired
},
+ mixins: [CoverageSelectionMixin],
+
getInitialState() {
return {
ready: false,
export const GeneralSize = React.createClass({
- mixins: [TooltipsMixin, DomainMixin],
-
propTypes: {
leakPeriodLabel: React.PropTypes.string,
leakPeriodDate: React.PropTypes.object
},
+ mixins: [TooltipsMixin, DomainMixin],
+
renderLeak () {
if (!this.hasLeakPeriod()) {
return null;
<button className="search-box-submit button-clean">
<i className="icon-search"></i>
</button>
- <input onChange={this.search} ref="input" className="search-box-input" type="search" placeholder="Search"/>
+ <input onChange={this.search}
+ ref="input"
+ className="search-box-input"
+ type="search"
+ placeholder="Search"/>
</form>
</div>
);
<button className="search-box-submit button-clean">
<i className="icon-search"></i>
</button>
- <input onChange={this.search} value={this.props.query} ref="input" className="search-box-input"
- type="search" placeholder="Search"/>
+ <input onChange={this.search}
+ value={this.props.query}
+ ref="input"
+ className="search-box-input"
+ type="search"
+ placeholder="Search"/>
</form>
</td>
<td className="thin text-middle">
import { TooltipsMixin } from './../mixins/tooltips-mixin';
export const BarChart = React.createClass({
- mixins: [ResizeMixin, TooltipsMixin],
-
propTypes: {
data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
xTicks: React.PropTypes.arrayOf(React.PropTypes.any),
barsWidth: React.PropTypes.number
},
+ mixins: [ResizeMixin, TooltipsMixin],
+
getDefaultProps() {
return {
xTicks: [],
tooltipAtts['title'] = d.tooltip;
tooltipAtts['data-toggle'] = 'tooltip';
}
- return <text key={index} className="bar-chart-tick" x={x} y={y} dy="1.5em" {...tooltipAtts}>{tick}</text>;
+ return <text key={index}
+ className="bar-chart-tick"
+ x={x}
+ y={y}
+ dy="1.5em"
+ {...tooltipAtts}>{tick}</text>;
});
return <g>{ticks}</g>;
},
tooltipAtts['title'] = d.tooltip;
tooltipAtts['data-toggle'] = 'tooltip';
}
- return <text key={index} className="bar-chart-tick" x={x} y={y} dy="-1em" {...tooltipAtts}>{value}</text>;
+ return <text key={index}
+ className="bar-chart-tick"
+ x={x}
+ y={y}
+ dy="-1em"
+ {...tooltipAtts}>{value}</text>;
});
return <g>{ticks}</g>;
},
tooltipAtts['title'] = d.tooltip;
tooltipAtts['data-toggle'] = 'tooltip';
}
- return <rect key={index} className="bar-chart-bar" {...tooltipAtts}
- x={x} y={y} width={this.props.barsWidth} height={height}/>;
+ return <rect key={index}
+ className="bar-chart-bar"
+ {...tooltipAtts}
+ x={x}
+ y={y}
+ width={this.props.barsWidth}
+ height={height}/>;
});
return <g>{bars}</g>;
},
export const BubbleChart = React.createClass({
- mixins: [ResizeMixin, TooltipsMixin],
-
propTypes: {
items: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
sizeRange: React.PropTypes.arrayOf(React.PropTypes.number),
formatYTick: React.PropTypes.func
},
+ mixins: [ResizeMixin, TooltipsMixin],
+
getDefaultProps() {
return {
sizeRange: [5, 45],
let x = xScale(tick);
let y1 = yScale.range()[0];
let y2 = yScale.range()[1];
- return <line key={index} x1={x} x2={x} y1={y1} y2={y2} className="bubble-chart-grid"/>;
+ return <line key={index}
+ x1={x}
+ x2={x}
+ y1={y1}
+ y2={y2}
+ className="bubble-chart-grid"/>;
});
return <g ref="xGrid">{lines}</g>;
let y = yScale(tick);
let x1 = xScale.range()[0];
let x2 = xScale.range()[1];
- return <line key={index} x1={x1} x2={x2} y1={y} y2={y} className="bubble-chart-grid"/>;
+ return <line key={index}
+ x1={x1}
+ x2={x2}
+ y1={y}
+ y2={y}
+ className="bubble-chart-grid"/>;
});
return <g ref="yGrid">{lines}</g>;
let ticks = xScale.ticks().map((tick, index) => {
let x = xScale(tick);
let y = yScale.range()[0];
- let text = this.props.formatXTick(tick);
- return <text key={index} className="bubble-chart-tick" x={x} y={y} dy="1.5em">{text}</text>;
+ let innerText = this.props.formatXTick(tick);
+ return <text key={index}
+ className="bubble-chart-tick"
+ x={x}
+ y={y}
+ dy="1.5em">{innerText}</text>;
});
return <g>{ticks}</g>;
let ticks = yScale.ticks(5).map((tick, index) => {
let x = xScale.range()[0];
let y = yScale(tick);
- let text = this.props.formatYTick(tick);
- return <text key={index} className="bubble-chart-tick bubble-chart-tick-y"
- x={x} y={y} dx="-0.5em" dy="0.3em">{text}</text>;
+ let innerText = this.props.formatYTick(tick);
+ return <text key={index}
+ className="bubble-chart-tick bubble-chart-tick-y"
+ x={x}
+ y={y}
+ dx="-0.5em"
+ dy="0.3em">{innerText}</text>;
});
return <g>{ticks}</g>;
export const DonutChart = React.createClass({
- mixins: [ResizeMixin, TooltipsMixin],
-
propTypes: {
data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
},
+ mixins: [ResizeMixin, TooltipsMixin],
+
getDefaultProps() {
return { thickness: 6, padding: [0, 0, 0, 0] };
},
.sort(null)
.value(d => d.value);
let sectors = pie(this.props.data).map((d, i) => {
- return <Sector key={i} data={d} radius={radius} fill={this.props.data[i].fill} thickness={this.props.thickness}/>;
+ return <Sector key={i}
+ data={d}
+ radius={radius}
+ fill={this.props.data[i].fill}
+ thickness={this.props.thickness}/>;
});
return <svg className="donut-chart" width={this.state.width} height={this.state.height}>
import { TooltipsMixin } from './../mixins/tooltips-mixin';
export const Histogram = React.createClass({
- mixins: [ResizeMixin, TooltipsMixin],
-
propTypes: {
data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
yTicks: React.PropTypes.arrayOf(React.PropTypes.any),
onBarClick: React.PropTypes.func
},
+ mixins: [ResizeMixin, TooltipsMixin],
+
getDefaultProps() {
return {
xTicks: [],
export const LineChart = React.createClass({
- mixins: [ResizeMixin, TooltipsMixin],
-
propTypes: {
data: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
xTicks: React.PropTypes.arrayOf(React.PropTypes.any),
interpolate: React.PropTypes.string
},
+ mixins: [ResizeMixin, TooltipsMixin],
+
getDefaultProps() {
return {
displayBackdrop: true,
let points = this.props.data.map((point, index) => {
let x = xScale(point.x);
let y = yScale(point.y);
- return <circle key={index} className="line-chart-point" r="3" cx={x} cy={y}/>;
+ return <circle key={index}
+ className="line-chart-point"
+ r="3"
+ cx={x}
+ cy={y}/>;
});
return <g>{points}</g>;
},
let x = xScale(point.x);
let y1 = yScale.range()[0];
let y2 = yScale(point.y);
- return <line key={index} className="line-chart-grid" x1={x} x2={x} y1={y1} y2={y2}/>;
+ return <line key={index}
+ className="line-chart-grid"
+ x1={x}
+ x2={x}
+ y1={y1}
+ y2={y2}/>;
});
return <g>{lines}</g>;
},
let point = this.props.data[index];
let x = xScale(point.x);
let y = yScale.range()[0];
- return <text key={index} className="line-chart-tick" x={x} y={y} dy="1.5em">{tick}</text>;
+ return <text key={index}
+ className="line-chart-tick"
+ x={x}
+ y={y}
+ dy="1.5em">{tick}</text>;
});
return <g>{ticks}</g>;
},
let point = this.props.data[index];
let x = xScale(point.x);
let y = yScale(point.y);
- return <text key={index} className="line-chart-tick" x={x} y={y} dy="-1em">{value}</text>;
+ return <text key={index}
+ className="line-chart-tick"
+ x={x}
+ y={y}
+ dy="-1em">{value}</text>;
});
return <g>{ticks}</g>;
},
renderLine (xScale, yScale) {
- let path = d3.svg.line()
+ let p = d3.svg.line()
.x(d => xScale(d.x))
.y(d => yScale(d.y))
.interpolate(this.props.interpolate);
- return <path className="line-chart-path" d={path(this.props.data)}/>;
+ return <path className="line-chart-path" d={p(this.props.data)}/>;
},
render () {
return <a onClick={e => e.stopPropagation()}
className="treemap-link"
href={this.props.link}
- style={{ fontSize: 12 }}><i className="icon-link"/></a>;
+ style={{ fontSize: 12 }}><span className="icon-link"/></a>;
},
render () {
cursor: typeof this.props.onClick === 'function' ? 'pointer' : 'default'
};
let isTextVisible = this.props.width >= 40 && this.props.height >= 40;
- return <div className="treemap-cell" {...tooltipAttrs} style={cellStyles} onClick={this.props.onClick}>
+ return <div className="treemap-cell"
+ {...tooltipAttrs}
+ style={cellStyles}
+ onClick={this.props.onClick}>
<div className="treemap-inner" dangerouslySetInnerHTML={{ __html: this.props.label }}
style={{ maxWidth: this.props.width, visibility: isTextVisible ? 'visible': 'hidden' }}/>
{this.renderLink()}
export const Treemap = React.createClass({
- mixins: [ResizeMixin, TooltipsMixin],
-
propTypes: {
items: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
height: React.PropTypes.number,
onRectangleClick: React.PropTypes.func
},
+ mixins: [ResizeMixin, TooltipsMixin],
+
getInitialState() {
return { width: this.props.width, height: this.props.height };
},
export const WordCloud = React.createClass({
- mixins: [TooltipsMixin],
-
propTypes: {
items: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
sizeRange: React.PropTypes.arrayOf(React.PropTypes.number)
},
+ mixins: [TooltipsMixin],
+
getDefaultProps() {
return {
sizeRange: [10, 24]
const url = ('' + window.SS.lf.gravatarServerUrl)
.replace('{EMAIL_MD5}', emailHash)
.replace('{SIZE}', this.props.size * 2);
- return <img className="rounded" src={url} width={this.props.size} height={this.props.size} alt={this.props.email}/>;
+ return <img className="rounded"
+ src={url}
+ width={this.props.size}
+ height={this.props.size}
+ alt={this.props.email}/>;
}
});
let htmlId = this.props.name + '__' + option.value;
return (
<li key={option.value}>
- <input onChange={this.onChange} type="radio" name={this.props.name} value={option.value} id={htmlId}
- checked={checked} disabled={this.props.disabled}/>
+ <input onChange={this.onChange}
+ type="radio"
+ name={this.props.name}
+ value={option.value}
+ id={htmlId}
+ checked={checked}
+ disabled={this.props.disabled}/>
<label htmlFor={htmlId}>{option.label}</label>
</li>
);
width = this.props.logoWidth || 100,
height = 30,
title = window.t('layout.sonar.slogan');
- return <img src={url} width={width} height={height} alt={title} title={title}/>;
+ return <img src={url}
+ width={width}
+ height={height}
+ alt={title}
+ title={title}/>;
},
render() {