Переглянути джерело

Drop SonarCloud about pages

tags/8.2.0.32929
Wouter Admiraal 4 роки тому
джерело
коміт
fcda3751ab
41 змінених файлів з 1 додано та 5936 видалено
  1. 1
    44
      server/sonar-web/src/main/js/apps/about/routes.ts
  2. 0
    97
      server/sonar-web/src/main/js/apps/about/sonarcloud/AsAService.tsx
  3. 0
    143
      server/sonar-web/src/main/js/apps/about/sonarcloud/AzureDevOps.tsx
  4. 0
    127
      server/sonar-web/src/main/js/apps/about/sonarcloud/BranchAnalysis.tsx
  5. 0
    217
      server/sonar-web/src/main/js/apps/about/sonarcloud/Contact.tsx
  6. 0
    377
      server/sonar-web/src/main/js/apps/about/sonarcloud/Home.tsx
  7. 0
    273
      server/sonar-web/src/main/js/apps/about/sonarcloud/Pricing.tsx
  8. 0
    229
      server/sonar-web/src/main/js/apps/about/sonarcloud/SQHome.tsx
  9. 0
    107
      server/sonar-web/src/main/js/apps/about/sonarcloud/SonarLintIntegration.tsx
  10. 0
    37
      server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/BranchAnalysis-test.tsx
  11. 0
    95
      server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/Home-test.tsx
  12. 0
    7
      server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/__snapshots__/BranchAnalysis-test.tsx.snap
  13. 0
    661
      server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/__snapshots__/Home-test.tsx.snap
  14. 0
    135
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/FeaturedProjects.css
  15. 0
    304
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/FeaturedProjects.tsx
  16. 0
    87
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/Footer.css
  17. 0
    172
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/Footer.tsx
  18. 0
    85
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/Languages.tsx
  19. 0
    48
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/LoginButtons.css
  20. 0
    41
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/LoginButtons.tsx
  21. 0
    139
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/NavBars.css
  22. 0
    110
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/NavBars.tsx
  23. 0
    45
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/Pricing.tsx
  24. 0
    32
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/SCChevronDownIcon.tsx
  25. 0
    63
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/SQPageContainer.tsx
  26. 0
    32
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/SQStartUsing.tsx
  27. 0
    52
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/SQTopNav.tsx
  28. 0
    41
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/StartUsing.tsx
  29. 0
    46
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/Statistics.css
  30. 0
    113
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/Statistics.tsx
  31. 0
    26
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__mocks__/react-countup.tsx
  32. 0
    162
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/FeaturedProjects-test.tsx
  33. 0
    26
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/Footer-test.tsx
  34. 0
    26
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/LoginButtons-test.tsx
  35. 0
    57
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/Statistics-test.tsx
  36. 0
    354
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/__snapshots__/FeaturedProjects-test.tsx.snap
  37. 0
    39
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/__snapshots__/LoginButtons-test.tsx.snap
  38. 0
    49
      server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/__snapshots__/Statistics-test.tsx.snap
  39. 0
    502
      server/sonar-web/src/main/js/apps/about/sonarcloud/new_style.css
  40. 0
    658
      server/sonar-web/src/main/js/apps/about/sonarcloud/style.css
  41. 0
    78
      server/sonar-web/src/main/js/apps/about/sonarcloud/utils.ts

+ 1
- 44
server/sonar-web/src/main/js/apps/about/routes.ts Переглянути файл

@@ -18,50 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { lazyLoad } from 'sonar-ui-common/components/lazyLoad';
import { isSonarCloud } from '../../helpers/system';

const routes = [
{
indexRoute: {
component: lazyLoad(() =>
isSonarCloud() ? import('./sonarcloud/Home') : import('./components/AboutApp')
)
},
childRoutes: isSonarCloud()
? [
{
path: 'contact',
component: lazyLoad(() => import('./sonarcloud/Contact'))
},
{
path: 'pricing',
component: lazyLoad(() => import('./sonarcloud/Pricing'))
},
{
path: 'sq',
childRoutes: [
{ indexRoute: { component: lazyLoad(() => import('./sonarcloud/SQHome')) } },
{
path: 'as-a-service',
component: lazyLoad(() => import('./sonarcloud/AsAService'))
},
{
path: 'branch-analysis-and-pr-decoration',
component: lazyLoad(() => import('./sonarcloud/BranchAnalysis'))
},
{
path: 'sonarlint-integration',
component: lazyLoad(() => import('./sonarcloud/SonarLintIntegration'))
},
{
path: 'vsts',
component: lazyLoad(() => import('./sonarcloud/AzureDevOps'))
}
]
}
]
: []
}
];
const routes = [{ indexRoute: { component: lazyLoad(() => import('./components/AboutApp')) } }];

export default routes;

+ 0
- 97
server/sonar-web/src/main/js/apps/about/sonarcloud/AsAService.tsx Переглянути файл

@@ -1,97 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { isLoggedIn } from '../../../helpers/users';
import SQPageContainer from './components/SQPageContainer';
import SQStartUsing from './components/SQStartUsing';
import SQTopNav from './components/SQTopNav';
import './style.css';

export default function AsAService() {
return (
<SQPageContainer>
{({ currentUser }) => (
<div className="page page-limited sc-page">
<Helmet title="Get started with SonarQube as a Service | SonarCloud">
<meta
content="Analyze your code with just a few clicks. Immediate access to the latest features and functionality. You use the service and we take care of the rest."
name="description"
/>
</Helmet>
<SQTopNav />

<div className="sc-child-header">
<img alt="" height="34" src={`${getBaseUrl()}/images/sonarcloud/as-a-service.svg`} />
<h1 className="sc-child-title">As a Service</h1>
<p className="sc-child-lead">
We fully operate the SonarQube base service, <br />
which is hosted in Frankfurt, Germany.
</p>
<img
alt=""
height="137"
src={`${getBaseUrl()}/images/sonarcloud/gears.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/gears.png 1x, ${getBaseUrl()}/images/sonarcloud/gears@2x.png 2x`}
width="270"
/>
</div>

<ul className="sc-features-list">
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Ready to use</h3>
<p className="sc-feature-description">
You need to worry about nothing but enjoying the service, everything else such as
hardware, provisioning, installation, configuration, monitoring is being taken care
of by us.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Always the latest and greatest</h3>
<p className="sc-feature-description">
SonarCloud always provides the latest and greatest features of SonarQube and our
selection of plugins. As soon as a new feature is fit for production, it will ship
to SonarCloud and wait that you use it.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Get started in minutes</h3>
<p className="sc-feature-description">
Simply sign up, create an organization for your team, and you are ready to run your
builds to get your projects analyzed in minutes.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Designed to scale</h3>
<p className="sc-feature-description">
You do not need to care about sizing or planning your future needs, we take care of
this and will make sure that the service can handle the analysis of your code at the
pace you decide. When you are getting close to your subscription limit, you decide
whether you want to go to the next level.
</p>
</li>
</ul>
{!isLoggedIn(currentUser) && <SQStartUsing />}
</div>
)}
</SQPageContainer>
);
}

+ 0
- 143
server/sonar-web/src/main/js/apps/about/sonarcloud/AzureDevOps.tsx Переглянути файл

@@ -1,143 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async';
import { Link } from 'react-router';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { isLoggedIn } from '../../../helpers/users';
import SQPageContainer from './components/SQPageContainer';
import './style.css';

const LANGUAGES = [
{ name: 'JavaScript', file: 'js.svg', width: 60 },
{ name: 'TypeScript', file: 'ts.svg', width: 130 },
{ name: 'C#', file: 'csharp.svg', width: 60 },
{ name: 'C++', file: 'c-c-plus-plus.svg', width: 53 },
{ name: 'T-SQL', file: 't-sql.svg', width: 80 },
{ name: 'VB', file: 'vb.svg', width: 70 }
];

export default function AzureDevOps() {
return (
<SQPageContainer>
{({ currentUser }) => (
<div className="page page-limited sc-page">
<Helmet title="Continuous Code Quality in Azure Devops | SonarCloud">
<meta
content="Enhance Azure DevOps with continuous code quality and automatically analyze branches and decorate pull requests."
name="description"
/>
</Helmet>
<ul className="sc-top-nav">
<li className="sc-top-nav-item">
<Link className="sc-top-nav-link" to="/about/sq">
Home
</Link>
</li>
</ul>
<div className="sc-child-header">
<h1 className="sc-child-title">Get the full experience in Azure DevOps</h1>
</div>

<ul className="sc-features-list">
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Native extension</h3>
<p className="sc-feature-description">
Using your existing Azure DevOps account and the SonarCloud Azure DevOps build
tasks, adding and configuring SonarCloud analysis to an existing build is a matter
of minutes.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Branches and PR 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>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Built-in Quality Gate</h3>
<p className="sc-feature-description">
A quality gate is available out of the box in order to verify code quality criteria
at any time, enabling to fail build pipelines but also enabling to notify, through a
webhook, any system that code quality criteria are not met.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Dedicated widget</h3>
<p className="sc-feature-description">
Once a project is in SonarCloud, a configurable widget can be added to the Azure
DevOps dashboard in order to add code quality to KPIs already used on the project.
</p>
</li>
</ul>

<div className="sc-vsts-start-wrapper">
<div className="sc-vsts-start">
{!isLoggedIn(currentUser) && (
<div className="sc-vsts-start-box">
<img
alt="SonarCloud"
height="38"
src={`${getBaseUrl()}/images/sonarcloud-square-logo.svg`}
/>
<h3 className="sc-vsts-start-title">Log in or Sign up</h3>
<a className="sc-orange-button" href="/sessions/init/microsoft">
SonarCloud
</a>
</div>
)}
<div className="sc-vsts-start-box">
<img
alt="Azure DevOps Extension"
height="38"
src={`${getBaseUrl()}/images/sonarcloud/windows.svg`}
/>
<h3 className="sc-vsts-start-title">Install Azure DevOps Extension</h3>
<a
className="sc-black-button"
href="https://marketplace.visualstudio.com/items?itemName=SonarSource.sonarcloud"
rel="noopener noreferrer"
target="_blank">
Marketplace
</a>
</div>
</div>
</div>

<div className="sc-integrations">
<h2 className="sc-sq-header2 sc-integrations-title">Analyze .NET languages and more</h2>
<ul className="sc-languages-list">
{LANGUAGES.map(language => (
<li key={language.name}>
<img
alt={language.name}
src={`${getBaseUrl()}/images/languages/${language.file}`}
style={{ width: `${language.width}px` }}
/>
</li>
))}
</ul>
</div>
</div>
)}
</SQPageContainer>
);
}

+ 0
- 127
server/sonar-web/src/main/js/apps/about/sonarcloud/BranchAnalysis.tsx Переглянути файл

@@ -1,127 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { isLoggedIn } from '../../../helpers/users';
import SQPageContainer from './components/SQPageContainer';
import SQStartUsing from './components/SQStartUsing';
import SQTopNav from './components/SQTopNav';
import './style.css';

export default function BranchAnalysis() {
return (
<SQPageContainer>
{({ currentUser }) => (
<div className="page page-limited sc-page">
<Helmet title="Pull requests analysis in Github, BitBucket and Azure DevOps | SonarCloud">
<meta
content="SonarCloud automatically analyzes branches and decorates pull requests with Github, BitBucket and Azure DevOps."
name="description"
/>
</Helmet>
<SQTopNav />

<div className="sc-child-header">
<img alt="" height="34" src={`${getBaseUrl()}/images/sonarcloud/branch-analysis.svg`} />
<h1 className="sc-child-title">
Branch analysis & <br />
pull request decoration
</h1>
<p className="sc-child-lead">
SonarCloud comes with a built-in feature to automatically analyze <br />
project branches and pull requests as soon as they get created.
</p>
</div>

<ul className="sc-features-list sc-branch-features-list">
<li className="sc-feature sc-branch-feature">
<img
alt=""
className="sc-branch-feature-right flex-0"
height="270"
src={`${getBaseUrl()}/images/sonarcloud/branch-01.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/branch-01.png 1x, ${getBaseUrl()}/images/sonarcloud/branch-01@2x.png 2x`}
width="463"
/>
<div className="flex-1">
<h3 className="sc-feature-title">Analyze branches and pull requests</h3>
<p className="sc-feature-description">
For all project branches (main, maintenance, version, feature, etc.), you get the
full experience in the project space, with a specific focus on that branch.
</p>
<p className="sc-feature-description">
When analyzing pull requests (PRs), a Quality Gate will be generated along with
the list of issues created in the PR.
</p>
<p className="sc-feature-description">
To save time and insure consistency, the analysis configuration is reused across
all branches of a project.
</p>
</div>
</li>
<li className="sc-feature sc-branch-feature">
<div className="flex-1">
<h3 className="sc-feature-title">Decorate PRs on Azure DevOps and GitHub</h3>
<p className="sc-feature-description">
Pull requests get decorated directly on Azure DevOps and GitHub. The result of the
PR analysis is available directly in the pull request itself, complementing nicely
manual reviews made by peers and enabling to make a more educated decision for
merging.
</p>
</div>
<img
alt=""
className="sc-branch-feature-left flex-0"
height="432"
src={`${getBaseUrl()}/images/sonarcloud/branch-02.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/branch-02.png 1x, ${getBaseUrl()}/images/sonarcloud/branch-02@2x.png 2x`}
width="471"
/>
</li>
<li className="sc-feature sc-branch-feature">
<img
alt=""
className="sc-branch-feature-right flex-0"
height="169"
src={`${getBaseUrl()}/images/sonarcloud/branch-03.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/branch-03.png 1x, ${getBaseUrl()}/images/sonarcloud/branch-03@2x.png 2x`}
width="460"
/>
<div className="flex-1">
<h3 className="sc-feature-title">Add a check in GitHub</h3>
<p className="sc-feature-description">
Finally, a check can be added to the PR to provide the Quality Gate status of the
PR, check that can optionally block the merge.
</p>
</div>
</li>
</ul>

<div className="sc-branch-bottom">
There is no longer an excuse for pushing issues to the master.
</div>

{!isLoggedIn(currentUser) && <SQStartUsing />}
</div>
)}
</SQPageContainer>
);
}

+ 0
- 217
server/sonar-web/src/main/js/apps/about/sonarcloud/Contact.tsx Переглянути файл

@@ -1,217 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Location } from 'history';
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
import { Link } from 'react-router';
import Select from 'sonar-ui-common/components/controls/Select';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { isLoggedIn } from '../../../helpers/users';
import SQPageContainer from './components/SQPageContainer';
import './style.css';

const CATEGORIES = [
{ label: 'Commercial', value: 'commercial' },
{ label: 'Confidential Request', value: 'confidential_request' }
];

interface Props {
location: Location;
}

interface State {
category: string;
organization: string;
question: string;
subject: string;
}

export default class Contact extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
const { query } = props.location;
this.state = {
category: query.category || '',
organization: query.organization || '',
question: query.question || '',
subject: query.subject || ''
};
}

getOrganizations = (organizations?: T.Organization[]) => {
return (organizations || []).map(org => ({
label: org.name,
value: org.key
}));
};

handleCategoryChange = ({ value }: { value: string }) => {
this.setState({ category: value });
};

handleOrganizationChange = ({ value }: { value: string }) => {
this.setState({ organization: value });
};

handleSubjectChange = (event: React.ChangeEvent<HTMLInputElement>) => {
this.setState({ subject: event.currentTarget.value });
};

handleQuestionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
this.setState({ question: event.currentTarget.value });
};

render() {
return (
<SQPageContainer>
{({ currentUser, userOrganizations }) => (
<div className="page page-limited sc-page sc-contact-page">
<Helmet title="Contact Us | SonarCloud">
<meta
content="If you are looking for help with SonarCloud, our Support forum is the best place to get help."
name="description"
/>
</Helmet>
<h1 className="sc-page-title">Contact us</h1>
<Alert display="inline" variant="warning">
If you are looking for help with SonarCloud, our{' '}
<a
href="https://community.sonarsource.com/c/help/sc"
rel="noopener noreferrer"
target="_blank">
<strong>Support forum</strong>
</a>{' '}
is the best place to get help.
</Alert>
<br />
<Alert display="inline" variant="warning">
Use this contact form for commercial or confidential requests only.
</Alert>
{!isLoggedIn(currentUser) && (
<p>
You can{' '}
<Link to={{ pathname: '/sessions/new', query: { return_to: '/about/contact' } }}>
log in to SonarCloud
</Link>{' '}
to automatically fill this form information and get better support.
</p>
)}
<form action="https://formspree.io/contact@sonarcloud.io" method="POST">
<div className="form-group">
<label htmlFor="contact-name">Name</label>
<input
autoFocus={true}
defaultValue={isLoggedIn(currentUser) ? currentUser.name : ''}
id="contact-name"
name="name"
required={true}
type="text"
/>
</div>
<div className="form-group">
<label htmlFor="contact-email">Email</label>
<input
defaultValue={isLoggedIn(currentUser) ? currentUser.email : ''}
id="contact-email"
name="_replyto"
required={true}
type="email"
/>
</div>
<div className="form-group category-select">
<label htmlFor="contact-category">Category</label>
<Select
id="contact-category"
name="category"
onChange={this.handleCategoryChange}
options={CATEGORIES}
placeholder="Choose a category"
required={true}
searchable={false}
value={this.state.category}
/>
<input
className="category-select-helper"
required={true}
tabIndex={-1}
value={this.state.category}
/>
</div>
{isLoggedIn(currentUser) && (
<div className="form-group category-select">
<label htmlFor="contact-organization">Organization concerned by the issue</label>
<Select
id="contact-organization"
name="organization"
onChange={this.handleOrganizationChange}
options={this.getOrganizations(userOrganizations)}
placeholder="Choose an organization"
searchable={false}
value={this.state.organization}
/>
</div>
)}
<div className="form-group">
<label htmlFor="contact-subject">Subject</label>
<input
id="contact-subject"
maxLength={70}
onChange={this.handleSubjectChange}
required={true}
type="text"
value={this.state.subject}
/>
<input
name="_subject"
type="hidden"
value={`[${this.state.category}] ${this.state.subject}`}
/>
</div>
<div className="form-group">
<label htmlFor="contact-question">How can we help?</label>
<textarea
className="form-control"
id="contact-question"
name="question"
onChange={this.handleQuestionChange}
placeholder="Please describe precisely what is your issue..."
required={true}
rows={8}
value={this.state.question}
/>
</div>
<div className="form-group">
{
// The following hidden input field must absolutely be kept
// This is a "honeypot" field to avoid spam by fooling scrapers
}
<input name="_gotcha" type="text" />
<button type="submit">Send Request</button>
</div>
{isLoggedIn(currentUser) && (
<input name="login" type="hidden" value={currentUser.login} />
)}
</form>
</div>
)}
</SQPageContainer>
);
}
}

+ 0
- 377
server/sonar-web/src/main/js/apps/about/sonarcloud/Home.tsx Переглянути файл

@@ -1,377 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async';
import { connect } from 'react-redux';
import { addWhitePageClass, removeWhitePageClass } from 'sonar-ui-common/helpers/pages';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { getGlobalSettingValue, Store } from '../../../store/rootReducer';
import FeaturedProjects from './components/FeaturedProjects';
import Footer from './components/Footer';
import { Languages } from './components/Languages';
import LoginButtons from './components/LoginButtons';
import { FixedNavBar, TopNavBar } from './components/NavBars';
import Statistics from './components/Statistics';
import './new_style.css';
import { FeaturedProject, HomepageData, requestHomepageData } from './utils';

interface Props {
homePageDataUrl?: string;
}

interface State {
data?: HomepageData;
}

export class Home extends React.PureComponent<Props, State> {
mounted = false;
state: State = {};

componentDidMount() {
this.mounted = true;
addWhitePageClass();
this.fetchData();
}

componentWillUnmount() {
removeWhitePageClass();
this.mounted = false;
}

fetchData = () => {
const { homePageDataUrl } = this.props;
if (homePageDataUrl) {
requestHomepageData(homePageDataUrl).then(
data => {
if (this.mounted) {
this.setState({ data });
}
},
() => {
/* Fail silently */
}
);
}
};

render() {
const { data } = this.state;

return (
<div className="global-container">
<div className="page-wrapper">
<div className="page-container sc-page">
<Helmet title="SonarCloud | Clean Code, Rockstar Status">
<meta
content="Enhance your workflow with continuous code quality, SonarCloud automatically analyzes and decorates pull requests on GitHub, Bitbucket and Azure DevOps on major languages."
name="description"
/>
</Helmet>
<FixedNavBar />
<PageBackgroundHeader />
<TopNavBar />
<PageTitle />
<EnhanceWorkflow />
<Functionality />
<Languages />
<Stats data={data} />
<Projects featuredProjects={(data && data.featuredProjects) || []} />
</div>
</div>
<Footer />
</div>
);
}
}

const mapStateToProps = (state: Store) => {
const homePageDataUrl = getGlobalSettingValue(state, 'sonar.homepage.url');
return {
homePageDataUrl: homePageDataUrl && homePageDataUrl.value
};
};

export default connect(mapStateToProps)(Home);

function PageBackgroundHeader() {
return (
<div className="sc-header-background">
<div className="sc-background-start" />
<div className="sc-background-end" />
<div className="sc-background-center">
<img alt="" height="418px" src={`${getBaseUrl()}/images/sonarcloud/home-header.svg`} />
</div>
</div>
);
}

function PageTitle() {
return (
<div className="sc-section sc-columns big-spacer-top">
<div className="sc-column sc-column-half display-flex-center">
<div>
<h1 className="sc-title-orange big-spacer-top">Clean Code</h1>
<h1 className="sc-spacer-bottom">Rockstar Status</h1>
<h5 className="sc-big-spacer-bottom sc-regular-weight">
Eliminate bugs and vulnerabilities.
<br />
Champion quality code in your projects.
</h5>
<div>
<h6>Go ahead! Analyze your repo:</h6>
<LoginButtons />
<p className="sc-mention sc-regular-weight big-spacer-top">
Free for Open-Source Projects
</p>
</div>
</div>
</div>
<div className="sc-column sc-column-half text-right">
<img
alt=""
src={`${getBaseUrl()}/images/sonarcloud/home-header-people.png`}
width="430px"
/>
</div>
</div>
);
}

function EnhanceWorkflow() {
return (
<div className="sc-section sc-columns">
<div className="sc-column sc-column-full">
<h3 className="sc-big-spacer-bottom">
Enhance Your Workflow
<br />
with Continuous Code Quality
</h3>
<img
alt=""
className="sc-big-spacer-bottom"
src={`${getBaseUrl()}/images/sonarcloud/home-branch.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/home-branch.png 1x, ${getBaseUrl()}/images/sonarcloud/home-branch@2x.png 2x`}
/>
<h5 className="spacer-bottom">Maximize your throughput and only release clean code</h5>
<h6 className="sc-big-spacer-bottom sc-regular-weight">
SonarCloud automatically analyzes branches and decorates pull requests
</h6>
</div>
</div>
);
}

function Functionality() {
return (
<div className="position-relative">
<div className="sc-functionality-background">
<div className="sc-background-center">
<img
alt=""
height="300px"
src={`${getBaseUrl()}/images/sonarcloud/home-grey-background.svg`}
/>
</div>
</div>
<div className="sc-functionality-container">
<div className="sc-section">
<h3 className="sc-big-spacer-bottom text-center">
Functionality
<br />
that Fits Your Projects
</h3>
<div className="sc-columns">
<div className="sc-column sc-column-small big-spacer-top">
<h6 className="sc-regular-weight spacer-bottom">Easy to Use</h6>
<p>
With just a few clicks you’re up and running right where your code lives. Immediate
access to the latest features and enhancements.
</p>
<div className="sc-separator" />
<span className="big-spacer-bottom sc-with-icon">
<img
alt=""
className="big-spacer-right"
src={`${getBaseUrl()}/images/sonarcloud/scale.svg`}
/>{' '}
Scale on-demand as your projects grow.
</span>
<span className="sc-with-icon">
<img
alt=""
className="big-spacer-right"
src={`${getBaseUrl()}/images/sonarcloud/stop.svg`}
/>{' '}
No contracts, stop/start anytime.
</span>
</div>
<div className="sc-column sc-column-big big-spacer-top">
<img
alt=""
className="sc-rounded-img"
src={`${getBaseUrl()}/images/sonarcloud/home-easy-to-use.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/home-easy-to-use.png 1x, ${getBaseUrl()}/images/sonarcloud/home-easy-to-use@2x.png 2x`}
/>
</div>
</div>
<div className="sc-columns">
<div className="sc-column sc-column-big">
<img
alt=""
className="sc-rounded-img"
src={`${getBaseUrl()}/images/sonarcloud/home-open-transparent.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/home-open-transparent.png 1x, ${getBaseUrl()}/images/sonarcloud/home-open-transparent@2x.png 2x`}
/>
</div>
<div className="sc-column sc-column-small">
<div>
<h6 className="sc-regular-weight spacer-bottom">Open and Transparent</h6>
<p className="big-spacer-bottom">
Project dashboards keep teams and stakeholders informed on code quality and
releasability.
</p>
<p>Display project badges and show your communities you’re all about awesome.</p>
<img
alt=""
className="big-spacer-top"
src={`${getBaseUrl()}/images/project_badges/sonarcloud-black.svg`}
width="200px"
/>
</div>
</div>
</div>
<div className="sc-columns">
<div className="sc-column sc-column-full big-spacer-bottom">
<div>
<h6 className="sc-regular-weight spacer-bottom">Effective Collaboration</h6>

<p className="sc-with-inline-icon">
Use
<img
alt="SonarCloud"
src={`${getBaseUrl()}/images/sonarcloud/sonarcloud-logo-text-only.svg`}
/>
with your team, share best practices and have fun writing quality code!
</p>
<br />
<p className="sc-with-inline-icon">
Connect with
<img
alt="SonarCloud"
src={`${getBaseUrl()}/images/sonarcloud/sonarlint-logo.svg`}
/>
and get real-time notifications in your IDE as you work.
</p>
<div className="big-spacer-top">
<img
alt=""
className="big-spacer-top huge-spacer-bottom"
src={`${getBaseUrl()}/images/sonarcloud/ide.svg`}
width="216px"
/>
</div>
<img alt="" src={`${getBaseUrl()}/images/sonarcloud/collab.svg`} width="540px" />
</div>
</div>
</div>
</div>
</div>
<div className="sc-functionality-background sc-functionality-background-bottom">
<div className="sc-background-center">
<img
alt=""
height="140px"
src={`${getBaseUrl()}/images/sonarcloud/home-background-grey-bottom.svg`}
/>
</div>
</div>
</div>
);
}

interface StatsProps {
data?: HomepageData;
}

function Stats({ data }: StatsProps) {
return (
<div className="sc-section sc-columns">
<div className="sc-column sc-column-full">
<h3>
Over 3,000 Projects
<br />
Continuously Analyzed
</h3>
{data && (
<Statistics
statistics={[
{ icon: 'rules', text: 'Static analysis rules checked', value: data.rules },
{ icon: 'locs', text: 'Lines of code analyzed', value: data.publicLoc },
{
icon: 'pull-request',
text: 'Pull Requests decorated/week',
value: data.newPullRequests7d
},
{
icon: 'open-source',
text: 'Open-source projects inspected',
value: data.publicProjects
}
]}
/>
)}
</div>
</div>
);
}

interface ProjectsProps {
featuredProjects: FeaturedProject[];
}

function Projects({ featuredProjects }: ProjectsProps) {
return (
<div className="sc-section sc-columns">
<div className="sc-column sc-column-full">
{featuredProjects.length > 0 && (
<>
<h6 className="big-spacer-bottom">
Transparency makes sense
<br />
and that’s why the trend is growing.
</h6>
<p>
Check out these open-source projects showing users
<br />
their commitment to quality.
</p>
<FeaturedProjects projects={featuredProjects} />
</>
)}
<h6 className="spacer-bottom">
Come join the fun, it’s entirely free for open-source projects!
</h6>
<div className="sc-spacer-bottom">
<LoginButtons />
</div>
</div>
</div>
);
}

+ 0
- 273
server/sonar-web/src/main/js/apps/about/sonarcloud/Pricing.tsx Переглянути файл

@@ -1,273 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async';
import { addWhitePageClass, removeWhitePageClass } from 'sonar-ui-common/helpers/pages';
import { scrollToElement } from 'sonar-ui-common/helpers/scrolling';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import Footer from './components/Footer';
import { FixedNavBar, TopNavBar } from './components/NavBars';
import './new_style.css';

export default class Pricing extends React.PureComponent {
container?: HTMLElement | null;

componentDidMount() {
addWhitePageClass();
}

componentWillUnmount() {
removeWhitePageClass();
}

handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
event.stopPropagation();
if (this.container) {
scrollToElement(this.container, { bottomOffset: window.innerHeight - 200 });
}
};

getReference = (node: HTMLElement | null) => {
this.container = node;
};

render() {
return (
<div className="global-container">
<div className="page-wrapper">
<div className="page-container sc-page">
<Helmet title="Plans and Pricing | SonarCloud">
<meta
content="Get all the SonarCloud features and functionality for free on your open-source projects. If you need privacy for your code, we have a pricing plan to fit your needs."
name="description"
/>
</Helmet>
<FixedNavBar onPricingPage={true} />
<PageBackgroundHeader />
<TopNavBar onPricingPage={true} whiteLogo={true} />
<ForEveryoneBlock onClick={this.handleClick} />
<LoginCTA />
<PricingFAQ getReference={this.getReference} />
</div>
</div>
<Footer />
</div>
);
}
}

function PageBackgroundHeader() {
return (
<div className="sc-header-background">
<div className="sc-background-center">
<img alt="" height="562px" src={`${getBaseUrl()}/images/sonarcloud/pricing-header.svg`} />
</div>
</div>
);
}

interface ForEveryoneBlockProps {
onClick: (event: React.MouseEvent<HTMLAnchorElement>) => void;
}

function ForEveryoneBlock({ onClick }: ForEveryoneBlockProps) {
return (
<div className="sc-section big-spacer-top">
<h2 className="white text-center sc-big-spacer-top sc-big-spacer-bottom">
SonarCloud is for everyone
</h2>
<div className="sc-pricing-free">
<h4>
Free for <span className="sc-title-orange">public projects</span>
</h4>
<ul className="big-spacer-top big-spacer-bottom">
<li>
<em>Unlimited lines of code</em>
</li>
<li>
<em>Anyone can see your project</em> and browse your code
</li>
<li>
You have access to the <em>full SonarCloud feature set</em>
</li>
<li>
<em>Choose members of your team</em> who can work on your projects
</li>
</ul>
<em>Loved by Open-Source Developers</em>
<div className="sc-pricing-privacy">
<h4 className="white">
Need <span className="sc-title-orange">privacy?</span>
</h4>
<ul className="big-spacer-top big-spacer-bottom">
<li>
<em>Create private projects,</em> priced per lines of code.{' '}
<a href="#" onClick={onClick}>
See price list
</a>
</li>
<li>
<em>You have strict control</em> over who can view your private data
</li>
</ul>
<div className="big-spacer-left">
<div className="starts-at">starts at 10€/month</div>
<em>Free 14-day trial</em>
</div>
</div>
</div>
</div>
);
}

function LoginCTA() {
return (
<div className="sc-section text-center pricing-section sc-big-spacer-bottom">
<h5 className="sc-big-spacer-top big-spacer-bottom">
Log in to SonarCloud and choose your pricing plan
</h5>
<a className="sc-orange-button" href={`${getBaseUrl()}/sessions/new`}>
Start Using SonarCloud
</a>
</div>
);
}

interface PricingFAQProps {
getReference: (node: HTMLDivElement | null) => void;
}

function PricingFAQ({ getReference }: PricingFAQProps) {
return (
<div className="sc-section pricing-section big-spacer-top sc-big-spacer-bottom">
<h5 className="text-center sc-big-spacer-top sc-big-spacer-bottom">Pricing FAQ</h5>
<div className="sc-columns">
<div className="sc-column sc-column-medium display-flex-center">
<div>
<div className="faq-title" ref={getReference}>
How does pricing work for private projects?
</div>
<p className="big-spacer-bottom">
Subscribing to a paid plan on SonarCloud allows you to create a private organization
containing private projects. You pay up front for a maximum number of private lines of
code to be analyzed in your organization.
<br />
<br />
Find your max LOC below to see what it will cost you per month:
</p>
<table className="loc-price sc-big-spacer-bottom">
<thead>
<tr>
<th>Up to lines of code</th>
<th>Price per month in €</th>
</tr>
</thead>
<tbody>
<tr>
<td>100k</td>
<td>10</td>
</tr>
<tr>
<td>250k</td>
<td>75</td>
</tr>
<tr>
<td>500k</td>
<td>150</td>
</tr>
<tr>
<td>1M</td>
<td>250</td>
</tr>
<tr>
<td>2M</td>
<td>500</td>
</tr>
<tr>
<td>5M</td>
<td>1500</td>
</tr>
<tr>
<td>10M</td>
<td>3000</td>
</tr>
<tr>
<td>20M</td>
<td>4000</td>
</tr>
</tbody>
</table>
<div className="faq-title">What payment options are available ?</div>
<p>
Payment is done online by credit card and will happen automatically every month, based
on the plan you choose. We also accept to receive a purchase order and a wire transfer
payment, if ordering a yearly subscription for more than 1M LOCs. In this case, you
need to contact us through the Contact form.
</p>
<div className="faq-title">Can I try a private project on SonarCloud for free?</div>
<p>
Your first 14 days are on us. You just have to upgrade your organization to a paid
plan, and fill your credit card information to get started. After your trial, if you
love it you can continue using SonarCloud and you will be charged for the plan you
selected when you first started your free trial. You can cancel anytime.
</p>
</div>
</div>
<div className="sc-column sc-column-medium display-flex-center">
<div>
<div className="faq-title">What is a Line of Code (LOC) on SonarCloud?</div>
<p>
LOCs are computed by summing up the LOCs of each project analyzed in SonarCloud. The
LOCs used for a project are the LOCs found during the most recent analysis of this
project.
</p>
<div className="faq-title">How are Lines of Code (LOCs) counted towards billing?</div>
<p>
Only LOC from your private projects are counted toward your maximum number of LOCs. If
your project contains branches, the counted LOCs are the ones of the biggest branch.
The count is not related to how frequently the source code is analyzed. If your
private project has a 6K LOCs and you analyze it 100 times in the month, this will be
counted as 6K for the billing. If you are getting close to the threshold you will be
notified to either upgrade your plan or reduce the number of LOCs in your projects.
</p>
<div className="faq-title">When will I be invoiced?</div>
<p>
You will be invoiced once a month, the day of the month after your trial ends. For
example if you start your free trial on January 1st, it will last till January 14th
and you will be first billed on January 15th for your upcoming month, e.g. January
15th to February 15th.
</p>
<div className="faq-title">Can I cancel my subscription?</div>
<p>
Of course! There&apos;s no commitment. You can delete your paid organization whenever
you wish, or simply downgrade to the free tier if you wish to keep on analysing some
public projects.
</p>
<div className="faq-title">Still have more questions?</div>
<p>
Contact us <a href={`${getBaseUrl()}/about/contact`}>here</a>.
</p>
</div>
</div>
</div>
</div>
);
}

+ 0
- 229
server/sonar-web/src/main/js/apps/about/sonarcloud/SQHome.tsx Переглянути файл

@@ -1,229 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async';
import { Link } from 'react-router';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { isLoggedIn } from '../../../helpers/users';
import LoginButtons from './components/LoginButtons';
import Pricing from './components/Pricing';
import SQPageContainer from './components/SQPageContainer';
import StartUsing from './components/StartUsing';
import './style.css';
import { LANGUAGES } from './utils';

const NB_LANGUAGE_PER_ROW = 8;

export default function SQHome() {
return (
<SQPageContainer>
{({ currentUser }) => (
<div className="page sc-page sc-sq-page">
<Helmet title="Use SonarQube as a Service, sign up for SonarCloud | SonarCloud">
<meta
content="Enhance your workflow with continuous code quality, SonarCloud automatically analyzes and decorates pull requests on GitHub, Bitbucket and Azure DevOps on major languages."
name="description"
/>
</Helmet>
<Jumbotron />

<h2 className="sc-sq-header2">You use the service, we take care of the rest</h2>
<Pricing />
{!isLoggedIn(currentUser) && <StartUsing />}

<Features />
<Languages />
<Integrations />
<BottomNote />
</div>
)}
</SQPageContainer>
);
}

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>
<LoginButtons />
</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</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 &amp; 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() {
const languagesPerRow = [];
for (let i = 0; i < LANGUAGES.length / NB_LANGUAGE_PER_ROW; i++) {
languagesPerRow[i] = LANGUAGES.slice(i * NB_LANGUAGE_PER_ROW, (i + 1) * NB_LANGUAGE_PER_ROW);
}

return (
<div className="sc-languages">
<h3 className="sc-feature-title">On {LANGUAGES.length} programming languages</h3>
{languagesPerRow.map((languagesRow, idx) => (
<ul className="sc-languages-list" key={idx}>
{languagesRow.map(language => (
<li key={language.name}>
<img
alt={language.name}
src={`${getBaseUrl()}/images/languages/${language.file}`}
width={language.width}
/>
</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">Azure DevOps</h3>
<img
alt="Azure DevOps"
className="big-spacer-top"
height="60"
src={`${getBaseUrl()}/images/sonarcloud/azure.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">
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>
);
}

+ 0
- 107
server/sonar-web/src/main/js/apps/about/sonarcloud/SonarLintIntegration.tsx Переглянути файл

@@ -1,107 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { Helmet } from 'react-helmet-async';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { isLoggedIn } from '../../../helpers/users';
import SQPageContainer from './components/SQPageContainer';
import SQStartUsing from './components/SQStartUsing';
import SQTopNav from './components/SQTopNav';
import './style.css';

export default function SonarLintIntegration() {
return (
<SQPageContainer>
{({ currentUser }) => (
<div className="page page-limited sc-page">
<Helmet title="Enhance SonarCloud experience with SonarLint | SonarCloud">
<meta
content="SonarLint connected teams are efficient, consistent and get more value. Connect SonarCloud with SonarLint and share consistent rulesets and analysis settings in everyone’s IDE."
name="description"
/>
</Helmet>
<SQTopNav />

<div className="sc-child-header">
<img
alt=""
height="34"
src={`${getBaseUrl()}/images/sonarcloud/sonarlint-integration.svg`}
/>
<h1 className="sc-child-title">SonarLint integration</h1>
<p className="sc-child-lead">
SonarCloud can be extended with{' '}
<a className="sc-child-lead-link" href="https://www.sonarlint.org/">
SonarLint
</a>{' '}
to provide developers maximum insight <br />
in their IDEs on code quality and make sure they do not introduce new issues.
</p>
<img
alt=""
height="147"
src={`${getBaseUrl()}/images/sonarcloud/sl-notif.png`}
srcSet={`${getBaseUrl()}/images/sonarcloud/sl-notif.png 1x, ${getBaseUrl()}/images/sonarcloud/sl-notif@2x.png 2x`}
width="450"
/>
</div>

<ul className="sc-features-list">
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Get instant feedback</h3>
<p className="sc-feature-description">
SonarLint will provide developers with instant feedback in their IDEs as they are
writing code, like with a spell checker. SonarLint also shows already existing
issues in the code and enables developers to differentiate what issues they
introduced.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Share quality profiles</h3>
<p className="sc-feature-description">
Teams will share the ruleset used to check quality on the project. This means that
not only everyone in the team uses the same rules but it also means that if you
update this ruleset, everybody will use immediately the updated one.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Share configuration</h3>
<p className="sc-feature-description">
Project configuration such as exclusions, parameters and false positives get
conveyed to the IDE as they get defined, enabling the team get exactly the same view
on the project they are working on.
</p>
</li>
<li className="sc-feature sc-child-feature">
<h3 className="sc-feature-title">Event notification</h3>
<p className="sc-feature-description">
Developers will get notified directly in their IDEs when the Quality Gate of their
project fails or when they have introduced an issue that has been picked by
SonarCloud.
</p>
</li>
</ul>

{!isLoggedIn(currentUser) && <SQStartUsing />}
</div>
)}
</SQPageContainer>
);
}

+ 0
- 37
server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/BranchAnalysis-test.tsx Переглянути файл

@@ -1,37 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import BranchAnalysis from '../BranchAnalysis';

// necessary to make the test run
jest.mock('Docs/EmbedDocsSuggestions.json', () => {}, { virtual: true });

beforeEach(() => {
jest.clearAllMocks();
});

it('should render', async () => {
const wrapper = shallow(<BranchAnalysis />);
await waitAndUpdate(wrapper);

expect(wrapper).toMatchSnapshot();
});

+ 0
- 95
server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/Home-test.tsx Переглянути файл

@@ -1,95 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { mockStore } from '../../../../helpers/testMocks';
import Home from '../Home';
import { requestHomepageData } from '../utils';

jest.mock('../utils', () => {
const utils = require.requireActual('../utils');
utils.requestHomepageData = jest.fn().mockResolvedValue({
publicProjects: 236,
publicLoc: 12345,
pullRequests: 123456,
rules: 1234,
featuredProjects: [
{
key: 'sonarsource-jfrog.simple-js-php-project',
avatarUrl: null,
organizationKey: 'sonarsource-jfrog',
organizationName: 'SonarSource & JFrog',
name: 'Simple JS & PHP project',
bugs: 0,
codeSmells: 7,
coverage: 9.7,
duplications: 56.2,
gateStatus: 'OK',
languages: ['js', 'php'],
maintainabilityRating: 1,
ncloc: 123456,
reliabilityRating: 1,
securityRating: 1,
vulnerabilities: 654321
}
]
});
return utils;
});

beforeEach(() => {
jest.clearAllMocks();
});

it('should render', async () => {
const wrapper = shallowRender('https://static.sonarcloud.io/homepage.json');
expect(requestHomepageData).toBeCalled();
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
expect(wrapper.find('PageBackgroundHeader').dive()).toMatchSnapshot();
expect(wrapper.find('PageTitle').dive()).toMatchSnapshot();
expect(wrapper.find('EnhanceWorkflow').dive()).toMatchSnapshot();
expect(wrapper.find('Functionality').dive()).toMatchSnapshot();
expect(wrapper.find('Languages').dive()).toMatchSnapshot();
expect(wrapper.find('Stats').dive()).toMatchSnapshot();
expect(wrapper.find('Projects').dive()).toMatchSnapshot();
});

it('should not render real Stats and Projects', () => {
const wrapper = shallowRender(undefined);
expect(requestHomepageData).not.toBeCalled();
expect(wrapper.find('Stats').dive()).toMatchSnapshot();
expect(wrapper.find('Projects').dive()).toMatchSnapshot();
});

function shallowRender(homePageDataUrl: string | undefined) {
return shallow(<Home />, {
context: {
store: mockStore({
settingsApp: {
values: {
global: { 'sonar.homepage.url': { key: 'sonar.homepage.url', value: homePageDataUrl } }
}
}
})
}
}).dive();
}

+ 0
- 7
server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/__snapshots__/BranchAnalysis-test.tsx.snap Переглянути файл

@@ -1,7 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render 1`] = `
<withRouter(Connect(SQPageContainer))>
<Component />
</withRouter(Connect(SQPageContainer))>
`;

+ 0
- 661
server/sonar-web/src/main/js/apps/about/sonarcloud/__tests__/__snapshots__/Home-test.tsx.snap Переглянути файл

@@ -1,661 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should not render real Stats and Projects 1`] = `
<div
className="sc-section sc-columns"
>
<div
className="sc-column sc-column-full"
>
<h3>
Over 3,000 Projects
<br />
Continuously Analyzed
</h3>
</div>
</div>
`;

exports[`should not render real Stats and Projects 2`] = `
<div
className="sc-section sc-columns"
>
<div
className="sc-column sc-column-full"
>
<h6
className="spacer-bottom"
>
Come join the fun, it’s entirely free for open-source projects!
</h6>
<div
className="sc-spacer-bottom"
>
<LoginButtons />
</div>
</div>
</div>
`;

exports[`should render 1`] = `
<div
className="global-container"
>
<div
className="page-wrapper"
>
<div
className="page-container sc-page"
>
<Helmet
defer={true}
encodeSpecialCharacters={true}
title="SonarCloud | Clean Code, Rockstar Status"
>
<meta
content="Enhance your workflow with continuous code quality, SonarCloud automatically analyzes and decorates pull requests on GitHub, Bitbucket and Azure DevOps on major languages."
name="description"
/>
</Helmet>
<FixedNavBar />
<PageBackgroundHeader />
<TopNavBar />
<PageTitle />
<EnhanceWorkflow />
<Functionality />
<Languages />
<Stats
data={
Object {
"featuredProjects": Array [
Object {
"avatarUrl": null,
"bugs": 0,
"codeSmells": 7,
"coverage": 9.7,
"duplications": 56.2,
"gateStatus": "OK",
"key": "sonarsource-jfrog.simple-js-php-project",
"languages": Array [
"js",
"php",
],
"maintainabilityRating": 1,
"name": "Simple JS & PHP project",
"ncloc": 123456,
"organizationKey": "sonarsource-jfrog",
"organizationName": "SonarSource & JFrog",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 654321,
},
],
"publicLoc": 12345,
"publicProjects": 236,
"pullRequests": 123456,
"rules": 1234,
}
}
/>
<Projects
featuredProjects={
Array [
Object {
"avatarUrl": null,
"bugs": 0,
"codeSmells": 7,
"coverage": 9.7,
"duplications": 56.2,
"gateStatus": "OK",
"key": "sonarsource-jfrog.simple-js-php-project",
"languages": Array [
"js",
"php",
],
"maintainabilityRating": 1,
"name": "Simple JS & PHP project",
"ncloc": 123456,
"organizationKey": "sonarsource-jfrog",
"organizationName": "SonarSource & JFrog",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 654321,
},
]
}
/>
</div>
</div>
<Footer />
</div>
`;

exports[`should render 2`] = `
<div
className="sc-header-background"
>
<div
className="sc-background-start"
/>
<div
className="sc-background-end"
/>
<div
className="sc-background-center"
>
<img
alt=""
height="418px"
src="/images/sonarcloud/home-header.svg"
/>
</div>
</div>
`;

exports[`should render 3`] = `
<div
className="sc-section sc-columns big-spacer-top"
>
<div
className="sc-column sc-column-half display-flex-center"
>
<div>
<h1
className="sc-title-orange big-spacer-top"
>
Clean Code
</h1>
<h1
className="sc-spacer-bottom"
>
Rockstar Status
</h1>
<h5
className="sc-big-spacer-bottom sc-regular-weight"
>
Eliminate bugs and vulnerabilities.
<br />
Champion quality code in your projects.
</h5>
<div>
<h6>
Go ahead! Analyze your repo:
</h6>
<LoginButtons />
<p
className="sc-mention sc-regular-weight big-spacer-top"
>
Free for Open-Source Projects
</p>
</div>
</div>
</div>
<div
className="sc-column sc-column-half text-right"
>
<img
alt=""
src="/images/sonarcloud/home-header-people.png"
width="430px"
/>
</div>
</div>
`;

exports[`should render 4`] = `
<div
className="sc-section sc-columns"
>
<div
className="sc-column sc-column-full"
>
<h3
className="sc-big-spacer-bottom"
>
Enhance Your Workflow
<br />
with Continuous Code Quality
</h3>
<img
alt=""
className="sc-big-spacer-bottom"
src="/images/sonarcloud/home-branch.png"
srcSet="/images/sonarcloud/home-branch.png 1x, /images/sonarcloud/home-branch@2x.png 2x"
/>
<h5
className="spacer-bottom"
>
Maximize your throughput and only release clean code
</h5>
<h6
className="sc-big-spacer-bottom sc-regular-weight"
>
SonarCloud automatically analyzes branches and decorates pull requests
</h6>
</div>
</div>
`;

exports[`should render 5`] = `
<div
className="position-relative"
>
<div
className="sc-functionality-background"
>
<div
className="sc-background-center"
>
<img
alt=""
height="300px"
src="/images/sonarcloud/home-grey-background.svg"
/>
</div>
</div>
<div
className="sc-functionality-container"
>
<div
className="sc-section"
>
<h3
className="sc-big-spacer-bottom text-center"
>
Functionality
<br />
that Fits Your Projects
</h3>
<div
className="sc-columns"
>
<div
className="sc-column sc-column-small big-spacer-top"
>
<h6
className="sc-regular-weight spacer-bottom"
>
Easy to Use
</h6>
<p>
With just a few clicks you’re up and running right where your code lives. Immediate access to the latest features and enhancements.
</p>
<div
className="sc-separator"
/>
<span
className="big-spacer-bottom sc-with-icon"
>
<img
alt=""
className="big-spacer-right"
src="/images/sonarcloud/scale.svg"
/>
Scale on-demand as your projects grow.
</span>
<span
className="sc-with-icon"
>
<img
alt=""
className="big-spacer-right"
src="/images/sonarcloud/stop.svg"
/>
No contracts, stop/start anytime.
</span>
</div>
<div
className="sc-column sc-column-big big-spacer-top"
>
<img
alt=""
className="sc-rounded-img"
src="/images/sonarcloud/home-easy-to-use.png"
srcSet="/images/sonarcloud/home-easy-to-use.png 1x, /images/sonarcloud/home-easy-to-use@2x.png 2x"
/>
</div>
</div>
<div
className="sc-columns"
>
<div
className="sc-column sc-column-big"
>
<img
alt=""
className="sc-rounded-img"
src="/images/sonarcloud/home-open-transparent.png"
srcSet="/images/sonarcloud/home-open-transparent.png 1x, /images/sonarcloud/home-open-transparent@2x.png 2x"
/>
</div>
<div
className="sc-column sc-column-small"
>
<div>
<h6
className="sc-regular-weight spacer-bottom"
>
Open and Transparent
</h6>
<p
className="big-spacer-bottom"
>
Project dashboards keep teams and stakeholders informed on code quality and releasability.
</p>
<p>
Display project badges and show your communities you’re all about awesome.
</p>
<img
alt=""
className="big-spacer-top"
src="/images/project_badges/sonarcloud-black.svg"
width="200px"
/>
</div>
</div>
</div>
<div
className="sc-columns"
>
<div
className="sc-column sc-column-full big-spacer-bottom"
>
<div>
<h6
className="sc-regular-weight spacer-bottom"
>
Effective Collaboration
</h6>
<p
className="sc-with-inline-icon"
>
Use
<img
alt="SonarCloud"
src="/images/sonarcloud/sonarcloud-logo-text-only.svg"
/>
with your team, share best practices and have fun writing quality code!
</p>
<br />
<p
className="sc-with-inline-icon"
>
Connect with
<img
alt="SonarCloud"
src="/images/sonarcloud/sonarlint-logo.svg"
/>
and get real-time notifications in your IDE as you work.
</p>
<div
className="big-spacer-top"
>
<img
alt=""
className="big-spacer-top huge-spacer-bottom"
src="/images/sonarcloud/ide.svg"
width="216px"
/>
</div>
<img
alt=""
src="/images/sonarcloud/collab.svg"
width="540px"
/>
</div>
</div>
</div>
</div>
</div>
<div
className="sc-functionality-background sc-functionality-background-bottom"
>
<div
className="sc-background-center"
>
<img
alt=""
height="140px"
src="/images/sonarcloud/home-background-grey-bottom.svg"
/>
</div>
</div>
</div>
`;

exports[`should render 6`] = `
<div
className="position-relative"
>
<div
className="sc-languages-container clearfix"
>
<div
className="sc-section sc-columns"
>
<div
className="sc-column-full"
>
<h3
className="sc-big-spacer-bottom"
>
SonarCloud speaks your language
</h3>
<ul
className="sc-languages-list"
style={
Object {
"height": undefined,
}
}
>
<li
key="Java"
>
<img
alt="Java"
src="/images/languages/java.svg"
width={65}
/>
</li>
<li
key="JavaScript"
>
<img
alt="JavaScript"
src="/images/languages/js.svg"
width={60}
/>
</li>
<li
key="TypeScript"
>
<img
alt="TypeScript"
src="/images/languages/ts.svg"
width={100}
/>
</li>
<li
key="C#"
>
<img
alt="C#"
src="/images/languages/csharp.svg"
width={60}
/>
</li>
<li
key="Python"
>
<img
alt="Python"
src="/images/languages/python.svg"
width={65}
/>
</li>
<li
key="C++"
>
<img
alt="C++"
src="/images/languages/c-c-plus-plus.svg"
width={53}
/>
</li>
<li
key="Go"
>
<img
alt="Go"
src="/images/languages/go.svg"
width={91}
/>
</li>
<li
key="Kotlin"
>
<img
alt="Kotlin"
src="/images/languages/kotlin.svg"
width={42}
/>
</li>
<li
key="Ruby"
>
<img
alt="Ruby"
src="/images/languages/ruby.svg"
width={43}
/>
</li>
<li
key="Swift"
>
<img
alt="Swift"
src="/images/languages/swift.svg"
width={64}
/>
</li>
</ul>
<a
className="bt bt-large bt-nav bt-orange2 display-inline-flex-center"
href="#"
onClick={[Function]}
>
See All Languages
<SCChevronDownIcon
className="little-spacer-left"
/>
</a>
</div>
</div>
</div>
</div>
`;

exports[`should render 7`] = `
<div
className="sc-section sc-columns"
>
<div
className="sc-column sc-column-full"
>
<h3>
Over 3,000 Projects
<br />
Continuously Analyzed
</h3>
<Statistics
statistics={
Array [
Object {
"icon": "rules",
"text": "Static analysis rules checked",
"value": 1234,
},
Object {
"icon": "locs",
"text": "Lines of code analyzed",
"value": 12345,
},
Object {
"icon": "pull-request",
"text": "Pull Requests decorated/week",
"value": undefined,
},
Object {
"icon": "open-source",
"text": "Open-source projects inspected",
"value": 236,
},
]
}
/>
</div>
</div>
`;

exports[`should render 8`] = `
<div
className="sc-section sc-columns"
>
<div
className="sc-column sc-column-full"
>
<h6
className="big-spacer-bottom"
>
Transparency makes sense
<br />
and that’s why the trend is growing.
</h6>
<p>
Check out these open-source projects showing users
<br />
their commitment to quality.
</p>
<FeaturedProjects
projects={
Array [
Object {
"avatarUrl": null,
"bugs": 0,
"codeSmells": 7,
"coverage": 9.7,
"duplications": 56.2,
"gateStatus": "OK",
"key": "sonarsource-jfrog.simple-js-php-project",
"languages": Array [
"js",
"php",
],
"maintainabilityRating": 1,
"name": "Simple JS & PHP project",
"ncloc": 123456,
"organizationKey": "sonarsource-jfrog",
"organizationName": "SonarSource & JFrog",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 654321,
},
]
}
/>
<h6
className="spacer-bottom"
>
Come join the fun, it’s entirely free for open-source projects!
</h6>
<div
className="sc-spacer-bottom"
>
<LoginButtons />
</div>
</div>
</div>
`;

+ 0
- 135
server/sonar-web/src/main/js/apps/about/sonarcloud/components/FeaturedProjects.css Переглянути файл

@@ -1,135 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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.
*/
.sc-featured-projects {
margin-top: 40px;
position: relative;
}

.sc-featured-projects-container {
margin: 0 40px;
overflow: hidden;
padding: 10px 8px 20px;
max-width: 985px;
}

.sc-featured-projects-inner {
display: flex;
order: 2;
position: relative;
left: calc(100% / -3);
transform: translateX(calc(100% / 3));
}

.sc-featured-projects-inner.reversing {
transform: translateX(calc(100% / -3));
}

.sc-featured-projects-inner.ready {
transform: translateX(0);
transition: transform 0.5s cubic-bezier(0.23, 1, 0.32, 1);
}

.sc-project-card-container {
flex: 1 0 calc(100% / 3);
}

.sc-project-card {
width: 255px;
display: inline-block;
margin: 0 10px;
padding: 25px;
border: 1px solid var(--sonarcloudBlack300) !important;
border-radius: 5px;
box-shadow: 0 1px 1px rgba(7, 7, 6, 0.1);
transition: all 0.1s ease-in;
color: inherit;
}

.sc-project-card:hover,
.sc-project-card:focus {
box-shadow: 0 10px 30px rgba(7, 7, 6, 0.2);
transform: translateY(-4px);
color: inherit;
}

.sc-project-card-header {
padding: 0 10px 16px;
}

.sc-project-card-limited {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

.sc-project-card-measures li {
display: flex;
align-items: baseline;
justify-content: space-between;
padding: 6px 0 4px;
border-bottom: 1px solid var(--sonarcloudBlack250);
}

.sc-project-card-measures li:last-of-type {
border: none;
}

.sc-project-card-measures li div {
display: inline-flex;
}

.sc-project-card .sc-mention {
color: var(--sonarcloudBlack500);
}

.sc-project-button {
display: block;
position: absolute;
top: 50%;
margin: 0;
padding: 4px;
border: none;
background: transparent;
color: var(--sonarcloudBlack300);
text-decoration: none;
cursor: pointer;
outline: none;
transition: all 0.2s ease;
}

.sc-project-button img {
opacity: 0.5;
width: 19px;
}

.sc-project-button:hover img {
opacity: 1;
}

.sc-project-button:last-child {
right: 0;
}

.sc-project-button:hover,
.sc-project-button:active,
.sc-project-button:focus {
color: var(--sonarcloudBlack500);
}

+ 0
- 304
server/sonar-web/src/main/js/apps/about/sonarcloud/components/FeaturedProjects.tsx Переглянути файл

@@ -1,304 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 classNames from 'classnames';
import { throttle } from 'lodash';
import * as React from 'react';
import CountUp from 'react-countup';
import DuplicationsRating from 'sonar-ui-common/components/ui/DuplicationsRating';
import Rating from 'sonar-ui-common/components/ui/Rating';
import { formatMeasure } from 'sonar-ui-common/helpers/measures';
import { getBaseUrl, getPathUrlAsString } from 'sonar-ui-common/helpers/urls';
import OrganizationAvatar from '../../../../components/common/OrganizationAvatar';
import CoverageRating from '../../../../components/ui/CoverageRating';
import { getProjectUrl } from '../../../../helpers/urls';
import { getMetricName } from '../../../overview/utils';
import ProjectCardLanguagesContainer from '../../../projects/components/ProjectCardLanguagesContainer';
import { FeaturedProject } from '../utils';
import './FeaturedProjects.css';

interface Props {
projects: FeaturedProject[];
}

interface State {
reversing: boolean;
slides: Array<{
order: number;
project: FeaturedProject;
}>;
sliding: boolean;
viewable: boolean;
}

export default class FeaturedProjects extends React.PureComponent<Props, State> {
container?: HTMLElement | null;
mounted = false;

constructor(props: Props) {
super(props);
this.state = {
reversing: false,
slides: this.orderProjectsFromProps(),
sliding: false,
viewable: false
};
this.handleScroll = throttle(this.handleScroll, 10);
}

componentDidMount() {
this.mounted = true;
document.addEventListener('scroll', this.handleScroll, true);
}

componentDidUpdate(prevProps: Props) {
if (prevProps.projects !== this.props.projects) {
this.setState({ slides: this.orderProjectsFromProps() });
}
}

componentWillUnmount() {
this.mounted = false;
document.removeEventListener('scroll', this.handleScroll, true);
}

handleScroll = () => {
if (this.container) {
const rect = this.container.getBoundingClientRect();
const windowHeight =
window.innerHeight ||
(document.documentElement ? document.documentElement.clientHeight : 0);
if (rect.top <= windowHeight && rect.top + rect.height >= 0) {
this.setState({ viewable: true });
}
}
};

orderProjectsFromProps = () => {
const { projects } = this.props;
if (projects.length === 0) {
return [];
}

// Last element should be put at the begining for proper carousel animation
return [projects.pop(), ...projects].map((project: FeaturedProject, id) => {
return {
order: id,
project
};
});
};

handlePrevClick = () => {
this.setState(({ slides }) => ({
reversing: true,
sliding: true,
slides: slides.map(slide => {
slide.order = slide.order === slides.length - 1 ? 0 : slide.order + 1;
return slide;
})
}));
setTimeout(() => {
if (this.mounted) {
this.setState({ sliding: false });
}
}, 50);
};

handleNextClick = () => {
this.setState(({ slides }) => ({
reversing: false,
sliding: true,
slides: slides.map(slide => {
slide.order = slide.order === 0 ? slides.length - 1 : slide.order - 1;
return slide;
})
}));
setTimeout(() => {
this.setState({ sliding: false });
}, 50);
};

render() {
const { reversing, sliding, viewable } = this.state;
return (
<div
className="sc-featured-projects sc-big-spacer-bottom"
ref={node => (this.container = node)}>
<button className="js-prev sc-project-button" onClick={this.handlePrevClick} type="button">
<img alt="" src={`${getBaseUrl()}/images/sonarcloud/chevron-left.svg`} />
</button>

<div className="sc-featured-projects-container">
<div
className={classNames('sc-featured-projects-inner', {
reversing,
ready: !sliding
})}>
{this.state.slides.map(slide => (
<ProjectCard
key={slide.project.key}
order={slide.order}
project={slide.project}
viewable={viewable}
/>
))}
</div>
</div>

<button className="js-next sc-project-button" onClick={this.handleNextClick} type="button">
<img alt="" src={`${getBaseUrl()}/images/sonarcloud/chevron-right.svg`} />
</button>
</div>
);
}
}

interface ProjectCardProps {
order: number;
project: FeaturedProject;
viewable: boolean;
}

export function ProjectCard({ project, order, viewable }: ProjectCardProps) {
return (
<div className="sc-project-card-container" style={{ order }}>
<a className="sc-project-card" href={getPathUrlAsString(getProjectUrl(project.key))}>
<div className="sc-project-card-header">
<OrganizationAvatar
className="no-border spacer-bottom"
organization={{
name: project.organizationName,
avatar: project.avatarUrl || undefined
}}
/>
<p className="sc-project-card-limited" title={project.organizationName}>
{project.organizationName}
</p>
<h5 className="sc-project-card-limited big-spacer-bottom" title={project.name}>
{project.name}
</h5>
</div>
<ul className="sc-project-card-measures">
<ProjectIssues
metric={project.bugs}
metricKey="bugs"
ratingMetric={project.reliabilityRating}
viewable={viewable}
/>
<ProjectIssues
metric={project.vulnerabilities}
metricKey="vulnerabilities"
ratingMetric={project.securityRating}
viewable={viewable}
/>
<ProjectIssues
metric={project.codeSmells}
metricKey="code_smells"
ratingMetric={project.maintainabilityRating}
viewable={viewable}
/>
<li>
<span>{getMetricName('coverage')}</span>
{project.coverage !== undefined ? (
<div>
{viewable && (
<CountUp
decimal="."
decimals={1}
delay={0}
duration={4}
end={project.coverage}
suffix="%">
{(data: { countUpRef?: React.RefObject<HTMLHeadingElement> }) => (
<h6 className="display-inline-block big-spacer-right" ref={data.countUpRef}>
0
</h6>
)}
</CountUp>
)}
<CoverageRating value={project.coverage} />
</div>
) : (
<span className="huge little-spacer-right">—</span>
)}
</li>
<li>
<span>{getMetricName('duplications')}</span>
<div>
{viewable && (
<CountUp
decimal="."
decimals={1}
delay={0}
duration={4}
end={project.duplications}
suffix="%">
{(data: { countUpRef?: React.RefObject<HTMLHeadingElement> }) => (
<h6 className="display-inline-block big-spacer-right" ref={data.countUpRef}>
0
</h6>
)}
</CountUp>
)}
<DuplicationsRating value={project.duplications} />
</div>
</li>
</ul>
<div className="sc-mention text-left big-spacer-top">
{formatMeasure(project.ncloc, 'SHORT_INT')} lines of code /{' '}
<ProjectCardLanguagesContainer
className="display-inline-block"
distribution={project.languages.join(';')}
/>
</div>
</a>
</div>
);
}

interface ProjectIssues {
metricKey: string;
metric: number;
ratingMetric: number;
viewable: boolean;
}

export function ProjectIssues({ metric, metricKey, ratingMetric, viewable }: ProjectIssues) {
const formattedValue = formatMeasure(metric, 'SHORT_INT');
const value = parseFloat(formattedValue);
const suffix = formattedValue.replace(value.toString(), '');
return (
<li>
<span>{getMetricName(metricKey)}</span>
<div>
{viewable && (
<CountUp delay={0} duration={4} end={value} suffix={suffix}>
{(data: { countUpRef?: React.RefObject<HTMLHeadingElement> }) => (
<h6 className="display-inline-block big-spacer-right" ref={data.countUpRef}>
0
</h6>
)}
</CountUp>
)}
<Rating value={ratingMetric} />
</div>
</li>
);
}

+ 0
- 87
server/sonar-web/src/main/js/apps/about/sonarcloud/components/Footer.css Переглянути файл

@@ -1,87 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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.
*/
.sc-footer {
background-color: var(--sonarcloudBlack800);
color: var(--sonarcloudBlack300);
font-size: 12px;
min-width: var(--minPageWidth);
}

.sc-footer *:focus {
box-shadow: 0 0 0 3px rgba(230, 92, 0, 0.25);
}

.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(--sonarcloudOrange500);
}

.sc-footer-logo {
position: absolute;
top: 30px;
right: 20px;
}

+ 0
- 172
server/sonar-web/src/main/js/apps/about/sonarcloud/components/Footer.tsx Переглянути файл

@@ -1,172 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 'sonar-ui-common/helpers/urls';
import './Footer.css';

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">
<Link className="sc-footer-link" to="/documentation">
Documentation
</Link>
</li>
<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" to="/about/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">
<Link
className="sc-footer-link"
rel="noopener noreferrer"
target="_blank"
to="/terms.pdf">
Terms
</Link>
</li>
<li className="spacer-top">
<Link className="sc-footer-link" to="/about/pricing/">
Pricing
</Link>
</li>
<li className="spacer-top">
<Link className="sc-footer-link" to="/documentation/privacy/">
Privacy
</Link>
</li>
<li className="spacer-top">
<Link className="sc-footer-link" to="/documentation/security/">
Security
</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-2019, 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>
);
}

+ 0
- 85
server/sonar-web/src/main/js/apps/about/sonarcloud/components/Languages.tsx Переглянути файл

@@ -1,85 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import { LANGUAGES } from '../utils';
import SCChevronDownIcon from './SCChevronDownIcon';

interface State {
height?: number;
open: boolean;
}

export class Languages extends React.PureComponent<{}, State> {
container?: HTMLElement | null;
state: State = { open: false };

componentDidUpdate() {
if (this.container && this.container.clientHeight !== this.container.scrollHeight) {
this.setState({ height: this.container.scrollHeight });
}
}

handleOpenClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
event.preventDefault();
event.stopPropagation();
this.setState({ height: this.container ? this.container.clientHeight : undefined, open: true });
};

render() {
const { open } = this.state;
const languages = open ? LANGUAGES : LANGUAGES.slice(0, 10);

return (
<div className="position-relative">
<div className="sc-languages-container clearfix">
<div className="sc-section sc-columns">
<div className="sc-column-full">
<h3 className="sc-big-spacer-bottom">SonarCloud speaks your language</h3>
<ul
className="sc-languages-list"
ref={node => (this.container = node)}
style={{ height: this.state.height }}>
{languages.map(language => (
<li key={language.name}>
<img
alt={language.name}
src={`${getBaseUrl()}/images/languages/${language.file}`}
width={language.width}
/>
</li>
))}
</ul>
{!open && (
<a
className="bt bt-large bt-nav bt-orange2 display-inline-flex-center"
href="#"
onClick={this.handleOpenClick}>
See All Languages
<SCChevronDownIcon className="little-spacer-left" />
</a>
)}
</div>
</div>
</div>
</div>
);
}
}

+ 0
- 48
server/sonar-web/src/main/js/apps/about/sonarcloud/components/LoginButtons.css Переглянути файл

@@ -1,48 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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.
*/
.sc-login-button {
display: inline-block;
background-color: var(--sonarcloudBlack100);
border: 1px solid var(--sonarcloudBlack300) !important;
color: var(--sonarcloudBlack800);
margin: 10px 12px auto auto;
font-size: 18px;
font-weight: 700;
padding: 0 15px;
border-radius: 4px;
height: 44px;
line-height: 44px;
white-space: nowrap;
transition: all 0.2s ease;
box-shadow: 0 1px 2px rgba(7, 7, 6, 0.1);
}

.sc-login-button > img {
height: 25px;
padding-top: 10px;
margin-right: 12px;
margin-bottom: 1px;
}

.sc-login-button:hover {
box-shadow: 0 10px 20px rgba(7, 7, 6, 0.2);
transform: translate(0, -2px);
color: var(--sonarcloudBlack800);
}

+ 0
- 41
server/sonar-web/src/main/js/apps/about/sonarcloud/components/LoginButtons.tsx Переглянути файл

@@ -1,41 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import './LoginButtons.css';

export default function LoginButtons() {
return (
<div>
<a className="sc-login-button" href={`${getBaseUrl()}/sessions/init/github`}>
<img alt="" height="25" src={`${getBaseUrl()}/images/sonarcloud/github.svg`} />
GitHub
</a>
<a className="sc-login-button" href={`${getBaseUrl()}/sessions/init/bitbucket`}>
<img alt="" height="25" src={`${getBaseUrl()}/images/sonarcloud/bitbucket.svg`} />
Bitbucket
</a>
<a className="sc-login-button" href={`${getBaseUrl()}/sessions/init/microsoft`}>
<img alt="" height="25" src={`${getBaseUrl()}/images/sonarcloud/azure.svg`} />
Azure DevOps
</a>
</div>
);
}

+ 0
- 139
server/sonar-web/src/main/js/apps/about/sonarcloud/components/NavBars.css Переглянути файл

@@ -1,139 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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.
*/
.sc-page .navbar {
position: fixed;
background-color: #fff;
width: 100%;
display: block;
transition: top 0.3s;
height: 60px;
line-height: 60px;
z-index: 10;
border-bottom: 1px solid var(--sonarcloudBlack300);
top: -100px;
}

.sc-page .navbar-inner {
position: relative;
}

.top-navbar {
height: 60px;
line-height: 60px;
}

.top-navbar img {
height: 48px;
vertical-align: middle;
margin-top: 12px;
}

.sc-page .navbar img {
height: 40px;
vertical-align: middle;
}

.top-navbar ul,
.sc-page .navbar ul {
float: right;
}

.top-navbar ul {
margin-top: 10px;
}

.top-navbar ul li,
.sc-page .navbar ul li {
display: inline-block;
margin: 0 0 0 30px;
line-height: 30px;
border-color: #fff;
transition: all 0.2s ease;
}

.sc-page .navbar ul li {
line-height: 54px;
}

.top-navbar ul li a,
.sc-page .navbar ul li a {
font-family: var(--sonarcloudFontFamily);
color: var(--sonarcloudBlack800);
font-weight: 700;
display: inline-block;
}

.sc-page .navbar ul li.outline {
line-height: 30px;
}

.top-navbar ul li a {
color: #fff;
}

.top-navbar ul li.outline a,
.sc-page .navbar ul li.outline a {
height: 30px;
border: 1px solid var(--sonarcloudBlack800);
padding: 0 10px;
border-radius: 3px;
transition: all 0.2s ease;
}

.top-navbar ul li.outline a {
border: 1px solid #fff;
}

.top-navbar ul li a.active,
.top-navbar ul li a:hover {
border-bottom: 2px solid #fff;
}

.sc-page .navbar ul li a.active,
.sc-page .navbar ul li a:hover {
border-bottom: 2px solid var(--sonarcloudOrange500);
color: var(--sonarcloudOrange500);
}

.top-navbar ul li.outline a:hover,
.sc-page .navbar ul li.outline a:hover {
border-bottom-width: 1px;
background: var(--sonarcloudOrange500);
color: #fff;
}

.top-navbar ul li.outline:hover a {
background: #fff;
color: var(--sonarcloudOrange500);
}

.sc-page .navbar ul li.outline:hover a {
border-color: var(--sonarcloudOrange500);
}

.sc-page .top-navbar a,
.sc-page .navbar a {
border-bottom: 2px solid rgba(255, 255, 255, 0);
transition: border-color 0.2s ease;
}

.sc-page .navbar-limited > a {
border: none !important;
}

+ 0
- 110
server/sonar-web/src/main/js/apps/about/sonarcloud/components/NavBars.tsx Переглянути файл

@@ -1,110 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { throttle } from 'lodash';
import * as React from 'react';
import NavBar from 'sonar-ui-common/components/ui/NavBar';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import './NavBars.css';

interface Props {
onPricingPage?: boolean;
}

interface State {
top: number;
}

export class FixedNavBar extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = { top: -100 };
this.handleScroll = throttle(this.handleScroll, 10);
}

componentDidMount() {
document.addEventListener('scroll', this.handleScroll, true);
}

componentWillUnmount() {
document.removeEventListener('scroll', this.handleScroll, true);
}

handleScroll = () => {
const scrollTop =
document.body.scrollTop ||
(document.documentElement ? document.documentElement.scrollTop : 0);
if (scrollTop > 100) {
this.setState({ top: 0 });
} else {
this.setState({ top: -100 });
}
};

render() {
return (
<NavBar height={60} top={this.state.top}>
<NavBarLinks onPricingPage={this.props.onPricingPage} />
</NavBar>
);
}
}

interface TopNavBarProps {
onPricingPage?: boolean;
whiteLogo?: boolean;
}

export function TopNavBar({ onPricingPage, whiteLogo }: TopNavBarProps) {
return (
<div className="top-navbar">
<div className="navbar-limited">
<NavBarLinks onPricingPage={onPricingPage} whiteLogo={whiteLogo} />
</div>
</div>
);
}

interface NavBarLinksProps {
onPricingPage?: boolean;
whiteLogo?: boolean;
}

function NavBarLinks({ onPricingPage, whiteLogo }: NavBarLinksProps) {
return (
<>
<a href={`${getBaseUrl()}/`}>
<img
alt="SonarCloud"
src={`${getBaseUrl()}/images/sonarcloud-logo-${whiteLogo ? 'white' : 'black'}.svg`}
/>
</a>
<ul>
<li>
<a className={onPricingPage ? 'active' : ''} href={`${getBaseUrl()}/about/pricing`}>
Pricing
</a>
</li>
<li className="outline">
<a href={`${getBaseUrl()}/sessions/new`}>Log in</a>
</li>
</ul>
</>
);
}

+ 0
- 45
server/sonar-web/src/main/js/apps/about/sonarcloud/components/Pricing.tsx Переглянути файл

@@ -1,45 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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">&nbsp;</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-news-link" to="/about/pricing/">
see prices
</Link>
</div>
</div>
);
}

+ 0
- 32
server/sonar-web/src/main/js/apps/about/sonarcloud/components/SCChevronDownIcon.tsx Переглянути файл

@@ -1,32 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 Icon, { IconProps } from 'sonar-ui-common/components/icons/Icon';

export default function SCChevronDownIcon({ className, fill = 'currentColor', size }: IconProps) {
return (
<Icon className={className} size={size} viewBox="0 0 24 24">
<path
d="M4 9a1 1 0 0 1 .29-.71 1 1 0 0 1 1.42 0l6.29 6.3 6.29-6.3a1.0041 1.0041 0 0 1 1.42 1.42l-7 7a1 1 0 0 1-1.42 0l-7-7A1 1 0 0 1 4 9z"
style={{ fill }}
/>
</Icon>
);
}

+ 0
- 63
server/sonar-web/src/main/js/apps/about/sonarcloud/components/SQPageContainer.tsx Переглянути файл

@@ -1,63 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { connect } from 'react-redux';
import { withRouter, WithRouterProps } from 'react-router';
import { addWhitePageClass, removeWhitePageClass } from 'sonar-ui-common/helpers/pages';
import GlobalContainer from '../../../../app/components/GlobalContainer';
import { getCurrentUser, getMyOrganizations, Store } from '../../../../store/rootReducer';
import Footer from './Footer';

interface StateProps {
currentUser: T.CurrentUser;
userOrganizations?: T.Organization[];
}

interface OwnProps {
children: (props: StateProps) => React.ReactNode;
}

type Props = StateProps & WithRouterProps & OwnProps;

class SQPageContainer extends React.Component<Props> {
componentDidMount() {
addWhitePageClass();
}

componentWillUnmount() {
removeWhitePageClass();
}

render() {
const { children, currentUser, userOrganizations } = this.props;
return (
<GlobalContainer footer={<Footer />} location={this.props.location}>
{children({ currentUser, userOrganizations })}
</GlobalContainer>
);
}
}

const mapStateToProps = (state: Store) => ({
currentUser: getCurrentUser(state),
userOrganizations: getMyOrganizations(state)
});

export default withRouter<OwnProps>(connect(mapStateToProps)(SQPageContainer));

+ 0
- 32
server/sonar-web/src/main/js/apps/about/sonarcloud/components/SQStartUsing.tsx Переглянути файл

@@ -1,32 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 SQStartUsing() {
return (
<div className="sc-child-start-using">
<div className="sc-child-start-using-text">Start using SonarCloud</div>
<Link className="sc-orange-button sc-child-start-using-link" to="/sessions/new">
Sign up now
</Link>
</div>
);
}

+ 0
- 52
server/sonar-web/src/main/js/apps/about/sonarcloud/components/SQTopNav.tsx Переглянути файл

@@ -1,52 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 SQTopNav() {
return (
<ul className="sc-top-nav">
<li className="sc-top-nav-item">
<Link
activeClassName="sc-top-nav-active"
className="sc-top-nav-link"
to="/about/sq/as-a-service">
As a Service
</Link>
</li>
<li className="sc-top-nav-item">
<Link
activeClassName="sc-top-nav-active"
className="sc-top-nav-link"
to="/about/sq/branch-analysis-and-pr-decoration">
Branch analysis & PR decoration
</Link>
</li>
<li className="sc-top-nav-item">
<Link
activeClassName="sc-top-nav-active"
className="sc-top-nav-link"
to="/about/sq/sonarlint-integration">
SonarLint integration
</Link>
</li>
</ul>
);
}

+ 0
- 41
server/sonar-web/src/main/js/apps/about/sonarcloud/components/StartUsing.tsx Переглянути файл

@@ -1,41 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 'sonar-ui-common/components/icons/ChevronRightIcon';

export default function StartUsing() {
return (
<div className="sc-narrow-container text-center">
<Link className="sc-orange-button 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>
);
}

+ 0
- 46
server/sonar-web/src/main/js/apps/about/sonarcloud/components/Statistics.css Переглянути файл

@@ -1,46 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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.
*/
.sc-stats {
display: flex;
justify-content: space-around;
}

.sc-stat-card {
flex: 0 0 244px;
display: flex;
align-items: center;
border: 1px solid var(--sonarcloudBlack300);
border-radius: 3px;
}

.sc-stat-icon {
background-color: var(--sonarcloudBlack200);
padding: 32px 20px;
}

.sc-stat-content {
padding: 0 20px;
text-align: left;
}

.sc-page .sc-stat-content span {
font-family: var(--sonarcloudFontFamily);
font-weight: 500;
}

+ 0
- 113
server/sonar-web/src/main/js/apps/about/sonarcloud/components/Statistics.tsx Переглянути файл

@@ -1,113 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { throttle } from 'lodash';
import * as React from 'react';
import CountUp from 'react-countup';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { formatMeasure } from 'sonar-ui-common/helpers/measures';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
import './Statistics.css';

interface Statistic {
icon: string;
text: string;
value: number;
}

interface Props {
statistics: Statistic[];
}

export default function Statistics({ statistics }: Props) {
return (
<div className="sc-stats">
{statistics.map(stat => (
<StatisticCard key={stat.icon} statistic={stat} />
))}
</div>
);
}

interface StatisticCardProps {
statistic: Statistic;
}

interface StatisticCardState {
viewable: boolean;
}

export class StatisticCard extends React.PureComponent<StatisticCardProps, StatisticCardState> {
container?: HTMLElement | null;

constructor(props: StatisticCardProps) {
super(props);
this.state = { viewable: false };
this.handleScroll = throttle(this.handleScroll, 10);
}

componentDidMount() {
document.addEventListener('scroll', this.handleScroll, true);
}

componentWillUnmount() {
document.removeEventListener('scroll', this.handleScroll, true);
}

handleScroll = () => {
if (this.container) {
const rect = this.container.getBoundingClientRect();
const windowHeight =
window.innerHeight ||
(document.documentElement ? document.documentElement.clientHeight : 0);
if (rect.top <= windowHeight && rect.top + rect.height >= 0) {
this.setState({ viewable: true });
}
}
};

render() {
const { statistic } = this.props;
const formattedString = formatMeasure(statistic.value, 'SHORT_INT', {
roundingFunc: Math.floor
});
const value = parseFloat(formattedString);
let suffix = formattedString.replace(value.toString(), '');
if (suffix === translate('short_number_suffix.g')) {
suffix = ' ' + translate('billion');
}
return (
<div className="sc-stat-card sc-big-spacer-top" ref={node => (this.container = node)}>
<div className="sc-stat-icon">
<img alt="" height={28} src={`${getBaseUrl()}/images/sonarcloud/${statistic.icon}.svg`} />
</div>
<div className="sc-stat-content">
{this.state.viewable && (
<CountUp delay={0} duration={4} end={value} suffix={suffix}>
{(data: { countUpRef?: React.RefObject<HTMLHeadingElement> }) => (
<h5 ref={data.countUpRef}>0</h5>
)}
</CountUp>
)}
<span>{statistic.text}</span>
</div>
</div>
);
}
}

+ 0
- 26
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__mocks__/react-countup.tsx Переглянути файл

@@ -1,26 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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';

export default class CountUp extends React.Component<any> {
render() {
return <div />;
}
}

+ 0
- 162
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/FeaturedProjects-test.tsx Переглянути файл

@@ -1,162 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
import * as React from 'react';
import { click } from 'sonar-ui-common/helpers/testUtils';
import FeaturedProjects, { ProjectCard, ProjectIssues } from '../FeaturedProjects';

const PROJECTS = [
{
key: 'sonarsource-jfrog.simple-js-php-project',
avatarUrl: null,
organizationKey: 'sonarsource-jfrog',
organizationName: 'SonarSource & JFrog',
name: 'Simple JS & PHP project',
bugs: 0,
codeSmells: 7,
coverage: 9.7,
duplications: 56.2,
gateStatus: 'OK',
languages: ['js', 'php'],
maintainabilityRating: 1,
ncloc: 324,
reliabilityRating: 1,
securityRating: 1,
vulnerabilities: 0
},
{
key: 'example-js',
avatarUrl: null,
organizationKey: 'autoscan',
organizationName: 'AutoScan',
name: 'example-js',
bugs: 13,
codeSmells: 5,
coverage: 0,
duplications: 0,
gateStatus: 'OK',
languages: ['go', 'js', 'php', 'py'],
maintainabilityRating: 1,
ncloc: 80,
reliabilityRating: 1,
securityRating: 1,
vulnerabilities: 0
},
{
key: 'example-js-2',
avatarUrl: null,
organizationKey: 'autoscan',
organizationName: 'AutoScan',
name: 'example-js',
bugs: 13,
codeSmells: 5,
coverage: 0,
duplications: 0,
gateStatus: 'OK',
languages: ['go', 'js', 'php', 'py'],
maintainabilityRating: 1,
ncloc: 80,
reliabilityRating: 1,
securityRating: 1,
vulnerabilities: 0
},
{
key: 'example-js-3',
avatarUrl: null,
organizationKey: 'autoscan',
organizationName: 'AutoScan',
name: 'example-js',
bugs: 13,
codeSmells: 5,
coverage: 0,
duplications: 0,
gateStatus: 'OK',
languages: ['go', 'js', 'php', 'py'],
maintainabilityRating: 1,
ncloc: 80,
reliabilityRating: 1,
securityRating: 1,
vulnerabilities: 0
},
{
key: 'example-js-4',
avatarUrl: null,
organizationKey: 'autoscan',
organizationName: 'AutoScan',
name: 'example-js',
bugs: 13,
codeSmells: 5,
coverage: 0,
duplications: 0,
gateStatus: 'OK',
languages: ['go', 'js', 'php', 'py'],
maintainabilityRating: 1,
ncloc: 80,
reliabilityRating: 1,
securityRating: 1,
vulnerabilities: 0
}
];

it('should render ProjectIssues correctly', () => {
expect(
shallow(<ProjectIssues metric={5} metricKey="foo" ratingMetric={20} viewable={true} />)
).toMatchSnapshot();
expect(
shallow(<ProjectIssues metric={15000} metricKey="foo" ratingMetric={20} viewable={true} />)
).toMatchSnapshot();
});

it('should render ProjectCard correctly', () => {
expect(
shallow(<ProjectCard order={1} project={PROJECTS[0]} viewable={true} />)
).toMatchSnapshot();
});

it('should render ProjectCard correctly when there is no coverage', () => {
expect(
shallow(
<ProjectCard order={1} project={{ ...PROJECTS[0], coverage: undefined }} viewable={true} />
)
.find('li')
.first()
).toMatchSnapshot();
});

it('should render correctly', () => {
const wrapper = shallow(<FeaturedProjects projects={PROJECTS} />);
expect(wrapper).toMatchSnapshot();
});

it('should cycle through projects', () => {
const wrapper = shallow<FeaturedProjects>(<FeaturedProjects projects={PROJECTS} />);
expect(wrapper.state().slides.map((slide: any) => slide.order)).toEqual([0, 1, 2, 3]);

click(wrapper.find('.js-next'));
expect(wrapper.state().slides.map((slide: any) => slide.order)).toEqual([3, 0, 1, 2]);

click(wrapper.find('.js-next'));
click(wrapper.find('.js-next'));
expect(wrapper.state().slides.map((slide: any) => slide.order)).toEqual([1, 2, 3, 0]);

click(wrapper.find('.js-prev'));
click(wrapper.find('.js-prev'));
expect(wrapper.state().slides.map((slide: any) => slide.order)).toEqual([3, 0, 1, 2]);
});

+ 0
- 26
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/Footer-test.tsx Переглянути файл

@@ -1,26 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
import * as React from 'react';
import Footer from '../Footer';

it('should render', () => {
expect(shallow(<Footer />)).toBeDefined();
});

+ 0
- 26
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/LoginButtons-test.tsx Переглянути файл

@@ -1,26 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
import * as React from 'react';
import LoginButtons from '../LoginButtons';

it('should render', () => {
expect(shallow(<LoginButtons />)).toMatchSnapshot();
});

+ 0
- 57
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/Statistics-test.tsx Переглянути файл

@@ -1,57 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
import Statistics, { StatisticCard } from '../Statistics';

const STATISTICS = { icon: 'stat-icon', text: 'my stat', value: 26666 };

it('should render', () => {
expect(shallow(<Statistics statistics={[STATISTICS]} />)).toMatchSnapshot();
});

it('should render StatisticCard', () => {
expect(shallowRender()).toMatchSnapshot();
});

it('should render big numbers correctly', () => {
function checkCountUp(wrapper: ShallowWrapper, end: number, suffix: string) {
expect(wrapper.find('CountUp').prop('end')).toBe(end);
expect(wrapper.find('CountUp').prop('suffix')).toBe(suffix);
}

checkCountUp(
shallowRender({ statistic: { ...STATISTICS, value: 999003632 } }),
999,
'short_number_suffix.m'
);
checkCountUp(
shallowRender({ statistic: { ...STATISTICS, value: 999861538 } }),
999,
'short_number_suffix.m'
);
checkCountUp(shallowRender({ statistic: { ...STATISTICS, value: 1100021731 } }), 1.1, ' billion');
});

function shallowRender(props: Partial<StatisticCard['props']> = {}) {
const wrapper = shallow(<StatisticCard statistic={STATISTICS} {...props} />);
wrapper.setState({ viewable: true });
return wrapper;
}

+ 0
- 354
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/__snapshots__/FeaturedProjects-test.tsx.snap Переглянути файл

@@ -1,354 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render ProjectCard correctly 1`] = `
<div
className="sc-project-card-container"
style={
Object {
"order": 1,
}
}
>
<a
className="sc-project-card"
href="/dashboard?id=sonarsource-jfrog.simple-js-php-project"
>
<div
className="sc-project-card-header"
>
<OrganizationAvatar
className="no-border spacer-bottom"
organization={
Object {
"avatar": undefined,
"name": "SonarSource & JFrog",
}
}
/>
<p
className="sc-project-card-limited"
title="SonarSource & JFrog"
>
SonarSource & JFrog
</p>
<h5
className="sc-project-card-limited big-spacer-bottom"
title="Simple JS & PHP project"
>
Simple JS & PHP project
</h5>
</div>
<ul
className="sc-project-card-measures"
>
<ProjectIssues
metric={0}
metricKey="bugs"
ratingMetric={1}
viewable={true}
/>
<ProjectIssues
metric={0}
metricKey="vulnerabilities"
ratingMetric={1}
viewable={true}
/>
<ProjectIssues
metric={7}
metricKey="code_smells"
ratingMetric={1}
viewable={true}
/>
<li>
<span>
overview.metric.coverage
</span>
<div>
<CountUp
decimal="."
decimals={1}
delay={0}
duration={4}
end={9.7}
suffix="%"
>
<Component />
</CountUp>
<CoverageRating
value={9.7}
/>
</div>
</li>
<li>
<span>
overview.metric.duplications
</span>
<div>
<CountUp
decimal="."
decimals={1}
delay={0}
duration={4}
end={56.2}
suffix="%"
>
<Component />
</CountUp>
<DuplicationsRating
value={56.2}
/>
</div>
</li>
</ul>
<div
className="sc-mention text-left big-spacer-top"
>
324
lines of code /
<Connect(ProjectCardLanguages)
className="display-inline-block"
distribution="js;php"
/>
</div>
</a>
</div>
`;

exports[`should render ProjectCard correctly when there is no coverage 1`] = `
<li>
<span>
overview.metric.coverage
</span>
<span
className="huge little-spacer-right"
>
</span>
</li>
`;

exports[`should render ProjectIssues correctly 1`] = `
<li>
<span>
overview.metric.foo
</span>
<div>
<CountUp
delay={0}
duration={4}
end={5}
suffix=""
>
<Component />
</CountUp>
<Rating
value={20}
/>
</div>
</li>
`;

exports[`should render ProjectIssues correctly 2`] = `
<li>
<span>
overview.metric.foo
</span>
<div>
<CountUp
delay={0}
duration={4}
end={15}
suffix="short_number_suffix.k"
>
<Component />
</CountUp>
<Rating
value={20}
/>
</div>
</li>
`;

exports[`should render correctly 1`] = `
<div
className="sc-featured-projects sc-big-spacer-bottom"
>
<button
className="js-prev sc-project-button"
onClick={[Function]}
type="button"
>
<img
alt=""
src="/images/sonarcloud/chevron-left.svg"
/>
</button>
<div
className="sc-featured-projects-container"
>
<div
className="sc-featured-projects-inner ready"
>
<ProjectCard
key="example-js-4"
order={0}
project={
Object {
"avatarUrl": null,
"bugs": 13,
"codeSmells": 5,
"coverage": 0,
"duplications": 0,
"gateStatus": "OK",
"key": "example-js-4",
"languages": Array [
"go",
"js",
"php",
"py",
],
"maintainabilityRating": 1,
"name": "example-js",
"ncloc": 80,
"organizationKey": "autoscan",
"organizationName": "AutoScan",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 0,
}
}
viewable={false}
/>
<ProjectCard
key="sonarsource-jfrog.simple-js-php-project"
order={1}
project={
Object {
"avatarUrl": null,
"bugs": 0,
"codeSmells": 7,
"coverage": 9.7,
"duplications": 56.2,
"gateStatus": "OK",
"key": "sonarsource-jfrog.simple-js-php-project",
"languages": Array [
"js",
"php",
],
"maintainabilityRating": 1,
"name": "Simple JS & PHP project",
"ncloc": 324,
"organizationKey": "sonarsource-jfrog",
"organizationName": "SonarSource & JFrog",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 0,
}
}
viewable={false}
/>
<ProjectCard
key="example-js"
order={2}
project={
Object {
"avatarUrl": null,
"bugs": 13,
"codeSmells": 5,
"coverage": 0,
"duplications": 0,
"gateStatus": "OK",
"key": "example-js",
"languages": Array [
"go",
"js",
"php",
"py",
],
"maintainabilityRating": 1,
"name": "example-js",
"ncloc": 80,
"organizationKey": "autoscan",
"organizationName": "AutoScan",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 0,
}
}
viewable={false}
/>
<ProjectCard
key="example-js-2"
order={3}
project={
Object {
"avatarUrl": null,
"bugs": 13,
"codeSmells": 5,
"coverage": 0,
"duplications": 0,
"gateStatus": "OK",
"key": "example-js-2",
"languages": Array [
"go",
"js",
"php",
"py",
],
"maintainabilityRating": 1,
"name": "example-js",
"ncloc": 80,
"organizationKey": "autoscan",
"organizationName": "AutoScan",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 0,
}
}
viewable={false}
/>
<ProjectCard
key="example-js-3"
order={4}
project={
Object {
"avatarUrl": null,
"bugs": 13,
"codeSmells": 5,
"coverage": 0,
"duplications": 0,
"gateStatus": "OK",
"key": "example-js-3",
"languages": Array [
"go",
"js",
"php",
"py",
],
"maintainabilityRating": 1,
"name": "example-js",
"ncloc": 80,
"organizationKey": "autoscan",
"organizationName": "AutoScan",
"reliabilityRating": 1,
"securityRating": 1,
"vulnerabilities": 0,
}
}
viewable={false}
/>
</div>
</div>
<button
className="js-next sc-project-button"
onClick={[Function]}
type="button"
>
<img
alt=""
src="/images/sonarcloud/chevron-right.svg"
/>
</button>
</div>
`;

+ 0
- 39
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/__snapshots__/LoginButtons-test.tsx.snap Переглянути файл

@@ -1,39 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render 1`] = `
<div>
<a
className="sc-login-button"
href="/sessions/init/github"
>
<img
alt=""
height="25"
src="/images/sonarcloud/github.svg"
/>
GitHub
</a>
<a
className="sc-login-button"
href="/sessions/init/bitbucket"
>
<img
alt=""
height="25"
src="/images/sonarcloud/bitbucket.svg"
/>
Bitbucket
</a>
<a
className="sc-login-button"
href="/sessions/init/microsoft"
>
<img
alt=""
height="25"
src="/images/sonarcloud/azure.svg"
/>
Azure DevOps
</a>
</div>
`;

+ 0
- 49
server/sonar-web/src/main/js/apps/about/sonarcloud/components/__tests__/__snapshots__/Statistics-test.tsx.snap Переглянути файл

@@ -1,49 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should render 1`] = `
<div
className="sc-stats"
>
<StatisticCard
key="stat-icon"
statistic={
Object {
"icon": "stat-icon",
"text": "my stat",
"value": 26666,
}
}
/>
</div>
`;

exports[`should render StatisticCard 1`] = `
<div
className="sc-stat-card sc-big-spacer-top"
>
<div
className="sc-stat-icon"
>
<img
alt=""
height={28}
src="/images/sonarcloud/stat-icon.svg"
/>
</div>
<div
className="sc-stat-content"
>
<CountUp
delay={0}
duration={4}
end={26}
suffix="short_number_suffix.k"
>
<Component />
</CountUp>
<span>
my stat
</span>
</div>
</div>
`;

+ 0
- 502
server/sonar-web/src/main/js/apps/about/sonarcloud/new_style.css Переглянути файл

@@ -1,502 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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,500,700,900');

.sc-page,
.sc-page span,
.sc-page li,
.sc-page p {
font-family: var(--baseFontFamily);
font-size: 15px;
}

.sc-page h1,
.sc-page h2,
.sc-page h3,
.sc-page h4,
.sc-page h5,
.sc-page h6 {
font-family: var(--sonarcloudFontFamily);
color: var(--sonarcloudBlack800);
}

.sc-page h1,
.sc-page h2,
.sc-page h3,
.sc-page h4,
.sc-page h5 {
font-weight: 700;
}

.sc-page h1 {
line-height: 62px;
font-size: 60px;
font-weight: 900;
}

.sc-page h2 {
line-height: 50px;
font-size: 44px;
}

.sc-page h3 {
line-height: 42px;
font-size: 36px;
}

.sc-page h4 {
line-height: 38px;
font-size: 32px;
}

.sc-page h5 {
line-height: 32px;
font-size: 26px;
}

.sc-page h6 {
line-height: 26px;
font-size: 21px;
}

.sc-page p {
line-height: 21px;
}

.sc-page a {
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}

.sc-page a:hover {
border-bottom: 1px solid var(--sonarcloudBlack100);
}

.sc-section {
position: relative;
max-width: 1040px;
padding: 0px 20px;
margin-left: auto;
margin-right: auto;
overflow: hidden;
}

.sc-mention,
.sc-mention span {
font-size: 12px;
font-style: italic;
}

.sc-light-weight {
font-weight: 300 !important;
}

.sc-regular-weight {
font-weight: 400 !important;
}

.sc-medium-weight {
font-weight: 500 !important;
}

.sc-bold-weight {
font-weight: 700 !important;
}

.sc-columns {
display: flex;
justify-content: space-around;
margin: 0 auto 80px;
}

.sc-column-half {
width: 50%;
}

.sc-column-full {
flex-grow: 1;
text-align: center;
}

.sc-column-small {
display: flex;
flex-direction: column;
justify-content: center;
max-width: 38%;
}

.sc-column-medium {
display: flex;
flex-direction: column;
justify-content: top;
max-width: 44%;
}

.sc-column-big {
max-width: 52%;
}

.sc-spacer-bottom {
margin-bottom: 20px;
}

.sc-big-spacer-top {
margin-top: 50px;
}

.sc-big-spacer-bottom {
margin-bottom: 50px;
}

.sc-title-orange {
color: var(--sonarcloudOrange500) !important;
}

.sc-separator {
margin: 20px 0;
width: 42px;
border-top: 1px solid var(--sonarcloudBlack300);
}

.sc-rounded-img {
border-radius: 3px;
box-shadow: 0 3px 40px rgba(0, 0, 0, 0.05);
}

.sc-header-background {
position: absolute;
width: 100%;
min-width: var(--minPageWidth);
z-index: 0;
}

.sc-functionality-background {
position: relative;
width: 100%;
min-width: var(--minPageWidth);
margin-top: -150px;
z-index: 0;
}

.sc-functionality-background-bottom {
margin-top: 0;
}

.sc-background-start {
position: absolute;
background-color: #fdc300;
height: 5px;
width: 50%;
left: 0;
z-index: 0;
}

.sc-background-end {
position: absolute;
background-color: var(--sonarcloudOrange500);
height: 5px;
width: 50%;
right: 0;
z-index: 0;
}

.sc-background-center {
display: flex;
justify-content: center;
overflow: hidden;
}

.sc-background-center img {
flex-grow: 0;
flex-shrink: 0;
z-index: 10;
}

.sc-with-icon,
.sc-with-inline-icon {
display: inline-flex;
align-items: center;
white-space: nowrap;
}

.sc-with-icon img {
height: 16px;
}

.sc-with-inline-icon img {
max-height: 21px;
padding: 0 6px;
}

.sc-functionality-container {
background-color: var(--sonarcloudBlack200);
}

.sc-functionality-container .sc-columns:last-of-type {
margin-bottom: 20px;
}

.sc-languages-container {
padding: 60px 0 0;
background-color: var(--sonarcloudBlack100);
margin-bottom: 90px;
box-sizing: border-box;
}

.sc-languages-container::after {
content: '';
display: block;
margin: 0 auto;
height: 1px;
background-color: var(--sonarcloudBlack300);
width: 100px;
}

.sc-languages-container .sc-section {
margin-bottom: 60px;
}

.sc-languages-list {
display: flex;
flex-wrap: wrap;
width: 800px;
margin: auto;
transition: height 0.3s ease;
}

.sc-languages-list > li {
display: inline-block;
text-align: center;
margin-bottom: 45px;
line-height: 60px;
width: 160px;
}

.sc-languages-list > li img {
vertical-align: middle;
}

.sc-languages-container a {
color: var(--sonarcloudBlack700);
border-bottom-color: var(--sonarcloudBlack300);
}

.sc-languages-container a:hover {
color: var(--sonarcloudBlack900);
border-bottom-color: var(--sonarcloudBlack900);
}

.sc-languages-container a.show-more {
display: inline-block;
font-weight: 700;
font-family: var(--sonarcloudFontFamily);
line-height: 33px;
font-size: 36px;
border: none;
border-radius: 50%;
height: 50px;
width: 50px;
}

.sc-languages-container a.show-more:hover {
background: var(--sonarcloudBlack700);
color: var(--sonarcloudBlack100);
}

.sc-page .white {
color: var(--sonarcloudBlack100) !important;
}

.sc-page h4 span {
font-family: var(--sonarcloudFontFamily);
font-size: 32px;
}

.sc-pricing-free {
font-family: var(--sonarcloudFontFamily);
box-sizing: border-box;
position: relative;
background: white;
border-radius: 6px;
box-shadow: rgba(0, 0, 0, 0.16) 0 10px 40px;
margin: 40px;
padding: 40px 50px;
width: 880px;
}

.sc-pricing-free ul {
width: 530px;
}

.sc-pricing-free ul li {
font-family: var(--sonarcloudFontFamily);
background: url(/images/sonarcloud/check.svg) no-repeat 0 19px;
background-size: 18px;
font-size: 21px;
line-height: 30px;
padding: 10px 10px 10px 32px;
}

.sc-pricing-privacy ul li,
.sc-pricing-privacy em {
color: var(--sonarcloudBlack100);
}

.sc-pricing-free ul li em {
font-weight: 700;
font-style: normal;
}

.sc-pricing-privacy {
box-sizing: border-box;
position: absolute;
border-radius: 7px;
background: linear-gradient(214deg, var(--sonarcloudBlack700) 0%, var(--sonarcloudBlack800) 100%);
color: var(--sonarcloudBlack100);
width: 350px;
right: -70px;
top: -20px;
padding: 60px 40px 40px;
}

.sc-pricing-privacy ul {
width: 100%;
}

.sc-pricing-privacy a {
color: var(--sonarcloudBlack100);
}

.sc-pricing-privacy .starts-at {
font-family: var(--sonarcloudFontFamily);
font-size: 26px;
font-weight: 700;
line-height: 40px;
}

a.sc-orange-button {
display: inline-block;
background-color: var(--sonarcloudOrange500);
color: var(--sonarcloudBlack100);
font-size: 18px;
font-weight: 700;
padding: 0 15px;
border-radius: 4px;
height: 44px;
line-height: 44px;
box-shadow: none;
border-bottom: none !important;
}

a.sc-orange-button:hover {
color: var(--sonarcloudBlack100);
background-color: var(--sonarcloudOrange700);
}

.pricing-section .faq-title {
font-family: var(--sonarcloudFontFamily);
font-size: 21px;
padding-bottom: 10px;
}

.pricing-section p {
font-size: 15px;
margin-bottom: 35px;
}

.pricing-section p a {
color: var(--sonarcloudOrange500);
border-bottom: 1px solid rgba(253, 106, 0, 0.3);
}

.pricing-section p a:hover {
color: var(--sonarcloudOrange700);
border-bottom: 1px solid var(--sonarcloudOrange700);
}

table.loc-price th {
padding: 0 30px 20px 0;
font-size: 15px;
font-weight: 700;
}

table.loc-price td {
line-height: 30px;
border-bottom: 1px solid var(--sonarcloudBlack300);
}

table.loc-price tr td:first-child {
font-weight: 700;
}

.sc-page .bt {
display: inline-block;
border-radius: 3px;
font-weight: 700;
cursor: pointer;
white-space: nowrap;
transition: all 0.2s ease;
margin-right: 4px;
}

.sc-page .bt-nav {
color: var(--sonarcloudBlack500);
border: none;
background: transparent;
padding: 5px 8px;
}

.sc-page .bt-nav:hover {
color: var(--sonarcloudBlack600);
}

.sc-page .bt-large {
height: 48px;
padding: 0 16px;
font-size: 18px;
}

.sc-page .bt-nav.bt-large {
height: 24px;
padding: 8px 8px;
}

.sc-page .bt-orange2 {
border: 1px solid var(--sonarcloudOrange500);
background-color: transparent;
color: var(--sonarcloudOrange500);
}

.sc-page .bt-orange2:hover,
.sc-page .bt-orange2:focus {
border: 1px solid var(--sonarcloudOrange700);
background-color: var(--sonarcloudOrange700);
}

.sc-page .bt-nav.bt-orange2 {
border: none;
color: var(--sonarcloudOrange500);
}

.sc-page .bt-nav.bt-orange2:hover,
.sc-page .bt-nav.bt-orange2:focus {
border: none;
background-color: transparent;
color: var(--sonarcloudOrange700);
}

+ 0
- 658
server/sonar-web/src/main/js/apps/about/sonarcloud/style.css Переглянути файл

@@ -1,658 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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,500,700');

.sc-page {
font-family: var(--sonarcloudFontFamily);
}

.sc-page p {
font-family: var(--systemFontFamily);
}

.sc-page *:focus {
box-shadow: 0 0 0 3px rgba(230, 92, 0, 0.25);
}

.sc-black-button,
.sc-orange-button {
display: inline-flex;
align-items: center;
height: 44px;
padding: 0 15px;
line-height: 44px;
border: none;
border-radius: 4px;
color: #fff;
font-size: 18px;
font-weight: 500;
}

.sc-black-button {
background-color: var(--sonarcloudBlack800);
}

.sc-black-button:hover,
.sc-black-button:focus {
color: #fff;
background-color: var(--sonarcloudBlack900);
}

.sc-orange-button {
background-color: var(--sonarcloudOrange500);
}

.sc-orange-button:hover,
.sc-orange-button:focus {
background-color: var(--sonarcloudOrange700);
color: #fff;
}

.sc-page-title {
line-height: 56px;
margin-top: 40px;
margin-bottom: 20px;
font-size: 50px;
font-weight: 700;
text-align: center;
}

.sc-page-subtitle {
line-height: 32px;
margin-bottom: 50px;
font-size: 22px;
font-weight: 300;
text-align: center;
}

.sc-features-list {
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: 40px;
}

.sc-feature-title {
line-height: 28px;
margin-bottom: 13px;
font-size: 21px;
font-weight: 400;
}

.sc-feature-description {
flex: 1 1 auto;
line-height: 22px;
font-size: 15px;
}

.sc-feature-description + .sc-feature-description {
margin-top: 10px;
}

.sc-feature-link {
margin-top: 16px;
color: var(--sonarcloudOrange500) !important;
font-size: 16px;
font-weight: 400;
}

.sc-feature-link:hover,
.sc-feature-link:focus {
color: var(--sonarcloudOrange700) !important;
}

.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: 6px;
box-sizing: border-box;
line-height: 20px;
font-size: 16px;
}

.sc-pricing-title {
line-height: 34px;
margin-bottom: 20px;
color: var(--sonarcloudOrange500);
font-size: 24px;
font-weight: 400;
}

.sc-pricing-price {
line-height: 72px;
color: var(--sonarcloudBlack800);
font-size: 65px;
font-weight: 700;
}

.sc-pricing-small {
font-size: 14px;
}

.sc-arrow-link {
position: relative;
border: none;
color: #444;
}

.sc-arrow-link:after {
content: '\2192';
position: absolute;
top: 0;
left: calc(100% + 5px);
transition: left 0.3s ease;
}

.sc-arrow-link:hover {
color: var(--baseFontColor);
}

.sc-arrow-link:focus {
color: var(--sonarcloudOrange500);
}

.sc-arrow-link:hover::after {
left: calc(100% + 10px);
}

.sc-start {
display: inline-flex;
align-items: center;
font-size: 16px;
font-weight: 700;
}

.sc-start:hover,
.sc-start:focus {
background-color: var(--sonarcloudOrange700);
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(--sonarcloudOrange500);
box-sizing: border-box;
color: var(--sonarcloudOrange500);
font-size: 16px;
font-weight: 700;
transition: box-shadow 0.3s ease;
}

.sc-browse:hover,
.sc-browse:focus {
background-color: var(--sonarcloudOrange500);
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);
font-size: 12px;
}

.sc-news-link:hover,
.sc-news-link:focus {
border-bottom-color: var(--sonarcloudOrange500);
color: var(--sonarcloudOrange500);
}

.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: 540px;
}

.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(--sonarcloudOrange500);
}

.sc-sq-jumbotron-login {
line-height: 25px;
font-size: 18px;
}

.sc-sq-header2 {
margin: 80px 0 40px;
line-height: 45px;
font-size: 32px;
font-weight: 300;
text-align: center;
}

.sc-languages {
margin: 60px 0;
text-align: center;
}

.sc-languages-list {
display: flex;
justify-content: center;
margin-top: 20px;
align-items: center;
}

.sc-languages-list > li {
text-align: center;
margin: 5px 8px;
width: 100px;
}

.sc-integrations {
position: relative;
background-color: var(--sonarcloudBlack200);
margin-left: -20px;
margin-right: -20px;
margin-bottom: -10px;
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: 200px;
}

.sc-integrations-list > li + li {
border-left: 1px solid var(--sonarcloudBorderGray);
}

.sc-bottom-note {
margin: 36px 0 16px;
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(--sonarcloudOrange500);
color: var(--sonarcloudOrange500);
}

.sc-sq-page {
background: url(/images/sonarcloud/sq-background.svg) no-repeat top center;
background-size: auto 200vh;
}

.sc-top-nav {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 30px;
}

.sc-top-nav-item + .sc-top-nav-item {
margin-left: 13px;
border-left: 1px solid var(--sonarcloudBlack300);
padding-left: 13px;
}

.sc-top-nav-link {
border-bottom-color: var(--sonarcloudBlack300);
color: var(--baseFontColor);
font-weight: 300;
}

a.sc-top-nav-link:hover,
a.sc-top-nav-link:focus {
border-bottom-color: var(--sonarcloudOrange500);
color: var(--sonarcloudOrange500);
}

.sc-top-nav-active {
border: none;
font-weight: 500;
}

.sc-child-header {
margin-bottom: 50px;
text-align: center;
}

.sc-child-title {
margin: 20px 0;
line-height: 45px;
font-size: 44px;
font-weight: 700;
}

.sc-child-lead {
margin: 20px 0 35px;
line-height: 30px;
font-size: 21px;
font-weight: 300;
font-family: var(--sonarcloudFontFamily);
}

.sc-child-lead-link {
border-bottom-color: rgba(255, 102, 0, 0.2);
color: var(--sonarcloudOrange500);
}

.sc-child-lead-link:hover,
.sc-child-lead-link:focus {
border-bottom-color: var(--sonarcloudOrange700);
color: var(--sonarcloudOrange700);
}

.sc-child-feature {
width: calc(50% - 40px);
}

.sc-child-start-using {
display: flex;
align-items: center;
justify-content: space-between;
width: 600px;
margin: 20px auto;
padding: 30px;
border: 1px solid var(--sonarcloudBorderGray);
border-radius: 5px;
box-shadow: 0 3px 3px 0 rgba(7, 7, 6, 0.05);
}

.sc-child-start-using-text {
font-size: 21px;
font-weight: 500;
}

.sc-child-start-using-link {
padding-right: 0;
}

.sc-child-start-using-link::after {
content: '→';
padding: 0 16px;
font-size: 16px;
font-weight: 300;
transition: padding 0.1s ease;
}

.sc-child-start-using-link:hover::after,
.sc-child-start-using-link:focus::after {
padding-left: 22px;
padding-right: 10px;
}

.sc-branch-features-list {
flex-direction: column;
}

.sc-branch-feature {
width: auto;
margin: 0;
padding: 20px 0 40px;
flex-direction: row;
align-items: center;
justify-content: space-between;
}

.sc-branch-feature + .sc-branch-feature {
border-top: 1px solid var(--sonarcloudBorderGray);
}

.sc-branch-feature-left {
margin-left: 60px;
}

.sc-branch-feature-right {
margin-right: 60px;
}

.sc-branch-bottom {
padding: 20px 0;
font-size: 21px;
font-weight: 500;
text-align: center;
}

.sc-vsts-start-wrapper {
margin-top: 20px;
margin-bottom: 50px;
text-align: center;
}

.sc-vsts-start {
display: inline-flex;
border: 1px solid var(--sonarcloudBorderGray);
border-radius: 5px;
box-shadow: 0 3px 3px 0 rgba(7, 7, 6, 0.05);
}

.sc-vsts-start-box {
display: flex;
flex-direction: column;
align-items: center;
width: 210px;
padding: 30px;
}

.sc-vsts-start-box + .sc-vsts-start-box {
border-left: 1px solid var(--sonarcloudBorderGray);
}

.sc-vsts-start-title {
margin: 16px 0 24px;
font-size: 21px;
font-weight: 300;
}

.sc-contact-page label {
display: block;
max-width: 100%;
margin-bottom: 5px;
font-size: 14px;
font-weight: 700;
}

.sc-contact-page input,
.sc-contact-page textarea {
display: block;
width: 100%;
max-width: 100%;
height: 30px;
padding: 6px 12px;
font-size: 14px;
font-family: inherit;
line-height: 1.42857143;
color: #555;
background-color: white;
border: 1px solid var(--gray80);
border-radius: 2px;
transition: border-color ease 0.3s;
}

.sc-contact-page input:focus,
.sc-contact-page textarea:focus {
border-color: #4b9fd5;
outline: none !important;
box-shadow: none;
}

.sc-contact-page input,
.sc-contact-page .Select {
width: 300px;
}

.sc-contact-page .Select-control {
height: 30px;
}

.sc-contact-page .Select-value,
.sc-contact-page .Select-placeholder {
margin-top: 4px;
}

.sc-contact-page .Select-placeholder {
font-style: italic;
color: var(--disableGrayText);
}

.sc-contact-page .Select-input {
box-shadow: none;
}

.sc-contact-page .category-select {
position: relative;
}

.sc-contact-page .category-select-helper {
opacity: 0;
z-index: -1;
position: absolute;
bottom: 0px;
}

.sc-contact-page input[name='_gotcha'] {
display: none !important;
}

.sc-contact-page textarea {
height: auto;
}

.sc-contact-page button {
padding: 6px 12px;
background: none;
color: var(--sonarcloudOrange500);
border: 1px solid var(--sonarcloudOrange500);
border-radius: 5px;
font-size: 12px;
font-weight: 400;
cursor: pointer;
}

.sc-contact-page button:hover {
color: white;
background-color: var(--sonarcloudOrange500);
}

.sc-contact-page button:focus {
color: white;
background-color: var(--sonarcloudOrange500);
outline: none;
}

.sc-contact-page button:active {
color: white;
background-color: var(--sonarcloudOrange500);
}

.sc-contact-page .form-group {
margin-bottom: 15px;
}

.sc-contact-page .sc-page-title {
text-align: left;
margin-top: 0;
}

.sc-contact-page p {
margin-bottom: 20px;
}

.sc-contact-page a {
color: var(--sonarcloudOrange500) !important;
border: none;
}

.sc-contact-page a:hover {
color: #cc5200 !important;
}

+ 0
- 78
server/sonar-web/src/main/js/apps/about/sonarcloud/utils.ts Переглянути файл

@@ -1,78 +0,0 @@
/*
* SonarQube
* Copyright (C) 2009-2020 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 { getJSON } from 'sonar-ui-common/helpers/request';

export interface FeaturedProject {
key: string;
avatarUrl: string | null;
organizationKey: string;
organizationName: string;
name: string;
bugs: number;
codeSmells: number;
coverage?: number;
duplications: number;
gateStatus: string;
languages: string[];
maintainabilityRating: number;
ncloc: number;
reliabilityRating: number;
securityRating: number;
vulnerabilities: number;
}

export interface HomepageData {
generatedAt: string;
publicProjects: number;
publicLoc: number;
rules: number;
featuredProjects: FeaturedProject[];
newPullRequests7d: number;
}

export const LANGUAGES = [
{ name: 'Java', file: 'java.svg', width: 65 },
{ name: 'JavaScript', file: 'js.svg', width: 60 },
{ name: 'TypeScript', file: 'ts.svg', width: 100 },
{ name: 'C#', file: 'csharp.svg', width: 60 },
{ name: 'Python', file: 'python.svg', width: 65 },
{ name: 'C++', file: 'c-c-plus-plus.svg', width: 53 },
{ name: 'Go', file: 'go.svg', width: 91 },
{ name: 'Kotlin', file: 'kotlin.svg', width: 42 },
{ name: 'Ruby', file: 'ruby.svg', width: 43 },
{ name: 'Swift', file: 'swift.svg', width: 64 },
{ name: 'ABAP', file: 'abap.svg', width: 62 },
{ name: 'Apex', file: 'apex.svg', width: 62 },
{ name: 'Flex', file: 'flex.png', width: 85 },
{ name: 'CSS', file: 'css.svg', width: 40 },
{ name: 'HTML', file: 'html5.svg', width: 40 },
{ name: 'Objective-C', file: 'obj-c.svg', width: 63 },
{ name: 'PHP', file: 'php.svg', width: 57 },
{ name: 'Scala', file: 'scala.svg', width: 29 },
{ name: 'T-SQL', file: 't-sql.svg', width: 53 },
{ name: 'PL/SQL', file: 'pl-sql.svg', width: 65 },
{ name: 'VB', file: 'vb.svg', width: 55 },
{ name: 'XML', file: 'xml.svg', width: 67 },
{ name: 'COBOL', file: 'cobol.svg', width: 65 }
];

export function requestHomepageData(url: string): Promise<HomepageData> {
return getJSON(url);
}

Завантаження…
Відмінити
Зберегти