diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2017-02-07 16:31:36 +0100 |
---|---|---|
committer | Stas Vilchik <stas-vilchik@users.noreply.github.com> | 2017-02-08 16:25:16 +0100 |
commit | 7e62aa89c132359ea678677d89943efefcaae7e8 (patch) | |
tree | acb9699d1f3a33d0980e952b28d19c0373cb35b8 | |
parent | 6d40de520d8927f6d2b9da67b427e8b589075fe4 (diff) | |
download | sonarqube-7e62aa89c132359ea678677d89943efefcaae7e8.tar.gz sonarqube-7e62aa89c132359ea678677d89943efefcaae7e8.zip |
SONAR-8750 Display a branding landing page
16 files changed, 651 insertions, 234 deletions
diff --git a/server/sonar-web/src/main/js/api/settings.js b/server/sonar-web/src/main/js/api/settings.js index 2e5ce2b4bfa..0276d4cd8bf 100644 --- a/server/sonar-web/src/main/js/api/settings.js +++ b/server/sonar-web/src/main/js/api/settings.js @@ -96,8 +96,3 @@ export function getServerId () { export function generateServerId (organization, ip) { return postJSON('/api/server_id/generate', { organization, ip }); } - -// TODO replace with /api/settings -export const getSettingValue = key => ( - getJSON(`/api/properties/${key}`).then(r => r[0] ? r[0].value : null) -); diff --git a/server/sonar-web/src/main/js/apps/about/components/IconLock.js b/server/sonar-web/src/main/js/apps/about/actions.js index fbdc836fad9..e07cd9df5e0 100644 --- a/server/sonar-web/src/main/js/apps/about/components/IconLock.js +++ b/server/sonar-web/src/main/js/apps/about/actions.js @@ -17,13 +17,14 @@ * 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'; +// @flow +import { getValues } from '../../api/settings'; +import { receiveValues } from '../settings/store/values/actions'; -export default function () { - /* eslint-disable max-len */ - return ( - <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 288 448" width="20" height="20"> - <path fill="#fff" d="M264 192q10 0 17 7t7 17v144q0 10-7 17t-17 7H24q-10 0-17-7t-7-17V216q0-10 7-17t17-7h8v-80q0-46.25 32.875-79.125T144 0t79.125 32.875T256 112q0 6.5-4.75 11.25T240 128h-16q-6.5 0-11.25-4.75T208 112q0-26.5-18.75-45.25T144 48 98.75 66.75 80 112v80h184z"/> - </svg> - ); -} +export const fetchAboutPageSettings = (): Function => (dispatch: Function): Promise<*> => { + const keys = ['sonar.lf.aboutText']; + + return getValues(keys.join()).then(values => { + dispatch(receiveValues(values)); + }); +}; 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 21db6186dee..fbc571db81e 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 @@ -33,10 +33,11 @@ import AboutStandards from './AboutStandards'; import AboutScanners from './AboutScanners'; import { searchProjects } from '../../../api/components'; import { getFacet } from '../../../api/issues'; -import * as settingsAPI from '../../../api/settings'; -import { getCurrentUser } from '../../../store/rootReducer'; -import '../styles.css'; +import { getCurrentUser, getSettingValue } from '../../../store/rootReducer'; import { translate } from '../../../helpers/l10n'; +import { fetchAboutPageSettings } from '../actions'; +import AboutAppForSonarQubeDotCom from './AboutAppForSonarQubeDotCom'; +import '../styles.css'; type State = { loading: boolean, @@ -45,15 +46,17 @@ type State = { [key: string]: { count: number } - }, - customText?: string + } }; class AboutApp extends React.Component { mounted: boolean; props: { - currentUser: { isLoggedIn: boolean } + currentUser: { isLoggedIn: boolean }, + customText?: string, + fetchAboutPageSettings: () => Promise<*>, + sonarqubeDotCom?: { value: string } }; state: State = { @@ -78,7 +81,7 @@ class AboutApp extends React.Component { } loadCustomText () { - return settingsAPI.getSettingValue('sonar.lf.aboutText'); + return this.props.fetchAboutPageSettings(); } loadData () { @@ -88,12 +91,11 @@ class AboutApp extends React.Component { this.loadCustomText() ]).then(responses => { if (this.mounted) { - const [projectsCount, issues, customText] = responses; + const [projectsCount, issues] = responses; const issueTypes = keyBy(issues.facet, 'val'); this.setState({ projectsCount, issueTypes, - customText, loading: false }); } @@ -105,7 +107,7 @@ class AboutApp extends React.Component { return null; } - const { customText } = this.state; + const { customText, sonarqubeDotCom } = this.props; // $FlowFixMe const bugs = this.state.issueTypes['BUG'].count; @@ -114,6 +116,18 @@ class AboutApp extends React.Component { // $FlowFixMe const codeSmells = this.state.issueTypes['CODE_SMELL'].count; + if (sonarqubeDotCom && sonarqubeDotCom.value === 'true') { + return ( + <AboutAppForSonarQubeDotCom + bugs={bugs} + codeSmells={codeSmells} + currentUser={this.props.currentUser} + customText={customText} + projectsCount={this.state.projectsCount} + vulnerabilities={vulnerabilities}/> + ); + } + return ( <div id="about-page" className="about-page"> <div className="about-page-container"> @@ -138,8 +152,8 @@ class AboutApp extends React.Component { </div> </div> - {customText != null && customText.length > 0 && ( - <div className="about-page-section" dangerouslySetInnerHTML={{ __html: customText }}/> + {customText != null && customText.value && ( + <div className="about-page-section" dangerouslySetInnerHTML={{ __html: customText.value }}/> )} <AboutLanguages/> @@ -172,7 +186,11 @@ class AboutApp extends React.Component { } const mapStateToProps = state => ({ - currentUser: getCurrentUser(state) + currentUser: getCurrentUser(state), + customText: getSettingValue(state, 'sonar.lf.aboutText'), + sonarqubeDotCom: getSettingValue(state, 'sonar.lf.sonarqube.com.enabled') }); -export default connect(mapStateToProps)(AboutApp); +const mapDispatchToProps = { fetchAboutPageSettings }; + +export default connect(mapStateToProps, mapDispatchToProps)(AboutApp); diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js new file mode 100644 index 00000000000..2c58a9d5d6f --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/components/AboutAppForSonarQubeDotCom.js @@ -0,0 +1,112 @@ +/* + * 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. + */ +// @flow +import React from 'react'; +import { Link } from 'react-router'; +import AboutProjects from './AboutProjects'; +import EntryIssueTypesForSonarQubeDotCom from './EntryIssueTypesForSonarQubeDotCom'; +import AboutRulesForSonarQubeDotCom from './AboutRulesForSonarQubeDotCom'; +import AboutLanguages from './AboutLanguages'; +import AboutCleanCode from './AboutCleanCode'; +import AboutQualityModelForSonarQubeDotCom from './AboutQualityModelForSonarQubeDotCom'; +import AboutQualityGates from './AboutQualityGates'; +import AboutLeakPeriod from './AboutLeakPeriod'; +import AboutStandards from './AboutStandards'; +import AboutScanners from './AboutScanners'; +import { translate } from '../../../helpers/l10n'; +import '../sonarqube-dot-com-styles.css'; + +export default class AboutAppForSonarQubeDotCom extends React.Component { + props: { + bugs: number, + codeSmells: number, + currentUser: { isLoggedIn: boolean }, + customText?: string, + projectsCount: number, + vulnerabilities: number, + }; + + render () { + const { customText } = this.props; + + + return ( + <div id="about-page" className="about-page sqcom-about-page"> + <div className="sqcom-about-page-entry"> + <div className="about-page-container"> + <div className="sqcom-about-page-intro"> + <h1 className="big-spacer-bottom"> + Continuous Code Quality<br/>as a Service + </h1> + <a className="button button-active" href="https://about.sonarqube.com/get-started/"> + Get Started + </a> + {!this.props.currentUser.isLoggedIn && ( + <Link to="/sessions/new" className="button big-spacer-left"> + {translate('layout.login')} + </Link> + )} + </div> + + <div className="sqcom-about-page-instance"> + <AboutProjects count={this.props.projectsCount}/> + <EntryIssueTypesForSonarQubeDotCom + bugs={this.props.bugs} + vulnerabilities={this.props.vulnerabilities} + codeSmells={this.props.codeSmells}/> + </div> + </div> + </div> + + <AboutRulesForSonarQubeDotCom/> + + <div className="about-page-container"> + {customText != null && customText.value && ( + <div className="about-page-section" dangerouslySetInnerHTML={{ __html: customText.value }}/> + )} + + <AboutLanguages/> + + <AboutQualityModelForSonarQubeDotCom/> + + <div className="flex-columns"> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutCleanCode/> + </div> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutLeakPeriod/> + </div> + </div> + + <div className="flex-columns"> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutQualityGates/> + </div> + <div className="flex-column flex-column-half about-page-group-boxes"> + <AboutStandards/> + </div> + </div> + + <AboutScanners/> + </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 ecaf724f924..0fd88aa97f2 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 @@ -31,12 +31,14 @@ export default class AboutProjects extends React.Component { return ( <div className="about-page-projects"> <div> - <Link to="/projects" className="about-page-projects-link"> - {formatMeasure(this.props.count, 'INT')} - </Link> - </div> - <div> - {translate('about_page.projects_analyzed')} + <div> + <Link to="/projects" className="about-page-projects-link"> + {formatMeasure(this.props.count, 'INT')} + </Link> + </div> + <div> + {translate('about_page.projects_analyzed')} + </div> </div> </div> ); diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutQualityModelForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutQualityModelForSonarQubeDotCom.js new file mode 100644 index 00000000000..86cfdb0f5e7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/components/AboutQualityModelForSonarQubeDotCom.js @@ -0,0 +1,65 @@ +/* + * 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'; +import BugIconForSonarQubeDotCom from './BugIconForSonarQubeDotCom'; +import VulnerabilityIconForSonarQubeDotCom from './VulnerabilityIconForSonarQubeDotCom'; +import CodeSmellIconForSonarQubeDotCom from './CodeSmellIconForSonarQubeDotCom'; + +export default class AboutQualityModelForSonarQubeDotCom extends React.Component { + render () { + return ( + <div className="boxed-group about-quality-model sqcom-about-quality-model"> + <h2>{translate('about_page.quality_model')}</h2> + + <div className="boxed-group-inner clearfix"> + <div className="flex-columns"> + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"><BugIconForSonarQubeDotCom/></div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.BUG.plural')}</strong> + {' '} + {translate('about_page.quality_model.bugs')} + </p> + </div> + + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"><VulnerabilityIconForSonarQubeDotCom/></div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.VULNERABILITY.plural')}</strong> + {' '} + {translate('about_page.quality_model.vulnerabilities')} + </p> + </div> + + <div className="flex-column flex-column-third"> + <div className="pull-left little-spacer-right"><CodeSmellIconForSonarQubeDotCom/></div> + <p className="about-page-text overflow-hidden"> + <strong>{translate('issue.type.CODE_SMELL.plural')}</strong> + {' '} + {translate('about_page.quality_model.code_smells')} + </p> + </div> + </div> + </div> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js new file mode 100644 index 00000000000..d16567bf084 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/components/AboutRulesForSonarQubeDotCom.js @@ -0,0 +1,49 @@ +/* + * 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. + */ +// @flow +import React from 'react'; +import { Link } from 'react-router'; +import { getRulesUrl } from '../../../helpers/urls'; + +export default class AboutRulesForSonarQubeDotCom extends React.Component { + render () { + return ( + <div className="sqcom-about-rules"> + <div className="about-page-container"> + <Link to={getRulesUrl()} className="sqcom-about-rules-link"> + +2000 rules + <span className="spacer-left"> + <svg width="15" height="36" viewBox="0 0 15 36"> + <g transform="matrix(1,0,0,1,-267,-362)"> + <path d="M268,363L281,380L269,397" style={{ fill: 'none', stroke: '#c1d9ea', strokeWidth: 1 }}/> + </g> + </svg> + </span> + </Link> + <Link to={getRulesUrl({ languages: 'js' })} className="sqcom-about-rules-link">JavaScript</Link> + <Link to={getRulesUrl({ languages: 'java' })} className="sqcom-about-rules-link">Java</Link> + <Link to={getRulesUrl({ languages: 'c,cpp' })} className="sqcom-about-rules-link">C/C++</Link> + <Link to={getRulesUrl({ languages: 'cs' })} className="sqcom-about-rules-link">C#</Link> + <Link to={getRulesUrl()} className="button">And More</Link> + </div> + </div> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/about/components/BugIconForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/BugIconForSonarQubeDotCom.js new file mode 100644 index 00000000000..858fffc0774 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/components/BugIconForSonarQubeDotCom.js @@ -0,0 +1,32 @@ +/* + * 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. + */ +// @flow +import React from 'react'; + +export default class BugIconForSonarQubeDotCom extends React.Component { + render () { + /* eslint-disable max-len */ + return ( + <svg viewBox="0 0 26 26" width="26" height="26"> + <path style={{ fill: 'currentcolor' }} d="M23.737 15.91l-2.298-2.297a.797.797 0 0 0-.542-.232h-2.18v-1.588l2.722-2.723a.773.773 0 0 0 .233-.542V4.243a.777.777 0 0 0-.775-.775.777.777 0 0 0-.774.775v3.962l-1.407 1.407v-.633a.777.777 0 0 0-.774-.774h-.517a4.51 4.51 0 0 0-2.852-3.446l2.698-2.698a.787.787 0 0 0 0-1.097.787.787 0 0 0-1.098 0L12.985 4.14 9.823.99a.787.787 0 0 0-1.097 0 .787.787 0 0 0 0 1.097l2.672 2.672a4.51 4.51 0 0 0-2.853 3.446H7.99a.777.777 0 0 0-.774.774v.633L5.81 8.192v-3.95a.777.777 0 0 0-.774-.774.777.777 0 0 0-.775.775v4.272c0 .206.078.4.233.542l2.723 2.723v1.6H5.035c-.207 0-.4.078-.542.233L2.195 15.91a.787.787 0 0 0 0 1.098.764.764 0 0 0 .542.232c.194 0 .4-.078.542-.232l2.078-2.078h1.86v.761l-2.789 3.64a.783.783 0 0 0-.155.477v4.505c0 .426.349.774.775.774a.777.777 0 0 0 .774-.774v-4.247l1.433-1.884a5.77 5.77 0 0 0 2.788 4.298l.077.039c.84.49 1.82.761 2.853.761a5.825 5.825 0 0 0 2.865-.761c.013-.013.039-.013.051-.026a5.75 5.75 0 0 0 2.801-4.31l1.446 1.883v4.247c0 .426.348.774.774.774a.777.777 0 0 0 .775-.774v-4.505a.811.811 0 0 0-.155-.477l-2.788-3.64v-.761H20.6l2.078 2.078a.764.764 0 0 0 .542.232c.193 0 .4-.078.542-.232a.787.787 0 0 0-.026-1.098zm-10.752-9.9c1.369 0 2.517.93 2.853 2.182h-5.705a2.954 2.954 0 0 1 2.852-2.181zm-4.22 11.527V9.754h3.433v9.254l-1.82 1.82a4.172 4.172 0 0 1-1.613-3.291zm3.046 4.04l1.149-1.15 1.148 1.15a4.188 4.188 0 0 1-1.148.167c-.388 0-.775-.064-1.15-.167zm5.356-4.04c0 1.342-.632 2.53-1.6 3.304l-1.82-1.82V9.754h3.433v7.783h-.013z"/> + </svg> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/about/components/CodeSmellIconForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/CodeSmellIconForSonarQubeDotCom.js new file mode 100644 index 00000000000..1e7887c0766 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/components/CodeSmellIconForSonarQubeDotCom.js @@ -0,0 +1,32 @@ +/* + * 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. + */ +// @flow +import React from 'react'; + +export default class CodeSmellIconForSonarQubeDotCom extends React.Component { + render () { + /* eslint-disable max-len */ + return ( + <svg viewBox="0 0 26 26" width="26" height="26"> + <path style={{ fill: 'currentcolor' }} d="M19.957 5.099a10.455 10.455 0 0 0-7.424-3.077c-1.42 0-2.792.278-4.087.825a10.426 10.426 0 0 0-3.338 2.249 10.462 10.462 0 0 0-3.076 7.427c0 1.418.279 2.791.826 4.087a10.497 10.497 0 0 0 2.25 3.338 10.426 10.426 0 0 0 3.338 2.25c1.295.546 2.67.825 4.086.825 1.419 0 2.791-.279 4.087-.826a10.426 10.426 0 0 0 3.338-2.249 10.465 10.465 0 0 0 3.075-7.425c0-1.417-.278-2.793-.823-4.086a10.396 10.396 0 0 0-2.252-3.338zm.393 10.725a8.436 8.436 0 0 1-1.818 2.695 8.452 8.452 0 0 1-5.996 2.486 8.442 8.442 0 0 1-5.997-2.486 8.455 8.455 0 0 1-2.486-5.996 8.43 8.43 0 0 1 2.486-5.995 8.452 8.452 0 0 1 5.996-2.486 8.445 8.445 0 0 1 5.997 2.486 8.452 8.452 0 0 1 2.485 5.995 8.35 8.35 0 0 1-.667 3.3zm-7.794 4.202h-.037a7.767 7.767 0 0 1-3.426-.835.317.317 0 0 1-.13-.44l2.25-3.923a.32.32 0 0 1 .403-.132c.284.119.595.189.92.189.326 0 .639-.067.92-.19a.32.32 0 0 1 .404.133l2.255 3.922c.09.157.03.36-.133.441a7.896 7.896 0 0 1-3.426.835zm-1.58-7.457c0-.003 0-.009-.003-.013a1.56 1.56 0 0 1 2.337-1.35c.468.269.781.77.781 1.35v.013a1.557 1.557 0 0 1-3.115 0zm-1.068.015H5.384a.318.318 0 0 1-.32-.334c.03-.614.19-1.992.981-3.391l.008-.016.007-.016a7.806 7.806 0 0 1 2.428-2.554.317.317 0 0 1 .448.106l2.282 3.903a.316.316 0 0 1-.082.414 2.371 2.371 0 0 0-.914 1.605.325.325 0 0 1-.314.283zm9.776-.007h-4.526a.32.32 0 0 1-.316-.282 2.371 2.371 0 0 0-.913-1.604.322.322 0 0 1-.082-.414l2.284-3.904a.317.317 0 0 1 .449-.106 7.787 7.787 0 0 1 2.426 2.554l.016.033a7.74 7.74 0 0 1 .98 3.387.319.319 0 0 1-.318.336z"/> + </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 index d55a975fd69..9b4816a6d24 100644 --- a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js +++ b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypes.js @@ -38,38 +38,46 @@ export default class EntryIssueTypes extends React.Component { return ( <div className="about-page-projects"> - <ul className="about-page-issue-types"> - <li> - <div className="about-page-issue-type-number"> - <Link to={getIssuesUrl({ resolved: false, types: 'BUG' })} - className="about-page-issue-type-link"> - {formatMeasure(bugs, 'SHORT_INT')} - </Link> - </div> - <span className="little-spacer-right"><BugIcon/></span> - {translate('issue.type.BUG.plural')} - </li> - <li> - <div className="about-page-issue-type-number"> - <Link to={getIssuesUrl({ resolved: false, types: 'VULNERABILITY' })} - className="about-page-issue-type-link"> - {formatMeasure(vulnerabilities, 'SHORT_INT')} - </Link> - </div> - <span className="little-spacer-right"><VulnerabilityIcon/></span> - {translate('issue.type.VULNERABILITY.plural')} - </li> - <li> - <div className="about-page-issue-type-number"> - <Link to={getIssuesUrl({ resolved: false, types: 'CODE_SMELL' })} - className="about-page-issue-type-link"> - {formatMeasure(codeSmells, 'SHORT_INT')} - </Link> - </div> - <span className="little-spacer-right"><CodeSmellIcon/></span> - {translate('issue.type.CODE_SMELL.plural')} - </li> - </ul> + <table className="about-page-issue-types"> + <tbody> + <tr> + <td className="about-page-issue-type-number"> + <Link to={getIssuesUrl({ resolved: false, types: 'BUG' })} + className="about-page-issue-type-link"> + {formatMeasure(bugs, 'SHORT_INT')} + </Link> + </td> + <td> + <span className="little-spacer-right"><BugIcon/></span> + {translate('issue.type.BUG.plural')} + </td> + </tr> + <tr> + <td className="about-page-issue-type-number"> + <Link to={getIssuesUrl({ resolved: false, types: 'VULNERABILITY' })} + className="about-page-issue-type-link"> + {formatMeasure(vulnerabilities, 'SHORT_INT')} + </Link> + </td> + <td> + <span className="little-spacer-right"><VulnerabilityIcon/></span> + {translate('issue.type.VULNERABILITY.plural')} + </td> + </tr> + <tr> + <td className="about-page-issue-type-number"> + <Link to={getIssuesUrl({ resolved: false, types: 'CODE_SMELL' })} + className="about-page-issue-type-link"> + {formatMeasure(codeSmells, 'SHORT_INT')} + </Link> + </td> + <td> + <span className="little-spacer-right"><CodeSmellIcon/></span> + {translate('issue.type.CODE_SMELL.plural')} + </td> + </tr> + </tbody> + </table> </div> ); } diff --git a/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js new file mode 100644 index 00000000000..ba634437720 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/components/EntryIssueTypesForSonarQubeDotCom.js @@ -0,0 +1,84 @@ +/* + * 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 { Link } from 'react-router'; +import { formatMeasure } from '../../../helpers/measures'; +import { translate } from '../../../helpers/l10n'; +import { getIssuesUrl } from '../../../helpers/urls'; +import BugIconForSonarQubeDotCom from './BugIconForSonarQubeDotCom'; +import VulnerabilityIconForSonarQubeDotCom from './VulnerabilityIconForSonarQubeDotCom'; +import CodeSmellIconForSonarQubeDotCom from './CodeSmellIconForSonarQubeDotCom'; + +export default class EntryIssueTypesForSonarQubeDotCom 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"> + <table className="about-page-issue-types"> + <tbody> + <tr> + <td className="about-page-issue-type-number"> + <Link to={getIssuesUrl({ resolved: false, types: 'BUG' })} + className="about-page-issue-type-link"> + {formatMeasure(bugs, 'SHORT_INT')} + </Link> + </td> + <td> + <span className="little-spacer-right"><BugIconForSonarQubeDotCom/></span> + {translate('issue.type.BUG.plural')} + </td> + </tr> + <tr> + <td className="about-page-issue-type-number"> + <Link to={getIssuesUrl({ resolved: false, types: 'VULNERABILITY' })} + className="about-page-issue-type-link"> + {formatMeasure(vulnerabilities, 'SHORT_INT')} + </Link> + </td> + <td> + <span className="little-spacer-right"><VulnerabilityIconForSonarQubeDotCom/></span> + {translate('issue.type.VULNERABILITY.plural')} + </td> + </tr> + <tr> + <td className="about-page-issue-type-number"> + <Link to={getIssuesUrl({ resolved: false, types: 'CODE_SMELL' })} + className="about-page-issue-type-link"> + {formatMeasure(codeSmells, 'SHORT_INT')} + </Link> + </td> + <td> + <span className="little-spacer-right"><CodeSmellIconForSonarQubeDotCom/></span> + {translate('issue.type.CODE_SMELL.plural')} + </td> + </tr> + </tbody> + </table> + </div> + ); + } +} 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 deleted file mode 100644 index 0718acd0253..00000000000 --- a/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.css +++ /dev/null @@ -1,29 +0,0 @@ -.oauth-provider { - display: block; - width: 180px; - line-height: 22px; - padding: 8px 12px; - border: none; - border-radius: 2px; - box-sizing: border-box; - background-color: #236a97; - color: #fff; - text-align: center; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.oauth-provider:hover, -.oauth-provider:focus { - color: #fff; - box-shadow: inset 0 0 16px rgba(0, 0, 0, 0.3); -} - -.oauth-provider > span { - padding-left: 6px; -} - -.oauth-provider-sonarqube { - background-color: #4b9fd5; -} diff --git a/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.js b/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.js deleted file mode 100644 index 1ae53658a2b..00000000000 --- a/server/sonar-web/src/main/js/apps/about/components/OAuthProvider.js +++ /dev/null @@ -1,46 +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'; -import './OAuthProvider.css'; - -export default class OAuthProvider extends React.Component { - static propTypes = { - provider: React.PropTypes.shape({ - key: React.PropTypes.string.isRequired, - name: React.PropTypes.string.isRequired, - iconPath: React.PropTypes.string.isRequired, - backgroundColor: React.PropTypes.string.isRequired - }).isRequired - }; - - render () { - const { key, name, iconPath, backgroundColor } = this.props.provider; - - const url = window.baseUrl + '/sessions/init/' + key; - const label = 'Log in with ' + name; - - return ( - <a className="oauth-provider" href={url} style={{ backgroundColor }} title={label}> - <img alt={name} width="20" height="20" src={window.baseUrl + iconPath}/> - <span>{label}</span> - </a> - ); - } -} diff --git a/server/sonar-web/src/main/js/apps/about/components/VulnerabilityIconForSonarQubeDotCom.js b/server/sonar-web/src/main/js/apps/about/components/VulnerabilityIconForSonarQubeDotCom.js new file mode 100644 index 00000000000..41ca97ce2f1 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/components/VulnerabilityIconForSonarQubeDotCom.js @@ -0,0 +1,32 @@ +/* + * 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. + */ +// @flow +import React from 'react'; + +export default class VulnerabilityIconForSonarQubeDotCom extends React.Component { + render () { + /* eslint-disable max-len */ + return ( + <svg viewBox="0 0 26 26" width="26" height="26"> + <path style={{ fill: 'currentcolor' }} d="M7.688 9.224V5.818c0-2.622 2.16-4.756 4.813-4.756 2.654 0 4.802 2.134 4.813 4.756v.931c0 .5-.413.909-.919.909a.916.916 0 0 1-.919-.909v-.93c0-1.624-1.332-2.94-2.975-2.94s-2.975 1.316-2.975 2.94v3.405h7.892c1.401 0 2.539 1.124 2.539 2.509v9.706c0 1.442-1.195 2.623-2.654 2.623H7.688c-1.46 0-2.654-1.18-2.654-2.623v-9.706c0-1.385 1.137-2.509 2.539-2.509h.115zm9.615 13.033a.814.814 0 0 0 .816-.806v-9.718a.692.692 0 0 0-.701-.692H7.573c-.39 0-.7.306-.7.692v9.718c0 .442.367.806.815.806h9.615zm-4.802-8.98c-1.045 0-1.907.84-1.907 1.884 0 .704.402 1.329.988 1.647v2.304c0 .5.414.908.92.908a.916.916 0 0 0 .918-.908v-2.316c.586-.318.988-.942.988-1.646a1.904 1.904 0 0 0-1.907-1.873zM22.99 8.804l-1.7-.681c-.47-.182-1.01.034-1.194.5a.904.904 0 0 0 .505 1.18l1.712.681c.115.046.23.068.344.068a.908.908 0 0 0 .85-.567.91.91 0 0 0-.517-1.18zm-2.837-1.703a.939.939 0 0 0 1.206.488l1.689-.715a.9.9 0 0 0 .482-1.192c-.195-.465-.735-.67-1.206-.477l-1.689.716a.876.876 0 0 0-.482 1.18zm-1.068-1.124c-.471-.181-.69-.715-.506-1.192l.69-1.68c.183-.465.723-.681 1.194-.5.471.182.69.716.506 1.181l-.69 1.692a.908.908 0 0 1-.85.567.932.932 0 0 1-.344-.068z"/> + </svg> + ); + } +} diff --git a/server/sonar-web/src/main/js/apps/about/sonarqube-dot-com-styles.css b/server/sonar-web/src/main/js/apps/about/sonarqube-dot-com-styles.css new file mode 100644 index 00000000000..0607c3dff15 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/sonarqube-dot-com-styles.css @@ -0,0 +1,146 @@ +@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700'); + +.sqcom-about-page { + font-family: 'Roboto', sans-serif; + font-size: 15px !important; + font-weight: 300; +} + +.sqcom-about-page-entry { + padding-top: 65px; + padding-bottom: 65px; + background-color: #4b9fd5; +} + +.sqcom-about-page-entry a { + color: #4b9fd5; +} + +.sqcom-about-page-entry .about-page-container { + display: flex; + justify-content: space-between; + align-items: center; +} + +.sqcom-about-page-intro { + +} + +.sqcom-about-page-intro > h1 { + line-height: 56px; + color: #fff; + font-size: 44px; + font-weight: 300; +} + +.sqcom-about-page-intro > .button { + height: 44px; + line-height: 42px; + padding-left: 20px; + padding-right: 20px; + border-color: #fff; + border-radius: 3px; + color: #fff; + font-size: 16px; + font-weight: 500; + text-transform: uppercase; + transition: none; +} + +.sqcom-about-page-intro > .button:hover { + background-color: #fff; + color: #4b9fd5; +} + +.sqcom-about-page-intro > .button-active { + border-color: #b0eb41; + background-color: #b0eb41; + color: #225463; +} + +.sqcom-about-page-intro > .button-active:hover { + border-color: #91d315; + background-color: #91d315; + color: #225463; +} + +.sqcom-about-page-instance { + display: flex; + align-items: stretch; +} + +.sqcom-about-page-instance .about-page-projects { + display: flex; + justify-content: center; + align-items: center; + min-width: 190px; + margin-left: 15px; + padding: 25px; + background-color: #fff; + color: #686868; + font-size: 18px; + font-weight: 300; +} + +.sqcom-about-page-instance .about-page-projects-link { + font-weight: 400; +} + +.sqcom-about-page-instance .about-page-issue-types > li + li { + margin-top: 20px; +} + +.sqcom-about-rules { + margin-bottom: 45px; + background-color: #3988bc; +} + +.sqcom-about-rules .about-page-container { + display: flex; + justify-content: space-between; + align-items: center; +} + +.sqcom-about-rules .button { + height: 33px; + line-height: 30px; + padding-left: 15px; + padding-right: 15px; + border-color: #fff; + border-radius: 3px; + color: #fff; + font-size: 14px; + font-weight: bold; + text-transform: uppercase; +} + +.sqcom-about-rules .button:hover { + background-color: #fff; + color: #4b9fd5; +} + +.sqcom-about-rules-link { + line-height: 36px; + padding: 24px 40px; + border: none; + color: #c1d9ea; + font-size: 20px; +} + +.sqcom-about-rules-link:first-child { + margin-left: -40px; +} + +.sqcom-about-rules-link:hover { + background-color: #398cc8; + color: #fff; +} + +.sqcom-about-rules-link:hover path { + fill: #fff; +} + +.sqcom-about-quality-model svg { + transform: translateY(-3px) !important; +} + 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 d09ede5c5f7..7d06cd0caf9 100644 --- a/server/sonar-web/src/main/js/apps/about/styles.css +++ b/server/sonar-web/src/main/js/apps/about/styles.css @@ -7,6 +7,8 @@ } .about-page .boxed-group h2 { + padding-left: 0; + padding-right: 0; font-size: 18px; } @@ -15,6 +17,8 @@ } .about-page .boxed-group-inner { + padding-left: 0; + padding-right: 0; padding-bottom: 25px; } @@ -81,8 +85,8 @@ text-align: left; } -.about-page-issue-types > li + li { - margin-top: 12px; +.about-page-issue-types tr + tr td { + padding-top: 12px; } .about-page-issue-types svg { @@ -91,9 +95,7 @@ } .about-page-issue-type-number { - display: inline-block; - min-width: 60px; - margin-right: 16px; + padding-right: 16px; text-align: right; } @@ -102,61 +104,9 @@ font-weight: bold; } -.about-login-form-header { - margin-bottom: 30px; - font-size: 18px; - font-weight: bold; -} - -.about-page-sign-up { - margin-top: 20px; - color: rgba(255, 255, 255, 0.7); -} - -.about-page-sign-up a { - color: #4b9fd5; - border-color: #4b9fd5; -} - -.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-bottom: 40px; -} - -.about-page-section-gray { - border-top: 1px solid #e6e6e6; - border-bottom: 1px solid #e6e6e6; - background-color: #f3f3f3; -} - -.about-page-section-image { - position: absolute; - z-index: 5; - top: -80px; - right: 100%; -} - -.about-page-center-container .about-page-section-image { - right: auto; - left: -210px; -} - -.about-page-header { - line-height: 1; - margin-bottom: 30px; - font-size: 28px; - font-weight: bold; + padding-top: 20px; + padding-bottom: 10px; } .about-page-text { @@ -171,40 +121,6 @@ border-bottom: 1px solid #cae3f2; } -.about-page-issues { - margin-top: 80px; -} - -.about-page-issues-box { - float: left; - width: 33%; - text-align: center; -} - -.about-page-issues-number { - display: inline-block; - font-size: 32px; - font-weight: bold; -} - -.about-page-issues-description { - margin-top: 12px; - padding: 0 15px; - line-height: 1.4; -} - -.about-page-issues-number + .about-page-issues-description { - border-top: none; - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.about-page-issues-header { - margin-bottom: 20px; - font-size: 21px; - text-transform: uppercase; -} - .about-page-languages { display: flex; justify-content: space-between; |