+++ /dev/null
-<svg viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M12.625 6.154a3.991 3.991 0 0 0-1.902-1.279v-.046C10.723 2.65 8.93.857 6.75.857c-2.179 0-3.972 1.793-3.972 3.972v.053A3.982 3.982 0 0 0 0 8.671c0 2.179 1.793 3.972 3.972 3.972a3.978 3.978 0 0 0 2.791-1.144 3.97 3.97 0 0 0 2.766 1.122c2.178 0 3.971-1.793 3.971-3.972 0-.905-.31-1.784-.877-2.489l.002-.006zm-3.073 5.489a2.99 2.99 0 0 1-2.973-2.971c0-.275-.225-.5-.5-.5a.501.501 0 0 0-.499.5 3.952 3.952 0 0 0 .56 2.032 2.971 2.971 0 0 1-2.164.936 2.985 2.985 0 0 1-2.97-2.97 2.985 2.985 0 0 1 2.97-2.971c.35 0 .697.062 1.026.183h.012c.114.038.223.09.324.155a.5.5 0 1 0 .65-.759 2.224 2.224 0 0 0-.646-.341 3.974 3.974 0 0 0-1.369-.243h-.192A2.985 2.985 0 0 1 6.75 1.85a2.986 2.986 0 0 1 2.972 2.972c0 .96-.466 1.863-1.249 2.42a.5.5 0 1 0 .58.814 3.983 3.983 0 0 0 1.526-2.184 2.979 2.979 0 0 1 1.941 2.789 2.986 2.986 0 0 1-2.969 2.972l.001.01z" fill="#f3702a" fill-rule="nonzero"/></svg>
\ No newline at end of file
+++ /dev/null
-<svg viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M12.625 6.154a3.991 3.991 0 0 0-1.902-1.279v-.046C10.723 2.65 8.93.857 6.75.857c-2.179 0-3.972 1.793-3.972 3.972v.053A3.982 3.982 0 0 0 0 8.671c0 2.179 1.793 3.972 3.972 3.972a3.978 3.978 0 0 0 2.791-1.144 3.97 3.97 0 0 0 2.766 1.122c2.178 0 3.971-1.793 3.971-3.972 0-.905-.31-1.784-.877-2.489l.002-.006zm-3.073 5.489a2.99 2.99 0 0 1-2.973-2.971c0-.275-.225-.5-.5-.5a.501.501 0 0 0-.499.5 3.952 3.952 0 0 0 .56 2.032 2.971 2.971 0 0 1-2.164.936 2.985 2.985 0 0 1-2.97-2.97 2.985 2.985 0 0 1 2.97-2.971c.35 0 .697.062 1.026.183h.012c.114.038.223.09.324.155a.5.5 0 1 0 .65-.759 2.224 2.224 0 0 0-.646-.341 3.974 3.974 0 0 0-1.369-.243h-.192A2.985 2.985 0 0 1 6.75 1.85a2.986 2.986 0 0 1 2.972 2.972c0 .96-.466 1.863-1.249 2.42a.5.5 0 1 0 .58.814 3.983 3.983 0 0 0 1.526-2.184 2.979 2.979 0 0 1 1.941 2.789 2.986 2.986 0 0 1-2.969 2.972l.001.01z" fill="#f3702a" fill-rule="nonzero"/></svg>
\ No newline at end of file
--- /dev/null
+<svg viewBox="0 0 105 30" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M69.959 19.694c-.42.734-1.346 1.698-2.905 1.698-1.378 0-3.032-.795-3.032-3.999v-5.337h1.596v5.054c0 1.736.509 2.905 1.958 2.905 1.074 0 1.817-.772 2.105-1.506.09-.246.147-.55.147-.85v-5.603h1.596v6.638c0 .94.016 1.772.074 2.492h-1.414l-.088-1.492h-.037zm-36.859.56c-.58.734-1.486 1.133-2.538 1.133-1.797 0-2.87-1.36-2.87-2.83 0-2.393 2.068-3.547 5.21-3.525v-.13c0-.49-.257-1.186-1.618-1.186-.906 0-1.87.32-2.45.696l-.509-1.85c.619-.36 1.833-.81 3.45-.81 2.96 0 3.902 1.812 3.902 3.977v3.204c0 .886.036 1.735.125 2.242h-2.487v.005l-.161-.926H33.1zm-15.716-3.79c0 3.372-2.304 4.923-4.68 4.923-2.597 0-4.593-1.774-4.593-4.755s1.89-4.886 4.738-4.886c2.718.006 4.535 1.948 4.535 4.717zm45.403.075c0 3.373-2.252 4.848-4.373 4.848-2.376 0-4.209-1.812-4.209-4.695 0-3.058 1.922-4.848 4.356-4.848 2.518 0 4.226 1.905 4.226 4.695zm16.675 3.057c-.492 1.017-1.56 1.79-2.996 1.79-2.125 0-3.758-1.866-3.758-4.64-.016-3.036 1.795-4.902 3.937-4.902 1.346 0 2.251.658 2.649 1.399h.036V7.792h1.603v11.032c0 .81.015 1.735.072 2.356h-1.434l-.073-1.584h-.036zm-29.325 1.246c-.419.228-1.346.528-2.524.528-2.649 0-4.37-1.866-4.37-4.657 0-2.812 1.852-4.847 4.716-4.847.943 0 1.78.244 2.215.473l-.361 1.284c-.383-.228-.98-.435-1.854-.435-2.016 0-3.104 1.545-3.104 3.45 0 2.11 1.308 3.41 3.046 3.41.906 0 1.509-.245 1.958-.452l.278 1.246zm-48.69-2.17c.507.32 1.56.696 2.376.696.832 0 1.178-.299 1.178-.772 0-.474-.272-.697-1.309-1.056-1.832-.642-2.54-1.68-2.523-2.775 0-1.712 1.414-3.019 3.613-3.019 1.036 0 1.958.245 2.502.528l-.492 1.98c-.397-.228-1.163-.527-1.922-.527-.67 0-1.052.283-1.052.756 0 .435.345.658 1.435 1.056 1.686.603 2.398 1.49 2.413 2.845 0 1.713-1.309 2.981-3.848 2.981-1.162 0-2.193-.268-2.87-.643l.498-2.05zm19.669 2.519h-2.758v-6.29h.005c0-1.147-.037-2.131-.073-2.943h2.398l.125 1.263h.052a3.224 3.224 0 0 1 2.738-1.47c1.817 0 3.179 1.247 3.179 3.962v5.467h-2.76v-5.108c0-1.187-.397-1.997-1.398-1.997-.764 0-1.215.549-1.397 1.076-.074.169-.111.453-.111.72v5.32zm18.77-.005h-2.76v-6.192c0-1.36-.036-2.246-.072-3.036h2.376l.09 1.698h.073c.455-1.339 1.545-1.904 2.397-1.904.257 0 .383 0 .582.038v2.698a3.76 3.76 0 0 0-.743-.076c-1.017 0-1.708.565-1.89 1.453-.038.19-.054.413-.054.642v4.679zm12.99-.006h-1.597V7.792h1.596V21.18zm2.942-4.543c0 1.997 1.104 3.509 2.67 3.509 1.523 0 2.67-1.49 2.67-3.547 0-1.545-.744-3.508-2.634-3.508s-2.706 1.81-2.706 3.546zm23.517-.87c0-.206-.014-.49-.073-.697-.235-1.055-1.105-1.925-2.304-1.925-1.648 0-2.633 1.506-2.633 3.525 0 1.85.869 3.372 2.597 3.372 1.073 0 2.052-.734 2.34-1.98.053-.229.073-.452.073-.718v-1.577zm-46.344 1.055c-1.45-.016-2.576.337-2.576 1.452 0 .735.471 1.094 1.089 1.094.69 0 1.25-.473 1.435-1.056.036-.152.052-.32.052-.49v-1zm-22.032-.261c0 1.582.634 2.774 1.817 2.774 1.073 0 1.759-1.116 1.759-2.774 0-1.377-.507-2.774-1.76-2.774-1.33 0-1.816 1.413-1.816 2.774z" fill="#fff" fill-rule="nonzero"/><path d="M102.86 13.634a4.959 4.959 0 0 0-2.363-1.649v-.06c0-2.823-2.208-5.124-4.93-5.124-2.724 0-4.933 2.296-4.933 5.125v.07c-1.994.653-3.45 2.595-3.45 4.886 0 2.823 2.21 5.125 4.932 5.125a4.832 4.832 0 0 0 3.465-1.475 4.817 4.817 0 0 0 3.461 1.475c2.717 0 4.933-2.296 4.933-5.125 0-1.18-.4-2.334-1.115-3.248zm-3.818 7.077c-2.031 0-3.685-1.718-3.685-3.83a.637.637 0 0 0-.623-.646.634.634 0 0 0-.624.647c0 .957.257 1.855.696 2.622a3.607 3.607 0 0 1-2.69 1.213c-2.032 0-3.687-1.719-3.687-3.83 0-2.11 1.655-3.829 3.687-3.829.44 0 .868.082 1.278.234.005 0 .009.005.014.005.142.05.342.147.404.201a.6.6 0 0 0 .874-.07.659.659 0 0 0-.068-.91c-.272-.239-.696-.402-.8-.44a4.767 4.767 0 0 0-1.697-.31c-.079 0-.157 0-.236.005.084-2.04 1.702-3.671 3.687-3.671 2.031 0 3.685 1.718 3.685 3.83a3.896 3.896 0 0 1-1.55 3.122.663.663 0 0 0-.147.898c.12.174.315.272.509.272.125 0 .25-.038.361-.12a5.164 5.164 0 0 0 1.895-2.812c1.424.549 2.413 1.979 2.413 3.595-.005 2.106-1.659 3.824-3.696 3.824z" fill="#f60" fill-rule="nonzero"/></svg>
--- /dev/null
+<svg viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M12.625 6.154a3.991 3.991 0 0 0-1.902-1.279v-.046C10.723 2.65 8.93.857 6.75.857c-2.179 0-3.972 1.793-3.972 3.972v.053A3.982 3.982 0 0 0 0 8.671c0 2.179 1.793 3.972 3.972 3.972a3.978 3.978 0 0 0 2.791-1.144 3.97 3.97 0 0 0 2.766 1.122c2.178 0 3.971-1.793 3.971-3.972 0-.905-.31-1.784-.877-2.489l.002-.006zm-3.073 5.489a2.99 2.99 0 0 1-2.973-2.971c0-.275-.225-.5-.5-.5a.501.501 0 0 0-.499.5 3.952 3.952 0 0 0 .56 2.032 2.971 2.971 0 0 1-2.164.936 2.985 2.985 0 0 1-2.97-2.97 2.985 2.985 0 0 1 2.97-2.971c.35 0 .697.062 1.026.183h.012c.114.038.223.09.324.155a.5.5 0 1 0 .65-.759 2.224 2.224 0 0 0-.646-.341 3.974 3.974 0 0 0-1.369-.243h-.192A2.985 2.985 0 0 1 6.75 1.85a2.986 2.986 0 0 1 2.972 2.972c0 .96-.466 1.863-1.249 2.42a.5.5 0 1 0 .58.814 3.983 3.983 0 0 0 1.526-2.184 2.979 2.979 0 0 1 1.941 2.789 2.986 2.986 0 0 1-2.969 2.972l.001.01z" fill="#f3702a" fill-rule="nonzero"/></svg>
\ No newline at end of file
interface Props {
children: React.ReactNode;
+ footer?: React.ReactNode;
location: { pathname: string };
}
export default function GlobalContainer(props: Props) {
// it is important to pass `location` down to `GlobalNav` to trigger render on url change
+ const { footer = <GlobalFooterContainer /> } = props;
return (
<SuggestionsProvider>
{({ suggestions }) => (
</Workspace>
</div>
</div>
- <GlobalFooterContainer />
+ {footer}
</div>
</StartupModal>
)}
import * as React from 'react';
import * as PropTypes from 'prop-types';
import { connect } from 'react-redux';
+import { Location } from 'history';
import { CurrentUser, isLoggedIn } from '../types';
import { getCurrentUser } from '../../store/rootReducer';
import { getHomePageUrl } from '../../helpers/urls';
-import { isSonarCloud } from '../../helpers/system';
-interface Props {
+interface StateProps {
currentUser: CurrentUser | undefined;
}
-class Landing extends React.PureComponent<Props> {
+interface OwnProps {
+ location: Location;
+}
+
+class Landing extends React.PureComponent<StateProps & OwnProps> {
static contextTypes = {
router: PropTypes.object.isRequired
};
} else {
this.context.router.replace('/projects');
}
- } else if (isSonarCloud()) {
- window.location.href = 'https://about.sonarcloud.io';
} else {
this.context.router.replace('/about');
}
currentUser: getCurrentUser(state)
});
-export default connect<Props>(mapStateToProps)(Landing);
+export default connect<StateProps, {}, OwnProps>(mapStateToProps)(Landing);
alt={text}
className="spacer-right"
height="18"
- src={`${getBaseUrl()}/images/embed-doc/${icon}`}
+ src={`${getBaseUrl()}/images/${icon}`}
width="18"
/>
{text}
<li className="divider" />
{this.renderTitle(translate('embed_docs.stay_connected'))}
<li>
- {this.renderIconLink('https://twitter.com/sonarcloud', 'twitter-icon.svg', 'Twitter')}
+ {this.renderIconLink(
+ 'https://twitter.com/sonarcloud',
+ 'embed-doc/twitter-icon.svg',
+ 'Twitter'
+ )}
</li>
<li>
{this.renderIconLink(
'https://blog.sonarsource.com/product/SonarCloud',
- 'sc-icon.svg',
+ 'sonarcloud-square-logo.svg',
translate('embed_docs.news')
)}
</li>
<li>
{this.renderIconLink(
'https://www.sonarsource.com/resources/product-news/',
- 'sq-icon.svg',
+ 'embed-doc/sq-icon.svg',
translate('embed_docs.news')
)}
</li>
<li>
- {this.renderIconLink('https://twitter.com/SonarQube', 'twitter-icon.svg', 'Twitter')}
+ {this.renderIconLink(
+ 'https://twitter.com/SonarQube',
+ 'embed-doc/twitter-icon.svg',
+ 'Twitter'
+ )}
</li>
</React.Fragment>
);
alt="embed_docs.news"
className="spacer-right"
height="18"
- src="/images/embed-doc/sc-icon.svg"
+ src="/images/sonarcloud-square-logo.svg"
width="18"
/>
embed_docs.news
modalZIndex: '6001',
modalOverlayZIndex: '6000',
- popupZIndex: '5000'
+ popupZIndex: '5000',
+
+ // sonarcloud
+ sonarcloudOrange: '#f60',
+ sonarcloudOrangeDark: '#e65c00',
+ sonarcloudFontFamily:
+ "Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
+ sonarcloudBlack300: '#cfd3d7',
+ sonarcloudBlack700: '#434447',
+ sonarcloudBlack800: '#2d3032'
};
<Route path="/" component={App}>
<IndexRoute component={lazyLoad(() => import('../components/Landing'))} />
+ <Route path="about" childRoutes={aboutRoutes} />
<Route component={GlobalContainer}>
- <Route path="about" childRoutes={aboutRoutes} />
<Route path="account" childRoutes={accountRoutes} />
<Route path="coding_rules" childRoutes={codingRulesRoutes} />
<Route path="component" childRoutes={componentRoutes} />
import AboutScanners from './AboutScanners';
import { searchProjects } from '../../../api/components';
import { getFacet } from '../../../api/issues';
+import GlobalContainer from '../../../app/components/GlobalContainer';
import { getAppState, getCurrentUser, getGlobalSettingValue } from '../../../store/rootReducer';
import { translate } from '../../../helpers/l10n';
import { fetchAboutPageSettings } from '../actions';
},
currentUser: { isLoggedIn: boolean },
customText?: string,
- fetchAboutPageSettings: () => Promise<*>
+ fetchAboutPageSettings: () => Promise<*>,
+ location: { pathname: string }
};
*/
}
return (
- <div className="page page-limited about-page" id="about-page">
- <div className="about-page-entry">
- <div className="about-page-intro">
- <h1 className="big-spacer-bottom">{translate('layout.sonar.slogan')}</h1>
- {!this.props.currentUser.isLoggedIn && (
- <Link className="button button-active big-spacer-right" to="/sessions/new">
- {translate('layout.login')}
- </Link>
- )}
- <a
- className="button"
- href="https://redirect.sonarsource.com/doc/home.html"
- rel="noopener noreferrer"
- target="_blank">
- {translate('about_page.read_documentation')}
- </a>
+ <GlobalContainer location={this.props.location}>
+ <div className="page page-limited about-page" id="about-page">
+ <div className="about-page-entry">
+ <div className="about-page-intro">
+ <h1 className="big-spacer-bottom">{translate('layout.sonar.slogan')}</h1>
+ {!this.props.currentUser.isLoggedIn && (
+ <Link className="button button-active big-spacer-right" to="/sessions/new">
+ {translate('layout.login')}
+ </Link>
+ )}
+ <a
+ className="button"
+ href="https://redirect.sonarsource.com/doc/home.html"
+ rel="noopener noreferrer"
+ target="_blank">
+ {translate('about_page.read_documentation')}
+ </a>
+ </div>
+
+ <div className="about-page-instance">
+ <AboutProjects count={projectsCount} loading={loading} />
+ <EntryIssueTypes
+ bugs={bugs}
+ codeSmells={codeSmells}
+ loading={loading}
+ vulnerabilities={vulnerabilities}
+ />
+ </div>
</div>
- <div className="about-page-instance">
- <AboutProjects count={projectsCount} loading={loading} />
- <EntryIssueTypes
- bugs={bugs}
- codeSmells={codeSmells}
- loading={loading}
- vulnerabilities={vulnerabilities}
- />
- </div>
- </div>
-
- {customText != null &&
- customText.value && (
- <div
- className="about-page-section"
- dangerouslySetInnerHTML={{ __html: customText.value }}
- />
- )}
+ {customText != null &&
+ customText.value && (
+ <div
+ className="about-page-section"
+ dangerouslySetInnerHTML={{ __html: customText.value }}
+ />
+ )}
- <AboutLanguages />
+ <AboutLanguages />
- <AboutQualityModel />
+ <AboutQualityModel />
- <div className="flex-columns">
- <div className="flex-column flex-column-half about-page-group-boxes">
- <AboutCleanCode />
+ <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-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 appState={this.props.appState} />
+ <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 appState={this.props.appState} />
+ </div>
</div>
- </div>
- <AboutScanners />
- </div>
+ <AboutScanners />
+ </div>
+ </GlobalContainer>
);
}
}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { lazyLoad } from '../../components/lazyLoad';
+import { isSonarCloud } from '../../helpers/system';
const routes = [
{
- indexRoute: { component: lazyLoad(() => import('./components/AboutApp')) }
+ indexRoute: {
+ component: lazyLoad(
+ () =>
+ isSonarCloud() ? import('./sonarcloud/HomeContainer') : import('./components/AboutApp')
+ )
+ }
}
];
--- /dev/null
+/*
+ * 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 { getBaseUrl } from '../../../helpers/urls';
+
+export default function Footer() {
+ return (
+ <footer className="sc-footer">
+ <div className="sc-footer-limited">
+ <nav className="sc-footer-nav">
+ <div className="sc-footer-nav-column">
+ <h4 className="sc-footer-nav-column-title">Need Help</h4>
+ <ul>
+ <li className="spacer-top">
+ <a
+ className="sc-footer-link"
+ href="https://community.sonarsource.com/c/help/sc"
+ rel="noopener noreferrer"
+ target="_blank">
+ Support Forum
+ </a>
+ </li>
+ <li className="spacer-top">
+ <Link
+ className="sc-footer-link"
+ rel="noopener noreferrer"
+ target="_blank"
+ to="/contact">
+ Contact Us
+ </Link>
+ </li>
+ <li className="spacer-top">
+ <a
+ className="sc-footer-link"
+ href="https://sonarcloud.statuspage.io/"
+ rel="noopener noreferrer"
+ target="_blank">
+ Status
+ </a>
+ </li>
+ </ul>
+ </div>
+ <div className="sc-footer-nav-column">
+ <h4 className="sc-footer-nav-column-title">News</h4>
+ <ul>
+ <li className="spacer-top">
+ <a
+ className="sc-footer-link"
+ href="https://blog.sonarsource.com/product/SonarCloud"
+ rel="noopener noreferrer"
+ target="_blank">
+ SonarCloud News
+ </a>
+ </li>
+ <li className="spacer-top">
+ <a
+ className="sc-footer-link"
+ href="https://twitter.com/sonarcloud"
+ rel="noopener noreferrer"
+ target="_blank">
+ Twitter
+ </a>
+ </li>
+ </ul>
+ </div>
+ <div className="sc-footer-nav-column">
+ <h4 className="sc-footer-nav-column-title">About</h4>
+ <ul>
+ <li className="spacer-top">
+ <a
+ className="sc-footer-link"
+ href="https://www.sonarsource.com/"
+ rel="noopener noreferrer"
+ target="_blank">
+ SonarSource
+ </a>
+ </li>
+ <li className="spacer-top">
+ <Link
+ className="sc-footer-link"
+ download="terms.pdf"
+ rel="noopener noreferrer"
+ target="_blank"
+ to="/terms.pdf">
+ Terms
+ </Link>
+ </li>
+ <li className="spacer-top">
+ <Link
+ className="sc-footer-link"
+ rel="noopener noreferrer"
+ target="_blank"
+ to="/privacy">
+ Privacy
+ </Link>
+ </li>
+ </ul>
+ </div>
+ </nav>
+
+ <div className="sc-footer-logo">
+ <Link className="display-inline-block link-no-underline" to="/">
+ <img alt="SonarCloud" height="45" src={`${getBaseUrl()}/images/sonarcloud-logo.svg`} />
+ </Link>
+ <div>
+ <a
+ className="sc-footer-link"
+ href="https://www.sonarsource.com"
+ rel="noopener noreferrer"
+ target="_blank">
+ A SonarSource™ product
+ </a>
+ </div>
+ </div>
+ </div>
+
+ <div className="sc-footer-copy">
+ <div className="sc-footer-limited">
+ © 2008-2018, SonarCloud by{' '}
+ <a
+ className="sc-footer-link sc-footer-copy-link"
+ href="https://www.sonarsource.com"
+ rel="noopener noreferrer"
+ target="_blank">
+ SonarSource SA
+ </a>. All rights reserved. SonarCloud is a service operated by{' '}
+ <a
+ className="sc-footer-link sc-footer-copy-link"
+ href="https://www.sonarsource.com"
+ rel="noopener noreferrer"
+ target="_blank">
+ SonarSource
+ </a>, the company that develops and promotes open source{' '}
+ <a
+ className="sc-footer-link sc-footer-copy-link"
+ href="http://sonarqube.org"
+ rel="noopener noreferrer"
+ target="_blank">
+ SonarQube
+ </a>{' '}
+ and{' '}
+ <a
+ className="sc-footer-link sc-footer-copy-link"
+ href="http://sonarlint.org"
+ rel="noopener noreferrer"
+ target="_blank">
+ SonarLint
+ </a>.
+ </div>
+ </div>
+ </footer>
+ );
+}
--- /dev/null
+/*
+ * 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 GlobalContainer from '../../../app/components/GlobalContainer';
+import { CurrentUser, isLoggedIn } from '../../../app/types';
+import ChevronRightIcon from '../../../components/icons-components/ChevronRightcon';
+import './style.css';
+
+interface Props {
+ currentUser: CurrentUser;
+ location: { pathname: string };
+}
+
+export default class Home 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 page-limited sc-page">
+ <h1 className="sc-page-title">Continuous Code Quality Online</h1>
+ <p className="sc-page-subtitle">
+ Analyze the quality of your source code to detect bugs, vulnerabilities <br />and code
+ smells throughout the development process.
+ </p>
+
+ <ul className="sc-features-list">
+ <li className="sc-feature">
+ <h2 className="sc-feature-title">Built on SonarQube</h2>
+ <p className="sc-feature-description">
+ The broadly used code review tool to detect bugs, code smells and vulnerability
+ issues.
+ </p>
+ </li>
+
+ <li className="sc-feature">
+ <h2 className="sc-feature-title">17 languages</h2>
+ <p className="sc-feature-description">
+ Java, JS, C#, C/C++, Objective-C, TypeScript, Python, Go, ABAP, PL/SQL, T-SQL and
+ more.
+ </p>
+ </li>
+
+ <li className="sc-feature">
+ <h2 className="sc-feature-title">Thousands of rules</h2>
+ <p className="sc-feature-description">
+ Track down hard-to-find bugs and quality issues thanks to powerful static code
+ analyzers.
+ </p>
+ </li>
+
+ <li className="sc-feature">
+ <h2 className="sc-feature-title">Cloud CI Integrations</h2>
+ <p className="sc-feature-description">
+ Schedule the execution of an analysis from Cloud CI engines: Travis, VSTS, AppVeyor
+ and more.
+ </p>
+ </li>
+
+ <li className="sc-feature">
+ <h2 className="sc-feature-title">Deep code analysis</h2>
+ <p className="sc-feature-description">
+ Explore all your source files, whether in branches or pull requests, to reach a
+ green quality gate and promote the build.
+ </p>
+ </li>
+
+ <li className="sc-feature">
+ <h2 className="sc-feature-title">Fast and Scalable</h2>
+ <p className="sc-feature-description">Scale on-demand as your projects grow.</p>
+ </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>
+
+ <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>
+ )}
+
+ <div className="sc-narrow-container text-center">
+ <h2 className="sc-feature-title">Explore open source projects on SonarCloud</h2>
+ <p className="sc-feature-description">
+ SonarCloud offers free analysis for open source projects. <br />It is public and open
+ to anyone who wants to browse the service.
+ </p>
+ </div>
+
+ <div className="sc-narrow-container text-center">
+ <Link className="sc-browse" to="/explore/projects">
+ Browse
+ </Link>
+ </div>
+
+ <div className="sc-narrow-container sc-news">
+ <h2 className="sc-news-title">News</h2>
+ <ChevronRightIcon className="big-spacer-left" fill="#cfd3d7" />
+ <a
+ className="sc-news-link big-spacer-left"
+ href="http://feedburner.google.com/fb/a/mailverify?uri=NewsSonarCloud&loc=en_US"
+ rel="noopener noreferrer"
+ target="_blank">
+ Subscribe by email
+ </a>
+ <a
+ className="sc-news-link big-spacer-left"
+ href="http://feeds.feedburner.com/NewsSonarCloud"
+ rel="noopener noreferrer"
+ target="_blank">
+ Subscribe by feed
+ </a>
+ <a
+ className="sc-news-link big-spacer-left"
+ href="https://blog.sonarsource.com/product/SonarCloud"
+ rel="noopener noreferrer"
+ target="_blank">
+ See all
+ </a>
+ </div>
+ </div>
+ </GlobalContainer>
+ );
+ }
+}
--- /dev/null
+/*
+ * 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 Home from './Home';
+import { getCurrentUser } from '../../../store/rootReducer';
+
+const mapStateToProps = (state: any) => ({
+ currentUser: getCurrentUser(state)
+});
+
+export default connect(mapStateToProps)(Home);
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import Footer from '../Footer';
+
+it('should render', () => {
+ expect(shallow(<Footer />)).toBeDefined();
+});
--- /dev/null
+/*
+ * 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 { shallow } from 'enzyme';
+import Home from '../Home';
+
+jest.mock('Docs/EmbedDocsSuggestions.json', () => ({}), { virtual: true });
+
+it('should render', () => {
+ expect(
+ shallow(<Home currentUser={{ isLoggedIn: false }} location={{ pathname: '/' }} />)
+ ).toBeDefined();
+});
+
+it('should not render "Start using SonarCloud" button', () => {
+ expect(
+ shallow(<Home currentUser={{ isLoggedIn: true }} location={{ pathname: '/' }} />)
+ .find('.sc-start')
+ .exists()
+ ).toBe(false);
+});
--- /dev/null
+/*
+ * 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 url('https://fonts.googleapis.com/css?family=Roboto:300,400,700');
+
+.sc-page {
+ font-family: var(--sonarcloudFontFamily);
+}
+
+.sc-page *:focus,
+.sc-footer *:focus {
+ box-shadow: 0 0 0 3px rgba(230, 92, 0, 0.25);
+}
+
+.sc-page-title {
+ line-height: 56px;
+ margin-top: 40px;
+ margin-bottom: 20px;
+ font-size: 40px;
+ font-weight: 300;
+ text-align: center;
+}
+
+.sc-page-subtitle {
+ line-height: 28px;
+ margin-bottom: 40px;
+ font-size: 20px;
+ font-weight: 300;
+ text-align: center;
+}
+
+.sc-features-list {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+}
+
+.sc-feature {
+ width: 30%;
+ margin-bottom: 30px;
+}
+
+.sc-feature-title {
+ line-height: 28px;
+ margin-bottom: 5px;
+ font-size: 20px;
+ font-weight: 400;
+}
+
+.sc-feature-description {
+ line-height: 22px;
+ font-size: 16px;
+ font-weight: 300;
+}
+
+.sc-narrow-container {
+ width: 700px;
+ margin: 40px auto;
+}
+
+.sc-pricing {
+ display: flex;
+ justify-content: space-between;
+}
+
+.sc-pricing-block {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ width: 330px;
+ padding: 20px 20px 30px;
+ border: 1px solid var(--sonarcloudBlack300);
+ border-radius: 10px;
+ box-sizing: border-box;
+ line-height: 20px;
+ font-size: 16px;
+}
+
+.sc-pricing-title {
+ line-height: 34px;
+ margin-bottom: 20px;
+ color: var(--sonarcloudOrange);
+ font-size: 24px;
+ font-weight: 400;
+}
+
+.sc-pricing-price {
+ line-height: 72px;
+ font-size: 65px;
+ font-weight: 700;
+}
+
+.sc-pricing-small {
+ font-size: 14px;
+}
+
+.sc-pricing-about {
+ position: relative;
+ border: none;
+ color: var(--baseFontColor);
+}
+
+.sc-pricing-about::after {
+ content: '→';
+ position: absolute;
+ top: 0;
+ left: calc(100% + 5px);
+ transition: left 0.3s ease;
+}
+
+.sc-pricing-about:hover {
+ color: var(--baseFontColor);
+}
+
+.sc-pricing-about:focus {
+ color: var(--sonarcloudOrange);
+}
+
+.sc-pricing-about:hover::after {
+ left: calc(100% + 10px);
+}
+
+.sc-start {
+ display: inline-flex;
+ align-items: center;
+ height: 44px;
+ line-height: 44px;
+ padding: 0 16px;
+ border-radius: 5px;
+ border: none;
+ color: #fff;
+ font-size: 16px;
+ font-weight: 700;
+ background-color: var(--sonarcloudOrange);
+}
+
+.sc-start:hover,
+.sc-start:focus {
+ background-color: var(--sonarcloudOrangeDark);
+ color: #fff;
+}
+
+.sc-browse {
+ display: inline-flex;
+ align-items: center;
+ height: 33px;
+ line-height: 33px;
+ padding: 0 16px;
+ border-radius: 5px;
+ border: 1px solid var(--sonarcloudOrange);
+ box-sizing: border-box;
+ color: var(--sonarcloudOrange);
+ font-size: 16px;
+ font-weight: 700;
+ transition: box-shadow 0.3s ease;
+}
+
+.sc-browse:hover,
+.sc-browse:focus {
+ background-color: var(--sonarcloudOrange);
+ color: #fff;
+}
+
+.sc-news {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-top: 1px solid var(--sonarcloudBlack300);
+ padding-top: 32px;
+}
+
+.sc-news-title {
+ display: inline-block;
+ font-size: 18px;
+}
+
+.sc-news-link {
+ border-bottom-color: var(--sonarcloudBlack300);
+ color: var(--baseFontColor);
+}
+
+.sc-news-link:hover,
+.sc-news-link:focus {
+ border-bottom-color: var(--sonarcloudOrange);
+ color: var(--sonarcloudOrange);
+}
+
+.sc-footer {
+ background-color: var(--sonarcloudBlack800);
+ color: var(--sonarcloudBlack300);
+ font-size: 12px;
+}
+
+.sc-footer-limited {
+ position: relative;
+ max-width: 1280px;
+ margin-left: auto;
+ margin-right: auto;
+ padding-left: 20px;
+ padding-right: 20px;
+}
+
+.sc-footer-copy {
+ padding: 20px 0;
+ border-top: 1px solid var(--sonarcloudBlack700);
+ line-height: 16px;
+ font-size: 11px;
+ text-align: center;
+}
+
+.sc-footer-copy-link {
+ text-decoration: underline;
+}
+
+.sc-footer-nav {
+ display: flex;
+ padding: 30px 0;
+}
+
+.sc-footer-nav-column {
+ margin-right: 60px;
+}
+
+.sc-footer-nav-column-title {
+ line-height: 1;
+ margin-bottom: 16px;
+ color: #fff;
+ font-size: 12px;
+ font-weight: 700;
+ text-transform: uppercase;
+}
+
+.sc-footer-link {
+ border: none;
+ color: inherit;
+}
+
+.sc-footer-link:hover {
+ color: #fff;
+}
+
+.sc-footer-link:focus {
+ color: var(--sonarcloudOrange);
+}
+
+.sc-footer-logo {
+ position: absolute;
+ top: 30px;
+ right: 20px;
+}
import LoginForm from './LoginForm';
import OAuthProviders from './OAuthProviders';
import { IdentityProvider } from '../../../app/types';
-import { getHostUrl } from '../../../helpers/urls';
+import { getBaseUrl } from '../../../helpers/urls';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import './LoginSonarCloud.css';
<img
alt="SonarCloud logo"
height={36}
- src={`${getHostUrl()}/images/sc-icon.svg`}
+ src={`${getBaseUrl()}/images/sonarcloud-square-logo.svg`}
width={36}
/>
<h1 className="sonarcloud-login-title">
<img
alt="SonarCloud logo"
height={36}
- src="null/images/sc-icon.svg"
+ src="/images/sonarcloud-square-logo.svg"
width={36}
/>
<h1
<img
alt="SonarCloud logo"
height={36}
- src="null/images/sc-icon.svg"
+ src="/images/sonarcloud-square-logo.svg"
width={36}
/>
<h1
<img
alt="SonarCloud logo"
height={36}
- src="null/images/sc-icon.svg"
+ src="/images/sonarcloud-square-logo.svg"
width={36}
/>
<h1