);
}
- renderComponentMeasuresOldLink() {
- return (
- <li>
- <Link
- to={{ pathname: '/component_measures_old', query: { id: this.props.component.key } }}
- activeClassName="active">
- Old Measures
- </Link>
- </li>
- );
- }
-
renderAdministration() {
const adminLinks = this.renderAdministrationLinks();
if (!adminLinks.some(link => link != null)) {
{this.renderDashboardLink()}
{this.renderIssuesLink()}
{this.renderComponentMeasuresLink()}
- {this.renderComponentMeasuresOldLink()}
{this.renderCodeLink()}
{this.renderActivityLink()}
{this.renderAdministration()}
layout.measures
</Link>
</li>
- <li>
- <Link
- activeClassName="active"
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/component_measures_old",
- "query": Object {
- "id": "foo",
- },
- }
- }
- >
- Old Measures
- </Link>
- </li>
<li>
<Link
activeClassName="active"
layout.measures
</Link>
</li>
- <li>
- <Link
- activeClassName="active"
- onlyActiveOnIndex={false}
- style={Object {}}
- to={
- Object {
- "pathname": "/component_measures_old",
- "query": Object {
- "id": "foo",
- },
- }
- }
- >
- Old Measures
- </Link>
- </li>
<li>
<Link
activeClassName="active"
import codingRulesRoutes from '../../apps/coding-rules/routes';
import componentRoutes from '../../apps/component/routes';
import componentMeasuresRoutes from '../../apps/component-measures/routes';
-import componentMeasuresOldRoutes from '../../apps/component-measures-old/routes';
import customMeasuresRoutes from '../../apps/custom-measures/routes';
import groupsRoutes from '../../apps/groups/routes';
import issuesRoutes from '../../apps/issues/routes';
import('../components/ProjectContainer').then(i => i.default)}>
<Route path="code" childRoutes={codeRoutes} />
<Route path="component_measures" childRoutes={componentMeasuresRoutes} />
- <Route path="component_measures_old" childRoutes={componentMeasuresOldRoutes} />
<Route path="custom_measures" childRoutes={customMeasuresRoutes} />
<Route path="dashboard" childRoutes={overviewRoutes} />
<Route path="project">
+++ /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.
- */
-import React from 'react';
-import Helmet from 'react-helmet';
-import Spinner from './../components/Spinner';
-import { translate } from '../../../helpers/l10n';
-import '../styles.css';
-
-export default class App extends React.PureComponent {
- state = { componentSet: false };
-
- componentDidMount() {
- this.props.setComponent(this.props.component);
- this.props.fetchMetrics();
- this.setState({ componentSet: true });
- }
-
- render() {
- if (this.props.metrics == null || !this.state.componentSet) {
- return <Spinner />;
- }
-
- return (
- <main id="component-measures">
- <Helmet title={translate('layout.measures')} />
- {this.props.children}
- </main>
- );
- }
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import App from './App';
-import { fetchMetrics, setComponent } from './actions';
-import { getComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer';
-
-const mapStateToProps = (state, ownProps) => ({
- component: getComponent(state, ownProps.location.query.id),
- metrics: getMeasuresAppAllMetrics(state)
-});
-
-const mapDispatchToProps = dispatch => {
- return {
- fetchMetrics: () => dispatch(fetchMetrics()),
- setComponent: component => dispatch(setComponent(component))
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(App);
+++ /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.
- */
-import { getMetrics } from '../../../api/metrics';
-
-/*
- * Actions
- */
-
-export const DISPLAY_HOME = 'measuresApp/app/DISPLAY_HOME';
-export const RECEIVE_METRICS = 'measuresApp/app/RECEIVE_METRICS';
-export const SET_COMPONENT = 'measuresApp/app/SET_COMPONENT';
-
-/*
- * Action Creators
- */
-
-export function displayHome() {
- return { type: DISPLAY_HOME };
-}
-
-function receiveMetrics(metrics) {
- return { type: RECEIVE_METRICS, metrics };
-}
-
-export function setComponent(component) {
- return { type: SET_COMPONENT, component };
-}
-
-/*
- * Workflow
- */
-
-export function fetchMetrics() {
- return dispatch => {
- getMetrics().then(metrics => {
- dispatch(receiveMetrics(metrics));
- });
- };
-}
+++ /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.
- */
-import { RECEIVE_METRICS, SET_COMPONENT } from './actions';
-
-const initialState = {
- metrics: undefined
-};
-
-export default function appReducer(state = initialState, action = {}) {
- switch (action.type) {
- case RECEIVE_METRICS:
- return { ...state, metrics: action.metrics };
- case SET_COMPONENT:
- return { ...state, component: action.component };
- default:
- return state;
- }
-}
+++ /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.
- */
-import React from 'react';
-
-export default function IconBubbles() {
- /* eslint max-len: 0 */
- return (
- <svg
- className="measure-tab-icon"
- viewBox="0 0 512 448"
- fillRule="evenodd"
- clipRule="evenodd"
- strokeLinejoin="round"
- strokeMiterlimit="1.414">
- <path d="M352 256c52.984 0 96 43.016 96 96s-43.016 96-96 96-96-43.016-96-96 43.016-96 96-96zM128 96c70.645 0 128 57.355 128 128 0 70.645-57.355 128-128 128C57.355 352 0 294.645 0 224 0 153.355 57.355 96 128 96zM352 0c52.984 0 96 43.016 96 96s-43.016 96-96 96-96-43.016-96-96 43.016-96 96-96z" />
- </svg>
- );
-}
+++ /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.
- */
-import React from 'react';
-
-export default function ListIcon() {
- /* eslint max-len: 0 */
- return (
- <svg
- className="measure-tab-icon"
- viewBox="0 0 448 448"
- fillRule="evenodd"
- clipRule="evenodd"
- strokeLinejoin="round"
- strokeMiterlimit="1.414">
- <path d="M448 48c0-8.83-7.17-16-16-16H16C7.17 32 0 39.17 0 48v32c0 8.83 7.17 16 16 16h416c8.83 0 16-7.17 16-16V48zM448 144c0-8.83-7.17-16-16-16H16c-8.83 0-16 7.17-16 16v32c0 8.83 7.17 16 16 16h416c8.83 0 16-7.17 16-16v-32zM448 240c0-8.83-7.17-16-16-16H16c-8.83 0-16 7.17-16 16v32c0 8.83 7.17 16 16 16h416c8.83 0 16-7.17 16-16v-32zM448 336.03c0-8.83-7.17-16-16-16H16c-8.83 0-16 7.17-16 16v32c0 8.83 7.17 16 16 16h416c8.83 0 16-7.17 16-16v-32z" />
- </svg>
- );
-}
+++ /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.
- */
-import React from 'react';
-
-export default function IconTree() {
- /* eslint max-len: 0 */
- return (
- <svg
- className="measure-tab-icon"
- viewBox="0 0 448 448"
- fillRule="evenodd"
- clipRule="evenodd"
- strokeLinejoin="round"
- strokeMiterlimit="1.414">
- <path d="M448 48c0-8.83-7.17-16-16-16H16C7.17 32 0 39.17 0 48v32c0 8.83 7.17 16 16 16h416c8.83 0 16-7.17 16-16V48zM448 144c0-8.83-6.146-16-13.714-16H77.714C70.144 128 64 135.17 64 144v32c0 8.83 6.145 16 13.714 16h356.572c7.568 0 13.714-7.17 13.714-16v-32zM448 240c0-8.83-5.12-16-11.428-16H139.428C133.12 224 128 231.17 128 240v32c0 8.83 5.12 16 11.428 16h297.144c6.307 0 11.428-7.17 11.428-16v-32zM448 336.03c0-8.83-4.097-16-9.142-16H201.143c-5.046 0-9.143 7.17-9.143 16v32c0 8.83 4.097 16 9.143 16h237.715c5.045 0 9.142-7.17 9.142-16v-32z" />
- </svg>
- );
-}
+++ /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.
- */
-import React from 'react';
-
-export default function IconTreemap() {
- return (
- <svg
- className="measure-tab-icon"
- viewBox="0 0 448 448"
- fillRule="evenodd"
- clipRule="evenodd"
- strokeLinejoin="round"
- strokeMiterlimit="1.414">
- <path d="M0 0h224v448H0zM256 0h192v256H256zM256 288h192v160H256z" />
- </svg>
- );
-}
+++ /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.
- */
-import React from 'react';
-import moment from 'moment';
-import Tooltip from '../../../components/controls/Tooltip';
-import { getPeriodLabel, getPeriodDate } from '../../../helpers/periods';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-export default function LeakPeriodLegend({ component, period }) {
- if (component.qualifier === 'APP') {
- return (
- <div className="measures-domains-leak-header">
- {translate('issues.leak_period')}
- </div>
- );
- }
-
- const label = (
- <div className="measures-domains-leak-header">
- {translateWithParameters('overview.leak_period_x', getPeriodLabel(period))}
- </div>
- );
-
- if (period.mode === 'days') {
- return label;
- }
-
- const date = getPeriodDate(period);
- const fromNow = moment(date).fromNow();
- const tooltip = fromNow + ', ' + moment(date).format('LL');
- return (
- <Tooltip placement="bottom" overlay={tooltip}>
- {label}
- </Tooltip>
- );
-}
+++ /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.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import Rating from '../../../components/ui/Rating';
-import Level from '../../../components/ui/Level';
-import { formatMeasure, isDiffMetric } from '../../../helpers/measures';
-import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin';
-import { formatLeak, getRatingTooltip } from '../utils';
-
-export default class Measure extends React.PureComponent {
- static propTypes = {
- className: PropTypes.string,
- measure: PropTypes.object,
- metric: PropTypes.object,
- decimals: PropTypes.number
- };
-
- renderRating(measure, metric) {
- const value = isDiffMetric(metric.key) ? measure.leak : measure.value;
- const tooltip = getRatingTooltip(metric.key, value);
- const rating = <Rating value={value} />;
-
- if (tooltip) {
- return (
- <TooltipsContainer>
- <span>
- <span title={tooltip} data-toggle="tooltip">
- {rating}
- </span>
- </span>
- </TooltipsContainer>
- );
- }
-
- return rating;
- }
-
- render() {
- const { measure, metric, decimals, className } = this.props;
- const finalMetric = metric || measure.metric;
-
- if (finalMetric.type === 'RATING') {
- return this.renderRating(measure, finalMetric);
- }
-
- if (finalMetric.type === 'LEVEL') {
- return <Level level={measure.value} />;
- }
-
- const formattedValue = isDiffMetric(finalMetric.key)
- ? formatLeak(measure.leak, finalMetric, { decimals })
- : formatMeasure(measure.value, finalMetric.type, { decimals });
- return (
- <span className={className}>
- {formattedValue != null ? formattedValue : '–'}
- </span>
- );
- }
-}
+++ /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.
- */
-import React from 'react';
-
-export default function Spinner() {
- return <i className="spinner spinner-margin" />;
-}
+++ /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.
- */
-import React from 'react';
-import Spinner from './../Spinner';
-import OriginalBubbleChart from '../../../../components/charts/BubbleChart';
-import bubbles from '../../config/bubbles';
-import { getComponentLeaves } from '../../../../api/components';
-import { formatMeasure } from '../../../../helpers/measures';
-import Workspace from '../../../../components/workspace/main';
-import { getComponentUrl } from '../../../../helpers/urls';
-import { getLocalizedMetricName, translateWithParameters } from '../../../../helpers/l10n';
-
-const HEIGHT = 500;
-const BUBBLES_LIMIT = 500;
-
-function getMeasure(component, metric) {
- return Number(component.measures[metric]) || 0;
-}
-
-export default class BubbleChart extends React.PureComponent {
- state = {
- fetching: 0,
- files: []
- };
-
- componentWillMount() {
- this.updateMetrics(this.props);
- }
-
- componentDidMount() {
- this.mounted = true;
- this.fetchFiles();
- }
-
- componentWillUpdate(nextProps) {
- this.updateMetrics(nextProps);
- }
-
- componentDidUpdate(nextProps) {
- if (nextProps.domainName !== this.props.domainName) {
- this.fetchFiles();
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- updateMetrics(props) {
- const { metrics, domainName } = props;
- const conf = bubbles[domainName];
- this.xMetric = metrics.find(m => m.key === conf.x);
- this.yMetric = metrics.find(m => m.key === conf.y);
- this.sizeMetric = metrics.find(m => m.key === conf.size);
- }
-
- fetchFiles() {
- const { component } = this.props;
- const metrics = [this.xMetric.key, this.yMetric.key, this.sizeMetric.key];
- const options = {
- s: 'metric',
- metricSort: this.sizeMetric.key,
- asc: false,
- ps: BUBBLES_LIMIT
- };
-
- if (this.mounted) {
- this.setState({ fetching: this.state.fetching + 1 });
- }
-
- getComponentLeaves(component.key, metrics, options).then(r => {
- const files = r.components.map(file => {
- const measures = {};
-
- file.measures.forEach(measure => {
- measures[measure.metric] = measure.value;
- });
- return { ...file, measures };
- });
-
- if (this.mounted) {
- this.setState({
- files,
- fetching: this.state.fetching - 1,
- total: files.length
- });
- }
- });
- }
-
- getTooltip(component) {
- const x = formatMeasure(getMeasure(component, this.xMetric.key), this.xMetric.type);
- const y = formatMeasure(getMeasure(component, this.yMetric.key), this.yMetric.type);
- const size = formatMeasure(getMeasure(component, this.sizeMetric.key), this.sizeMetric.type);
- const inner = [
- component.name,
- `${this.xMetric.name}: ${x}`,
- `${this.yMetric.name}: ${y}`,
- `${this.sizeMetric.name}: ${size}`
- ].join('<br>');
-
- return `<div class="text-left">${inner}</div>`;
- }
-
- handleBubbleClick(component) {
- if (['FIL', 'UTS'].includes(component.qualifier)) {
- Workspace.openComponent({ key: component.key });
- } else {
- window.location = getComponentUrl(component.refKey || component.key);
- }
- }
-
- renderBubbleChart() {
- const items = this.state.files.map(file => {
- return {
- x: getMeasure(file, this.xMetric.key),
- y: getMeasure(file, this.yMetric.key),
- size: getMeasure(file, this.sizeMetric.key),
- link: file,
- tooltip: this.getTooltip(file)
- };
- });
-
- const formatXTick = tick => formatMeasure(tick, this.xMetric.type);
- const formatYTick = tick => formatMeasure(tick, this.yMetric.type);
-
- return (
- <OriginalBubbleChart
- items={items}
- height={HEIGHT}
- padding={[25, 60, 50, 60]}
- formatXTick={formatXTick}
- formatYTick={formatYTick}
- onBubbleClick={this.handleBubbleClick.bind(this)}
- />
- );
- }
-
- render() {
- const { fetching } = this.state;
-
- if (fetching) {
- return (
- <div className="measure-details-bubble-chart">
- <div className="note text-center" style={{ lineHeight: `${HEIGHT}px` }}>
- <Spinner />
- </div>
- </div>
- );
- }
-
- return (
- <div className="measure-details-bubble-chart">
- <div>
- {this.renderBubbleChart()}
- </div>
-
- <div className="measure-details-bubble-chart-axis x">
- {getLocalizedMetricName(this.xMetric)}
- </div>
- <div className="measure-details-bubble-chart-axis y">
- {getLocalizedMetricName(this.yMetric)}
- </div>
- <div className="measure-details-bubble-chart-axis size">
- {translateWithParameters(
- 'component_measures.legend.size_x',
- getLocalizedMetricName(this.sizeMetric)
- )}
- </div>
- </div>
- );
- }
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import MeasureBubbleChart from './BubbleChart';
-import { getMeasuresAppAllMetrics, getMeasuresAppComponent } from '../../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- component: getMeasuresAppComponent(state),
- metrics: getMeasuresAppAllMetrics(state)
- };
-};
-
-const mapDispatchToProps = () => {
- return {};
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(MeasureBubbleChart);
+++ /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.
- */
-const bubblesConfig = {
- Reliability: { x: 'ncloc', y: 'reliability_remediation_effort', size: 'bugs' },
- Security: { x: 'ncloc', y: 'security_remediation_effort', size: 'vulnerabilities' },
- Maintainability: { x: 'ncloc', y: 'sqale_index', size: 'code_smells' },
- Coverage: { x: 'complexity', y: 'coverage', size: 'uncovered_lines' },
- Duplications: { x: 'ncloc', y: 'duplicated_lines', size: 'duplicated_blocks' }
-};
-
-export default bubblesConfig;
+++ /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.
- */
-export default {
- coverage: ['uncovered_lines', 'uncovered_conditions'],
- line_coverage: ['uncovered_lines'],
- branch_coverage: ['uncovered_conditions'],
- uncovered_lines: ['line_coverage'],
- uncovered_conditions: ['branch_coverage'],
-
- new_coverage: ['new_uncovered_lines', 'new_uncovered_conditions'],
- new_line_coverage: ['new_uncovered_lines'],
- new_branch_coverage: ['new_uncovered_conditions'],
- new_uncovered_lines: ['new_line_coverage'],
- new_uncovered_conditions: ['new_branch_coverage'],
-
- duplicated_lines_density: ['duplicated_lines'],
- new_duplicated_lines_density: ['new_duplicated_lines'],
- duplicated_lines: ['duplicated_lines_density'],
- new_duplicated_lines: ['new_duplicated_lines_density']
-};
+++ /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.
- */
-export const domains = {
- Reliability: {
- main: ['bugs', 'new_bugs', 'reliability_rating'],
- order: [
- 'bugs',
- 'new_bugs',
- 'reliability_rating',
- 'reliability_remediation_effort',
- 'new_reliability_remediation_effort'
- ]
- },
-
- Security: {
- main: ['vulnerabilities', 'new_vulnerabilities', 'security_rating'],
- order: [
- 'vulnerabilities',
- 'new_vulnerabilities',
- 'security_rating',
- 'security_remediation_effort',
- 'new_security_remediation_effort'
- ]
- },
-
- Maintainability: {
- main: ['code_smells', 'new_code_smells', 'sqale_rating'],
- order: [
- 'code_smells',
- 'new_code_smells',
- 'sqale_rating',
- 'sqale_index',
- 'new_technical_debt',
- 'sqale_debt_ratio',
- 'new_sqale_debt_ratio',
- 'effort_to_reach_maintainability_rating_a'
- ]
- },
-
- Coverage: {
- main: ['coverage', 'new_coverage', 'tests'],
- order: [
- 'coverage',
- 'new_coverage',
- 'line_coverage',
- 'new_line_coverage',
- 'branch_coverage',
- 'new_branch_coverage',
- 'uncovered_lines',
- 'new_uncovered_lines',
- 'uncovered_conditions',
- 'new_uncovered_conditions',
- 'new_lines_to_cover',
-
- 'lines_to_cover',
-
- 'tests',
- 'test_success',
- 'test_errors',
- 'test_failures',
- 'skipped_tests',
- 'test_success_density',
- 'test_execution_time'
- ]
- },
-
- Duplications: {
- main: ['duplicated_lines_density', 'new_duplicated_lines_density'],
- order: [
- 'duplicated_lines_density',
- 'new_duplicated_lines_density',
- 'duplicated_blocks',
- 'new_duplicated_blocks',
- 'duplicated_lines',
- 'new_duplicated_lines',
- 'duplicated_files'
- ]
- },
-
- Size: {
- main: ['ncloc'],
- order: [
- 'ncloc',
- 'lines',
- 'new_lines',
- 'statements',
- 'functions',
- 'classes',
- 'files',
- 'directories'
- ]
- },
-
- Complexity: {
- main: ['complexity'],
- order: ['complexity', 'function_complexity', 'file_complexity', 'class_complexity']
- },
-
- Releasability: {
- main: ['alert_status', 'releasability_rating'],
- order: ['alert_status']
- },
-
- Issues: {
- main: ['violations', 'new_violations'],
- order: [
- 'violations',
- 'new_violations',
- 'blocker_violations',
- 'new_blocker_violations',
- 'critical_violations',
- 'new_critical_violations',
- 'major_violations',
- 'new_major_violations',
- 'minor_violations',
- 'new_minor_violations',
- 'info_violations',
- 'new_info_violations',
- 'open_issues',
- 'reopened_issues',
- 'confirmed_issues',
- 'false_positive_issues'
- ]
- }
-};
+++ /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.
- */
-import React from 'react';
-import { Link, IndexLink } from 'react-router';
-import Spinner from './../components/Spinner';
-import MeasureDetailsHeader from './MeasureDetailsHeader';
-import MeasureDrilldown from './drilldown/MeasureDrilldown';
-import MetricNotFound from './MetricNotFound';
-import { getPeriod, getPeriodDate } from '../../../helpers/periods';
-import { translate, translateWithParameters } from '../../../helpers/l10n';
-
-export default class MeasureDetails extends React.PureComponent {
- mounted: boolean;
-
- state = {
- loading: true
- };
-
- componentDidMount() {
- this.mounted = true;
- this.loadData();
- }
-
- componentDidUpdate(prevProps) {
- if (prevProps.params.metricKey !== this.props.params.metricKey) {
- this.loadData();
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- metricExists(): boolean {
- const { metrics } = this.props;
- const { metricKey } = this.props.params;
- const metric = metrics.find(metric => metric.key === metricKey);
- return !!metric;
- }
-
- loadData() {
- if (this.metricExists()) {
- this.setState({ loading: true });
- const periodIndex = this.props.location.query.period || 1;
- const onLoaded = () => this.mounted && this.setState({ loading: false });
- this.props
- .fetchMeasure(this.props.params.metricKey, Number(periodIndex))
- .then(onLoaded, onLoaded);
- }
- }
-
- render() {
- if (!this.metricExists()) {
- return <MetricNotFound />;
- }
-
- if (this.state.loading) {
- return <Spinner />;
- }
-
- const { component, metric, secondaryMeasure, measure, periods, children } = this.props;
-
- if (!measure) {
- return <MetricNotFound />;
- }
-
- const { tab } = this.props.params;
- const periodIndex = this.props.location.query.period || 1;
- const period = getPeriod(periods, Number(periodIndex));
- const periodDate = getPeriodDate(period);
-
- return (
- <section id="component-measures-details" className="page page-container page-limited">
- <div className="note">
- <IndexLink
- to={{ pathname: '/component_measures_old', query: { id: component.key } }}
- id="component-measures-back-to-all-measures"
- className="text-muted">
- {translate('component_measures.all_measures')}
- </IndexLink>
- {!!metric.domain &&
- <span>
- {' / '}
- <Link
- to={{
- pathname: `/component_measures_old/domain/${metric.domain}`,
- query: { id: component.key }
- }}
- className="text-muted">
- {translateWithParameters('component_measures.domain_measures', metric.domain)}
- </Link>
- </span>}
- </div>
-
- <MeasureDetailsHeader
- component={component}
- leakPeriod={period}
- measure={measure}
- metric={metric}
- secondaryMeasure={secondaryMeasure}
- />
-
- {measure &&
- <MeasureDrilldown
- component={component}
- metric={metric}
- tab={tab}
- leakPeriod={period}
- leakPeriodDate={periodDate}>
- {children}
- </MeasureDrilldown>}
- </section>
- );
- }
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import MeasureDetails from './MeasureDetails';
-import { fetchMeasure } from './actions';
-import {
- getMeasuresAppAllMetrics,
- getMeasuresAppDetailsMetric,
- getMeasuresAppDetailsMeasure,
- getMeasuresAppDetailsSecondaryMeasure,
- getMeasuresAppDetailsPeriods,
- getMeasuresAppComponent
-} from '../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- component: getMeasuresAppComponent(state),
- metrics: getMeasuresAppAllMetrics(state),
- metric: getMeasuresAppDetailsMetric(state),
- measure: getMeasuresAppDetailsMeasure(state),
- secondaryMeasure: getMeasuresAppDetailsSecondaryMeasure(state),
- periods: getMeasuresAppDetailsPeriods(state)
- };
-};
-
-const mapDispatchToProps = { fetchMeasure };
-
-export default connect(mapStateToProps, mapDispatchToProps)(MeasureDetails);
+++ /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.
- */
-import React from 'react';
-import { Link } from 'react-router';
-import Measure from './../components/Measure';
-import LanguageDistribution from '../../../components/charts/LanguageDistribution';
-import LeakPeriodLegend from '../components/LeakPeriodLegend';
-import IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
-import HistoryIcon from '../../../components/icons-components/HistoryIcon';
-import Tooltip from '../../../components/controls/Tooltip';
-import ComplexityDistribution from '../../../components/shared/ComplexityDistribution';
-import { isDiffMetric } from '../../../helpers/measures';
-import { TooltipsContainer } from '../../../components/mixins/tooltips-mixin';
-import { getComponentMeasureHistory } from '../../../helpers/urls';
-import { getLocalizedMetricName, translate } from '../../../helpers/l10n';
-
-export default function MeasureDetailsHeader({
- component,
- measure,
- metric,
- secondaryMeasure,
- leakPeriod
-}) {
- const isDiff = isDiffMetric(metric.key);
- return (
- <header className="measure-details-header">
- <h2 className="measure-details-metric">
- <IssueTypeIcon query={metric.key} className="little-spacer-right" />
- {getLocalizedMetricName(metric)}
- {!isDiff &&
- <Tooltip placement="right" overlay={translate('component_measures.show_metric_history')}>
- <Link
- className="js-show-history spacer-left button button-small button-compact"
- to={getComponentMeasureHistory(component.key, metric.key)}>
- <HistoryIcon />
- </Link>
- </Tooltip>}
- </h2>
-
- {isDiff &&
- <div className="pull-right">
- <LeakPeriodLegend component={component} period={leakPeriod} />
- </div>}
-
- <TooltipsContainer options={{ html: false }}>
- <div className="measure-details-value">
- {isDiff
- ? <div className="measure-details-value-leak">
- <Measure measure={measure} metric={metric} />
- </div>
- : <div className="measure-details-value-absolute">
- <Measure measure={measure} metric={metric} />
- </div>}
-
- {secondaryMeasure &&
- secondaryMeasure.metric === 'ncloc_language_distribution' &&
- <div className="measure-details-secondary">
- <LanguageDistribution distribution={secondaryMeasure.value} />
- </div>}
-
- {secondaryMeasure &&
- secondaryMeasure.metric === 'function_complexity_distribution' &&
- <div className="measure-details-secondary">
- <ComplexityDistribution distribution={secondaryMeasure.value} of="function" />
- </div>}
-
- {secondaryMeasure &&
- secondaryMeasure.metric === 'file_complexity_distribution' &&
- <div className="measure-details-secondary">
- <ComplexityDistribution distribution={secondaryMeasure.value} of="file" />
- </div>}
- </div>
- </TooltipsContainer>
- </header>
- );
-}
+++ /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
-import React from 'react';
-import { translate } from '../../../helpers/l10n';
-
-export default function MetricNotFound() {
- return (
- <div className="page page-limited">
- <div className="alert alert-danger">
- {translate('component_measures.not_found')}
- </div>
- </div>
- );
-}
+++ /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.
- */
-import { getMeasuresAndMeta } from '../../../api/measures';
-import { enhanceWithLeak } from '../utils';
-import { getMeasuresAppComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer';
-
-/*
- * Actions
- */
-
-export const REQUEST_MEASURE = 'measuresApp/details/REQUEST_MEASURE';
-export const RECEIVE_MEASURE = 'measuresApp/details/RECEIVE_MEASURE';
-
-/*
- * Action Creators
- */
-
-function requestMeasure(metric) {
- return { type: REQUEST_MEASURE, metric };
-}
-
-function receiveMeasure(measure, secondaryMeasure, periods) {
- return { type: RECEIVE_MEASURE, measure, secondaryMeasure, periods };
-}
-
-/*
- * Workflow
- */
-
-export function fetchMeasure(metricKey, periodIndex = 1) {
- return (dispatch, getState) => {
- const state = getState();
- const component = getMeasuresAppComponent(state);
- const metrics = getMeasuresAppAllMetrics(state);
- const metricsToRequest = [metricKey];
-
- if (metricKey === 'ncloc') {
- metricsToRequest.push('ncloc_language_distribution');
- }
- if (metricKey === 'function_complexity') {
- metricsToRequest.push('function_complexity_distribution');
- }
- if (metricKey === 'file_complexity') {
- metricsToRequest.push('file_complexity_distribution');
- }
-
- const metric = metrics.find(m => m.key === metricKey);
- dispatch(requestMeasure(metric));
-
- return getMeasuresAndMeta(component.key, metricsToRequest, {
- additionalFields: 'periods'
- }).then(r => {
- const measures = enhanceWithLeak(r.component.measures, periodIndex);
- const measure = measures.find(m => m.metric === metricKey);
- const secondaryMeasure = measures.find(m => m.metric !== metricKey);
- dispatch(receiveMeasure(measure, secondaryMeasure, r.periods));
- });
- };
-}
+++ /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.
- */
-import React from 'react';
-import QualifierIcon from '../../../../components/shared/QualifierIcon';
-import { formatLeak } from '../../utils';
-import { formatMeasure, isDiffMetric } from '../../../../helpers/measures';
-
-const Breadcrumb = ({ component, metric, onBrowse }) => {
- const handleClick = e => {
- e.preventDefault();
- e.target.blur();
- onBrowse(component);
- };
-
- let inner;
- if (onBrowse) {
- inner = (
- <a id={'component-measures-breadcrumb-' + component.key} href="#" onClick={handleClick}>
- {component.name}
- </a>
- );
- } else {
- inner = (
- <span>
- {component.name}
- </span>
- );
- }
-
- const value = isDiffMetric(metric.key)
- ? formatLeak(component.leak, metric)
- : formatMeasure(component.value, metric.type);
-
- return (
- <span>
- <QualifierIcon qualifier={component.qualifier} />
-
- {inner}
- {value != null &&
- <span>
- {' (' + value + ')'}
- </span>}
- </span>
- );
-};
-
-export default Breadcrumb;
+++ /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.
- */
-import React from 'react';
-import Breadcrumb from './Breadcrumb';
-
-const Breadcrumbs = ({ breadcrumbs, metric, onBrowse }) =>
- <ul className="component-measures-breadcrumbs">
- {breadcrumbs.map((component, index) =>
- <li key={component.key}>
- <Breadcrumb
- component={component}
- metric={metric}
- onBrowse={index + 1 < breadcrumbs.length ? onBrowse : null}
- />
- </li>
- )}
- </ul>;
-
-export default Breadcrumbs;
+++ /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.
- */
-import React from 'react';
-import classNames from 'classnames';
-import QualifierIcon from '../../../../components/shared/QualifierIcon';
-import { splitPath } from '../../../../helpers/path';
-import { getComponentUrl } from '../../../../helpers/urls';
-
-const ComponentCell = ({ component, isSelected, onClick }) => {
- const linkClassName = classNames('link-no-underline', {
- selected: isSelected
- });
-
- const handleClick = e => {
- const isLeftClickEvent = e.button === 0;
- const isModifiedEvent = !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
-
- if (isLeftClickEvent && !isModifiedEvent) {
- e.preventDefault();
- onClick();
- }
- };
-
- let head = '';
- let tail = component.name;
-
- if (['DIR', 'FIL', 'UTS'].includes(component.qualifier)) {
- const parts = splitPath(component.path);
- head = parts.head;
- tail = parts.tail;
- }
-
- const inner = (
- <span title={component.refKey || component.key}>
- <QualifierIcon qualifier={component.qualifier} />
-
- {head.length > 0 &&
- <span className="note">
- {head}/
- </span>}
- <span>{tail}</span>
- </span>
- );
-
- return (
- <td style={{ maxWidth: 0 }}>
- <div
- style={{
- maxWidth: '100%',
- whiteSpace: 'nowrap',
- overflow: 'hidden',
- textOverflow: 'ellipsis'
- }}>
- {component.refId == null || component.qualifier === 'DEV_PRJ'
- ? <a
- id={'component-measures-component-link-' + component.key}
- className={linkClassName}
- href={getComponentUrl(component.key)}
- onClick={handleClick}>
- {inner}
- </a>
- : <a
- id={'component-measures-component-link-' + component.key}
- className={linkClassName}
- href={getComponentUrl(component.refKey || component.key)}>
- <span className="big-spacer-right">
- <i className="icon-detach" />
- </span>
-
- {inner}
- </a>}
- </div>
- </td>
- );
-};
-
-export default ComponentCell;
+++ /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.
- */
-import React from 'react';
-import ComponentsListRow from './ComponentsListRow';
-import EmptyComponentsList from './EmptyComponentsList';
-import complementary from '../../config/complementary';
-import { getLocalizedMetricName } from '../../../../helpers/l10n';
-
-const ComponentsList = ({ components, metrics, selected, metric, onClick }) => {
- if (!components.length) {
- return <EmptyComponentsList />;
- }
-
- const otherMetrics = (complementary[metric.key] || []).map(metric => {
- return metrics.find(m => m.key === metric);
- });
-
- return (
- <table className="data zebra zebra-hover">
- {otherMetrics.length > 0 &&
- <thead>
- <tr>
- <th> </th>
- <th className="text-right">
- <span className="small">
- {getLocalizedMetricName(metric)}
- </span>
- </th>
- {otherMetrics.map(metric =>
- <th key={metric.key} className="text-right">
- <span className="small">
- {getLocalizedMetricName(metric)}
- </span>
- </th>
- )}
- </tr>
- </thead>}
-
- <tbody>
- {components.map(component =>
- <ComponentsListRow
- key={component.id}
- component={component}
- otherMetrics={otherMetrics}
- isSelected={component === selected}
- metric={metric}
- onClick={onClick}
- />
- )}
- </tbody>
- </table>
- );
-};
-
-export default ComponentsList;
+++ /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.
- */
-import React from 'react';
-import ComponentCell from './ComponentCell';
-import MeasureCell from './MeasureCell';
-
-const replaceMeasure = (component, measure) => {
- return {
- ...component,
- value: measure.value,
- leak: measure.leak
- };
-};
-
-const ComponentsListRow = ({ component, otherMetrics, isSelected, metric, onClick }) => {
- const handleClick = () => {
- onClick(component);
- };
-
- const otherMeasures = otherMetrics.map(metric => {
- const measure = component.measures.find(measure => measure.metric === metric.key);
- return { ...measure, metric };
- });
-
- return (
- <tr>
- <ComponentCell
- component={component}
- isSelected={isSelected}
- onClick={handleClick.bind(this, component)}
- />
-
- <MeasureCell component={component} metric={metric} />
-
- {otherMeasures.map(measure =>
- <MeasureCell
- key={measure.metric.key}
- component={replaceMeasure(component, measure)}
- metric={measure.metric}
- />
- )}
- </tr>
- );
-};
-
-export default ComponentsListRow;
+++ /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.
- */
-import React from 'react';
-import { translate } from '../../../../helpers/l10n';
-
-const EmptyComponentsList = () => {
- return (
- <div className="note">
- {translate('no_results')}
- </div>
- );
-};
-
-export default EmptyComponentsList;
+++ /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.
- */
-import React from 'react';
-import Breadcrumbs from './Breadcrumbs';
-import { translateWithParameters } from '../../../../helpers/l10n';
-
-const ListHeader = props => {
- const { metric, breadcrumbs, onBrowse } = props;
- const { selectedIndex, componentsCount, onSelectPrevious, onSelectNext } = props;
- const hasPrevious = selectedIndex > 0;
- const hasNext = selectedIndex < componentsCount - 1;
- const blur = fn => {
- return e => {
- e.target.blur();
- fn();
- };
- };
-
- return (
- <header className="measure-details-viewer-header">
- {breadcrumbs != null &&
- breadcrumbs.length > 1 &&
- <div className="measure-details-header-container">
- <Breadcrumbs breadcrumbs={breadcrumbs} metric={metric} onBrowse={onBrowse} />
- </div>}
-
- {selectedIndex != null &&
- selectedIndex !== -1 &&
- <div className="pull-right">
- <span className="note spacer-right">
- {translateWithParameters(
- 'component_measures.x_of_y',
- selectedIndex + 1,
- componentsCount
- )}
- </span>
-
- <div className="button-group">
- {hasPrevious && <button onClick={blur(onSelectPrevious)}><</button>}
- {hasNext && <button onClick={blur(onSelectNext)}>></button>}
- </div>
- </div>}
- </header>
- );
-};
-
-export default ListHeader;
+++ /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.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-import moment from 'moment';
-import ComponentsList from './ComponentsList';
-import ListHeader from './ListHeader';
-import Spinner from '../../components/Spinner';
-import SourceViewer from '../../../../components/SourceViewer/SourceViewer';
-import ListFooter from '../../../../components/controls/ListFooter';
-
-export default class ListView extends React.PureComponent {
- static contextTypes = {
- router: PropTypes.object.isRequired
- };
-
- componentDidMount() {
- const { component, metric } = this.props;
- if (component.qualifier === 'DEV') {
- const { router } = this.context;
- router.replace({ pathname: `metric/${metric.key}/tree`, query: { id: component.key } });
- }
- this.handleChangeBaseComponent(component);
- }
-
- componentDidUpdate(nextProps) {
- if (nextProps.metric !== this.props.metric) {
- this.handleChangeBaseComponent(this.props.component);
- }
-
- if (this.props.selected) {
- this.scrollToViewer();
- } else if (this.scrollTop) {
- this.scrollToStoredPosition();
- }
- }
-
- scrollToViewer() {
- const { container } = this.refs;
- const top = container.getBoundingClientRect().top + window.scrollY - 95 - 10;
-
- // scroll only to top
- if (window.scrollY > top) {
- window.scrollTo(0, top);
- }
- }
-
- scrollToStoredPosition() {
- window.scrollTo(0, this.scrollTop);
- this.scrollTop = null;
- }
-
- storeScrollPosition() {
- this.scrollTop = window.scrollY;
- }
-
- handleChangeBaseComponent(baseComponent) {
- const { metric, onFetchList } = this.props;
- const periodIndex = this.props.location.query.period || 1;
- onFetchList(baseComponent, metric, Number(periodIndex));
- }
-
- handleFetchMore() {
- const periodIndex = this.props.location.query.period || 1;
- this.props.onFetchMore(Number(periodIndex));
- }
-
- changeSelected(selected) {
- this.props.onSelect(selected);
- }
-
- handleClick(selected) {
- this.storeScrollPosition();
- this.props.onSelect(selected);
- }
-
- handleBreadcrumbClick() {
- this.props.onSelect(undefined);
- }
-
- render() {
- const {
- component,
- components,
- metrics,
- metric,
- leakPeriod,
- selected,
- total,
- fetching
- } = this.props;
- const { onSelectNext, onSelectPrevious } = this.props;
-
- const breadcrumbs = [component];
- if (selected) {
- breadcrumbs.push(selected);
- }
- const selectedIndex = components.indexOf(selected);
- const sourceViewerPeriod = metric.key.indexOf('new_') === 0 && !!leakPeriod ? leakPeriod : null;
- const sourceViewerPeriodDate =
- sourceViewerPeriod != null ? moment(sourceViewerPeriod.date).toDate() : null;
-
- const filterLine =
- sourceViewerPeriodDate != null
- ? line => {
- if (line.scmDate) {
- const scmDate = moment(line.scmDate).toDate();
- return scmDate >= sourceViewerPeriodDate;
- } else {
- return false;
- }
- }
- : undefined;
-
- return (
- <div ref="container" className="measure-details-plain-list">
- <ListHeader
- metric={metric}
- breadcrumbs={breadcrumbs}
- componentsCount={components.length}
- selectedIndex={selectedIndex}
- onSelectPrevious={onSelectPrevious}
- onSelectNext={onSelectNext}
- onBrowse={this.handleBreadcrumbClick.bind(this)}
- />
-
- {!selected &&
- <div className={classNames({ 'new-loading': fetching })}>
- {!fetching || components.length !== 0
- ? <div>
- <ComponentsList
- components={components}
- metrics={metrics}
- selected={selected}
- metric={metric}
- onClick={this.handleClick.bind(this)}
- />
- <ListFooter
- count={components.length}
- total={total}
- loadMore={this.handleFetchMore.bind(this)}
- />
- </div>
- : <Spinner />}
- </div>}
-
- {!!selected &&
- <div className="measure-details-viewer">
- <SourceViewer component={selected.key} filterLine={filterLine} />
- </div>}
- </div>
- );
- }
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import ListView from './ListView';
-import {
- fetchList,
- fetchMore,
- selectComponent,
- selectNext,
- selectPrevious
-} from '../../store/listViewActions';
-import {
- getMeasuresAppListComponents,
- getMeasuresAppListSelected,
- getMeasuresAppListTotal,
- getMeasuresAppListPageIndex,
- getMeasuresAppAllMetrics,
- getMeasuresAppDetailsMetric,
- isMeasuresAppFetching,
- getMeasuresAppComponent
-} from '../../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- components: getMeasuresAppListComponents(state),
- selected: getMeasuresAppListSelected(state),
- total: getMeasuresAppListTotal(state),
- pageIndex: getMeasuresAppListPageIndex(state),
- component: getMeasuresAppComponent(state),
- metrics: getMeasuresAppAllMetrics(state),
- metric: getMeasuresAppDetailsMetric(state),
- fetching: isMeasuresAppFetching(state)
- };
-};
-
-const mapDispatchToProps = dispatch => {
- return {
- onFetchList: (baseComponent, metric, periodIndex) =>
- dispatch(fetchList(baseComponent, metric, periodIndex)),
- onFetchMore: periodIndex => dispatch(fetchMore(periodIndex)),
- onSelect: component => dispatch(selectComponent(component)),
- onSelectNext: component => dispatch(selectNext(component)),
- onSelectPrevious: component => dispatch(selectPrevious(component))
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(ListView);
+++ /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.
- */
-import React from 'react';
-import Measure from '../../components/Measure';
-
-const MeasureCell = ({ component, metric }) => {
- return (
- <td className="thin nowrap text-right">
- <span id={'component-measures-component-measure-' + component.key + '-' + metric.key}>
- <Measure measure={{ value: component.value, leak: component.leak }} metric={metric} />
- </span>
- </td>
- );
-};
-
-export default MeasureCell;
+++ /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.
- */
-import React from 'react';
-import { Link } from 'react-router';
-import IconList from './../../components/IconList';
-import IconTree from './../../components/IconTree';
-import IconBubbles from './../../components/IconBubbles';
-import IconTreemap from './../../components/IconTreemap';
-import { hasBubbleChart, hasTreemap } from '../../utils';
-import { translate } from '../../../../helpers/l10n';
-
-export default function MeasureDrilldown(props) {
- const { children, component, metric, ...other } = props;
-
- const child = React.cloneElement(children, { ...other });
-
- return (
- <div className="measure-details-drilldown">
- <ul className="measure-details-drilldown-mode">
- {component.qualifier !== 'DEV' &&
- <li>
- <Link
- activeClassName="active"
- to={{
- pathname: `/component_measures_old/metric/${metric.key}/list`,
- query: { id: component.key }
- }}>
- <IconList />
- {translate('component_measures.tab.list')}
- </Link>
- </li>}
-
- <li>
- <Link
- activeClassName="active"
- to={{
- pathname: `/component_measures_old/metric/${metric.key}/tree`,
- query: { id: component.key }
- }}>
- <IconTree />
- {translate('component_measures.tab.tree')}
- </Link>
- </li>
-
- {hasBubbleChart(metric.key) &&
- <li>
- <Link
- activeClassName="active"
- to={{
- pathname: `/component_measures_old/metric/${metric.key}/bubbles`,
- query: { id: component.key }
- }}>
- <IconBubbles />
- {translate('component_measures.tab.bubbles')}
- </Link>
- </li>}
-
- {hasTreemap(metric) &&
- <li>
- <Link
- activeClassName="active"
- to={{
- pathname: `/component_measures_old/metric/${metric.key}/treemap`,
- query: { id: component.key }
- }}>
- <IconTreemap />
- {translate('component_measures.tab.treemap')}
- </Link>
- </li>}
- </ul>
-
- {child}
- </div>
- );
-}
+++ /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.
- */
-import React from 'react';
-import moment from 'moment';
-import ComponentsList from './ComponentsList';
-import ListHeader from './ListHeader';
-import Spinner from '../../components/Spinner';
-import SourceViewer from '../../../../components/SourceViewer/SourceViewer';
-import ListFooter from '../../../../components/controls/ListFooter';
-
-export default class TreeView extends React.PureComponent {
- componentDidMount() {
- this.handleChangeBaseComponent(this.props.component);
- }
-
- componentDidUpdate(nextProps) {
- if (nextProps.metric !== this.props.metric) {
- this.handleChangeBaseComponent(this.props.component);
- }
-
- if (this.props.selected) {
- this.scrollToViewer();
- } else if (this.scrollTop) {
- this.scrollToStoredPosition();
- }
- }
-
- scrollToViewer() {
- const { container } = this.refs;
- const top = container.getBoundingClientRect().top + window.scrollY - 95 - 10;
-
- // scroll only to top
- if (window.scrollY > top) {
- window.scrollTo(0, top);
- }
- }
-
- scrollToStoredPosition() {
- window.scrollTo(0, this.scrollTop);
- this.scrollTop = null;
- }
-
- storeScrollPosition() {
- this.scrollTop = window.scrollY;
- }
-
- handleChangeBaseComponent(baseComponent) {
- const { metric, onStart } = this.props;
- const periodIndex = this.props.location.query.period || 1;
- onStart(baseComponent, metric, Number(periodIndex));
- }
-
- handleFetchMore() {
- this.props.onFetchMore();
- }
-
- changeSelected(selected) {
- this.props.onSelect(selected);
- }
-
- canDrilldown(component) {
- return !['FIL', 'UTS'].includes(component.qualifier);
- }
-
- handleClick(selected) {
- if (this.canDrilldown(selected)) {
- this.props.onDrilldown(selected);
- } else {
- this.storeScrollPosition();
- this.props.onSelect(selected);
- }
- }
-
- handleBreadcrumbClick(component) {
- this.props.onUseBreadcrumbs(component, this.props.metric);
- }
-
- render() {
- const {
- components,
- metrics,
- breadcrumbs,
- metric,
- leakPeriod,
- selected,
- total,
- fetching
- } = this.props;
- const { onSelectNext, onSelectPrevious } = this.props;
-
- const selectedIndex = components.indexOf(selected);
- const sourceViewerPeriod = metric.key.indexOf('new_') === 0 && !!leakPeriod ? leakPeriod : null;
- const sourceViewerPeriodDate =
- sourceViewerPeriod != null ? moment(sourceViewerPeriod.date).toDate() : null;
-
- const filterLine =
- sourceViewerPeriodDate != null
- ? line => {
- if (line.scmDate) {
- const scmDate = moment(line.scmDate).toDate();
- return scmDate >= sourceViewerPeriodDate;
- } else {
- return false;
- }
- }
- : undefined;
-
- return (
- <div ref="container" className="measure-details-plain-list">
- <ListHeader
- metric={metric}
- breadcrumbs={breadcrumbs}
- componentsCount={components.length}
- selectedIndex={selectedIndex}
- onSelectPrevious={onSelectPrevious}
- onSelectNext={onSelectNext}
- onBrowse={this.handleBreadcrumbClick.bind(this)}
- />
-
- {!selected &&
- <div>
- {!fetching || components.length !== 0
- ? <div>
- <ComponentsList
- components={components}
- metrics={metrics}
- selected={selected}
- metric={metric}
- onClick={this.handleClick.bind(this)}
- />
- <ListFooter
- count={components.length}
- total={total}
- loadMore={this.handleFetchMore.bind(this)}
- />
- </div>
- : <Spinner />}
- </div>}
-
- {!!selected &&
- <div className="measure-details-viewer">
- <SourceViewer component={selected.key} filterLine={filterLine} />
- </div>}
- </div>
- );
- }
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import TreeView from './TreeView';
-import {
- start,
- drilldown,
- useBreadcrumbs,
- fetchMore,
- selectComponent,
- selectNext,
- selectPrevious
-} from '../../store/treeViewActions';
-import {
- getMeasuresAppTreeComponents,
- getMeasuresAppTreeBreadcrumbs,
- getMeasuresAppTreeSelected,
- getMeasuresAppTreeTotal,
- getMeasuresAppTreePageIndex,
- getMeasuresAppAllMetrics,
- getMeasuresAppDetailsMetric,
- isMeasuresAppFetching,
- getMeasuresAppComponent
-} from '../../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- components: getMeasuresAppTreeComponents(state),
- breadcrumbs: getMeasuresAppTreeBreadcrumbs(state),
- selected: getMeasuresAppTreeSelected(state),
- total: getMeasuresAppTreeTotal(state),
- pageIndex: getMeasuresAppTreePageIndex(state),
- component: getMeasuresAppComponent(state),
- metrics: getMeasuresAppAllMetrics(state),
- metric: getMeasuresAppDetailsMetric(state),
- fetching: isMeasuresAppFetching(state)
- };
-};
-
-const mapDispatchToProps = dispatch => {
- return {
- onStart: (rootComponent, metric, periodIndex) =>
- dispatch(start(rootComponent, metric, periodIndex)),
- onDrilldown: component => dispatch(drilldown(component)),
- onUseBreadcrumbs: component => dispatch(useBreadcrumbs(component)),
- onFetchMore: () => dispatch(fetchMore()),
- onSelect: component => dispatch(selectComponent(component)),
- onSelectNext: component => dispatch(selectNext(component)),
- onSelectPrevious: component => dispatch(selectPrevious(component))
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(TreeView);
+++ /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.
- */
-import { DISPLAY_HOME } from '../app/actions';
-import { REQUEST_MEASURE, RECEIVE_MEASURE } from './actions';
-
-const initialState = {
- metric: undefined,
- secondaryMeasure: undefined,
- measure: undefined,
- periods: undefined
-};
-
-export default function appReducer(state = initialState, action = {}) {
- switch (action.type) {
- case DISPLAY_HOME:
- return initialState;
- case REQUEST_MEASURE:
- return { ...state, metric: action.metric };
- case RECEIVE_MEASURE:
- return {
- ...state,
- measure: action.measure,
- secondaryMeasure: action.secondaryMeasure,
- periods: action.periods
- };
- default:
- return state;
- }
-}
+++ /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.
- */
-import React from 'react';
-import { scaleLinear, scaleOrdinal } from 'd3-scale';
-import Spinner from './../../components/Spinner';
-import { getLeakValue } from '../../utils';
-import { Treemap } from '../../../../components/charts/treemap';
-import { getChildren } from '../../../../api/components';
-import { formatMeasure } from '../../../../helpers/measures';
-import {
- translate,
- translateWithParameters,
- getLocalizedMetricName
-} from '../../../../helpers/l10n';
-import { getComponentUrl } from '../../../../helpers/urls';
-import Workspace from '../../../../components/workspace/main';
-
-const HEIGHT = 500;
-
-export default class MeasureTreemap extends React.PureComponent {
- state = {
- fetching: true,
- components: [],
- breadcrumbs: []
- };
-
- componentDidMount() {
- const { component } = this.props;
-
- this.mounted = true;
- this.fetchComponents(component.key);
- }
-
- componentDidUpdate(nextProps) {
- if (nextProps.metric !== this.props.metric) {
- this.fetchComponents(this.props.component.key);
- }
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- fetchComponents(componentKey) {
- const { metric } = this.props;
- const metrics = ['ncloc', metric.key];
- const options = {
- s: 'metric',
- metricSort: 'ncloc',
- asc: false
- };
-
- return getChildren(componentKey, metrics, options).then(r => {
- const components = r.components.map(component => {
- const measures = {};
- const key = component.refKey || component.key;
-
- component.measures.forEach(measure => {
- const shouldUseLeak = measure.metric.indexOf('new_') === 0;
- measures[measure.metric] = shouldUseLeak ? getLeakValue(measure) : measure.value;
- });
- return { ...component, measures, key };
- });
-
- this.setState({
- components,
- fetching: false
- });
- });
- }
-
- getTooltip(component) {
- const { metric } = this.props;
-
- let inner = [
- component.name,
- `${translate('metric.ncloc.name')}: ${formatMeasure(component.measures['ncloc'], 'INT')}`
- ];
-
- const colorMeasure = component.measures[metric.key];
- const formatted = colorMeasure != null ? formatMeasure(colorMeasure, metric.type) : '—';
- inner.push(`${getLocalizedMetricName(metric)}: ${formatted}`);
- inner = inner.join('<br>');
- return `<div class="text-left">${inner}</div>`;
- }
- getPercentColorScale(metric) {
- const color = scaleLinear().domain([0, 25, 50, 75, 100]);
- color.range(
- metric.direction === 1
- ? ['#d4333f', '#ed7d20', '#eabe06', '#b0d513', '#00aa00']
- : ['#00aa00', '#b0d513', '#eabe06', '#ed7d20', '#d4333f']
- );
- return color;
- }
- getRatingColorScale() {
- return scaleLinear()
- .domain([1, 2, 3, 4, 5])
- .range(['#00aa00', '#b0d513', '#eabe06', '#ed7d20', '#d4333f']);
- }
- getLevelColorScale() {
- return scaleOrdinal()
- .domain(['ERROR', 'WARN', 'OK', 'NONE'])
- .range(['#d4333f', '#ed7d20', '#00aa00', '#b4b4b4']);
- }
- getScale() {
- const { metric } = this.props;
- if (metric.type === 'LEVEL') {
- return this.getLevelColorScale();
- }
- if (metric.type === 'RATING') {
- return this.getRatingColorScale();
- }
- return this.getPercentColorScale(metric);
- }
- handleRectangleClick(node) {
- const isFile = node.qualifier === 'FIL' || node.qualifier === 'UTS';
- if (isFile) {
- Workspace.openComponent({ key: node.key });
- return;
- }
- this.fetchComponents(node.key).then(() => {
- let nextBreadcrumbs = [...this.state.breadcrumbs];
- const index = this.state.breadcrumbs.findIndex(b => b.key === node.key);
- if (index !== -1) {
- nextBreadcrumbs = nextBreadcrumbs.slice(0, index);
- }
- nextBreadcrumbs = [
- ...nextBreadcrumbs,
- {
- key: node.key,
- name: node.name,
- qualifier: node.qualifier
- }
- ];
- this.setState({ breadcrumbs: nextBreadcrumbs });
- });
- }
- handleReset() {
- const { component } = this.props;
- this.fetchComponents(component.key).then(() => {
- this.setState({ breadcrumbs: [] });
- });
- }
- renderTreemap() {
- const { metric } = this.props;
- const colorScale = this.getScale();
- const items = this.state.components
- .filter(component => component.measures['ncloc'])
- .map(component => {
- const colorMeasure = component.measures[metric.key];
- return {
- id: component.id,
- key: component.key,
- name: component.name,
- qualifier: component.qualifier,
- size: component.measures['ncloc'],
- color: colorMeasure != null ? colorScale(colorMeasure) : '#777',
- tooltip: this.getTooltip(component),
- label: component.name,
- link: getComponentUrl(component.key)
- };
- });
- return (
- <Treemap
- items={items}
- breadcrumbs={this.state.breadcrumbs}
- height={HEIGHT}
- canBeClicked={() => true}
- onRectangleClick={this.handleRectangleClick.bind(this)}
- onReset={this.handleReset.bind(this)}
- />
- );
- }
- render() {
- const { metric } = this.props;
- const { fetching } = this.state;
- if (fetching) {
- return (
- <div className="measure-details-treemap">
- <div className="note text-center" style={{ lineHeight: `${HEIGHT}px` }}>
- <Spinner />
- </div>
- </div>
- );
- }
- return (
- <div className="measure-details-treemap">
- <ul className="list-inline note measure-details-treemap-legend">
- <li>
- {translateWithParameters(
- 'component_measures.legend.color_x',
- getLocalizedMetricName(metric)
- )}
- </li>
- <li>
- {translateWithParameters(
- 'component_measures.legend.size_x',
- translate('metric.ncloc.name')
- )}
- </li>
- </ul>
- {this.renderTreemap()}
- </div>
- );
- }
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import MeasureTreemap from './MeasureTreemap';
-import {
- getMeasuresAppDetailsMetric,
- getMeasuresAppComponent
-} from '../../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- component: getMeasuresAppComponent(state),
- metric: getMeasuresAppDetailsMetric(state)
- };
-};
-
-const mapDispatchToProps = () => {
- return {};
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(MeasureTreemap);
+++ /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.
- */
-import React from 'react';
-import AllMeasuresDomain from './AllMeasuresDomain';
-import { getLeakPeriodLabel } from '../../../helpers/periods';
-
-export default function AllMeasures(props) {
- const { component, domains, periods } = props;
- const leakPeriodLabel = getLeakPeriodLabel(periods);
-
- return (
- <ul className="measures-domains">
- {domains.map(domain =>
- <AllMeasuresDomain
- key={domain.name}
- domain={domain}
- component={component}
- leakPeriodLabel={leakPeriodLabel}
- />
- )}
- </ul>
- );
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import AllMeasures from './AllMeasures';
-import {
- getMeasuresAppHomeDomains,
- getMeasuresAppHomePeriods,
- getMeasuresAppComponent
-} from '../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- component: getMeasuresAppComponent(state),
- domains: getMeasuresAppHomeDomains(state),
- periods: getMeasuresAppHomePeriods(state)
- };
-};
-
-export default connect(mapStateToProps)(AllMeasures);
+++ /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.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import HomeMeasuresList from './HomeMeasuresList';
-import { getLocalizedMetricDomain } from '../../../helpers/l10n';
-
-export default function AllMeasuresDomain(props) {
- const { domain, component, displayHeader } = props;
-
- return (
- <li>
- {displayHeader &&
- <header className="page-header">
- <h3 className="page-title">
- {getLocalizedMetricDomain(domain.name)}
- </h3>
- </header>}
-
- <HomeMeasuresList domain={domain} component={component} />
- </li>
- );
-}
-
-AllMeasuresDomain.defaultProps = {
- displayHeader: true
-};
-
-AllMeasuresDomain.propTypes = {
- displayHeader: PropTypes.bool
-};
+++ /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.
- */
-import React from 'react';
-import HomeMeasuresList from './HomeMeasuresList';
-import MeasureBubbleChartContainer from '../components/bubbleChart/MeasureBubbleChartContainer';
-import { hasBubbleChart } from '../utils';
-
-export default function DomainMeasures(props) {
- const { component, domains } = props;
- const { domainName } = props.params;
- const domain = domains.find(d => d.name === domainName);
-
- return (
- <section id="component-measures-domain">
- <HomeMeasuresList domain={domain} component={component} />
-
- {hasBubbleChart(domainName) && <MeasureBubbleChartContainer domainName={domainName} />}
- </section>
- );
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import DomainMeasures from './DomainMeasures';
-import {
- getMeasuresAppHomeDomains,
- getMeasuresAppHomePeriods,
- getMeasuresAppComponent
-} from '../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- component: getMeasuresAppComponent(state),
- domains: getMeasuresAppHomeDomains(state),
- periods: getMeasuresAppHomePeriods(state)
- };
-};
-
-export default connect(mapStateToProps)(DomainMeasures);
+++ /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.
- */
-import React from 'react';
-import { Link, IndexLink } from 'react-router';
-import LeakPeriodLegend from '../components/LeakPeriodLegend';
-import { getLeakPeriod } from '../../../helpers/periods';
-import { translate, getLocalizedMetricDomain } from '../../../helpers/l10n';
-
-export default class Home extends React.PureComponent {
- componentDidMount() {
- document.querySelector('html').classList.add('dashboard-page');
- this.props.onDisplay();
- this.props.fetchMeasures();
- }
-
- componentWillUnmount() {
- document.querySelector('html').classList.remove('dashboard-page');
- }
-
- render() {
- const { component, domains, periods } = this.props;
-
- if (domains == null) {
- return null;
- }
-
- const leakPeriod = getLeakPeriod(periods);
-
- return (
- <section id="component-measures-home" className="page page-container page-limited">
- <header id="component-measures-home-header" className="home-header">
- <nav className="nav-pills pull-left">
- <ul>
- <li>
- <IndexLink
- to={{ pathname: '/component_measures_old', query: { id: component.key } }}
- activeClassName="active">
- {translate('all')}
- </IndexLink>
- </li>
- {domains.map(domain =>
- <li key={domain.name}>
- <Link
- to={{
- pathname: `/component_measures_old/domain/${domain.name}`,
- query: { id: component.key }
- }}
- activeClassName="active">
- {getLocalizedMetricDomain(domain.name)}
- </Link>
- </li>
- )}
- </ul>
- </nav>
-
- {leakPeriod != null && <LeakPeriodLegend component={component} period={leakPeriod} />}
- </header>
-
- <main id="component-measures-home-main">
- {this.props.children}
- </main>
- </section>
- );
- }
-}
+++ /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.
- */
-import { connect } from 'react-redux';
-import Home from './Home';
-import { fetchMeasures } from './actions';
-import { displayHome } from '../app/actions';
-import {
- getMeasuresAppHomeDomains,
- getMeasuresAppHomePeriods,
- getMeasuresAppComponent
-} from '../../../store/rootReducer';
-
-const mapStateToProps = state => {
- return {
- component: getMeasuresAppComponent(state),
- domains: getMeasuresAppHomeDomains(state),
- periods: getMeasuresAppHomePeriods(state)
- };
-};
-
-const mapDispatchToProps = dispatch => {
- return {
- onDisplay: () => dispatch(displayHome()),
- fetchMeasures: () => dispatch(fetchMeasures())
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(Home);
+++ /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.
- */
-import React from 'react';
-import { partition, sortBy } from 'lodash';
-import MeasuresList from './MeasuresList';
-import { domains } from '../config/domains';
-import { getLocalizedMetricName } from '../../../helpers/l10n';
-
-function sortMeasures(measures, order) {
- const [known, unknown] = partition(measures, measure => order.includes(measure.metric.key));
- return [
- ...sortBy(known, measure => order.indexOf(measure.metric.key)),
- ...sortBy(unknown, measure => getLocalizedMetricName(measure.metric))
- ];
-}
-
-function filterIssuesMeasures(measures) {
- const BANNED_MEASURES = [
- 'blocker_violations',
- 'new_blocker_violations',
- 'critical_violations',
- 'new_critical_violations',
- 'major_violations',
- 'new_major_violations',
- 'minor_violations',
- 'new_minor_violations',
- 'info_violations',
- 'new_info_violations'
- ];
- return measures.filter(measure => !BANNED_MEASURES.includes(measure.metric.key));
-}
-
-const HomeMeasuresList = ({ domain, component }) => {
- const { measures, name } = domain;
- const config = domains[name] || {};
-
- const filteredMeasures = filterIssuesMeasures(measures);
-
- const configMain = config.main || [];
- const [mainMeasures, otherMeasures] = partition(filteredMeasures, measure =>
- configMain.includes(measure.metric.key)
- );
-
- const configOrder = config.order || [];
- const sortedMainMeasures = sortMeasures(mainMeasures, configOrder);
- const sortedOtherMeasures = sortMeasures(otherMeasures, configOrder);
-
- return (
- <div className="home-measures-list clearfix">
- {sortedMainMeasures.length > 0 &&
- <MeasuresList
- className="main-domain-measures"
- measures={sortedMainMeasures}
- component={component}
- spaces={[]}
- />}
-
- {sortedOtherMeasures.length > 0 &&
- <MeasuresList measures={sortedOtherMeasures} component={component} spaces={[]} />}
- </div>
- );
-};
-
-export default HomeMeasuresList;
+++ /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.
- */
-import React from 'react';
-import Measure from '../components/Measure';
-import { isDiffMetric } from '../../../helpers/measures';
-
-const MeasureListValue = ({ measure }) => {
- const { metric } = measure;
-
- if (isDiffMetric(metric.key)) {
- return (
- <div
- id={`measure-${measure.metric.key}-leak`}
- className="domain-measures-value domain-measures-leak">
- <Measure measure={measure} />
- </div>
- );
- }
-
- return (
- <div id={`measure-${measure.metric.key}-value`} className="domain-measures-value">
- <Measure measure={measure} />
- </div>
- );
-};
-
-export default MeasureListValue;
+++ /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.
- */
-import React from 'react';
-import { Link } from 'react-router';
-import MeasureListValue from './MeasureListValue';
-import { getLocalizedMetricName } from '../../../helpers/l10n';
-import IssueTypeIcon from '../../../components/ui/IssueTypeIcon';
-
-const MeasuresList = ({ measures, component, className = 'domain-measures' }) => {
- return (
- <ul className={className}>
- {measures.map(measure =>
- <li key={measure.metric.key} id={`measure-${measure.metric.key}`}>
- <Link
- to={{
- pathname: `/component_measures_old/metric/${measure.metric.key}`,
- query: { id: component.key }
- }}>
- <div className="domain-measures-name">
- <IssueTypeIcon query={measure.metric.key} className="little-spacer-right" />
- <span id={`measure-${measure.metric.key}-name`}>
- {getLocalizedMetricName(measure.metric)}
- </span>
- </div>
-
- <MeasureListValue measure={measure} />
- </Link>
- </li>
- )}
- </ul>
- );
-};
-
-export default MeasuresList;
+++ /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.
- */
-import { startFetching, stopFetching } from '../store/statusActions';
-import { getMeasuresAndMeta } from '../../../api/measures';
-import { getLeakValue } from '../utils';
-import { getMeasuresAppComponent, getMeasuresAppAllMetrics } from '../../../store/rootReducer';
-
-export const RECEIVE_MEASURES = 'measuresApp/home/RECEIVE_MEASURES';
-
-export function receiveMeasures(measures, periods) {
- return { type: RECEIVE_MEASURES, measures, periods };
-}
-
-function banQualityGate(component, measures) {
- let newMeasures = [...measures];
-
- if (!['VW', 'SVW', 'APP'].includes(component.qualifier)) {
- newMeasures = newMeasures.filter(measure => measure.metric !== 'alert_status');
- }
-
- if (component.qualifier === 'APP') {
- newMeasures = newMeasures.filter(
- measure =>
- measure.metric !== 'releasability_rating' && measure.metric !== 'releasability_effort'
- );
- }
-
- return newMeasures;
-}
-
-export function fetchMeasures() {
- return (dispatch, getState) => {
- dispatch(startFetching());
-
- const state = getState();
- const component = getMeasuresAppComponent(state);
- const metrics = getMeasuresAppAllMetrics(state);
-
- const metricKeys = metrics
- .filter(metric => !metric.hidden)
- .filter(metric => metric.type !== 'DATA' && metric.type !== 'DISTRIB')
- .map(metric => metric.key);
-
- getMeasuresAndMeta(component.key, metricKeys, { additionalFields: 'periods' }).then(r => {
- const measures = banQualityGate(component, r.component.measures)
- .map(measure => {
- const metric = metrics.find(metric => metric.key === measure.metric);
- const leak = getLeakValue(measure);
- return { ...measure, metric, leak };
- })
- .filter(measure => {
- const hasValue = measure.value != null;
- const hasLeakValue = measure.leak != null;
- return hasValue || hasLeakValue;
- });
-
- const newBugs = measures.find(measure => measure.metric.key === 'new_bugs');
-
- const applicationPeriods = newBugs ? [{ index: 1 }] : [];
- const periods = component.qualifier === 'APP' ? applicationPeriods : r.periods;
-
- dispatch(receiveMeasures(measures, periods));
- dispatch(stopFetching());
- });
- };
-}
+++ /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.
- */
-import { groupBy, partition, sortBy, toPairs } from 'lodash';
-import { RECEIVE_MEASURES } from './actions';
-import { getLocalizedMetricName } from '../../../helpers/l10n';
-
-const initialState = {
- measures: undefined,
- domains: undefined,
- periods: undefined
-};
-
-function groupByDomains(measures) {
- const KNOWN_DOMAINS = [
- 'Releasability',
- 'Reliability',
- 'Security',
- 'Maintainability',
- 'Coverage',
- 'Duplications',
- 'Size',
- 'Complexity'
- ];
-
- const domains = sortBy(
- toPairs(groupBy(measures, measure => measure.metric.domain)).map(r => {
- const [name, measures] = r;
- const sortedMeasures = sortBy(measures, measure => getLocalizedMetricName(measure.metric));
-
- return { name, measures: sortedMeasures };
- }),
- 'name'
- );
- const [knownDomains, unknownDomains] = partition(domains, domain =>
- KNOWN_DOMAINS.includes(domain.name)
- );
- return [
- ...sortBy(knownDomains, domain => KNOWN_DOMAINS.indexOf(domain.name)),
- ...sortBy(unknownDomains, domain => domain.name)
- ];
-}
-
-export default function(state = initialState, action = {}) {
- switch (action.type) {
- case RECEIVE_MEASURES:
- return {
- ...state,
- measures: action.measures,
- domains: groupByDomains(action.measures),
- periods: action.periods
- };
- default:
- return state;
- }
-}
+++ /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.
- */
-import { isDiffMetric } from '../../helpers/measures';
-
-export function checkHistoryExistence(nextState, replace) {
- const { metricKey } = nextState.params;
-
- if (isDiffMetric(metricKey)) {
- replace({
- pathname: metricKey,
- query: nextState.location.query
- });
- }
-}
+++ /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.
- */
-const routes = [
- {
- getComponent(_, callback) {
- import('./app/AppContainer').then(i => callback(null, i.default));
- },
- childRoutes: [
- {
- getComponent(_, callback) {
- import('./home/HomeContainer').then(i => callback(null, i.default));
- },
- childRoutes: [
- {
- getIndexRoute(_, callback) {
- import('./home/AllMeasuresContainer').then(i =>
- callback(null, { component: i.default })
- );
- }
- },
- {
- path: 'domain/:domainName',
- getComponent(_, callback) {
- import('./home/DomainMeasuresContainer').then(i => callback(null, i.default));
- }
- }
- ]
- },
- {
- path: 'metric/:metricKey',
- getComponent(_, callback) {
- import('./details/MeasureDetailsContainer').then(i => callback(null, i.default));
- },
- childRoutes: [
- {
- indexRoute: {
- onEnter(nextState, replace) {
- const { params, location } = nextState;
- replace({
- pathname: `/component_measures_old/metric/${params.metricKey}/list`,
- query: location.query
- });
- }
- }
- },
- {
- path: 'list',
- getComponent(_, callback) {
- import('./details/drilldown/ListViewContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'tree',
- getComponent(_, callback) {
- import('./details/drilldown/TreeViewContainer').then(i => callback(null, i.default));
- }
- },
- {
- path: 'history',
- onEnter(nextState, replace) {
- replace({
- pathname: '/project/activity',
- query: {
- id: nextState.location.query.id,
- graph: 'custom',
- custom_metrics: nextState.params.metricKey
- }
- });
- }
- },
- {
- path: 'treemap',
- getComponent(_, callback) {
- import('./details/treemap/MeasureTreemapContainer').then(i =>
- callback(null, i.default)
- );
- }
- }
- ]
- }
- ]
- }
-];
-
-export default routes;
+++ /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.
- */
-import { getComponentTree } from '../../../api/components';
-import { enhanceWithMeasure } from '../utils';
-import { startFetching, stopFetching } from './statusActions';
-import complementary from '../config/complementary';
-import { getMeasuresAppList } from '../../../store/rootReducer';
-
-export const UPDATE_STORE = 'measuresApp/drilldown/list/UPDATE_STORE';
-
-function updateStore(state) {
- return { type: UPDATE_STORE, state };
-}
-
-function getComplementary(metric) {
- const comp = complementary[metric] || [];
- return [metric, ...comp];
-}
-
-function makeRequest(baseComponent, metric, options, periodIndex = 1) {
- const asc = metric.direction === 1;
- const ps = 100;
- const finalOptions = { asc, ps, metricSortFilter: 'withMeasuresOnly' };
-
- if (metric.key.indexOf('new_') === 0) {
- Object.assign(options, {
- s: 'metricPeriod,name',
- metricSort: metric.key,
- metricPeriodSort: periodIndex
- });
- } else {
- Object.assign(options, {
- s: 'metric,name',
- metricSort: metric.key
- });
- }
-
- Object.assign(finalOptions, options);
- return getComponentTree('leaves', baseComponent.key, getComplementary(metric.key), finalOptions);
-}
-
-function fetchLeaves(baseComponent, metric, pageIndex = 1, periodIndex = 1) {
- const options = { p: pageIndex };
-
- return makeRequest(baseComponent, metric, options, periodIndex).then(r => {
- const nextComponents = enhanceWithMeasure(r.components, metric.key, periodIndex);
-
- return {
- components: nextComponents,
- pageIndex: r.paging.pageIndex,
- total: r.paging.total
- };
- });
-}
-
-/**
- * Fetch the first page of components for a given base component
- * @param baseComponent
- * @param metric
- * @param periodIndex
- */
-export function fetchList(baseComponent, metric, periodIndex = 1) {
- return (dispatch, getState) => {
- const list = getMeasuresAppList(getState());
- if (list.baseComponent === baseComponent && list.metric === metric) {
- return Promise.resolve();
- }
-
- dispatch(startFetching());
- return fetchLeaves(baseComponent, metric, 1, periodIndex).then(r => {
- dispatch(
- updateStore({
- ...r,
- baseComponent,
- metric
- })
- );
- dispatch(stopFetching());
- });
- };
-}
-
-export function fetchMore(periodIndex) {
- return (dispatch, getState) => {
- const { baseComponent, metric, pageIndex, components } = getMeasuresAppList(getState());
- dispatch(startFetching());
- return fetchLeaves(baseComponent, metric, pageIndex + 1, periodIndex).then(r => {
- const nextComponents = [...components, ...r.components];
- dispatch(updateStore({ ...r, components: nextComponents }));
- dispatch(stopFetching());
- });
- };
-}
-
-/**
- * Select specified component from the list
- * @param component A component to select
- */
-export function selectComponent(component) {
- return dispatch => {
- dispatch(updateStore({ selected: component }));
- };
-}
-
-/**
- * Select next element from the list of components
- */
-export function selectNext() {
- return (dispatch, getState) => {
- const { components, selected } = getMeasuresAppList(getState());
- const selectedIndex = components.indexOf(selected);
- if (selectedIndex < components.length - 1) {
- const nextSelected = components[selectedIndex + 1];
- dispatch(selectComponent(nextSelected));
- }
- };
-}
-
-/**
- * Select previous element from the list of components
- */
-export function selectPrevious() {
- return (dispatch, getState) => {
- const { components, selected } = getMeasuresAppList(getState());
- const selectedIndex = components.indexOf(selected);
- if (selectedIndex > 0) {
- const nextSelected = components[selectedIndex - 1];
- dispatch(selectComponent(nextSelected));
- }
- };
-}
+++ /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.
- */
-import { DISPLAY_HOME } from './../app/actions';
-import { UPDATE_STORE } from './listViewActions';
-
-const initialState = {
- components: [],
- total: 0
-};
-
-export default function drilldownReducer(state = initialState, action = {}) {
- switch (action.type) {
- case DISPLAY_HOME:
- return initialState;
- case UPDATE_STORE:
- return { ...state, ...action.state };
- default:
- return state;
- }
-}
+++ /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.
- */
-import { combineReducers } from 'redux';
-import appReducer from './../app/reducer';
-import statusReducer from './statusReducer';
-import homeReducer from '../home/reducer';
-import detailsReducer from '../details/reducer';
-import listViewReducer from './listViewReducer';
-import treeViewReducer from './treeViewReducer';
-
-export default combineReducers({
- app: appReducer,
- home: homeReducer,
- details: detailsReducer,
- list: listViewReducer,
- tree: treeViewReducer,
- status: statusReducer
-});
-
-export const getComponent = state => state.app.component;
-
-export const getAllMetrics = state => state.app.metrics;
-
-export const getDetailsMetric = state => state.details.metric;
-
-export const getDetailsMeasure = state => state.details.measure;
-
-export const getDetailsSecondaryMeasure = state => state.details.secondaryMeasure;
-
-export const getDetailsPeriods = state => state.details.periods;
-
-export const isFetching = state => state.status.fetching;
-
-export const getList = state => state.list;
-
-export const getListComponents = state => state.list.components;
-
-export const getListSelected = state => state.list.selected;
-
-export const getListTotal = state => state.list.total;
-
-export const getListPageIndex = state => state.list.pageIndex;
-
-export const getTree = state => state.tree;
-
-export const getTreeComponents = state => state.tree.components;
-
-export const getTreeBreadcrumbs = state => state.tree.breadcrumbs;
-
-export const getTreeSelected = state => state.tree.selected;
-
-export const getTreeTotal = state => state.tree.total;
-
-export const getTreePageIndex = state => state.tree.pageIndex;
-
-export const getHomeDomains = state => state.home.domains;
-
-export const getHomePeriods = state => state.home.periods;
+++ /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.
- */
-export const START_FETCHING = 'measuresApp/status/START_FETCHING';
-export const STOP_FETCHING = 'measuresApp/status/STOP_FETCHING';
-
-export function startFetching() {
- return { type: START_FETCHING };
-}
-
-export function stopFetching() {
- return { type: STOP_FETCHING };
-}
+++ /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.
- */
-import { START_FETCHING, STOP_FETCHING } from './statusActions';
-
-const initialState = {
- fetching: false
-};
-
-export default function drilldownReducer(state = initialState, action = {}) {
- switch (action.type) {
- case START_FETCHING:
- return { ...state, fetching: true };
- case STOP_FETCHING:
- return { ...state, fetching: false };
- default:
- return state;
- }
-}
+++ /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.
- */
-import { initial } from 'lodash';
-import { getComponentTree } from '../../../api/components';
-import { enhanceWithMeasure } from '../utils';
-import { startFetching, stopFetching } from './statusActions';
-import complementary from '../config/complementary';
-import { getMeasuresAppTree } from '../../../store/rootReducer';
-
-/*
- * Actions
- */
-
-export const UPDATE_STORE = 'measuresApp/drilldown/tree/UPDATE_STORE';
-export const INIT = 'measuresApp/drilldown/tree/INIT';
-
-/*
- * Action Creators
- */
-
-/**
- * Internal
- * Update store
- * @param state
- * @returns {{type: string, state: *}}
- */
-function updateStore(state) {
- return { type: UPDATE_STORE, state };
-}
-
-/**
- * Init tree view drilldown for the given root component and given metric
- * @param rootComponent
- * @param metric
- * @param periodIndex
- * @returns {{type: string, rootComponent: *, metric: *}}
- */
-function init(rootComponent, metric, periodIndex = 1) {
- return { type: INIT, rootComponent, metric, periodIndex };
-}
-
-/*
- * Workflow
- */
-
-function getComplementary(metric) {
- const comp = complementary[metric] || [];
- return [metric, ...comp];
-}
-
-function makeRequest(rootComponent, baseComponent, metric, options, periodIndex = 1) {
- const asc = metric.direction === 1;
- const ps = 100;
- const finalOptions = { asc, ps, metricSortFilter: 'withMeasuresOnly' };
-
- if (metric.key.indexOf('new_') === 0) {
- Object.assign(options, {
- s: 'metricPeriod,name',
- metricSort: metric.key,
- metricPeriodSort: periodIndex
- });
- } else {
- Object.assign(options, {
- s: 'metric,name',
- metricSort: metric.key
- });
- }
-
- if (rootComponent.qualifier === 'DEV' && baseComponent.qualifier !== 'DEV') {
- Object.assign(options, { developerId: rootComponent.id });
- }
-
- Object.assign(finalOptions, options);
-
- const finalKey = baseComponent.refKey || baseComponent.key;
-
- return getComponentTree('children', finalKey, getComplementary(metric.key), finalOptions);
-}
-
-function fetchComponents(rootComponent, baseComponent, metric, pageIndex = 1, periodIndex = 1) {
- const options = { p: pageIndex };
-
- return makeRequest(rootComponent, baseComponent, metric, options, periodIndex).then(r => {
- const nextComponents = enhanceWithMeasure(r.components, metric.key, periodIndex);
-
- return {
- baseComponent,
- components: nextComponents,
- pageIndex: r.paging.pageIndex,
- total: r.paging.total
- };
- });
-}
-
-/**
- * Fetch the first page of components for a given base component
- * @param baseComponent
- */
-function fetchList(baseComponent) {
- return (dispatch, getState) => {
- const { metric, periodIndex, rootComponent } = getMeasuresAppTree(getState());
-
- dispatch(startFetching());
- return fetchComponents(rootComponent, baseComponent, metric, 1, periodIndex).then(r => {
- dispatch(
- updateStore({
- ...r,
- baseComponent,
- breadcrumbs: [baseComponent]
- })
- );
- dispatch(stopFetching());
- });
- };
-}
-
-/**
- * Init tree view with root component and metric.
- * Fetch the first page of components if needed.
- * @param rootComponent
- * @param metric
- * @param periodIndex
- * @returns {function()}
- */
-export function start(rootComponent, metric, periodIndex = 1) {
- return (dispatch, getState) => {
- const tree = getMeasuresAppTree(getState());
- if (rootComponent === tree.rootComponent && metric === tree.metric) {
- return Promise.resolve();
- }
-
- dispatch(init(rootComponent, metric, periodIndex));
- dispatch(fetchList(rootComponent));
- };
-}
-
-/**
- * Drilldown to the component
- * @param component
- */
-export function drilldown(component) {
- return (dispatch, getState) => {
- const { metric, rootComponent, breadcrumbs, periodIndex } = getMeasuresAppTree(getState());
- dispatch(startFetching());
- return fetchComponents(rootComponent, component, metric, 1, periodIndex).then(r => {
- dispatch(
- updateStore({
- ...r,
- breadcrumbs: [...breadcrumbs, component],
- selected: undefined
- })
- );
- dispatch(stopFetching());
- });
- };
-}
-
-/**
- * Go up using breadcrumbs
- * @param component
- */
-export function useBreadcrumbs(component) {
- return (dispatch, getState) => {
- const { metric, rootComponent, breadcrumbs, periodIndex } = getMeasuresAppTree(getState());
- const index = breadcrumbs.indexOf(component);
- dispatch(startFetching());
- return fetchComponents(rootComponent, component, metric, 1, periodIndex).then(r => {
- dispatch(
- updateStore({
- ...r,
- breadcrumbs: breadcrumbs.slice(0, index + 1),
- selected: undefined
- })
- );
- dispatch(stopFetching());
- });
- };
-}
-
-export function fetchMore() {
- return (dispatch, getState) => {
- const {
- rootComponent,
- baseComponent,
- metric,
- pageIndex,
- components,
- periodIndex
- } = getMeasuresAppTree(getState());
- dispatch(startFetching());
- return fetchComponents(
- rootComponent,
- baseComponent,
- metric,
- pageIndex + 1,
- periodIndex
- ).then(r => {
- const nextComponents = [...components, ...r.components];
- dispatch(updateStore({ ...r, components: nextComponents }));
- dispatch(stopFetching());
- });
- };
-}
-
-/**
- * Select given component from the list
- * @param component
- */
-export function selectComponent(component) {
- return (dispatch, getState) => {
- const { breadcrumbs } = getMeasuresAppTree(getState());
- const nextBreadcrumbs = [...breadcrumbs, component];
- dispatch(
- updateStore({
- selected: component,
- breadcrumbs: nextBreadcrumbs
- })
- );
- };
-}
-
-/**
- * Select next element from the list of components
- */
-export function selectNext() {
- return (dispatch, getState) => {
- const { components, selected, breadcrumbs } = getMeasuresAppTree(getState());
- const selectedIndex = components.indexOf(selected);
- if (selectedIndex < components.length - 1) {
- const nextSelected = components[selectedIndex + 1];
- const nextBreadcrumbs = [...initial(breadcrumbs), nextSelected];
- dispatch(
- updateStore({
- selected: nextSelected,
- breadcrumbs: nextBreadcrumbs
- })
- );
- }
- };
-}
-
-/**
- * Select previous element from the list of components
- */
-export function selectPrevious() {
- return (dispatch, getState) => {
- const { components, selected, breadcrumbs } = getMeasuresAppTree(getState());
- const selectedIndex = components.indexOf(selected);
- if (selectedIndex > 0) {
- const nextSelected = components[selectedIndex - 1];
- const nextBreadcrumbs = [...initial(breadcrumbs), nextSelected];
- dispatch(
- updateStore({
- selected: nextSelected,
- breadcrumbs: nextBreadcrumbs
- })
- );
- }
- };
-}
+++ /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.
- */
-import { pick } from 'lodash';
-import { DISPLAY_HOME } from './../app/actions';
-import { UPDATE_STORE, INIT } from './treeViewActions';
-
-const initialState = {
- components: [],
- breadcrumbs: [],
- total: 0
-};
-
-export default function drilldownReducer(state = initialState, action = {}) {
- switch (action.type) {
- case DISPLAY_HOME:
- return initialState;
- case UPDATE_STORE:
- return { ...state, ...action.state };
- case INIT:
- return { ...state, ...pick(action, ['rootComponent', 'metric', 'periodIndex']) };
- default:
- return state;
- }
-}
+++ /dev/null
-.home-header {
- display: flex;
- justify-content: space-between;
- align-items: flex-start;
- margin-bottom: 20px;
-}
-
-.measures-domains {
-}
-
-.measures-domains > li {
- margin-bottom: 20px;
-}
-
-.measures-domains > li > div {
- border: 1px solid #e6e6e6;
- background-color: #fff;
-}
-
-.measures-domains-leak-header {
- line-height: 22px;
- padding: 0 10px;
- border: 1px solid #eae3c7;
- background-color: #fbf3d5;
- white-space: nowrap;
-}
-
-.main-domain-measures {
- display: flex;
- flex-wrap: wrap;
- justify-content: space-around;
- float: left;
- width: 480px;
- margin-right: 60px;
-}
-
-.main-domain-measures > li {
- padding: 12px 0;
-}
-
-.main-domain-measures > li > a {
- display: flex;
- flex-direction: column-reverse;
- width: 160px;
- border: none;
- text-align: center;
-}
-
-.main-domain-measures .domain-measures-value {
- height: 40px;
- box-sizing: border-box;
- color: #444;
- font-size: 30px;
- font-weight: 300;
-}
-
-.main-domain-measures .domain-measures-value .rating,
-.measure-details-value .rating {
- vertical-align: top;
- width: 40px;
- height: 40px;
- line-height: 40px;
- border-radius: 40px;
- font-size: 24px;
-}
-
-.main-domain-measures .domain-measures-name {
- margin-top: 8px;
-}
-
-.main-domain-measures .domain-measures-name > span:last-child {
- border-bottom: 1px solid #cae3f2;
-}
-
-.main-domain-measures .domain-measures-leak {
- margin: 0 20px;
- border: 1px solid #eae3c7;
- background-color: #fbf3d5;
-}
-
-.domain-measures {
- overflow: hidden;
- line-height: 1.4;
-}
-
-.domain-measures > li > a {
- display: flex;
- justify-content: space-between;
- border: none;
-}
-
-.domain-measures > li:nth-child(odd) > a {
- background-color: #f8f8f8;
-}
-
-.domain-measures > li > a:hover {
- background-color: #ecf6fe !important;
-}
-
-.domain-measures .domain-measures-name,
-.domain-measures .domain-measures-value {
- padding: 7px 10px;
- box-sizing: border-box;
-}
-
-.domain-measures .domain-measures-name {
- width: calc(100% - 160px);
- line-height: 24px;
-}
-
-.domain-measures .domain-measures-name > span {
- border-bottom: 1px solid #cae3f2;
-}
-
-.domain-measures .domain-measures-value {
- min-width: 80px;
- color: #444;
- text-align: right;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.domain-measures .domain-measures-leak {
- background-color: #fbf3d5;
- transition: background-color 0.3s ease;
-}
-
-.domain-measures .domain-measures > li:nth-child(odd) .domain-measures-leak {
- background-color: #f5eed0;
-}
-
-.measure-details {
- margin-top: 10px;
-}
-
-.measure-details-header {
- position: relative;
- margin-top: 10px;
- margin-bottom: 30px;
-}
-
-.measure-details-metric,
-.measure-details-value {
-}
-
-.measure-details-metric {
- display: inline-block;
- margin-bottom: 10px;
-}
-
-.measure-details-metric > a:not(.button) {
- border: none;
- color: #444;
-}
-
-.measure-details-metric > a:not(.button):hover {
- color: #236a97;
-}
-
-.measure-details-value {
- font-size: 24px;
-}
-
-.measure-details-value-absolute {
- display: inline-block;
- vertical-align: middle;
- padding: 5px 0;
- font-weight: 300;
-}
-
-.measure-details-value-leak {
- display: inline-block;
- vertical-align: middle;
- padding: 4px 10px;
- border: 1px solid #eae3c7;
- background-color: #fbf3d5;
- font-weight: 300;
-}
-
-.measure-details-value-absolute + .measure-details-value-leak {
- margin-left: 20px;
-}
-
-.measure-details-secondary {
- display: inline-block;
- vertical-align: middle;
- width: 260px;
- margin-left: 20px;
-}
-
-.measure-details-drilldown {
- margin-top: 20px;
-}
-
-.measure-details-drilldown-mode {
- display: flex;
- margin-bottom: 10px;
- border-bottom: 1px solid #e6e6e6;
-}
-
-.measure-details-drilldown-mode > li {
- margin-bottom: -1px;
-}
-
-.measure-details-drilldown-mode > li + li {
- margin-left: 2px;
-}
-
-.measure-details-drilldown-mode > li > a {
- display: inline-block;
- padding: 5px 10px;
- border-bottom: 2px solid transparent;
- color: #444;
-}
-
-.measure-details-drilldown-mode > li > a:hover,
-.measure-details-drilldown-mode > li > a.active {
- border-bottom-color: #4b9fd5;
-}
-
-.measure-details-drilldown-mode > li > a.active .measure-tab-icon path {
- fill: #4b9fd5;
-}
-
-.measure-details-plain-list {
-}
-
-.measure-details-components {
- width: 300px;
- padding: 10px;
- box-sizing: border-box;
-}
-
-.measure-details-components > li > a {
- display: flex;
- padding-top: 5px;
- padding-bottom: 5px;
- border: none;
- color: #444;
-}
-
-.measure-details-components > li > a:hover,
-.measure-details-components > li > a.selected {
- background-color: #cae3f2 !important;
-}
-
-.measure-details-component-name,
-.measure-details-component-value {
- padding-right: 10px;
- box-sizing: border-box;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
-}
-
-.measure-details-component-name {
- width: calc(100% - 60px);
- padding-left: 10px;
-}
-
-.measure-details-component-value {
- width: 60px;
- text-align: right;
-}
-
-.measure-details-viewer {
- min-height: 100vh;
-}
-
-.measure-details-viewer-header {
- margin-bottom: 10px;
- line-height: 24px;
-}
-
-.measure-details-viewer-header .button-group {
- vertical-align: top;
-}
-
-.measure-details-header-container {
- display: inline-block;
- line-height: 16px;
- padding-right: 10px;
-}
-
-.measure-tab-icon {
- display: inline-block;
- width: 14px;
- height: 14px;
- margin-right: 6px;
-}
-
-.measure-tab-icon path {
- fill: #aeaeae;
- transition: fill 0.3s ease;
-}
-
-.measure-details-components-up-icon path {
- fill: #aeaeae;
-}
-
-.measure-details-history {
- padding: 10px 0;
-}
-
-.measure-details-bubble-chart {
- position: relative;
- margin: 40px 0 10px;
- padding: 30px 0 30px 60px;
- border: 1px solid #e6e6e6;
- background-color: #fff;
-}
-
-.measure-details-bubble-chart-axis {
- position: absolute;
- color: #777;
- font-size: 12px;
-}
-
-.measure-details-bubble-chart-axis.x {
- left: 50%;
- bottom: 10px;
- width: 500px;
- margin-left: -250px;
- text-align: center;
-}
-
-.measure-details-bubble-chart-axis.y {
- top: 50%;
- left: -20px;
- transform: rotate(-90deg);
-}
-
-.measure-details-bubble-chart-axis.size {
- left: 50%;
- top: 10px;
- width: 500px;
- margin-left: -250px;
- text-align: center;
-}
-
-.measure-details-treemap {
- margin: 20px 0;
-}
-
-.measure-details-treemap-legend {
- margin-bottom: 10px;
-}
-
-.component-measures-breadcrumbs {
- display: flex;
- flex-wrap: wrap;
-}
-
-.component-measures-breadcrumbs > li {
- padding: 5px 5px 3px;
-}
-
-.component-measures-breadcrumbs > li:first-child {
- padding-left: 0;
-}
-
-.component-measures-breadcrumbs > li::after {
- position: relative;
- top: -1px;
- padding-left: 10px;
- color: #777;
- font-size: 11px;
- content: ">";
-}
-
-.component-measures-breadcrumbs > li:last-child::after {
- display: none;
-}
-
-.home-measures-list {
- border: 1px solid #e6e6e6;
- background-color: #fff;
-}
-
-.nav-pills > ul {
- display: flex;
- flex-wrap: wrap;
-}
-
-.nav-pills > ul > li > a {
- display: inline-block;
- vertical-align: middle;
- padding: 3px 10px;
- border: 1px solid transparent;
- border-radius: 24px;
- color: #236a97;
- transition: none;
-}
-
-.nav-pills > ul > li > a:hover {
- border-color: #236a97;
-}
-
-.nav-pills > ul > li.active > a,
-.nav-pills > ul > li > a.active {
- background-color: #236a97;
- color: #fff;
-}
+++ /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.
- */
-import bubbles from './config/bubbles';
-import {
- formatMeasure,
- formatMeasureVariation,
- getRatingTooltip as nextGetRatingTooltip,
- isDiffMetric
-} from '../../helpers/measures';
-
-export function getLeakValue(measure, periodIndex = 1) {
- if (!measure) {
- return null;
- }
-
- const period = measure.periods
- ? measure.periods.find(period => period.index === periodIndex)
- : null;
-
- return period ? period.value : null;
-}
-
-export function getSingleMeasureValue(measures) {
- if (!measures || !measures.length) {
- return null;
- }
-
- return measures[0].value;
-}
-
-export function getSingleLeakValue(measures, periodIndex = 1) {
- if (!measures || !measures.length) {
- return null;
- }
-
- const measure = measures[0];
-
- const period = measure.periods
- ? measure.periods.find(period => period.index === periodIndex)
- : null;
-
- return period ? period.value : null;
-}
-
-export function formatLeak(value, metric, options) {
- if (isDiffMetric(metric.key)) {
- return formatMeasure(value, metric.type, options);
- } else {
- return formatMeasureVariation(value, metric.type, options);
- }
-}
-
-export function enhanceWithLeak(measures, periodIndex = 1) {
- function enhanceSingle(measure) {
- return { ...measure, leak: getLeakValue(measure, periodIndex) };
- }
-
- if (Array.isArray(measures)) {
- return measures.map(enhanceSingle);
- } else {
- return enhanceSingle(measures);
- }
-}
-
-export function enhanceWithSingleMeasure(components, periodIndex = 1) {
- return components.map(component => {
- return {
- ...component,
- value: getSingleMeasureValue(component.measures),
- leak: getSingleLeakValue(component.measures, periodIndex)
- };
- });
-}
-
-export function enhanceWithMeasure(components, metric, periodIndex = 1) {
- return components.map(component => {
- const measuresWithLeak = enhanceWithLeak(component.measures, periodIndex);
- const measure = measuresWithLeak.find(measure => measure.metric === metric);
- const value = measure ? measure.value : null;
- const leak = measure ? measure.leak : null;
- return { ...component, value, leak, measures: measuresWithLeak };
- });
-}
-
-export function hasBubbleChart(domainName) {
- return !!bubbles[domainName];
-}
-
-export function hasTreemap(metric) {
- return ['PERCENT', 'RATING', 'LEVEL'].indexOf(metric.type) !== -1;
-}
-
-export function filterOutEmptyMeasures(components) {
- return components.filter(component => component.value !== null || component.leak !== null);
-}
-
-export function getRatingTooltip(metricKey, value) {
- const finalMetricKey = metricKey.indexOf('new_') === 0 ? metricKey.substr(4) : metricKey;
- const KNOWN_RATINGS = ['sqale_rating', 'reliability_rating', 'security_rating'];
- if (KNOWN_RATINGS.includes(finalMetricKey)) {
- return nextGetRatingTooltip(finalMetricKey, value);
- }
- return null;
-}
+++ /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.
- */
-import React from 'react';
-import PropTypes from 'prop-types';
-import QualifierIcon from '../shared/QualifierIcon';
-
-export class TreemapBreadcrumbs extends React.PureComponent {
- static propTypes = {
- breadcrumbs: PropTypes.arrayOf(
- PropTypes.shape({
- key: PropTypes.string.isRequired,
- name: PropTypes.string.isRequired,
- qualifier: PropTypes.string.isRequired
- }).isRequired
- ).isRequired
- };
-
- handleItemClick = (item, e) => {
- e.preventDefault();
- this.props.onRectangleClick(item);
- };
-
- handleReset = e => {
- e.preventDefault();
- this.props.onReset();
- };
-
- renderHome = () => {
- return (
- <span className="treemap-breadcrumbs-item">
- <a onClick={this.handleReset} className="icon-home" href="#" />
- </span>
- );
- };
-
- renderBreadcrumbsItems = b => {
- return (
- <span key={b.key} className="treemap-breadcrumbs-item" title={b.name}>
- <i className="icon-chevron-right" />
- <QualifierIcon qualifier={b.qualifier} />
- <a onClick={this.handleItemClick.bind(this, b)} href="#">
- {b.name}
- </a>
- </span>
- );
- };
-
- render() {
- const breadcrumbs = this.props.breadcrumbs.map(this.renderBreadcrumbsItems);
- return (
- <div className="treemap-breadcrumbs">
- {this.props.breadcrumbs.length ? this.renderHome() : null}
- {breadcrumbs}
- </div>
- );
- }
-}
+++ /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.
- */
-import React from 'react';
-import createReactClass from 'create-react-class';
-import PropTypes from 'prop-types';
-import { scaleLinear } from 'd3-scale';
-import { treemap as d3Treemap, hierarchy as d3Hierarchy } from 'd3-hierarchy';
-import { TreemapBreadcrumbs } from './treemap-breadcrumbs';
-import { ResizeMixin } from './../mixins/resize-mixin';
-import { TooltipsMixin } from './../mixins/tooltips-mixin';
-import { translate } from '../../helpers/l10n';
-
-const SIZE_SCALE = scaleLinear().domain([3, 15]).range([11, 18]).clamp(true);
-
-function mostCommitPrefix(strings) {
- const sortedStrings = strings.slice(0).sort();
- const firstString = sortedStrings[0];
- const firstStringLength = firstString.length;
- const lastString = sortedStrings[sortedStrings.length - 1];
- let i = 0;
- while (i < firstStringLength && firstString.charAt(i) === lastString.charAt(i)) {
- i++;
- }
- const prefix = firstString.substr(0, i);
- const prefixTokens = prefix.split(/[\s\\\/]/);
- const lastPrefixPart = prefixTokens[prefixTokens.length - 1];
- return prefix.substr(0, prefix.length - lastPrefixPart.length);
-}
-
-export class TreemapRect extends React.PureComponent {
- static propTypes = {
- x: PropTypes.number.isRequired,
- y: PropTypes.number.isRequired,
- width: PropTypes.number.isRequired,
- height: PropTypes.number.isRequired,
- fill: PropTypes.string.isRequired,
- label: PropTypes.string.isRequired,
- onClick: PropTypes.func
- };
-
- renderLink = () => {
- if (!this.props.link) {
- return null;
- }
-
- if (this.props.width < 24 || this.props.height < 24) {
- return null;
- }
-
- return (
- <a
- onClick={e => e.stopPropagation()}
- className="treemap-link"
- href={this.props.link}
- style={{ fontSize: 12 }}>
- <span className="icon-link" />
- </a>
- );
- };
-
- render() {
- let tooltipAttrs = {};
- if (this.props.tooltip) {
- tooltipAttrs = {
- 'data-toggle': 'tooltip',
- 'data-title': this.props.tooltip
- };
- }
- 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: typeof this.props.onClick === 'function' ? 'pointer' : 'default'
- };
- const isTextVisible = this.props.width >= 40 && this.props.height >= 40;
- /* eslint-disable jsx-a11y/onclick-has-focus, jsx-a11y/onclick-has-role */
- 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()}
- </div>
- );
- }
-}
-
-export const Treemap = createReactClass({
- displayName: 'Treemap',
-
- propTypes: {
- items: PropTypes.arrayOf(PropTypes.object).isRequired,
- height: PropTypes.number,
- onRectangleClick: PropTypes.func
- },
-
- mixins: [ResizeMixin, TooltipsMixin],
-
- getInitialState() {
- return { width: this.props.width, height: this.props.height };
- },
-
- renderWhenNoData() {
- return (
- <div className="sonar-d3">
- <div
- className="treemap-container"
- style={{ width: this.state.width, height: this.state.height }}>
- {translate('no_data')}
- </div>
- <TreemapBreadcrumbs {...this.props} />
- </div>
- );
- },
-
- render() {
- if (!this.state.width || !this.state.height) {
- return <div> </div>;
- }
-
- if (!this.props.items.length) {
- return this.renderWhenNoData();
- }
-
- const hierarchy = d3Hierarchy({ children: this.props.items })
- .sum(d => d.size)
- .sort((a, b) => b.value - a.value);
-
- const treemap = d3Treemap().round(true).size([this.state.width, this.state.height]);
-
- const nodes = treemap(hierarchy).leaves();
-
- const prefix = mostCommitPrefix(this.props.items.map(item => item.label));
- const prefixLength = prefix.length;
-
- const rectangles = nodes.map(node => {
- const key = node.data.label;
- const label = prefixLength
- ? `${prefix}<br>${node.data.label.substr(prefixLength)}`
- : node.data.label;
- const onClick = this.props.canBeClicked(node.data)
- ? () => this.props.onRectangleClick(node.data)
- : null;
- return (
- <TreemapRect
- key={key}
- x={node.x0}
- y={node.y0}
- width={node.x1 - node.x0}
- height={node.y1 - node.y0}
- fill={node.data.color}
- label={label}
- prefix={prefix}
- tooltip={node.data.tooltip}
- link={node.data.link}
- onClick={onClick}
- />
- );
- });
-
- return (
- <div className="sonar-d3">
- <div
- className="treemap-container"
- style={{ width: this.state.width, height: this.state.height }}>
- {rectangles}
- </div>
- <TreemapBreadcrumbs {...this.props} />
- </div>
- );
- }
-});
import organizations, * as fromOrganizations from './organizations/duck';
import organizationsMembers, * as fromOrganizationsMembers from './organizationsMembers/reducer';
import globalMessages, * as fromGlobalMessages from './globalMessages/duck';
-import measuresApp, * as fromMeasuresApp from '../apps/component-measures-old/store/rootReducer';
import permissionsApp, * as fromPermissionsApp from '../apps/permissions/shared/store/rootReducer';
import projectAdminApp, * as fromProjectAdminApp from '../apps/project-admin/store/rootReducer';
import projectsApp, * as fromProjectsApp from '../apps/projects/store/reducer';
users,
// apps
- measuresApp,
permissionsApp,
projectAdminApp,
projectsApp,
export const getProjectAdminGlobalMessages = state =>
fromProjectAdminApp.getGlobalMessages(state.projectAdminApp);
-
-export const getMeasuresAppComponent = state => fromMeasuresApp.getComponent(state.measuresApp);
-
-export const getMeasuresAppAllMetrics = state => fromMeasuresApp.getAllMetrics(state.measuresApp);
-
-export const getMeasuresAppDetailsMetric = state =>
- fromMeasuresApp.getDetailsMetric(state.measuresApp);
-
-export const getMeasuresAppDetailsMeasure = state =>
- fromMeasuresApp.getDetailsMeasure(state.measuresApp);
-
-export const getMeasuresAppDetailsSecondaryMeasure = state =>
- fromMeasuresApp.getDetailsSecondaryMeasure(state.measuresApp);
-
-export const getMeasuresAppDetailsPeriods = state =>
- fromMeasuresApp.getDetailsPeriods(state.measuresApp);
-
-export const isMeasuresAppFetching = state => fromMeasuresApp.isFetching(state.measuresApp);
-
-export const getMeasuresAppList = state => fromMeasuresApp.getList(state.measuresApp);
-
-export const getMeasuresAppListComponents = state =>
- fromMeasuresApp.getListComponents(state.measuresApp);
-
-export const getMeasuresAppListSelected = state =>
- fromMeasuresApp.getListSelected(state.measuresApp);
-
-export const getMeasuresAppListTotal = state => fromMeasuresApp.getListTotal(state.measuresApp);
-
-export const getMeasuresAppListPageIndex = state =>
- fromMeasuresApp.getListPageIndex(state.measuresApp);
-
-export const getMeasuresAppTree = state => fromMeasuresApp.getTree(state.measuresApp);
-
-export const getMeasuresAppTreeComponents = state =>
- fromMeasuresApp.getTreeComponents(state.measuresApp);
-
-export const getMeasuresAppTreeBreadcrumbs = state =>
- fromMeasuresApp.getTreeBreadcrumbs(state.measuresApp);
-
-export const getMeasuresAppTreeSelected = state =>
- fromMeasuresApp.getTreeSelected(state.measuresApp);
-
-export const getMeasuresAppTreeTotal = state => fromMeasuresApp.getTreeTotal(state.measuresApp);
-
-export const getMeasuresAppTreePageIndex = state =>
- fromMeasuresApp.getTreePageIndex(state.measuresApp);
-
-export const getMeasuresAppHomeDomains = state => fromMeasuresApp.getHomeDomains(state.measuresApp);
-
-export const getMeasuresAppHomePeriods = state => fromMeasuresApp.getHomePeriods(state.measuresApp);
line-height: inherit;
}
-.sonar-d3 .treemap-breadcrumbs {
- margin-top: 10px;
- padding-top: 7px;
- border-top: 1px solid #e6e6e6;
- line-height: 1.3;
-}
-
-.sonar-d3 .treemap-breadcrumbs-item {
- color: @secondFontColor;
-
- & > [class^="icon-qualifier-"] {
- margin-right: 4px;
- }
-}
-
-.sonar-d3 .treemap-breadcrumbs-item + .treemap-breadcrumbs-item {
- margin-left: 10px;
-
- & > .icon-chevron-right {
- margin-right: 10px;
- }
-}
-
.word-cloud {
display: flex;
flex-wrap: wrap;