Browse Source

SONAR-8382 apply feedback on about page (#1411)

tags/6.2-RC2
Stas Vilchik 7 years ago
parent
commit
e12f240303

+ 45
- 41
server/sonar-web/src/main/js/apps/about/components/AboutApp.js View File

@@ -19,9 +19,8 @@
*/
import React from 'react';
import keyBy from 'lodash/keyBy';
import LoginSection from './LoginSection';
import LoginForm from './LoginForm';
import AboutProjects from './AboutProjects';
import EntryIssueTypes from './EntryIssueTypes';
import AboutCleanCode from './AboutCleanCode';
import AboutIssues from './AboutIssues';
import AboutQualityGates from './AboutQualityGates';
@@ -40,10 +39,12 @@ export default class AboutApp extends React.Component {

componentDidMount () {
this.mounted = true;
document.querySelector('html').classList.add('dashboard-page');
this.loadData();
}

componentWillUnmount () {
document.querySelector('html').classList.remove('dashboard-page');
this.mounted = false;
}

@@ -52,7 +53,7 @@ export default class AboutApp extends React.Component {
}

loadIssues () {
return getFacet({ resolved: false }, 'types').then(r => keyBy(r.facet, 'val'));
return getFacet({ resolved: false }, 'types');
}

loadData () {
@@ -62,7 +63,8 @@ export default class AboutApp extends React.Component {
this.loadIssues()
]).then(responses => {
if (this.mounted) {
const [options, projectsCount, issueTypes] = responses;
const [options, projectsCount, issues] = responses;
const issueTypes = keyBy(issues.facet, 'val');
this.setState({
projectsCount,
issueTypes,
@@ -79,9 +81,7 @@ export default class AboutApp extends React.Component {
return null;
}

const isAuthenticated = !!window.SS.user;
const { signUpAllowed, landingText } = window.sonarqube;
const loginFormShown = !isAuthenticated && this.props.location.query.login !== undefined;
const { landingText } = window.sonarqube;

const logoUrl = this.state.logoUrl || `${window.baseUrl}/images/logo.svg`;
const logoWidth = this.state.logoWidth || 100;
@@ -91,49 +91,53 @@ export default class AboutApp extends React.Component {
return (
<div id="about-page" className="about-page">
<div className="about-page-entry">

<div className="about-page-logo">
<img src={logoUrl} width={2 * logoWidth} height={2 * logoHeight} alt={logoTitle}/>
</div>

{loginFormShown ? (
<div className="about-page-entry-box">
<LoginForm/>
<div className="about-page-container clearfix">
<div className="pull-left">
<div className="about-page-logo">
<img src={logoUrl} width={2 * logoWidth} height={2 * logoHeight} alt={logoTitle}/>
</div>
) : (
<div className="about-page-entry-box">
<AboutProjects count={this.state.projectsCount}/>
{!isAuthenticated && <LoginSection/>}
</div>
)}

{signUpAllowed && !isAuthenticated && (
<div className="about-page-sign-up">
No account yet? <a href={window.baseUrl + '/users/new'}>Sign up</a>
</div>
)}
</div>
</div>

{landingText.length > 0 && (
<div className="about-page-section bordered-bottom">
<div className="about-page-container" dangerouslySetInnerHTML={{ __html: landingText }}/>
<div className="about-page-entry-column">
<EntryIssueTypes
bugs={this.state.issueTypes['BUG'].count}
vulnerabilities={this.state.issueTypes['VULNERABILITY'].count}
codeSmells={this.state.issueTypes['CODE_SMELL'].count}/>
</div>
)}

<AboutCleanCode/>
<div className="about-page-entry-column">
<AboutProjects count={this.state.projectsCount}/>
</div>
</div>
</div>

<AboutIssues
bugs={this.state.issueTypes['BUG'].count}
vulnerabilities={this.state.issueTypes['VULNERABILITY'].count}
codeSmells={this.state.issueTypes['CODE_SMELL'].count}/>
<div className="about-page-container">

<AboutQualityGates/>
{landingText.length > 0 && (
<div className="about-page-section" dangerouslySetInnerHTML={{ __html: landingText }}/>
)}

<AboutLeakPeriod/>
<div className="columns">
<div className="column-two-thirds">
<AboutCleanCode/>
<AboutLeakPeriod/>
</div>
<div className="column-third">
<AboutIssues/>
</div>
</div>

<AboutStandards/>
<div className="columns">
<div className="column-half">
<AboutQualityGates/>
</div>
<div className="column-half">
<AboutStandards/>
</div>
</div>

<AboutScanners/>
<AboutScanners/>
</div>
</div>
);
}

+ 5
- 13
server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js View File

@@ -18,23 +18,15 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
import DropImage from './DropImage';
import { translate } from '../../../helpers/l10n';

export default class AboutCleanCode extends React.Component {
render () {
return (
<div className="about-page-section">
<div className="about-page-center-container">
<h2 className="about-page-header">Keep your code clean by fixing the leak</h2>
<p className="about-page-text about-page-text-center">
By fixing new issues as they appear in code, you create and maintain a clean code base.
<br/>
Even on legacy projects, focusing on keeping new code clean will eventually yield a code base you can be
proud of.
</p>
<div className="about-page-section-image">
<DropImage/>
</div>
<div className="boxed-group">
<h2>{translate('about_page.clean_code')}</h2>
<div className="boxed-group-inner">
<p className="about-page-text">{translate('about_page.clean_code.text')}</p>
</div>
</div>
);

+ 13
- 57
server/sonar-web/src/main/js/apps/about/components/AboutIssues.js View File

@@ -18,68 +18,24 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
import { formatMeasure } from '../../../helpers/measures';
import { getIssuesUrl } from '../../../helpers/urls';
import { translate } from '../../../helpers/l10n';

export default class AboutIssues extends React.Component {
static propTypes = {
bugs: React.PropTypes.number.isRequired,
vulnerabilities: React.PropTypes.number.isRequired,
codeSmells: React.PropTypes.number.isRequired
};

render () {
const displayNumbers = this.props.bugs > 0 || this.props.vulnerabilities > 0 || this.props.codeSmells > 0;

return (
<div className="about-page-section about-page-section-gray">
<div className="about-page-container">
<h2 className="about-page-header text-center">Track incoming issues using the SonarQube Quality Model</h2>
<div className="about-page-issues">
<div className="about-page-issues-box">
{displayNumbers && (
<a className="about-page-issues-number"
href={getIssuesUrl({ resolved: false, types: 'BUG' })}>
{formatMeasure(this.props.bugs, 'SHORT_INT')}
</a>
)}
<div className="about-page-issues-description">
<h3 className="about-page-issues-header">Bugs</h3>
<p className="about-page-issues-text">
Bugs track code that is demonstrably wrong or highly likely to yield unexpected behavior.
</p>
</div>
</div>
<div className="about-page-issues-box">
{displayNumbers && (
<a className="about-page-issues-number"
href={getIssuesUrl({ resolved: false, types: 'VULNERABILITY' })}>
{formatMeasure(this.props.vulnerabilities, 'SHORT_INT')}
</a>
)}
<div className="about-page-issues-description">
<h3 className="about-page-issues-header">Vulnerabilities</h3>
<p className="about-page-issues-text">
Vulnerabilities are raised on code that is potentially vulnerable to exploitation by hackers.
</p>
</div>
</div>
<div className="about-page-issues-box">
{displayNumbers && (
<a className="about-page-issues-number"
href={getIssuesUrl({ resolved: false, types: 'CODE_SMELL' })}>
{formatMeasure(this.props.codeSmells, 'SHORT_INT')}
</a>
)}
<div className="about-page-issues-description">
<h3 className="about-page-issues-header">Code Smells</h3>
<p className="about-page-issues-text">
Code Smells will confuse maintainers or give them pause. They are measured primarily in terms of
the time they will take to fix.
</p>
</div>
</div>
</div>
<div className="boxed-group">
<h2>{translate('about_page.quality_model')}</h2>

<div className="boxed-group-inner clearfix">
<h3 className="spacer-bottom">{translate('issue.type.BUG.plural')}</h3>
<p className="about-page-text">{translate('about_page.quality_model.bugs')}</p>

<h3 className="big-spacer-top spacer-bottom">{translate('issue.type.VULNERABILITY.plural')}</h3>
<p className="about-page-text">{translate('about_page.quality_model.vulnerabilities')}</p>

<h3 className="big-spacer-top spacer-bottom">{translate('issue.type.CODE_SMELL.plural')}</h3>
<p className="about-page-text">{translate('about_page.quality_model.code_smells')}</p>
</div>
</div>
);

+ 7
- 16
server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js View File

@@ -18,28 +18,19 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
import ReadMore from './ReadMore';
import { translate } from '../../../helpers/l10n';

const link = 'http://redirect.sonarsource.com/doc/fix-the-leak.html';

export default class AboutLeakPeriod extends React.Component {
render () {
return (
<div className="about-page-section">
<div className="about-page-container clearfix">
<img className="pull-left" src={window.baseUrl + '/images/understanding-leak-period.svg'}
width={500} height={175} alt="Understanding the Leak Period"/>
<h2 className="about-page-header">Understanding the Leak Period</h2>
<p className="about-page-text">
The leak metaphor and the default Quality Gate are based on the leak period - the recent period against
which you're tracking issues. For some <code>previous_version</code> makes the most sense, for others
the last 30 days is a good option.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={link} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
<div className="boxed-group">
<h2>{translate('about_page.leak_period')}</h2>
<div className="boxed-group-inner">
<p className="about-page-text">{translate('about_page.leak_period.text')}</p>
<ReadMore link={link}/>
</div>
</div>
);

+ 10
- 9
server/sonar-web/src/main/js/apps/about/components/AboutProjects.js View File

@@ -19,6 +19,7 @@
*/
import React from 'react';
import { formatMeasure } from '../../../helpers/measures';
import { translate } from '../../../helpers/l10n';

export default class AboutProjects extends React.Component {
static propTypes = {
@@ -26,16 +27,16 @@ export default class AboutProjects extends React.Component {
};

render () {
const { count } = this.props;
const label = count > 1 ? `${formatMeasure(count, 'INT')} projects` : '1 project';

return (
<div className="about-page-text">
{count > 0 ? (
<a href={window.baseUrl + '/projects'}>{label}</a>
) : 'Put your projects'}
{' '}
under continuous<br/>code quality management
<div className="about-page-projects">
<div className="big-spacer-bottom">
<a className="about-page-projects-link" href={window.baseUrl + '/projects'}>
{formatMeasure(this.props.count, 'INT')}
</a>
</div>
<div>
{translate('about_page.projects_analyzed')}
</div>
</div>
);
}

+ 7
- 16
server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js View File

@@ -18,28 +18,19 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
import ReadMore from './ReadMore';
import { translate } from '../../../helpers/l10n';

const link = 'http://redirect.sonarsource.com/doc/quality-gates.html';

export default class AboutQualityGates extends React.Component {
render () {
return (
<div className="about-page-section">
<div className="about-page-container clearfix">
<img className="pull-right" src={window.baseUrl + '/images/understanding-quality-gates.svg'}
width={500} height={175} alt="Understanding Quality Gates"/>
<h2 className="about-page-header">Understanding Quality Gates</h2>
<p className="about-page-text">
Your project's quality gate is the set of conditions the project must meet before it can be released
into production. The quality gate is designed to ensure that the next version's quality will be better
than the last.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={link} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
<div className="boxed-group">
<h2>{translate('about_page.quality_gates')}</h2>
<div className="boxed-group-inner">
<p className="about-page-text">{translate('about_page.quality_gates.text')}</p>
<ReadMore link={link}/>
</div>
</div>
);

+ 36
- 104
server/sonar-web/src/main/js/apps/about/components/AboutScanners.js View File

@@ -18,116 +18,48 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
import ReadMore from './ReadMore';
import { translate } from '../../../helpers/l10n';

const links = {
sonarqube: 'http://redirect.sonarsource.com/doc/install-configure-scanner.html',
msbuild: 'http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html',
maven: 'http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html',
gradle: 'http://redirect.sonarsource.com/doc/gradle.html',
jenkins: 'http://redirect.sonarsource.com/plugins/jenkins.html',
ant: 'http://redirect.sonarsource.com/doc/install-configure-scanner-ant.html'
};
const scanners = [
{
key: 'sonarqube',
link: 'http://redirect.sonarsource.com/doc/install-configure-scanner.html'
}, {
key: 'msbuild',
link: 'http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html'
}, {
key: 'maven',
link: 'http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html'
}, {
key: 'gradle',
link: 'http://redirect.sonarsource.com/doc/gradle.html'
}, {
key: 'jenkins',
link: 'http://redirect.sonarsource.com/plugins/jenkins.html'
}, {
key: 'ant',
link: 'http://redirect.sonarsource.com/doc/install-configure-scanner-ant.html'
}
];

export default class AboutScanners extends React.Component {
render () {
return (
<div className="about-page-section">
<div className="about-page-container">
<h2 className="about-page-header text-center">Start analyzing your projects with a SonarQube Scanner</h2>
<div className="boxed-group">
<h2>Start analyzing your projects with a SonarQube Scanner</h2>
<div className="boxed-group-inner">
<div className="about-page-analyzers">
<div className="about-page-analyzer-box">
<div className=" big-spacer-bottom">
<img src={window.baseUrl + '/images/scanner-logos/sonarqube.svg'} height={80}
alt="SonarQube Scanner"/>
</div>
<p className="about-page-text">
The SonarQube Scanner is a Java-based command-line tool that can analyze any language SonarQube
supports.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={links.sonarqube} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
</div>
<div className="about-page-analyzer-box">
<div className=" big-spacer-bottom">
<img src={window.baseUrl + '/images/scanner-logos/msbuild.png'} height={80}
alt="SonarQube Scanner for MSBuild"/>
</div>
<p className="about-page-text">
Built in collaboration with Microsoft, the SonarQube Scanner for MSBuild is the recommended way to
launch a SonarQube analysis on MSBuild projects and solutions.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={links.msbuild} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
</div>
<div className="about-page-analyzer-box">
<div className=" big-spacer-bottom">
<img src={window.baseUrl + '/images/scanner-logos/maven.svg'} height={80}
alt="SonarQube Scanner for Maven"/>
</div>
<p className="about-page-text">
Using the SonarQube Scanner for Maven is as simple as running <code>mvn sonar:sonar</code> on your
Maven project.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={links.maven} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
</div>
<div className="about-page-analyzer-box">
<div className=" big-spacer-bottom">
<img src={window.baseUrl + '/images/scanner-logos/gradle.svg'} height={80}
alt="SonarQube Scanner for Gradle"/>
</div>
<p className="about-page-text">
The SonarQube Scanner for Gradle provides an easy way to start analysis of a Gradle project.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={links.gradle} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
</div>
<div className="about-page-analyzer-box">
<div className=" big-spacer-bottom">
<img src={window.baseUrl + '/images/scanner-logos/jenkins.svg'} height={80}
alt="SonarQube Scanner for Jenkins"/>
</div>
<p className="about-page-text">
The SonarQube Scanner for Jenkins lets you integrate analysis seamlessly into a job or a pipeline.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={links.jenkins} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
</div>
<div className="about-page-analyzer-box">
<div className=" big-spacer-bottom">
<img src={window.baseUrl + '/images/scanner-logos/ant.svg'} height={80}
alt="SonarQube Scanner for Ant"/>
</div>
<p className="about-page-text">
The SonarQube Scanner for Ant lets you start an analysis directly from an Apache Ant script.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={links.ant} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
</div>
{scanners.map(scanner => (
<div key={scanner.key} className="about-page-analyzer-box">
<div className="big-spacer-bottom">
<img src={`${window.baseUrl}/images/scanner-logos/${scanner.key}.svg`} height={80}
alt={translate('about_page.scanners', scanner.key)}/>
</div>
<p className="about-page-text">{translate('about_page.scanners.sonarqube.text')}</p>
<ReadMore link={scanner.link}/>
</div>
))}
</div>
</div>
</div>

+ 46
- 14
server/sonar-web/src/main/js/apps/about/components/AboutStandards.js View File

@@ -18,27 +18,59 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
import ReadMore from './ReadMore';
import { translate } from '../../../helpers/l10n';
import { getRulesUrl } from '../../../helpers/urls';

const link = 'http://redirect.sonarsource.com/doc/rules.html';

const owaspTags = 'owasp-a1,owasp-a2,owasp-a3,owasp-a4,owasp-a5,owasp-a6,owasp-a7,owasp-a8,owasp-a9,owasp-a10';

export default class AboutStandards extends React.Component {
render () {
return (
<div className="about-page-section">
<div className="about-page-container clearfix">
<img className="pull-right" src={window.baseUrl + '/images/recognized-standards.svg'}
width={500} height={175} alt="Conform to recognized standards"/>
<h2 className="about-page-header">Conform to recognized standards</h2>
<p className="about-page-text">
SonarAnalyzers offer rules that support industry standards: MISRA, CERT, CWE, OWASP Top 10 and SANS Top
25. Configure your Quality Profile with standard-related rules to ensure adherence.
</p>
<div className="big-spacer-top">
<a className="about-page-link-more" href={link} target="_blank">
<span>Read more</span>
<i className="icon-detach spacer-left"/>
</a>
<div className="boxed-group">
<h2>{translate('about_page.standards')}</h2>
<div className="boxed-group-inner">
<p className="about-page-text">{translate('about_page.standards.text')}</p>

<div className="spacer-top">
<ul className="list-inline">
<li>
<a className="link-with-icon" href={getRulesUrl({ tags: 'misra' })}>
<i className="icon-tags"/>
<span className="little-spacer-left">MISRA</span>
</a>
</li>
<li>
<a className="link-with-icon" href={getRulesUrl({ tags: 'cert' })}>
<i className="icon-tags"/>
<span className="little-spacer-left">CERT</span>
</a>
</li>
<li>
<a className="link-with-icon" href={getRulesUrl({ tags: 'cwe' })}>
<i className="icon-tags"/>
<span className="little-spacer-left">CWE</span>
</a>
</li>
<li>
<a className="link-with-icon" href={getRulesUrl({ tags: owaspTags })}>
<i className="icon-tags"/>
<span className="little-spacer-left">OWASP Top 10</span>
</a>
</li>
<li>
<a className="link-with-icon"
href={getRulesUrl({ tags: 'sans-top25-porous,sans-top25-risky,sans-top25-insecure' })}>
<i className="icon-tags"/>
<span className="little-spacer-left">SANS Top 25</span>
</a>
</li>
</ul>
</div>

<ReadMore link={link}/>
</div>
</div>
);

+ 0
- 36
server/sonar-web/src/main/js/apps/about/components/DropImage.js View File

@@ -1,36 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact 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 () {
/* eslint-disable max-len */
return (
<svg viewBox="0 0 131 230" width={131} height={230} xmlns="http://www.w3.org/2000/svg" fillRule="evenodd" clipRule="evenodd" strokeLinejoin="round" strokeMiterlimit="1.414">
<path d="M0 40.99h131v52.113H0V40.99z" fill="#D8D8D8" fillRule="nonzero"/>
<path d="M80.223 40.99h38.66v52.113h-38.66V40.99z" fill="#DFDFDF" fillRule="nonzero"/>
<path d="M7.812 0h115.476v40.99H7.812V0z" fill="#D8D8D8" fillRule="nonzero"/>
<path d="M71.61 0h38.458v41.29h-38.46V0z" fill="#DFDFDF" fillRule="nonzero"/>
<path d="M7.812 40.99h115.376v-7.317L7.812 38.383v2.606z" fill="#C9C8C8" fillRule="nonzero"/>
<path d="M41.463 181.395l-7.01 8.72 5.308 14.23 6.71 10.122 11.218 6.714 12.82 3.008 9.514-2.506.6-12.828-10.915-8.117-11.518-7.016-16.727-12.325z" fill="#6ABAE4" fillRule="nonzero"/>
<path d="M108.065 184.702l-37.457-72.157-37.157 72.157C26.04 209.957 50.178 230 70.81 230c20.532 0 45.87-19.642 37.257-45.298zm-37.758 37.18c-.5 0-1.1 0-1.602-.1 0 0-.7-.1-1.903-.3-.3-.1-.6-.1-1-.2-.502-.1-1.003-.2-1.504-.4-1.1-.302-2.303-.603-3.405-1.104-.6-.2-1.202-.5-1.803-.7-.6-.302-1.202-.603-1.903-.903-1.302-.602-2.503-1.504-3.805-2.305-1.202-.902-2.504-1.804-3.606-3.007-1.202-1.002-2.203-2.305-3.205-3.508-.9-1.302-1.902-2.505-2.603-3.908-.8-1.303-1.302-2.706-1.903-4.01-.4-1.402-1-2.604-1.202-3.907-.1-.602-.3-1.203-.4-1.804-.1-.602-.1-1.203-.2-1.704-.2-1.102-.2-2.104-.2-3.006 0-.902 0-1.604.1-2.305.1-1.202.2-2.004.2-2.004s.1.702.4 1.904c.1.602.3 1.303.5 2.205.2.802.502 1.704.902 2.706l.6 1.504c.302.5.502 1.002.803 1.504.5 1.102 1.302 2.004 1.903 3.106.8 1.002 1.602 2.005 2.503 2.907.902.903 1.903 1.704 2.905 2.606 1.1.702 2.103 1.504 3.205 2.005 1.1.602 2.203 1.003 3.305 1.504 1.1.3 2.103.7 3.205.902l1.502.3c.5 0 .9.1 1.402.1.9.1 1.602.1 2.203.1h.902c.4 0 .7-.1 1-.1 1.203-.1 2.004-.2 2.004-.2 3.305-.3 6.21 2.205 6.51 5.512 0 3.408-2.504 6.314-5.81 6.615z" fill="#429BCD" fillRule="nonzero"/>
</svg>

);
}

+ 69
- 0
server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js View File

@@ -0,0 +1,69 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact 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 { formatMeasure } from '../../../helpers/measures';
import { translate } from '../../../helpers/l10n';
import { getIssuesUrl } from '../../../helpers/urls';

export default class EntryIssueTypes extends React.Component {
static propTypes = {
bugs: React.PropTypes.number.isRequired,
vulnerabilities: React.PropTypes.number.isRequired,
codeSmells: React.PropTypes.number.isRequired
};

render () {
const { bugs, vulnerabilities, codeSmells } = this.props;

return (
<div className="about-page-projects">
<ul className="about-page-issue-types">
<li>
<div className="about-page-issue-type-number">
<a className="about-page-issue-type-link"
href={getIssuesUrl({ resolved: false, types: 'BUG' })}>
{formatMeasure(bugs, 'SHORT_INT')}
</a>
</div>
{translate('issue.type.BUG.plural')}
</li>
<li>
<div className="about-page-issue-type-number">
<a className="about-page-issue-type-link"
href={getIssuesUrl({ resolved: false, types: 'VULNERABILITY' })}>
{formatMeasure(vulnerabilities, 'SHORT_INT')}
</a>
</div>
{translate('issue.type.VULNERABILITY.plural')}
</li>
<li>
<div className="about-page-issue-type-number">
<a className="about-page-issue-type-link"
href={getIssuesUrl({ resolved: false, types: 'CODE_SMELL' })}>
{formatMeasure(codeSmells, 'SHORT_INT')}
</a>
</div>
{translate('issue.type.CODE_SMELL.plural')}
</li>
</ul>
</div>
);
}
}

+ 1
- 1
server/sonar-web/src/main/js/apps/about/components/LoginSection.js View File

@@ -30,7 +30,7 @@ export default class LoginSection extends React.Component {

return (
<div id="about-login">
<div className="about-page-auth-providers">
<div className="about-page-auth-providers big-spacer-top">
{authProviders.map(provider => (
<OAuthProvider key={provider.key} provider={provider}/>
))}

+ 1
- 0
server/sonar-web/src/main/js/apps/about/components/OAuthProvider.css View File

@@ -8,6 +8,7 @@
box-sizing: border-box;
background-color: #236a97;
color: #fff;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

+ 38
- 0
server/sonar-web/src/main/js/apps/about/components/ReadMore.js View File

@@ -0,0 +1,38 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact 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';

export default class ReadMore extends React.Component {
static propTypes = {
link: React.PropTypes.string.isRequired
};

render () {
return (
<div className="big-spacer-top">
<a className="about-page-link-more" href={this.props.link} target="_blank">
<span>{translate('about_page.read_more')}</span>
<i className="icon-detach spacer-left"/>
</a>
</div>
);
}
}

+ 72
- 54
server/sonar-web/src/main/js/apps/about/styles.css View File

@@ -1,11 +1,20 @@
.about-page {
}

.about-page .boxed-group h2 {
font-size: 18px;
font-weight: bold;
text-align: center;
}

.about-page-container {
position: relative;
width: 1080px;
margin-left: auto;
margin-right: auto;
padding-left: 20px;
padding-right: 20px;
box-sizing: border-box;
}

.about-page-center-container {
@@ -15,36 +24,66 @@
text-align: center;
}

.about-page-container .pull-left {
margin-right: 40px;
.about-page-logo {
padding: 20px 0;
}

.about-page-container .pull-right {
margin-left: 40px;
.about-page-entry {
margin-bottom: 50px;
padding: 40px 0 50px;
background-color: #363636;
}

.about-page-logo {
margin-bottom: 30px;
.about-page-entry .about-page-header {
color: rgba(255, 255, 255, 0.9);
}

.about-page-entry {
padding: 75px 0;
background-color: #363636;
.about-page-entry-column {
float: right;
text-align: center;
box-sizing: border-box;
}

.about-page-entry-column + .about-page-entry-column {
margin-right: 60px;
padding-right: 60px;
border-right: 1px solid rgba(75, 159, 213, 0.2);
}

.about-page-entry .alert {
font-size: 13px;
}

.about-page-entry-box {
width: 320px;
margin-left: auto;
margin-right: auto;
padding: 40px 30px;
box-sizing: border-box;
border-radius: 2px;
background-color: #fff;
.about-page-projects {
line-height: 1.4;
color: rgba(255, 255, 255, 0.9);
font-size: 16px;
text-align: center;
}

.about-page-projects-link {
border-bottom-color: rgba(75, 159, 213, 0.2);
color: rgb(75, 159, 213);
font-size: 44px;
font-weight: bold;
}

.about-page-issue-types {
text-align: left;
}

.about-page-issue-type-number {
display: inline-block;
min-width: 60px;
margin-right: 8px;
text-align: right;
}

.about-page-issue-type-link {
border-bottom-color: rgba(75, 159, 213, 0.2);
color: rgb(75, 159, 213);
font-size: 24px;
font-weight: bold;
}

.about-login-form-header {
@@ -64,16 +103,19 @@
}

.about-page-auth-providers {
width: 200px;
}

.about-page-auth-providers .oauth-provider {
width: 100%;
}

.about-page-auth-providers .oauth-provider + .oauth-provider {
margin-top: 20px;
}

.about-page-section {
padding-top: 80px;
padding-bottom: 80px;
padding-bottom: 40px;
}

.about-page-section-gray {
@@ -102,8 +144,7 @@
}

.about-page-text {
line-height: 1.5;
font-size: 15px;
line-height: 1.4;
}

.about-page-link-more {
@@ -115,43 +156,25 @@
}

.about-page-issues {
display: flex;
justify-content: space-around;
margin-top: 80px;
}

.about-page-issues-box {
width: 280px;
float: left;
width: 33%;
text-align: center;
}

.about-page-issues-number {
display: block;
border: none;
padding: 20px 0;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
background-color: #4b9fd5;
color: #fff;
font-size: 50px;
display: inline-block;
font-size: 32px;
font-weight: bold;
}

.about-page-issues-number:hover {
background-color: #236a97;
color: #fff;
}

.about-page-issues-number:focus {
color: #fff;
}

.about-page-issues-description {
min-height: 120px;
padding: 25px 20px 25px;
border: 1px solid #e6e6e6;
border-radius: 2px;
background-color: #fff;
margin-top: 12px;
padding: 0 15px;
line-height: 1.4;
}

.about-page-issues-number + .about-page-issues-description {
@@ -166,18 +189,13 @@
text-transform: uppercase;
}

.about-page-issues-text {
line-height: 1.3;
font-size: 14px;
}

.about-page-analyzers {
display: flex;
justify-content: space-around;
justify-content: space-between;
flex-wrap: wrap;
}

.about-page-analyzer-box {
width: 280px;
margin-top: 80px;
width: 310px;
margin-top: 40px;
}

BIN
server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.png View File


+ 8
- 0
server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.svg View File

@@ -0,0 +1,8 @@
<svg viewBox="0 0 56 80" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.41">
<path d="M56.03 16.67L42.68 11.3 19.38 34 5.33 23.33 0 26.02v28l5.3 2.67L19.34 46 42.7 68.7l13.33-5.34v-46.7z" fill="#68217A" fill-rule="nonzero"/>
<path d="M58.03 15.3v49.4l-15.8 6.33-23.06-22.38-13.64 10.4-7.53-3.8V24.78l7.56-3.8 13.65 10.4 23.02-22.4 15.8 6.34zm-38.5 21.34L5.14 25.67 2 27.24V52.8l3.1 1.54 14.4-10.96 23.66 22.97L54.03 62V18.02l-10.9-4.37-23.6 23z" fill="#fff"/>
<path d="M41.35 30L28 39.97l13.36 10.05V30z" fill="#fff" fill-rule="nonzero"/>
<g>
<path d="M6.67 34.02v12l6.67-6.05-6.67-5.95z" fill="#fff" fill-rule="nonzero"/>
</g>
</svg>

+ 40
- 0
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -2685,3 +2685,43 @@ component_measures.legend.color_x=Color: {0}
component_measures.legend.size_x=Size: {0}
component_measures.x_of_y={0} of {1}
component_measures.no_history=There is no historical data.


#------------------------------------------------------------------------------
#
# ABOUT PAGE
#
#------------------------------------------------------------------------------
about_page.projects_analyzed=Projects Analyzed
about_page.issues_found=Issues Found
about_page.read_more=Read More

about_page.clean_code=Keep your code clean by fixing the leak
about_page.clean_code.text=By fixing new issues as they appear in code, you create and maintain a clean code base. Even on legacy projects, focusing on keeping new code clean will eventually yield a code base you can be proud of.

about_page.leak_period=Understanding the Leak Period
about_page.leak_period.text=The leak metaphor and the default Quality Gate are based on the leak period - the recent period against which you're tracking issues. For some previous_version makes the most sense, for others the last 30 days is a good option.

about_page.quality_model=SonarQube Quality Model
about_page.quality_model.bugs=Bugs track code that is demonstrably wrong or highly likely to yield unexpected behavior.
about_page.quality_model.vulnerabilities=Vulnerabilities are raised on code that is potentially vulnerable to exploitation by hackers.
about_page.quality_model.code_smells=Code Smells will confuse maintainers or give them pause. They are measured primarily in terms of the time they will take to fix.

about_page.quality_gates=Understanding Quality Gates
about_page.quality_gates.text=Your project's quality gate is the set of conditions the project must meet before it can be released into production. The quality gate is designed to ensure that the next version's quality will be better than the last.

about_page.standards=Conform to recognized standards
about_page.standards.text=SonarAnalyzers offer rules that support industry standards. Configure your Quality Profile with standard-related rules to ensure adherence.

about_page.scanners.sonarqube=SonarQube Scanner
about_page.scanners.sonarqube.text=The SonarQube Scanner is a Java-based command-line tool that can analyze any language SonarQube supports.
about_page.scanners.msbuild=SonarQube Scanner for MSBuild
about_page.scanners.msbuild.text=Built in collaboration with Microsoft, the SonarQube Scanner for MSBuild is the recommended way to launch a SonarQube analysis on MSBuild projects and solutions.
about_page.scanners.maven=SonarQube Scanner for Maven
about_page.scanners.maven.text=Using the SonarQube Scanner for Maven is as simple as running mvn sonar:sonar on your Maven project.
about_page.scanners.gradle=SonarQube Scanner for Gradle
about_page.scanners.gradle.text=The SonarQube Scanner for Gradle provides an easy way to start analysis of a Gradle project.
about_page.scanners.jenkins=SonarQube Scanner for Jenkins
about_page.scanners.jenkins.text=The SonarQube Scanner for Jenkins lets you integrate analysis seamlessly into a job or a pipeline.
about_page.scanners.ant=SonarQube Scanner for Ant"
about_page.scanners.ant.text=The SonarQube Scanner for Ant lets you start an analysis directly from an Apache Ant script.

Loading…
Cancel
Save