<div className="page page-limited">
<div className="overview page-with-sidebar">
<div className="overview-main page-main">
- <QualityGate component={component} measures={measures} periods={periods} />
+ <QualityGate component={component} measures={measures} />
<TooltipsContainer>
<div className="overview-domains-list">
const formattedValue = newCoverageValue != null
? <div>
- <DrilldownLink
- component={component.key}
- metric={newCoverageMeasure.metric.key}
- period={leakPeriod.index}>
+ <DrilldownLink component={component.key} metric={newCoverageMeasure.metric.key}>
<span className="js-overview-main-new-coverage">
{formatMeasure(newCoverageValue, 'PERCENT')}
</span>
<DrilldownLink
className="spacer-right overview-domain-secondary-measure-value"
component={component.key}
- metric={newLinesToCover.metric.key}
- period={leakPeriod.index}>
+ metric={newLinesToCover.metric.key}>
<span className="js-overview-main-new-coverage">
{formatMeasure(newLinesToCoverValue, 'SHORT_INT')}
</span>
const formattedValue = newDuplicationsValue != null
? <div>
- <DrilldownLink
- component={component.key}
- metric={newDuplicationsMeasure.metric.key}
- period={leakPeriod.index}>
+ <DrilldownLink component={component.key} metric={newDuplicationsMeasure.metric.key}>
<span className="js-overview-main-new-duplications">
{formatMeasure(newDuplicationsValue, 'PERCENT')}
</span>
<DrilldownLink
className="spacer-right overview-domain-secondary-measure-value"
component={component.key}
- metric={newLinesMeasure.metric.key}
- period={leakPeriod.index}>
+ metric={newLinesMeasure.metric.key}>
<span className="js-overview-main-new-lines">
{formatMeasure(newLinesValue, 'SHORT_INT')}
</span>
* 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 QualityGateConditions from './QualityGateConditions';
import EmptyQualityGate from './EmptyQualityGate';
-import { ComponentType, MeasuresListType, PeriodsListType } from '../propTypes';
import { translate } from '../../../helpers/l10n';
import Level from '../../../components/ui/Level';
+import type { Component, MeasuresList } from '../types';
-function parseQualityGateDetails(rawDetails) {
+function parseQualityGateDetails(rawDetails: string) {
return JSON.parse(rawDetails);
}
-function isProject(component) {
+function isProject(component: Component) {
return component.qualifier === 'TRK';
}
-const QualityGate = ({ component, measures, periods }) => {
+type Props = {
+ component: Component,
+ measures: MeasuresList
+};
+
+export default function QualityGate({ component, measures }: Props) {
const statusMeasure = measures.find(measure => measure.metric.key === 'alert_status');
const detailsMeasure = measures.find(measure => measure.metric.key === 'quality_gate_details');
const level = statusMeasure.value;
let conditions = [];
- if (detailsMeasure) {
+ if (detailsMeasure && detailsMeasure.value) {
conditions = parseQualityGateDetails(detailsMeasure.value).conditions;
}
</h2>
{conditions.length > 0 &&
- <QualityGateConditions component={component} periods={periods} conditions={conditions} />}
+ <QualityGateConditions component={component} conditions={conditions} />}
</div>
);
-};
-
-QualityGate.propTypes = {
- component: ComponentType.isRequired,
- measures: MeasuresListType.isRequired,
- periods: PeriodsListType.isRequired
-};
-
-export default QualityGate;
+}
import Measure from '../../component-measures/components/Measure';
import { getPeriodValue, isDiffMetric, formatMeasure } from '../../../helpers/measures';
import { translate } from '../../../helpers/l10n';
-import { getPeriod, getPeriodDate } from '../../../helpers/periods';
import { getComponentIssuesUrl } from '../../../helpers/urls';
import IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
+import type { Component } from '../types';
export default class QualityGateCondition extends React.PureComponent {
props: {
- component: { key: string },
- periods: Array<{
- index: number,
- date: string,
- mode: string,
- parameter?: string
- }>,
+ component: Component,
condition: {
level: string,
measure: {
}
wrapWithLink(children: React.Element<*>) {
- const { component, periods, condition } = this.props;
-
- const period = getPeriod(periods, condition.period);
- const periodDate = getPeriodDate(period);
+ const { component, condition } = this.props;
const className = classNames(
'overview-quality-gate-condition',
'overview-quality-gate-condition-' + condition.level.toLowerCase(),
- { 'overview-quality-gate-condition-leak': period != null }
+ { 'overview-quality-gate-condition-leak': condition.period != null }
);
const metricKey = condition.measure.metric.key;
className={className}
component={component.key}
metric={condition.measure.metric.key}
- period={condition.period}
- periodDate={periodDate}>
+ sinceLeakPeriod={condition.period != null}>
{children}
</DrilldownLink>;
}
render() {
- const { periods, condition } = this.props;
+ const { condition } = this.props;
const { measure } = condition;
const { metric } = measure;
const threshold = condition.level === 'ERROR' ? condition.error : condition.warning;
const actual = condition.period ? getPeriodValue(measure, condition.period) : measure.value;
- const period = getPeriod(periods, condition.period);
const operator = isRating
? translate('quality_gates.operator', condition.op, 'rating')
{metric.name}
</div>
{!isDiff &&
- period != null &&
+ condition.period != null &&
<div className="overview-quality-gate-condition-period">
{translate('quality_gates.conditions.leak')}
</div>}
}
render() {
- const { component, periods } = this.props;
+ const { component } = this.props;
const { loading, conditions } = this.state;
if (loading) {
<QualityGateCondition
key={condition.measure.metric.key}
component={component}
- periods={periods}
condition={condition}
/>
))}
metric
});
+const periods = [{ value: '3', index: 1 }];
+
it('open_issues', () => {
const condition = {
actual: '10',
op: 'GT'
};
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
type: 'INT',
name: 'new_open_issues'
},
+ periods: [{ value: '10', index: 1 }],
value: '10'
},
metric: 'new_open_issues',
- op: 'GT'
+ op: 'GT',
+ period: 1
};
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
it('reliability_rating', () => {
const condition = mockRatingCondition('reliability_rating');
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
it('security_rating', () => {
const condition = mockRatingCondition('security_rating');
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
it('sqale_rating', () => {
const condition = mockRatingCondition('sqale_rating');
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
it('new_reliability_rating', () => {
const condition = mockRatingCondition('new_reliability_rating');
+ condition.period = 1;
+ condition.measure.periods = periods;
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
it('new_security_rating', () => {
const condition = mockRatingCondition('new_security_rating');
+ condition.period = 1;
+ condition.measure.periods = periods;
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
it('new_sqale_rating', () => {
const condition = mockRatingCondition('new_sqale_rating');
+ condition.period = 1;
+ condition.measure.periods = periods;
expect(
- shallow(
- <QualityGateCondition component={{ key: 'abcd-key' }} periods={[]} condition={condition} />
- )
+ shallow(<QualityGateCondition component={{ key: 'abcd-key' }} condition={condition} />)
).toMatchSnapshot();
});
exports[`new_open_issues 1`] = `
<DrilldownLink
- className="overview-quality-gate-condition overview-quality-gate-condition-error"
+ className="overview-quality-gate-condition overview-quality-gate-condition-error overview-quality-gate-condition-leak"
component="abcd-key"
metric="new_open_issues"
- periodDate={null}
+ sinceLeakPeriod={true}
>
<div
className="overview-quality-gate-condition-container"
exports[`new_reliability_rating 1`] = `
<Link
- className="overview-quality-gate-condition overview-quality-gate-condition-error"
+ className="overview-quality-gate-condition overview-quality-gate-condition-error overview-quality-gate-condition-leak"
onlyActiveOnIndex={false}
style={Object {}}
to={
exports[`new_security_rating 1`] = `
<Link
- className="overview-quality-gate-condition overview-quality-gate-condition-error"
+ className="overview-quality-gate-condition overview-quality-gate-condition-error overview-quality-gate-condition-leak"
onlyActiveOnIndex={false}
style={Object {}}
to={
exports[`new_sqale_rating 1`] = `
<Link
- className="overview-quality-gate-condition overview-quality-gate-condition-error"
+ className="overview-quality-gate-condition overview-quality-gate-condition-error overview-quality-gate-condition-leak"
onlyActiveOnIndex={false}
style={Object {}}
to={
className="overview-quality-gate-condition overview-quality-gate-condition-error"
component="abcd-key"
metric="open_issues"
- periodDate={null}
+ sinceLeakPeriod={false}
>
<div
className="overview-quality-gate-condition-container"
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+//@flow
+export type Component = {
+ id: string,
+ key: string,
+ qualifier: string
+};
+
+export type Metric = {
+ key: string,
+ name: string,
+ type: string
+};
+
+export type Measure = {
+ metric: Metric,
+ value?: string,
+ periods?: Array<Period>
+};
+
+export type Period = {
+ index: number,
+ date: string,
+ mode: string,
+ parameter?: string
+};
+
+export type MeasuresList = Array<Measure>;
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import moment from 'moment';
import React from 'react';
import { Link } from 'react-router';
import { getComponentDrilldownUrl, getComponentIssuesUrl } from '../../helpers/urls';
];
export class DrilldownLink extends React.PureComponent {
+ static propTypes = {
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.node,
+ React.PropTypes.arrayOf(React.PropTypes.node)
+ ]),
+ className: React.PropTypes.string,
+ component: React.PropTypes.string.isRequired,
+ metric: React.PropTypes.string.isRequired,
+ sinceLeakPeriod: React.PropTypes.bool
+ };
isIssueMeasure = () => {
return ISSUE_MEASURES.indexOf(this.props.metric) !== -1;
};
propsToIssueParams = () => {
const params = {};
- if (this.props.periodDate) {
- params.createdAfter = moment(this.props.periodDate).format('YYYY-MM-DDTHH:mm:ssZZ');
+ if (this.props.sinceLeakPeriod) {
+ params.sinceLeakPeriod = true;
}
switch (this.props.metric) {