diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-06-14 17:49:14 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-06-21 20:21:28 +0200 |
commit | c4803912bda0edfceeb09d9115c1dd2cdf8db96e (patch) | |
tree | 589a54b8bd7818affa76c78694b87a0f46ddc8da /server/sonar-web/src/main | |
parent | ece8b13900f69483dc52be0d30bb240aacc0756f (diff) | |
download | sonarqube-c4803912bda0edfceeb09d9115c1dd2cdf8db96e.tar.gz sonarqube-c4803912bda0edfceeb09d9115c1dd2cdf8db96e.zip |
SONARCLOUD-62 move /sq page (#373)
Diffstat (limited to 'server/sonar-web/src/main')
8 files changed, 644 insertions, 44 deletions
diff --git a/server/sonar-web/src/main/js/app/theme.js b/server/sonar-web/src/main/js/app/theme.js index 76560dcf985..75f6dcdc4d1 100644 --- a/server/sonar-web/src/main/js/app/theme.js +++ b/server/sonar-web/src/main/js/app/theme.js @@ -113,7 +113,9 @@ module.exports = { sonarcloudOrangeDark: '#e65c00', sonarcloudFontFamily: "Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif", + sonarcloudBlack200: '#f9f9fb', sonarcloudBlack300: '#cfd3d7', sonarcloudBlack700: '#434447', - sonarcloudBlack800: '#2d3032' + sonarcloudBlack800: '#2d3032', + sonarcloudBlack900: '#070706' }; diff --git a/server/sonar-web/src/main/js/apps/about/routes.ts b/server/sonar-web/src/main/js/apps/about/routes.ts index ad8591fc26a..7758ecaa78e 100644 --- a/server/sonar-web/src/main/js/apps/about/routes.ts +++ b/server/sonar-web/src/main/js/apps/about/routes.ts @@ -27,7 +27,10 @@ const routes = [ () => isSonarCloud() ? import('./sonarcloud/HomeContainer') : import('./components/AboutApp') ) - } + }, + childRoutes: isSonarCloud + ? [{ path: 'sq', component: lazyLoad(() => import('./sonarcloud/SQHomeContainer')) }] + : [] } ]; diff --git a/server/sonar-web/src/main/js/apps/about/sonarcloud/Home.tsx b/server/sonar-web/src/main/js/apps/about/sonarcloud/Home.tsx index 5118ad30058..e5d99cc504f 100644 --- a/server/sonar-web/src/main/js/apps/about/sonarcloud/Home.tsx +++ b/server/sonar-web/src/main/js/apps/about/sonarcloud/Home.tsx @@ -20,6 +20,8 @@ import * as React from 'react'; import { Link } from 'react-router'; import Footer from './Footer'; +import Pricing from './Pricing'; +import StartUsing from './StartUsing'; import GlobalContainer from '../../../app/components/GlobalContainer'; import { CurrentUser, isLoggedIn } from '../../../app/types'; import ChevronRightIcon from '../../../components/icons-components/ChevronRightcon'; @@ -98,43 +100,9 @@ export default class Home extends React.PureComponent<Props> { </li> </ul> - <div className="sc-pricing sc-narrow-container"> - <div className="sc-pricing-block"> - <h3 className="sc-pricing-title">Open Source Projects</h3> - <span className="sc-pricing-small"> </span> - <span className="sc-pricing-price">Free</span> - </div> + <Pricing /> - <div className="sc-pricing-block"> - <h3 className="sc-pricing-title">Private Projects</h3> - <span className="sc-pricing-small">14 days free trial</span> - <strong> - From <span className="sc-pricing-price">10€</span>/mo - </strong> - <Link - className="sc-pricing-about sc-pricing-small" - to="/documentation/sonarcloud-pricing"> - see prices - </Link> - </div> - </div> - - {!isLoggedIn(this.props.currentUser) && ( - <div className="sc-narrow-container text-center"> - <Link className="sc-start" to="/sessions/new"> - Start using SonarCloud <ChevronRightIcon className="spacer-left" /> - </Link> - <div className="big-spacer-top"> - <a - className="text-muted" - href="https://community.sonarsource.com/c/help/sc" - rel="noopener noreferrer" - target="_blank"> - Need help? - </a> - </div> - </div> - )} + {!isLoggedIn(this.props.currentUser) && <StartUsing />} <div className="sc-narrow-container text-center"> <h2 className="sc-feature-title">Explore open source projects on SonarCloud</h2> diff --git a/server/sonar-web/src/main/js/apps/about/sonarcloud/Pricing.tsx b/server/sonar-web/src/main/js/apps/about/sonarcloud/Pricing.tsx new file mode 100644 index 00000000000..b6055d50309 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/sonarcloud/Pricing.tsx @@ -0,0 +1,44 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; + +export default function Pricing() { + return ( + <div className="sc-pricing sc-narrow-container"> + <div className="sc-pricing-block"> + <h3 className="sc-pricing-title">Open Source Projects</h3> + <span className="sc-pricing-small"> </span> + <span className="sc-pricing-price">Free</span> + </div> + + <div className="sc-pricing-block"> + <h3 className="sc-pricing-title">Private Projects</h3> + <span className="sc-pricing-small">14 days free trial</span> + <strong> + From <span className="sc-pricing-price">10€</span>/mo + </strong> + <Link className="sc-arrow-link sc-pricing-small" to="/documentation/sonarcloud-pricing"> + see prices + </Link> + </div> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/about/sonarcloud/SQHome.tsx b/server/sonar-web/src/main/js/apps/about/sonarcloud/SQHome.tsx new file mode 100644 index 00000000000..80fce789569 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/sonarcloud/SQHome.tsx @@ -0,0 +1,351 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; +import Footer from './Footer'; +import Pricing from './Pricing'; +import StartUsing from './StartUsing'; +import GlobalContainer from '../../../app/components/GlobalContainer'; +import { getBaseUrl } from '../../../helpers/urls'; +import './style.css'; +import { CurrentUser, isLoggedIn } from '../../../app/types'; + +interface Props { + currentUser: CurrentUser; + location: { pathname: string }; +} + +export default class SQHome extends React.PureComponent<Props> { + componentDidMount() { + document.documentElement.classList.add('white-page'); + document.body.classList.add('white-page'); + } + + componentWillUnmount() { + document.documentElement.classList.remove('white-page'); + document.body.classList.remove('white-page'); + } + + render() { + return ( + <GlobalContainer footer={<Footer />} location={this.props.location}> + <div className="page sc-page sc-sq-page"> + <Jumbotron /> + + <h2 className="sc-sq-header2">You use the service, we take care of the rest</h2> + <Pricing /> + {!isLoggedIn(this.props.currentUser) && <StartUsing />} + + <Features /> + <Languages /> + <Integrations /> + <BottomNote /> + </div> + </GlobalContainer> + ); + } +} + +function Jumbotron() { + return ( + <div className="sc-sq-jumbotron"> + <div className="sc-sq-jumbotron-left"> + <h1 className="sc-sq-jumbotron-title"> + Use SonarQube<br /> + <span className="sc-sq-jumbotron-title-orange">as a Service</span> + </h1> + <div className="sc-sq-jumbotron-login"> + {'—'} + <br />Log in or sign up with + </div> + <div> + <Link className="sc-sq-login-button" to="/sessions/init/github"> + <img alt="" height="25" src={`${getBaseUrl()}/images/sonarcloud/github-white.svg`} /> + GitHub + </Link> + <Link className="sc-sq-login-button" to="/sessions/init/bitbucket"> + <img alt="" height="25" src={`${getBaseUrl()}/images/sonarcloud/bitbucket-white.svg`} /> + Bitbucket + </Link> + <Link className="sc-sq-login-button" to="/sessions/init/microsoft"> + <img alt="" height="25" src={`${getBaseUrl()}/images/sonarcloud/windows-white.svg`} /> + VSTS + </Link> + </div> + </div> + <div className="sc-sq-jumbotron-right"> + <img + alt="SonarCloud project dashboard" + src={`${getBaseUrl()}/images/sonarcloud/sq-homepage.png`} + srcSet={`${getBaseUrl()}/images/sonarcloud/sq-homepage.png 1x, ${getBaseUrl()}/images/sonarcloud/sq-homepage@2x.png 2x`} + /> + </div> + </div> + ); +} + +function Features() { + return ( + <> + <h2 className="sc-sq-header2"> + The right solution for developers + <span className="sc-sq-dot">•</span> + </h2> + <ul className="sc-features-list"> + <li className="sc-feature"> + <img + alt="" + className="big-spacer-bottom" + height="34" + src={`${getBaseUrl()}/images/sonarcloud/as-a-service.svg`} + /> + <h3 className="sc-feature-title">As a Service</h3> + <p className="sc-feature-description"> + We provide a fully operated version of SonarQube which is hosted on Amazon AWS in Europe + (Frankfurt, Germany). + </p> + <Link className="sc-arrow-link sc-feature-link" to="/about/sq/as-a-service"> + See more + </Link> + </li> + <li className="sc-feature"> + <img + alt="" + className="big-spacer-bottom" + height="34" + src={`${getBaseUrl()}/images/sonarcloud/branch-analysis.svg`} + /> + <h3 className="sc-feature-title">Branch & pull request analysis</h3> + <p className="sc-feature-description"> + SonarCloud comes with a built-in feature to automatically analyze project branches and + pull requests as soon as they get created. + </p> + <Link + className="sc-arrow-link sc-feature-link" + to="/about/sq/branch-analysis-and-pr-decoration"> + See more + </Link> + </li> + <li className="sc-feature"> + <img + alt="" + className="big-spacer-bottom" + height="34" + src={`${getBaseUrl()}/images/sonarcloud/sonarlint-integration.svg`} + /> + <h3 className="sc-feature-title">SonarLint integration</h3> + <p className="sc-feature-description"> + The full SonarCloud experience can be enhanced with SonarLint, that enables developers + to receive real time information directly in their IDEs. + </p> + <Link className="sc-arrow-link sc-feature-link" to="/about/sq/sonarlint-integration"> + See more + </Link> + </li> + </ul> + </> + ); +} + +function Languages() { + return ( + <div className="sc-languages"> + <h3 className="sc-feature-title">On 17 programming languages</h3> + <ul className="sc-languages-list"> + <li> + <img + alt="Java" + height="60" + src={`${getBaseUrl()}/images/languages/java.svg`} + width="60" + /> + </li> + <li> + <img + alt="JavaScript" + height="60" + src={`${getBaseUrl()}/images/languages/js.svg`} + width="60" + /> + </li> + <li> + <img + alt="TypeScript" + height="60" + src={`${getBaseUrl()}/images/languages/ts.svg`} + width="60" + /> + </li> + <li> + <img + alt="C#" + height="60" + src={`${getBaseUrl()}/images/languages/c-sharp.svg`} + width="60" + /> + </li> + <li> + <img + alt="C++" + height="60" + src={`${getBaseUrl()}/images/languages/c-plus.svg`} + width="60" + /> + </li> + <li> + <img alt="Go" height="60" src={`${getBaseUrl()}/images/languages/go.svg`} width="60" /> + </li> + <li> + <img + alt="Python" + height="60" + src={`${getBaseUrl()}/images/languages/python.svg`} + width="60" + /> + </li> + <li> + <img alt="PHP" height="60" src={`${getBaseUrl()}/images/languages/php.svg`} width="60" /> + </li> + </ul> + <ul className="sc-languages-list"> + <li> + <img alt="VB" height="60" src={`${getBaseUrl()}/images/languages/vb.svg`} width="60" /> + </li> + <li> + <img + alt="Flex" + height="60" + src={`${getBaseUrl()}/images/languages/flex.png`} + width="85" + /> + </li> + <li> + <img + alt="HTML" + height="60" + src={`${getBaseUrl()}/images/languages/html5.svg`} + width="60" + /> + </li> + <li> + <img + alt="Swift" + height="60" + src={`${getBaseUrl()}/images/languages/swift.svg`} + width="60" + /> + </li> + <li> + <img + alt="Objective-C" + height="60" + src={`${getBaseUrl()}/images/languages/obj-c.svg`} + width="60" + /> + </li> + <li> + <img + alt="T-SQL" + height="60" + src={`${getBaseUrl()}/images/languages/tsql.svg`} + width="60" + /> + </li> + <li> + <img + alt="PL/SQL" + height="60" + src={`${getBaseUrl()}/images/languages/plsql.svg`} + width="60" + /> + </li> + <li> + <img + alt="ABAP" + height="60" + src={`${getBaseUrl()}/images/languages/abap.svg`} + width="60" + /> + </li> + <li> + <img alt="XML" height="60" src={`${getBaseUrl()}/images/languages/xml.svg`} width="60" /> + </li> + </ul> + </div> + ); +} + +function Integrations() { + return ( + <div className="sc-integrations"> + <h2 className="sc-sq-header2 sc-integrations-title">Fully integrated experience with</h2> + <ul className="sc-integrations-list"> + <li> + <h3 className="sc-feature-title">GitHub</h3> + <img + alt="GitHub" + className="big-spacer-top" + height="60" + src={`${getBaseUrl()}/images/sonarcloud/github-big.svg`} + /> + </li> + <li> + <h3 className="sc-feature-title">VSTS</h3> + <img + alt="VSTS" + className="big-spacer-top" + height="60" + src={`${getBaseUrl()}/images/sonarcloud/vsts-big.svg`} + /> + <div className="big-spacer-top"> + <Link className="sc-arrow-link sc-feature-link" to="/about/sq/vsts"> + See more + </Link> + </div> + </li> + <li> + <h3 className="sc-feature-title">Bitbucket</h3> + <img + alt="Bitbucket" + className="big-spacer-top" + height="60" + src={`${getBaseUrl()}/images/sonarcloud/bitbucket-big.svg`} + /> + </li> + </ul> + </div> + ); +} + +function BottomNote() { + return ( + <div className="sc-bottom-note"> + <span className="sc-sq-dot spacer-right">•</span> + Includes all features of SonarSource{' '} + <a + className="sc-bottom-note-link link-base-color" + href="https://www.sonarsource.com/plans-and-pricing/developer/" + rel="noopener noreferrer" + target="_blank"> + Developer Edition + </a> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/about/sonarcloud/SQHomeContainer.tsx b/server/sonar-web/src/main/js/apps/about/sonarcloud/SQHomeContainer.tsx new file mode 100644 index 00000000000..33be1be21d8 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/sonarcloud/SQHomeContainer.tsx @@ -0,0 +1,28 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import { connect } from 'react-redux'; +import SQHome from './SQHome'; +import { getCurrentUser } from '../../../store/rootReducer'; + +const mapStateToProps = (state: any) => ({ + currentUser: getCurrentUser(state) +}); + +export default connect(mapStateToProps)(SQHome); diff --git a/server/sonar-web/src/main/js/apps/about/sonarcloud/StartUsing.tsx b/server/sonar-web/src/main/js/apps/about/sonarcloud/StartUsing.tsx new file mode 100644 index 00000000000..cade5100554 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/about/sonarcloud/StartUsing.tsx @@ -0,0 +1,41 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { Link } from 'react-router'; +import ChevronRightIcon from '../../../components/icons-components/ChevronRightcon'; + +export default function StartUsing() { + return ( + <div className="sc-narrow-container text-center"> + <Link className="sc-start" to="/sessions/new"> + Start using SonarCloud <ChevronRightIcon className="spacer-left" /> + </Link> + <div className="big-spacer-top"> + <a + className="text-muted" + href="https://community.sonarsource.com/c/help/sc" + rel="noopener noreferrer" + target="_blank"> + Need help? + </a> + </div> + </div> + ); +} diff --git a/server/sonar-web/src/main/js/apps/about/sonarcloud/style.css b/server/sonar-web/src/main/js/apps/about/sonarcloud/style.css index 711ee61ea32..1c3d8ada395 100644 --- a/server/sonar-web/src/main/js/apps/about/sonarcloud/style.css +++ b/server/sonar-web/src/main/js/apps/about/sonarcloud/style.css @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,700'); +@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700'); .sc-page { font-family: var(--sonarcloudFontFamily); @@ -49,9 +49,16 @@ display: flex; flex-wrap: wrap; justify-content: space-between; + align-items: stretch; + max-width: 1000px; + margin-left: auto; + margin-right: auto; } .sc-feature { + display: flex; + flex-direction: column; + align-items: flex-start; width: 30%; margin-bottom: 30px; } @@ -64,11 +71,24 @@ } .sc-feature-description { + flex: 1 1 auto; line-height: 22px; font-size: 16px; font-weight: 300; } +.sc-feature-link { + margin-top: 16px; + color: var(--sonarcloudOrange) !important; + font-size: 16px; + font-weight: 300; +} + +.sc-feature-link:hover, +.sc-feature-link:focus { + color: var(--sonarcloudOrangeDark) !important; +} + .sc-narrow-container { width: 700px; margin: 40px auto; @@ -102,6 +122,7 @@ .sc-pricing-price { line-height: 72px; + color: var(--sonarcloudBlack800); font-size: 65px; font-weight: 700; } @@ -110,13 +131,13 @@ font-size: 14px; } -.sc-pricing-about { +.sc-arrow-link { position: relative; border: none; color: var(--baseFontColor); } -.sc-pricing-about::after { +.sc-arrow-link::after { content: '→'; position: absolute; top: 0; @@ -124,15 +145,15 @@ transition: left 0.3s ease; } -.sc-pricing-about:hover { +.sc-arrow-link:hover { color: var(--baseFontColor); } -.sc-pricing-about:focus { +.sc-arrow-link:focus { color: var(--sonarcloudOrange); } -.sc-pricing-about:hover::after { +.sc-arrow-link:hover::after { left: calc(100% + 10px); } @@ -264,3 +285,145 @@ top: 30px; right: 20px; } + +.sc-sq-jumbotron { + display: flex; + justify-content: space-between; + max-width: 1160px; + margin: 30px auto 0; + color: var(--sonarcloudBlack800); +} + +.sc-sq-jumbotron-left { + min-width: 500px; +} + +.sc-sq-jumbotron-right { + max-width: 725px; +} + +.sc-sq-jumbotron-right img { + max-width: 100%; + border-radius: 6px; + box-shadow: 0px 15px 50px rgba(0, 0, 0, 0.21); +} + +.sc-sq-jumbotron-title { + line-height: 61px; + margin-top: 90px; + margin-bottom: 20px; + color: var(--sonarcloudBlack800); + font-size: 60px; + font-weight: 700; +} + +.sc-sq-jumbotron-title-orange { + color: var(--sonarcloudOrange); +} + +.sc-sq-jumbotron-login { + line-height: 25px; + font-size: 18px; +} + +.sc-sq-login-button { + display: inline-flex; + align-items: center; + height: 44px; + margin-top: 16px; + margin-right: 16px; + padding: 0 15px; + line-height: 44px; + border: none; + border-radius: 4px; + background-color: var(--sonarcloudBlack800); + color: #fff; + font-size: 18px; + font-weight: 500; +} + +.sc-sq-login-button:hover, +.sc-sq-login-button:focus { + color: #fff; + background-color: var(--sonarcloudBlack900); +} + +.sc-sq-login-button > img { + margin-right: 12px; + margin-bottom: 1px; +} + +.sc-sq-header2 { + margin: 80px 0 40px; + line-height: 45px; + font-size: 32px; + font-weight: 300; + text-align: center; +} + +.sc-sq-dot { + vertical-align: super; + color: var(--sonarcloudOrange); + font-size: 24px; +} + +.sc-languages { + margin: 60px 0; + text-align: center; +} + +.sc-languages-list { + display: flex; + justify-content: center; + margin-top: 20px; +} + +.sc-languages-list > li { + margin: 11px 22px; +} + +.sc-integrations { + position: relative; + background-color: var(--sonarcloudBlack200); + padding: 44px 0px; + text-align: center; +} + +.sc-integrations-title { + margin-top: 0; +} + +.sc-integrations-list { + display: flex; + justify-content: center; +} + +.sc-integrations-list > li { + width: 170px; +} + +.sc-integrations-list > li + li { + border-left: 1px solid var(--sonarcloudBlack300); +} + +.sc-bottom-note { + margin: 16px 0; + font-size: 16px; + font-weight: 300; + text-align: center; +} + +.sc-bottom-note > a { + font-weight: 500; +} + +.sc-bottom-note-link:hover, +.sc-bottom-note-link:focus { + border-bottom-color: var(--sonarcloudOrange); + color: var(--sonarcloudOrange); +} + +.sc-sq-page { + background: url(/images/sonarcloud/sq-background.svg) no-repeat top center; + background-size: auto 200vh; +} |