*/ | */ | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { Link } from 'react-router'; | import { Link } from 'react-router'; | ||||
import LanguageDistributionContainer from '../../../components/charts/LanguageDistributionContainer'; | |||||
import LanguageDistribution from '../../../components/charts/LanguageDistribution'; | |||||
import Tooltip from '../../../components/controls/Tooltip'; | import Tooltip from '../../../components/controls/Tooltip'; | ||||
import HistoryIcon from '../../../components/icons/HistoryIcon'; | import HistoryIcon from '../../../components/icons/HistoryIcon'; | ||||
import IssueTypeIcon from '../../../components/icons/IssueTypeIcon'; | import IssueTypeIcon from '../../../components/icons/IssueTypeIcon'; | ||||
secondaryMeasure.metric === 'ncloc_language_distribution' && | secondaryMeasure.metric === 'ncloc_language_distribution' && | ||||
secondaryMeasure.value !== undefined && ( | secondaryMeasure.value !== undefined && ( | ||||
<div className="measure-details-secondary"> | <div className="measure-details-secondary"> | ||||
<LanguageDistributionContainer | |||||
alignTicks={true} | |||||
distribution={secondaryMeasure.value} | |||||
width={260} | |||||
/> | |||||
<LanguageDistribution distribution={secondaryMeasure.value} /> | |||||
</div> | </div> | ||||
)} | )} | ||||
</div> | </div> |
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
.histogram-tick { | .histogram-tick { | ||||
text-anchor: end; | |||||
text-anchor: end !important; | |||||
} | } | ||||
.histogram-tick-start { | .histogram-tick-start { | ||||
text-anchor: start; | |||||
text-anchor: start !important; | |||||
} | } | ||||
.histogram-value { | .histogram-value { | ||||
text-anchor: start; | |||||
text-anchor: start !important; | |||||
} | } |
*/ | */ | ||||
import { sortBy } from 'lodash'; | import { sortBy } from 'lodash'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import { connect } from 'react-redux'; | |||||
import Histogram from '../../components/charts/Histogram'; | import Histogram from '../../components/charts/Histogram'; | ||||
import { translate } from '../../helpers/l10n'; | import { translate } from '../../helpers/l10n'; | ||||
import { formatMeasure } from '../../helpers/measures'; | import { formatMeasure } from '../../helpers/measures'; | ||||
import { getLanguages, Store } from '../../store/rootReducer'; | |||||
import { MetricType } from '../../types/metrics'; | |||||
interface Props { | |||||
alignTicks?: boolean; | |||||
interface LanguageDistributionProps { | |||||
distribution: string; | distribution: string; | ||||
languages: T.Languages; | languages: T.Languages; | ||||
width: number; | |||||
} | } | ||||
export default function LanguageDistribution(props: Props) { | |||||
const NUMBER_FORMAT_THRESHOLD = 1000; | |||||
export function LanguageDistribution(props: LanguageDistributionProps) { | |||||
let distribution = props.distribution.split(';').map(point => { | let distribution = props.distribution.split(';').map(point => { | ||||
const tokens = point.split('='); | const tokens = point.split('='); | ||||
return { language: tokens[0], lines: parseInt(tokens[1], 10) }; | return { language: tokens[0], lines: parseInt(tokens[1], 10) }; | ||||
const data = distribution.map(d => d.lines); | const data = distribution.map(d => d.lines); | ||||
const yTicks = distribution.map(d => getLanguageName(d.language)).map(cutLanguageName); | const yTicks = distribution.map(d => getLanguageName(d.language)).map(cutLanguageName); | ||||
const yTooltips = distribution.map(d => (d.lines > 1000 ? formatMeasure(d.lines, 'INT') : '')); | |||||
const yValues = distribution.map(d => formatMeasure(d.lines, 'SHORT_INT')); | |||||
const yTooltips = distribution.map(d => | |||||
d.lines > NUMBER_FORMAT_THRESHOLD ? formatMeasure(d.lines, MetricType.Integer) : '' | |||||
); | |||||
const yValues = distribution.map(d => formatMeasure(d.lines, MetricType.ShortInteger)); | |||||
return ( | return ( | ||||
<Histogram | <Histogram | ||||
alignTicks={props.alignTicks} | |||||
bars={data} | bars={data} | ||||
height={distribution.length * 25} | height={distribution.length * 25} | ||||
padding={[0, 60, 0, 80]} | padding={[0, 60, 0, 80]} | ||||
width={props.width} | |||||
width={260} | |||||
yTicks={yTicks} | yTicks={yTicks} | ||||
yTooltips={yTooltips} | yTooltips={yTooltips} | ||||
yValues={yValues} | yValues={yValues} | ||||
function cutLanguageName(name: string) { | function cutLanguageName(name: string) { | ||||
return name.length > 10 ? `${name.substr(0, 7)}...` : name; | return name.length > 10 ? `${name.substr(0, 7)}...` : name; | ||||
} | } | ||||
const mapStateToProps = (state: Store) => ({ | |||||
languages: getLanguages(state) | |||||
}); | |||||
export default connect(mapStateToProps)(LanguageDistribution); |
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2021 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 { getLanguages, Store } from '../../store/rootReducer'; | |||||
import LanguageDistribution from './LanguageDistribution'; | |||||
const mapStateToProps = (state: Store) => ({ | |||||
languages: getLanguages(state) | |||||
}); | |||||
export default connect(mapStateToProps)(LanguageDistribution); |
*/ | */ | ||||
import { shallow } from 'enzyme'; | import { shallow } from 'enzyme'; | ||||
import * as React from 'react'; | import * as React from 'react'; | ||||
import LanguageDistribution from '../LanguageDistribution'; | |||||
import { LanguageDistribution } from '../LanguageDistribution'; | |||||
it('renders', () => { | it('renders', () => { | ||||
expect( | expect( | ||||
<LanguageDistribution | <LanguageDistribution | ||||
distribution="java=1734;js=845;cpp=73;<null>=15" | distribution="java=1734;js=845;cpp=73;<null>=15" | ||||
languages={{ java: { key: 'java', name: 'Java' }, js: { key: 'js', name: 'JavaScript' } }} | languages={{ java: { key: 'java', name: 'Java' }, js: { key: 'js', name: 'JavaScript' } }} | ||||
width={100} | |||||
/> | /> | ||||
) | ) | ||||
).toMatchSnapshot(); | ).toMatchSnapshot(); |
80, | 80, | ||||
] | ] | ||||
} | } | ||||
width={100} | |||||
width={260} | |||||
yTicks={ | yTicks={ | ||||
Array [ | Array [ | ||||
"Java", | "Java", |