aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-11-25 16:08:41 +0100
committerGitHub <noreply@github.com>2016-11-25 16:08:41 +0100
commite12f240303a57ca726860ab3ce3d03b1bf8d5b5a (patch)
tree2fe3510ee115c244307e0fe62b30755c57621018 /server/sonar-web/src/main
parentd8cc30cca9971ea5e254c6a0ad538efd0998baaf (diff)
downloadsonarqube-e12f240303a57ca726860ab3ce3d03b1bf8d5b5a.tar.gz
sonarqube-e12f240303a57ca726860ab3ce3d03b1bf8d5b5a.zip
SONAR-8382 apply feedback on about page (#1411)
Diffstat (limited to 'server/sonar-web/src/main')
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutApp.js86
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js18
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutIssues.js70
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js23
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutProjects.js19
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js23
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutScanners.js140
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/AboutStandards.js60
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/DropImage.js36
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js69
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/LoginSection.js2
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/OAuthProvider.css1
-rw-r--r--server/sonar-web/src/main/js/apps/about/components/ReadMore.js38
-rw-r--r--server/sonar-web/src/main/js/apps/about/styles.css126
-rw-r--r--server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.pngbin14320 -> 0 bytes
-rw-r--r--server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.svg8
16 files changed, 358 insertions, 361 deletions
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js
index f6138107d1d..dedff134191 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutApp.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutApp.js
@@ -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>
);
}
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js b/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js
index 1da76b6945e..9c3c57c5e0a 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutCleanCode.js
@@ -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>
);
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutIssues.js b/server/sonar-web/src/main/js/apps/about/components/AboutIssues.js
index f762de45f26..dd2f0b3584e 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutIssues.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutIssues.js
@@ -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>
);
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js b/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js
index 3da6656a460..1755b96e69a 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutLeakPeriod.js
@@ -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>
);
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js b/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js
index af7852bb772..0c407f7b063 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutProjects.js
@@ -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>
);
}
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js b/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js
index 4ba827fdf80..024fb12b510 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutQualityGates.js
@@ -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>
);
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js b/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js
index f6f0a263ca0..764f63876a7 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutScanners.js
@@ -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>
diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js b/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js
index 42a84da0054..437c7b5e021 100644
--- a/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js
+++ b/server/sonar-web/src/main/js/apps/about/components/AboutStandards.js
@@ -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>
);
diff --git a/server/sonar-web/src/main/js/apps/about/components/DropImage.js b/server/sonar-web/src/main/js/apps/about/components/DropImage.js
deleted file mode 100644
index 63ef476e87b..00000000000
--- a/server/sonar-web/src/main/js/apps/about/components/DropImage.js
+++ /dev/null
@@ -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>
-
- );
-}
diff --git a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js
new file mode 100644
index 00000000000..4ebae3adc72
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js
@@ -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>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/about/components/LoginSection.js b/server/sonar-web/src/main/js/apps/about/components/LoginSection.js
index 43942c7cb09..08773d996bd 100644
--- a/server/sonar-web/src/main/js/apps/about/components/LoginSection.js
+++ b/server/sonar-web/src/main/js/apps/about/components/LoginSection.js
@@ -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}/>
))}
diff --git a/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.css b/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.css
index 5bd25619460..0718acd0253 100644
--- a/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.css
+++ b/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.css
@@ -8,6 +8,7 @@
box-sizing: border-box;
background-color: #236a97;
color: #fff;
+ text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
diff --git a/server/sonar-web/src/main/js/apps/about/components/ReadMore.js b/server/sonar-web/src/main/js/apps/about/components/ReadMore.js
new file mode 100644
index 00000000000..2199979f1ca
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/about/components/ReadMore.js
@@ -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>
+ );
+ }
+}
diff --git a/server/sonar-web/src/main/js/apps/about/styles.css b/server/sonar-web/src/main/js/apps/about/styles.css
index 1c79a4a3d33..a61922f9218 100644
--- a/server/sonar-web/src/main/js/apps/about/styles.css
+++ b/server/sonar-web/src/main/js/apps/about/styles.css
@@ -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;
}
diff --git a/server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.png b/server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.png
deleted file mode 100644
index 7b82a40d1e7..00000000000
--- a/server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.png
+++ /dev/null
Binary files differ
diff --git a/server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.svg b/server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.svg
new file mode 100644
index 00000000000..811245afe89
--- /dev/null
+++ b/server/sonar-web/src/main/webapp/images/scanner-logos/msbuild.svg
@@ -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>