@@ -35,7 +35,7 @@ public class SettingsPage { | |||
} | |||
public SettingsPage assertMenuContains(String categoryName) { | |||
$(".settings-menu").$(By.linkText(categoryName)).shouldBe(visible); | |||
$(".side-tabs-menu").$(By.linkText(categoryName)).shouldBe(visible); | |||
return this; | |||
} | |||
@@ -50,7 +50,7 @@ public class SettingsPage { | |||
} | |||
public SettingsPage openCategory(String categoryName) { | |||
$(".settings-menu").$(By.linkText(categoryName)).click(); | |||
$(".side-tabs-menu").$(By.linkText(categoryName)).click(); | |||
return this; | |||
} | |||
@@ -19,6 +19,7 @@ | |||
*/ | |||
// @flow | |||
import { getJSON, postJSON, post } from '../helpers/request'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
export function getComponents(data?: Object) { | |||
const url = '/api/projects/search'; | |||
@@ -55,7 +56,7 @@ export function createProject( | |||
} | |||
) { | |||
const url = '/api/projects/create'; | |||
return postJSON(url, data); | |||
return postJSON(url, data).catch(throwGlobalError); | |||
} | |||
export function searchProjectTags(data?: { ps?: number, q?: string }) { |
@@ -20,6 +20,7 @@ | |||
// @flow | |||
import { getJSON, post, postJSON } from '../helpers/request'; | |||
import type { Organization } from '../store/organizations/duck'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
export const getOrganizations = (organizations?: Array<string>) => { | |||
const data = {}; | |||
@@ -44,7 +45,9 @@ type GetOrganizationNavigation = { | |||
}; | |||
export const getOrganization = (key: string): Promise<GetOrganizationType> => { | |||
return getOrganizations([key]).then(r => r.organizations.find(o => o.key === key)); | |||
return getOrganizations([key]) | |||
.then(r => r.organizations.find(o => o.key === key)) | |||
.catch(throwGlobalError); | |||
}; | |||
export const getOrganizationNavigation = (key: string): Promise<GetOrganizationNavigation> => { | |||
@@ -52,12 +55,13 @@ export const getOrganizationNavigation = (key: string): Promise<GetOrganizationN | |||
}; | |||
export const createOrganization = (fields: {}): Promise<Organization> => | |||
postJSON('/api/organizations/create', fields).then(r => r.organization); | |||
postJSON('/api/organizations/create', fields).then(r => r.organization, throwGlobalError); | |||
export const updateOrganization = (key: string, changes: {}) => | |||
post('/api/organizations/update', { key, ...changes }); | |||
export const deleteOrganization = (key: string) => post('/api/organizations/delete', { key }); | |||
export const deleteOrganization = (key: string) => | |||
post('/api/organizations/delete', { key }).catch(throwGlobalError); | |||
export const searchMembers = ( | |||
data: { organization?: string, p?: number, ps?: number, q?: string, selected?: string } |
@@ -17,14 +17,16 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
// @flow | |||
import { getJSON, postJSON, post } from '../helpers/request'; | |||
import throwGlobalError from '../app/utils/throwGlobalError'; | |||
/** | |||
* List tokens for given user login | |||
* @param {string} login | |||
* @returns {Promise} | |||
*/ | |||
export function getTokens(login) { | |||
export function getTokens(login: string) { | |||
const url = '/api/user_tokens/search'; | |||
const data = { login }; | |||
return getJSON(url, data).then(r => r.userTokens); | |||
@@ -36,10 +38,16 @@ export function getTokens(login) { | |||
* @param {string} tokenName | |||
* @returns {Promise} | |||
*/ | |||
export function generateToken(userLogin, tokenName) { | |||
export function generateToken( | |||
tokenName: string, | |||
userLogin?: string | |||
): Promise<{ name: string, token: string }> { | |||
const url = '/api/user_tokens/generate'; | |||
const data = { login: userLogin, name: tokenName }; | |||
return postJSON(url, data); | |||
const data: { [string]: string } = { name: tokenName }; | |||
if (userLogin) { | |||
data.login = userLogin; | |||
} | |||
return postJSON(url, data).catch(throwGlobalError); | |||
} | |||
/** | |||
@@ -48,8 +56,11 @@ export function generateToken(userLogin, tokenName) { | |||
* @param {string} tokenName | |||
* @returns {Promise} | |||
*/ | |||
export function revokeToken(userLogin, tokenName) { | |||
export function revokeToken(tokenName: string, userLogin?: string) { | |||
const url = '/api/user_tokens/revoke'; | |||
const data = { login: userLogin, name: tokenName }; | |||
return post(url, data); | |||
const data: { [string]: string } = { name: tokenName }; | |||
if (userLogin) { | |||
data.login = userLogin; | |||
} | |||
return post(url, data).catch(throwGlobalError); | |||
} |
@@ -43,7 +43,7 @@ export default function GlobalFooterForSonarQubeDotCom() { | |||
{' - '} | |||
<a href="https://about.sonarcloud.io/contact/">{translate('footer.help')}</a> | |||
{' - '} | |||
{<Link to="/about">{translate('footer.about')}</Link>} | |||
<Link to="/about">{translate('footer.about')}</Link> | |||
</div> | |||
</div> | |||
); |
@@ -0,0 +1,118 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Modal from 'react-modal'; | |||
import classNames from 'classnames'; | |||
import LinksHelp from './LinksHelp'; | |||
import LinksHelpSonarCloud from './LinksHelpSonarCloud'; | |||
import ShortcutsHelp from './ShortcutsHelp'; | |||
import TutorialsHelp from './TutorialsHelp'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { | |||
onClose: () => void, | |||
sonarCloud?: boolean | |||
}; | |||
type State = { | |||
section: string | |||
}; | |||
export default class GlobalHelp extends React.PureComponent { | |||
props: Props; | |||
state: State = { section: 'shortcuts' }; | |||
handleCloseClick = (event: Event) => { | |||
event.preventDefault(); | |||
this.props.onClose(); | |||
}; | |||
handleSectionClick = (event: Event & { currentTarget: HTMLElement }) => { | |||
event.preventDefault(); | |||
const { section } = event.currentTarget.dataset; | |||
this.setState({ section }); | |||
}; | |||
renderSection = () => { | |||
switch (this.state.section) { | |||
case 'shortcuts': | |||
return <ShortcutsHelp />; | |||
case 'links': | |||
return this.props.sonarCloud | |||
? <LinksHelpSonarCloud onClose={this.props.onClose} /> | |||
: <LinksHelp onClose={this.props.onClose} />; | |||
case 'tutorials': | |||
return <TutorialsHelp onClose={this.props.onClose} />; | |||
default: | |||
return null; | |||
} | |||
}; | |||
renderMenuItem = (section: string) => ( | |||
<li key={section}> | |||
<a | |||
className={classNames({ active: section === this.state.section })} | |||
data-section={section} | |||
href="#" | |||
onClick={this.handleSectionClick}> | |||
{translate('help.section', section)} | |||
</a> | |||
</li> | |||
); | |||
renderMenu = () => ( | |||
<ul className="side-tabs-menu"> | |||
{['shortcuts', 'tutorials', 'links'].map(this.renderMenuItem)} | |||
</ul> | |||
); | |||
render() { | |||
return ( | |||
<Modal | |||
isOpen={true} | |||
contentLabel={translate('help')} | |||
className="modal modal-medium" | |||
overlayClassName="modal-overlay" | |||
onRequestClose={this.props.onClose}> | |||
<div className="modal-head"> | |||
<h2>{translate('help')}</h2> | |||
</div> | |||
<div className="side-tabs-layout"> | |||
<div className="side-tabs-side"> | |||
{this.renderMenu()} | |||
</div> | |||
<div className="side-tabs-main"> | |||
{this.renderSection()} | |||
</div> | |||
</div> | |||
<div className="modal-foot"> | |||
<a className="js-modal-close" href="#" onClick={this.handleCloseClick}> | |||
{translate('close')} | |||
</a> | |||
</div> | |||
</Modal> | |||
); | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { onClose: () => void }; | |||
export default function LinksHelp({ onClose }: Props) { | |||
return ( | |||
<div> | |||
<h2 className="spacer-top spacer-bottom">{translate('help.section.links')}</h2> | |||
<a href="http://www.sonarqube.org">{translate('footer.community')}</a>{' - '} | |||
<a href="https://redirect.sonarsource.com/doc/home.html"> | |||
{translate('footer.documentation')} | |||
</a> | |||
{' - '} | |||
<a href="https://redirect.sonarsource.com/doc/community.html"> | |||
{translate('footer.support')} | |||
</a> | |||
{' - '} | |||
<a href="https://redirect.sonarsource.com/doc/plugin-library.html"> | |||
{translate('footer.plugins')} | |||
</a> | |||
{' - '} | |||
<Link to="/web_api" onClick={onClose}>{translate('footer.web_api')}</Link> | |||
{' - '} | |||
<Link to="/about" onClick={onClose}>{translate('footer.about')}</Link> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,45 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { onClose: () => void }; | |||
export default function LinksHelpSonarCloud({ onClose }: Props) { | |||
return ( | |||
<div> | |||
<h2 className="spacer-top spacer-bottom">{translate('help.section.links')}</h2> | |||
<a href="https://about.sonarcloud.io/news/">{translate('footer.news')}</a> | |||
{' - '} | |||
<a href="https://about.sonarcloud.io/terms.pdf">{translate('footer.terms')}</a> | |||
{' - '} | |||
<a href="https://twitter.com/sonarqube">{translate('footer.twitter')}</a> | |||
{' - '} | |||
<a href="https://about.sonarcloud.io/get-started/">{translate('footer.get_started')}</a> | |||
{' - '} | |||
<a href="https://about.sonarcloud.io/contact/">{translate('footer.help')}</a> | |||
{' - '} | |||
<Link to="/about" onClick={onClose}>{translate('footer.about')}</Link> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,135 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { translate } from '../../../helpers/l10n'; | |||
export default function ShortcutsHelp() { | |||
return ( | |||
<div> | |||
<h2 className="spacer-top spacer-bottom">{translate('help.section.shortcuts')}</h2> | |||
<div className="columns"> | |||
<div className="column-half"> | |||
<div className="spacer-bottom"> | |||
<h3 className="shortcuts-section-title">{translate('shortcuts.section.global')}</h3> | |||
<ul className="shortcuts-list"> | |||
<li> | |||
<span className="shortcut-button spacer-right">s</span> | |||
{translate('shortcuts.section.global.search')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">?</span> | |||
{translate('shortcuts.section.global.shortcuts')} | |||
</li> | |||
</ul> | |||
</div> | |||
<h3 className="shortcuts-section-title">{translate('shortcuts.section.rules')}</h3> | |||
<ul className="shortcuts-list"> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">↑</span> | |||
<span className="shortcut-button spacer-right">↓</span> | |||
{translate('shortcuts.section.rules.navigate_between_rules')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">→</span> | |||
{translate('shortcuts.section.rules.open_details')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">←</span> | |||
{translate('shortcuts.section.rules.return_to_list')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">a</span> | |||
{translate('shortcuts.section.rules.activate')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">d</span> | |||
{translate('shortcuts.section.rules.deactivate')} | |||
</li> | |||
</ul> | |||
</div> | |||
<div className="column-half"> | |||
<h3 className="shortcuts-section-title">{translate('shortcuts.section.issues')}</h3> | |||
<ul className="shortcuts-list"> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">↑</span> | |||
<span className="shortcut-button spacer-right">↓</span> | |||
{translate('shortcuts.section.issues.navigate_between_issues')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">→</span> | |||
{translate('shortcuts.section.issues.open_details')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">←</span> | |||
{translate('shortcuts.section.issues.return_to_list')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">alt</span> | |||
<span className="little-spacer-right">+</span> | |||
<span className="shortcut-button little-spacer-right">↑</span> | |||
<span className="shortcut-button spacer-right">↓</span> | |||
{translate('issues.to_navigate_issue_locations')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">alt</span> | |||
<span className="little-spacer-right">+</span> | |||
<span className="shortcut-button little-spacer-right">←</span> | |||
<span className="shortcut-button spacer-right">→</span> | |||
{translate('issues.to_switch_flows')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">f</span> | |||
{translate('shortcuts.section.issue.do_transition')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">a</span> | |||
{translate('shortcuts.section.issue.assign')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">m</span> | |||
{translate('shortcuts.section.issue.assign_to_me')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">i</span> | |||
{translate('shortcuts.section.issue.change_severity')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">c</span> | |||
{translate('shortcuts.section.issue.comment')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">ctrl</span> | |||
<span className="shortcut-button spacer-right">enter</span> | |||
{translate('shortcuts.section.issue.submit_comment')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">t</span> | |||
{translate('shortcuts.section.issue.change_tags')} | |||
</li> | |||
</ul> | |||
</div> | |||
</div> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { Link } from 'react-router'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { onClose: () => void }; | |||
export default function TutorialsHelp({ onClose }: Props) { | |||
return ( | |||
<div> | |||
<h2 className="spacer-top spacer-bottom">{translate('help.section.tutorials')}</h2> | |||
<Link to="/tutorials/onboarding" onClick={onClose}>Onboarding Tutorial</Link> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import GlobalHelp from '../GlobalHelp'; | |||
import { click } from '../../../../helpers/testUtils'; | |||
it('switches between tabs', () => { | |||
const wrapper = shallow(<GlobalHelp onClose={jest.fn()} />); | |||
expect(wrapper.find('ShortcutsHelp')).toHaveLength(1); | |||
clickOnSection(wrapper, 'links'); | |||
expect(wrapper.find('LinksHelp')).toHaveLength(1); | |||
clickOnSection(wrapper, 'tutorials'); | |||
expect(wrapper.find('TutorialsHelp')).toHaveLength(1); | |||
clickOnSection(wrapper, 'shortcuts'); | |||
expect(wrapper.find('ShortcutsHelp')).toHaveLength(1); | |||
}); | |||
function clickOnSection(wrapper: Object, section: string) { | |||
click(wrapper.find(`[data-section="${section}"]`), { currentTarget: { dataset: { section } } }); | |||
} |
@@ -23,8 +23,8 @@ import GlobalNavBranding from './GlobalNavBranding'; | |||
import GlobalNavMenu from './GlobalNavMenu'; | |||
import GlobalNavUserContainer from './GlobalNavUserContainer'; | |||
import Search from '../../search/Search'; | |||
import ShortcutsHelp from './ShortcutsHelp'; | |||
import { getCurrentUser, getAppState } from '../../../../store/rootReducer'; | |||
import GlobalHelp from '../../help/GlobalHelp'; | |||
import { getCurrentUser, getAppState, getSettingValue } from '../../../../store/rootReducer'; | |||
class GlobalNav extends React.PureComponent { | |||
state = { helpOpen: false }; | |||
@@ -84,15 +84,21 @@ class GlobalNav extends React.PureComponent { | |||
</ul> | |||
</div> | |||
{this.state.helpOpen && <ShortcutsHelp onClose={this.closeHelp} />} | |||
{this.state.helpOpen && | |||
<GlobalHelp onClose={this.closeHelp} sonarCloud={this.props.sonarCloud} />} | |||
</nav> | |||
); | |||
} | |||
} | |||
const mapStateToProps = state => ({ | |||
currentUser: getCurrentUser(state), | |||
appState: getAppState(state) | |||
}); | |||
const mapStateToProps = state => { | |||
const sonarCloudSetting = getSettingValue(state, 'sonar.lf.sonarqube.com.enabled'); | |||
return { | |||
currentUser: getCurrentUser(state), | |||
appState: getAppState(state), | |||
sonarCloud: sonarCloudSetting != null && sonarCloudSetting.value === 'true' | |||
}; | |||
}; | |||
export default connect(mapStateToProps)(GlobalNav); |
@@ -1,188 +0,0 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Modal from 'react-modal'; | |||
import { Link } from 'react-router'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = { | |||
onClose: () => void | |||
}; | |||
export default class ShortcutsHelp extends React.PureComponent { | |||
props: Props; | |||
handleCloseClick = (event: Event) => { | |||
event.preventDefault(); | |||
this.props.onClose(); | |||
}; | |||
render() { | |||
return ( | |||
<Modal | |||
isOpen={true} | |||
contentLabel="shortcuts help" | |||
className="modal modal-large" | |||
overlayClassName="modal-overlay" | |||
onRequestClose={this.props.onClose}> | |||
<div className="modal-head"> | |||
<h2>{translate('help')}</h2> | |||
</div> | |||
<div className="modal-body modal-container"> | |||
<div className="spacer-bottom"> | |||
<a href="http://www.sonarqube.org">{translate('footer.community')}</a>{' - '} | |||
<a href="https://redirect.sonarsource.com/doc/home.html"> | |||
{translate('footer.documentation')} | |||
</a> | |||
{' - '} | |||
<a href="https://redirect.sonarsource.com/doc/community.html"> | |||
{translate('footer.support')} | |||
</a> | |||
{' - '} | |||
<a href="https://redirect.sonarsource.com/doc/plugin-library.html"> | |||
{translate('footer.plugins')} | |||
</a> | |||
{' - '} | |||
<Link to="/web_api" onClick={this.props.onClose}>{translate('footer.web_api')}</Link> | |||
{' - '} | |||
<Link to="/about" onClick={this.props.onClose}>{translate('footer.about')}</Link> | |||
</div> | |||
<h2 className="spacer-top spacer-bottom">{translate('shortcuts.modal_title')}</h2> | |||
<div className="columns"> | |||
<div className="column-half"> | |||
<div className="spacer-bottom"> | |||
<h3 className="shortcuts-section-title">{translate('shortcuts.section.global')}</h3> | |||
<ul className="shortcuts-list"> | |||
<li> | |||
<span className="shortcut-button spacer-right">s</span> | |||
{translate('shortcuts.section.global.search')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">?</span> | |||
{translate('shortcuts.section.global.shortcuts')} | |||
</li> | |||
</ul> | |||
</div> | |||
<h3 className="shortcuts-section-title">{translate('shortcuts.section.rules')}</h3> | |||
<ul className="shortcuts-list"> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">↑</span> | |||
<span className="shortcut-button spacer-right">↓</span> | |||
{translate('shortcuts.section.rules.navigate_between_rules')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">→</span> | |||
{translate('shortcuts.section.rules.open_details')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">←</span> | |||
{translate('shortcuts.section.rules.return_to_list')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">a</span> | |||
{translate('shortcuts.section.rules.activate')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">d</span> | |||
{translate('shortcuts.section.rules.deactivate')} | |||
</li> | |||
</ul> | |||
</div> | |||
<div className="column-half"> | |||
<h3 className="shortcuts-section-title">{translate('shortcuts.section.issues')}</h3> | |||
<ul className="shortcuts-list"> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">↑</span> | |||
<span className="shortcut-button spacer-right">↓</span> | |||
{translate('shortcuts.section.issues.navigate_between_issues')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">→</span> | |||
{translate('shortcuts.section.issues.open_details')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">←</span> | |||
{translate('shortcuts.section.issues.return_to_list')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">alt</span> | |||
<span className="little-spacer-right">+</span> | |||
<span className="shortcut-button little-spacer-right">↑</span> | |||
<span className="shortcut-button spacer-right">↓</span> | |||
{translate('issues.to_navigate_issue_locations')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">alt</span> | |||
<span className="little-spacer-right">+</span> | |||
<span className="shortcut-button little-spacer-right">←</span> | |||
<span className="shortcut-button spacer-right">→</span> | |||
{translate('issues.to_switch_flows')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">f</span> | |||
{translate('shortcuts.section.issue.do_transition')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">a</span> | |||
{translate('shortcuts.section.issue.assign')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">m</span> | |||
{translate('shortcuts.section.issue.assign_to_me')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">i</span> | |||
{translate('shortcuts.section.issue.change_severity')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">c</span> | |||
{translate('shortcuts.section.issue.comment')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button little-spacer-right">ctrl</span> | |||
<span className="shortcut-button spacer-right">enter</span> | |||
{translate('shortcuts.section.issue.submit_comment')} | |||
</li> | |||
<li> | |||
<span className="shortcut-button spacer-right">t</span> | |||
{translate('shortcuts.section.issue.change_tags')} | |||
</li> | |||
</ul> | |||
</div> | |||
</div> | |||
</div> | |||
<div className="modal-foot"> | |||
<a className="js-modal-close" href="#" onClick={this.handleCloseClick}> | |||
{translate('close')} | |||
</a> | |||
</div> | |||
</Modal> | |||
); | |||
} | |||
} |
@@ -34,6 +34,8 @@ | |||
} | |||
.boxed-group-actions { | |||
position: relative; | |||
z-index: 12; | |||
float: right; | |||
margin-top: 15px; | |||
margin-right: 20px; |
@@ -63,6 +63,7 @@ import qualityProfilesRoutes from '../../apps/quality-profiles/routes'; | |||
import sessionsRoutes from '../../apps/sessions/routes'; | |||
import settingsRoutes from '../../apps/settings/routes'; | |||
import systemRoutes from '../../apps/system/routes'; | |||
import tutorialRoutes from '../../apps/tutorials/routes'; | |||
import updateCenterRoutes from '../../apps/update-center/routes'; | |||
import usersRoutes from '../../apps/users/routes'; | |||
import webAPIRoutes from '../../apps/web-api/routes'; | |||
@@ -159,6 +160,7 @@ const startReactApp = () => { | |||
<Route path="quality_gates" childRoutes={qualityGatesRoutes} /> | |||
<Route path="portfolios" component={PortfoliosPage} /> | |||
<Route path="profiles" childRoutes={qualityProfilesRoutes} /> | |||
<Route path="tutorials" childRoutes={tutorialRoutes} /> | |||
<Route path="web_api" childRoutes={webAPIRoutes} /> | |||
<Route component={ProjectContainer}> |
@@ -0,0 +1,28 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import getStore from './getStore'; | |||
import { onFail } from '../../store/rootActions'; | |||
export default function throwGlobalError(error: Object) { | |||
const store = getStore(); | |||
onFail(store.dispatch)(error); | |||
return Promise.reject(); | |||
} |
@@ -52,17 +52,13 @@ export default Marionette.ItemView.extend({ | |||
this.errors = []; | |||
this.newToken = null; | |||
const tokenName = this.$('.js-generate-token-form input').val(); | |||
generateToken(this.model.id, tokenName) | |||
.then(response => { | |||
generateToken(tokenName, this.model.id).then( | |||
response => { | |||
this.newToken = response; | |||
this.requestTokens(); | |||
}) | |||
.catch(error => { | |||
error.response.json().then(response => { | |||
this.errors = response.errors; | |||
this.render(); | |||
}); | |||
}); | |||
}, | |||
() => {} | |||
); | |||
}, | |||
onRevokeTokenFormSubmit(e) { | |||
@@ -71,7 +67,7 @@ export default Marionette.ItemView.extend({ | |||
const token = this.tokens.find(token => token.name === `${tokenName}`); | |||
if (token) { | |||
if (token.deleting) { | |||
revokeToken(this.model.id, tokenName).then(this.requestTokens.bind(this)); | |||
revokeToken(tokenName, this.model.id).then(this.requestTokens.bind(this), () => {}); | |||
} else { | |||
token.deleting = true; | |||
this.render(); |
@@ -103,10 +103,9 @@ export default class CreateProjectForm extends React.PureComponent { | |||
this.props.onProjectCreated(); | |||
} | |||
}, | |||
error => { | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
this.props.onRequestFail(error); | |||
} | |||
} | |||
); |
@@ -83,15 +83,15 @@ class App extends React.PureComponent { | |||
<Helmet title={translate('settings.page')} /> | |||
<PageHeader component={this.props.component} /> | |||
<div className="settings-layout"> | |||
<div className="settings-side"> | |||
<div className="side-tabs-layout settings-layout"> | |||
<div className="side-tabs-side"> | |||
<AllCategoriesList | |||
component={this.props.component} | |||
selectedCategory={selectedCategory} | |||
defaultCategory={this.props.defaultCategory} | |||
/> | |||
</div> | |||
<div className="settings-main"> | |||
<div className="side-tabs-main"> | |||
<CategoryDefinitionsList component={this.props.component} category={selectedCategory} /> | |||
{selectedCategory === 'exclusions' && <WildcardsHelp />} |
@@ -70,7 +70,7 @@ export default class CategoriesList extends React.PureComponent { | |||
const sortedCategories = sortBy(categoriesWithName, category => category.name.toLowerCase()); | |||
return ( | |||
<ul className="settings-menu"> | |||
<ul className="side-tabs-menu"> | |||
{sortedCategories.map(category => ( | |||
<li key={category.key}> | |||
{this.renderLink(category)} |
@@ -1,60 +1,7 @@ | |||
.settings-layout { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: stretch; | |||
margin-bottom: 60px; | |||
} | |||
.settings-main { | |||
position: relative; | |||
z-index: 2; | |||
flex-grow: 1; | |||
padding: 15px 20px; | |||
border: 1px solid #e6e6e6; | |||
box-sizing: border-box; | |||
background-color: #fff; | |||
} | |||
.settings-side { | |||
position: relative; | |||
z-index: 3; | |||
width: 160px; | |||
flex-shrink: 0; | |||
padding: 10px 0; | |||
box-sizing: border-box; | |||
transform: translateX(1px); | |||
} | |||
.settings-menu {} | |||
.settings-menu > li { | |||
margin-bottom: 4px; | |||
} | |||
.settings-menu > li > a { | |||
display: block; | |||
padding: 10px 10px; | |||
line-height: 1.5; | |||
border-top-left-radius: 3px; | |||
border-bottom-left-radius: 3px; | |||
border: 1px solid #e6e6e6; | |||
border-right: none; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
transition: color 0.3s ease, background-color 0.3s ease; | |||
} | |||
.settings-menu > li > a:hover, | |||
.settings-menu > li > a:focus, | |||
.settings-menu > li > a.active { | |||
background-color: #fff; | |||
} | |||
.settings-menu > li > a.active { | |||
color: #444; | |||
cursor: default; | |||
} | |||
.settings-definitions-list > li + li { | |||
margin-top: 30px; | |||
} |
@@ -0,0 +1,181 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Step from './Step'; | |||
import LanguageStep from './LanguageStep'; | |||
import type { Result } from './LanguageStep'; | |||
import JavaMaven from './commands/JavaMaven'; | |||
import JavaGradle from './commands/JavaGradle'; | |||
import DotNet from './commands/DotNet'; | |||
import Msvc from './commands/Msvc'; | |||
import ClangGCC from './commands/ClangGCC'; | |||
import Other from './commands/Other'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = {| | |||
open: boolean, | |||
organization?: string, | |||
sonarCloud: boolean, | |||
stepNumber: number, | |||
token: string | |||
|}; | |||
type State = { | |||
result?: Result | |||
}; | |||
export default class AnalysisStep extends React.PureComponent { | |||
props: Props; | |||
state: State = {}; | |||
handleLanguageSelect = (result?: Result) => { | |||
this.setState({ result }); | |||
}; | |||
handleLanguageReset = () => { | |||
this.setState({ result: undefined }); | |||
}; | |||
getHost = () => window.location.origin + window.baseUrl; | |||
renderForm = () => { | |||
return ( | |||
<div className="boxed-group-inner"> | |||
<div className="flex-columns"> | |||
<div className="flex-column flex-column-half bordered-right"> | |||
<LanguageStep | |||
onDone={this.handleLanguageSelect} | |||
onReset={this.handleLanguageReset} | |||
sonarCloud={this.props.sonarCloud} | |||
/> | |||
</div> | |||
<div className="flex-column flex-column-half"> | |||
{this.renderCommand()} | |||
</div> | |||
</div> | |||
</div> | |||
); | |||
}; | |||
renderFormattedCommand = (...lines: Array<string>) => ( | |||
<pre>{lines.join(' ' + '\\' + '\n' + ' ')}</pre> | |||
); | |||
renderCommand = () => { | |||
const { result } = this.state; | |||
if (!result) { | |||
return null; | |||
} | |||
if (result.language === 'java') { | |||
return result.javaBuild === 'maven' | |||
? this.renderCommandForMaven() | |||
: this.renderCommandForGradle(); | |||
} else if (result.language === 'dotnet') { | |||
return this.renderCommandForDotNet(); | |||
} else if (result.language === 'c-family') { | |||
return result.cFamilyCompiler === 'msvc' | |||
? this.renderCommandForMSVC() | |||
: this.renderCommandForClangGCC(); | |||
} else { | |||
return this.renderCommandForOther(); | |||
} | |||
}; | |||
renderCommandForMaven = () => ( | |||
<JavaMaven | |||
host={this.getHost()} | |||
organization={this.props.organization} | |||
token={this.props.token} | |||
/> | |||
); | |||
renderCommandForGradle = () => ( | |||
<JavaGradle | |||
host={this.getHost()} | |||
organization={this.props.organization} | |||
token={this.props.token} | |||
/> | |||
); | |||
renderCommandForDotNet = () => { | |||
return ( | |||
<DotNet | |||
host={this.getHost()} | |||
organization={this.props.organization} | |||
// $FlowFixMe | |||
projectKey={this.state.result.projectKey} | |||
token={this.props.token} | |||
/> | |||
); | |||
}; | |||
renderCommandForMSVC = () => { | |||
return ( | |||
<Msvc | |||
host={this.getHost()} | |||
organization={this.props.organization} | |||
// $FlowFixMe | |||
projectKey={this.state.result.projectKey} | |||
token={this.props.token} | |||
/> | |||
); | |||
}; | |||
renderCommandForClangGCC = () => ( | |||
<ClangGCC | |||
host={this.getHost()} | |||
organization={this.props.organization} | |||
// $FlowFixMe | |||
os={this.state.result.os} | |||
// $FlowFixMe | |||
projectKey={this.state.result.projectKey} | |||
token={this.props.token} | |||
/> | |||
); | |||
renderCommandForOther = () => ( | |||
<Other | |||
host={this.getHost()} | |||
organization={this.props.organization} | |||
// $FlowFixMe | |||
os={this.state.result.os} | |||
// $FlowFixMe | |||
projectKey={this.state.result.projectKey} | |||
token={this.props.token} | |||
/> | |||
); | |||
renderResult = () => null; | |||
render() { | |||
return ( | |||
<Step | |||
open={this.props.open} | |||
renderForm={this.renderForm} | |||
renderResult={this.renderResult} | |||
stepNumber={this.props.stepNumber} | |||
stepTitle={translate('onboarding.analysis.header')} | |||
/> | |||
); | |||
} | |||
} |
@@ -0,0 +1,188 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import NewProjectForm from './NewProjectForm'; | |||
import RadioToggle from '../../../components/controls/RadioToggle'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = {| | |||
onDone: (result: Result) => void, | |||
onReset: () => void, | |||
organization?: string, | |||
sonarCloud: boolean | |||
|}; | |||
type State = { | |||
language?: string, | |||
javaBuild?: string, | |||
cFamilyCompiler?: string, | |||
os?: string, | |||
projectKey?: string | |||
}; | |||
export type Result = State; | |||
export default class LanguageStep extends React.PureComponent { | |||
props: Props; | |||
static defaultProps = { sonarCloud: false }; | |||
state: State = {}; | |||
isConfigured = () => { | |||
const { language, javaBuild, cFamilyCompiler, os, projectKey } = this.state; | |||
const isJavaConfigured = language === 'java' && javaBuild != null; | |||
const isDotNetConfigured = language === 'dotnet' && projectKey != null; | |||
const isCFamilyConfigured = | |||
language === 'c-family' && (cFamilyCompiler === 'msvc' || os != null) && projectKey != null; | |||
const isOtherConfigured = language === 'other' && projectKey != null; | |||
return isJavaConfigured || isDotNetConfigured || isCFamilyConfigured || isOtherConfigured; | |||
}; | |||
handleChange = () => { | |||
if (this.isConfigured()) { | |||
this.props.onDone(this.state); | |||
} else { | |||
this.props.onReset(); | |||
} | |||
}; | |||
handleLanguageChange = (language: string) => { | |||
this.setState({ language }, this.handleChange); | |||
}; | |||
handleJavaBuildChange = (javaBuild: string) => { | |||
this.setState({ javaBuild }, this.handleChange); | |||
}; | |||
handleCFamilyCompilerChange = (cFamilyCompiler: string) => { | |||
this.setState({ cFamilyCompiler }, this.handleChange); | |||
}; | |||
handleOSChange = (os: string) => { | |||
this.setState({ os }, this.handleChange); | |||
}; | |||
handleProjectKeyDone = (projectKey: string) => { | |||
this.setState({ projectKey }, this.handleChange); | |||
}; | |||
handleProjectKeyDelete = () => { | |||
this.setState({ projectKey: undefined }, this.handleChange); | |||
}; | |||
renderJavaBuild = () => ( | |||
<div className="big-spacer-top"> | |||
<h4 className="spacer-bottom"> | |||
{translate('onboarding.language.java.build_technology')} | |||
</h4> | |||
<RadioToggle | |||
name="java-build" | |||
onCheck={this.handleJavaBuildChange} | |||
options={['maven', 'gradle'].map(build => ({ | |||
label: translate('onboarding.language.java.build_technology', build), | |||
value: build | |||
}))} | |||
value={this.state.javaBuild} | |||
/> | |||
</div> | |||
); | |||
renderCFamilyCompiler = () => ( | |||
<div className="big-spacer-top"> | |||
<h4 className="spacer-bottom"> | |||
{translate('onboarding.language.c-family.compiler')} | |||
</h4> | |||
<RadioToggle | |||
name="c-family-compiler" | |||
onCheck={this.handleCFamilyCompilerChange} | |||
options={['msvc', 'clang-gcc'].map(compiler => ({ | |||
label: translate('onboarding.language.c-family.compiler', compiler), | |||
value: compiler | |||
}))} | |||
value={this.state.cFamilyCompiler} | |||
/> | |||
</div> | |||
); | |||
renderOS = () => ( | |||
<div className="big-spacer-top"> | |||
<h4 className="spacer-bottom"> | |||
{translate('onboarding.language.os')} | |||
</h4> | |||
<RadioToggle | |||
name="os" | |||
onCheck={this.handleOSChange} | |||
options={['linux', 'win', 'mac'].map(os => ({ | |||
label: translate('onboarding.language.os', os), | |||
value: os | |||
}))} | |||
value={this.state.os} | |||
/> | |||
</div> | |||
); | |||
renderProjectKey = () => ( | |||
<NewProjectForm | |||
onDelete={this.handleProjectKeyDelete} | |||
onDone={this.handleProjectKeyDone} | |||
organization={this.props.organization} | |||
projectKey={this.state.projectKey} | |||
/> | |||
); | |||
render() { | |||
const shouldAskProjectKey = | |||
this.state.language === 'dotnet' || | |||
(this.state.language === 'c-family' && | |||
(this.state.cFamilyCompiler === 'msvc' || | |||
(this.state.cFamilyCompiler === 'clang-gcc' && this.state.os != null))) || | |||
(this.state.language === 'other' && this.state.os !== undefined); | |||
const languages = this.props.sonarCloud | |||
? ['java', 'dotnet', 'c-family', 'other'] | |||
: ['java', 'dotnet', 'other']; | |||
return ( | |||
<div> | |||
<div> | |||
<h4 className="spacer-bottom">{translate('onboarding.language')}</h4> | |||
<RadioToggle | |||
name="language" | |||
onCheck={this.handleLanguageChange} | |||
options={languages.map(language => ({ | |||
label: translate('onboarding.language', language), | |||
value: language | |||
}))} | |||
value={this.state.language} | |||
/> | |||
</div> | |||
{this.state.language === 'java' && this.renderJavaBuild()} | |||
{this.state.language === 'c-family' && this.renderCFamilyCompiler()} | |||
{((this.state.language === 'c-family' && this.state.cFamilyCompiler === 'clang-gcc') || | |||
this.state.language === 'other') && | |||
this.renderOS()} | |||
{shouldAskProjectKey && this.renderProjectKey()} | |||
</div> | |||
); | |||
} | |||
} |
@@ -0,0 +1,157 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { debounce } from 'lodash'; | |||
import { | |||
createOrganization, | |||
deleteOrganization, | |||
getOrganization | |||
} from '../../../api/organizations'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = {| | |||
onDelete: () => void, | |||
onDone: (organization: string) => void, | |||
organization?: string | |||
|}; | |||
type State = { | |||
done: boolean, | |||
loading: boolean, | |||
organization: string, | |||
unique: boolean | |||
}; | |||
export default class NewOrganizationForm extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State; | |||
constructor(props: Props) { | |||
super(props); | |||
this.state = { | |||
done: props.organization != null, | |||
loading: false, | |||
organization: props.organization || '', | |||
unique: true | |||
}; | |||
this.validateOrganization = debounce(this.validateOrganization, 500); | |||
} | |||
componentDidMount() { | |||
this.mounted = true; | |||
} | |||
componentWillUnmount() { | |||
this.mounted = false; | |||
} | |||
stopLoading = () => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
}; | |||
validateOrganization = (organization: string) => { | |||
getOrganization(organization).then(response => { | |||
if (this.mounted) { | |||
this.setState({ unique: response == null }); | |||
} | |||
}); | |||
}; | |||
sanitizeOrganization = (organization: string) => | |||
organization.toLowerCase().replace(/[^a-z0-9-]/, '').replace(/^-/, ''); | |||
handleOrganizationChange = (event: { target: HTMLInputElement }) => { | |||
const organization = this.sanitizeOrganization(event.target.value); | |||
this.setState({ organization }); | |||
this.validateOrganization(organization); | |||
}; | |||
handleOrganizationCreate = (event: Event) => { | |||
event.preventDefault(); | |||
const { organization } = this.state; | |||
if (organization) { | |||
this.setState({ loading: true }); | |||
createOrganization({ key: organization, name: organization }).then(() => { | |||
if (this.mounted) { | |||
this.setState({ done: true, loading: false }); | |||
this.props.onDone(organization); | |||
} | |||
}, this.stopLoading); | |||
} | |||
}; | |||
handleOrganizationDelete = (event: Event) => { | |||
event.preventDefault(); | |||
const { organization } = this.state; | |||
if (organization) { | |||
this.setState({ loading: true }); | |||
deleteOrganization(organization).then(() => { | |||
if (this.mounted) { | |||
this.setState({ done: false, loading: false, organization: '' }); | |||
this.props.onDelete(); | |||
} | |||
}, this.stopLoading); | |||
} | |||
}; | |||
render() { | |||
const { done, loading, organization, unique } = this.state; | |||
const valid = unique && organization.length >= 2; | |||
return done | |||
? <form onSubmit={this.handleOrganizationDelete}> | |||
<span className="spacer-right text-middle">{organization}</span> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="button-clean"> | |||
<i className="icon-delete" /> | |||
</button>} | |||
</form> | |||
: <form onSubmit={this.handleOrganizationCreate}> | |||
<input | |||
autoFocus={true} | |||
className="input-super-large spacer-right text-middle" | |||
onChange={this.handleOrganizationChange} | |||
maxLength={32} | |||
minLength={2} | |||
placeholder={translate('onboarding.organization.placeholder')} | |||
required={true} | |||
type="text" | |||
value={organization} | |||
/> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="text-middle" disabled={!valid}>{translate('create')}</button>} | |||
{!unique && | |||
<span className="big-spacer-left text-danger text-middle"> | |||
<i className="icon-alert-error little-spacer-right text-text-top" /> | |||
{translate('this_name_is_already_taken')} | |||
</span>} | |||
<div className="note spacer-top abs-width-300"> | |||
{translate('onboarding.organization.key_requirement')} | |||
</div> | |||
</form>; | |||
} | |||
} |
@@ -0,0 +1,145 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { createProject, deleteProject } from '../../../api/components'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = {| | |||
onDelete: () => void, | |||
onDone: (projectKey: string) => void, | |||
organization?: string, | |||
projectKey?: string | |||
|}; | |||
type State = { | |||
done: boolean, | |||
loading: boolean, | |||
projectKey: string | |||
}; | |||
export default class NewProjectForm extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State; | |||
constructor(props: Props) { | |||
super(props); | |||
this.state = { | |||
done: props.projectKey != null, | |||
loading: false, | |||
projectKey: props.projectKey || '' | |||
}; | |||
} | |||
componentDidMount() { | |||
this.mounted = true; | |||
} | |||
componentWillUnmount() { | |||
this.mounted = false; | |||
} | |||
stopLoading = () => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
}; | |||
sanitizeProjectKey = (projectKey: string) => projectKey.replace(/[^a-zA-Z0-9-_\.:]/, ''); | |||
handleProjectKeyChange = (event: { target: HTMLInputElement }) => { | |||
this.setState({ projectKey: this.sanitizeProjectKey(event.target.value) }); | |||
}; | |||
handleProjectCreate = (event: Event) => { | |||
event.preventDefault(); | |||
const { projectKey } = this.state; | |||
const data: { [string]: string } = { | |||
name: projectKey, | |||
project: projectKey | |||
}; | |||
if (this.props.organization) { | |||
data.organization = this.props.organization; | |||
} | |||
this.setState({ loading: true }); | |||
createProject(data).then(() => { | |||
if (this.mounted) { | |||
this.setState({ done: true, loading: false }); | |||
this.props.onDone(projectKey); | |||
} | |||
}, this.stopLoading); | |||
}; | |||
handleProjectDelete = (event: Event) => { | |||
event.preventDefault(); | |||
const { projectKey } = this.state; | |||
this.setState({ loading: true }); | |||
deleteProject(projectKey).then(() => { | |||
if (this.mounted) { | |||
this.setState({ done: false, loading: false, projectKey: '' }); | |||
this.props.onDelete(); | |||
} | |||
}, this.stopLoading); | |||
}; | |||
render() { | |||
const { done, loading, projectKey } = this.state; | |||
const valid = projectKey.length > 0; | |||
const form = done | |||
? <form onSubmit={this.handleProjectDelete}> | |||
<span className="spacer-right text-middle">{projectKey}</span> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="button-clean"> | |||
<i className="icon-delete" /> | |||
</button>} | |||
</form> | |||
: <form onSubmit={this.handleProjectCreate}> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
minLength={1} | |||
maxLength={400} | |||
onChange={this.handleProjectKeyChange} | |||
required={true} | |||
type="text" | |||
value={projectKey} | |||
/> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="text-middle" disabled={!valid}>{translate('Done')}</button>} | |||
<div className="note spacer-top abs-width-300"> | |||
{translate('onboarding.project_key_requirement')} | |||
</div> | |||
</form>; | |||
return ( | |||
<div className="big-spacer-top"> | |||
<h4 className="spacer-bottom"> | |||
{translate('onboarding.language.project_key')} | |||
</h4> | |||
{form} | |||
</div> | |||
); | |||
} | |||
} |
@@ -0,0 +1,109 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import TokenStep from './TokenStep'; | |||
import OrganizationStep from './OrganizationStep'; | |||
import AnalysisStep from './AnalysisStep'; | |||
import { translate } from '../../../helpers/l10n'; | |||
import handleRequiredAuthentication from '../../../app/utils/handleRequiredAuthentication'; | |||
import './styles.css'; | |||
type Props = { | |||
currentUser: { login: string, isLoggedIn: boolean }, | |||
organizationsEnabled: boolean, | |||
sonarCloud: boolean | |||
}; | |||
type State = { | |||
organization?: string, | |||
step: string, | |||
token?: string | |||
}; | |||
export default class Onboarding extends React.PureComponent { | |||
props: Props; | |||
state: State; | |||
constructor(props: Props) { | |||
super(props); | |||
this.state = { step: props.organizationsEnabled ? 'organization' : 'token' }; | |||
} | |||
componentDidMount() { | |||
if (!this.props.currentUser.isLoggedIn) { | |||
handleRequiredAuthentication(); | |||
} | |||
} | |||
handleTokenDone = (token: string) => { | |||
this.setState({ step: 'analysis', token }); | |||
}; | |||
handleOrganizationDone = (organization: string) => { | |||
this.setState({ organization, step: 'token' }); | |||
}; | |||
render() { | |||
if (!this.props.currentUser.isLoggedIn) { | |||
return null; | |||
} | |||
const { organizationsEnabled, sonarCloud } = this.props; | |||
const { step, token } = this.state; | |||
let stepNumber = 1; | |||
return ( | |||
<div className="page page-limited"> | |||
<header className="page-header"> | |||
<h1 className="page-title"> | |||
{translate(sonarCloud ? 'onboarding.header.sonarcloud' : 'onboarding.header')} | |||
</h1> | |||
<div className="page-description"> | |||
{translate('onboarding.header.description')} | |||
</div> | |||
</header> | |||
{organizationsEnabled && | |||
<OrganizationStep | |||
currentUser={this.props.currentUser} | |||
onContinue={this.handleOrganizationDone} | |||
open={step === 'organization'} | |||
stepNumber={stepNumber++} | |||
/>} | |||
<TokenStep | |||
onContinue={this.handleTokenDone} | |||
open={step === 'token'} | |||
stepNumber={stepNumber++} | |||
/> | |||
<AnalysisStep | |||
organization={this.state.organization} | |||
open={step === 'analysis'} | |||
sonarCloud={sonarCloud} | |||
stepNumber={stepNumber} | |||
token={token} | |||
/> | |||
</div> | |||
); | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import { connect } from 'react-redux'; | |||
import Onboarding from './Onboarding'; | |||
import { | |||
getCurrentUser, | |||
areThereCustomOrganizations, | |||
getSettingValue | |||
} from '../../../store/rootReducer'; | |||
const mapStateToProps = state => { | |||
const sonarCloudSetting = getSettingValue(state, 'sonar.lf.sonarqube.com.enabled'); | |||
return { | |||
currentUser: getCurrentUser(state), | |||
organizationsEnabled: areThereCustomOrganizations(state), | |||
sonarCloud: sonarCloudSetting != null && sonarCloudSetting.value === 'true' | |||
}; | |||
}; | |||
export default connect(mapStateToProps)(Onboarding); |
@@ -0,0 +1,240 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Select from 'react-select'; | |||
import classNames from 'classnames'; | |||
import { sortBy } from 'lodash'; | |||
import Step from './Step'; | |||
import NewOrganizationForm from './NewOrganizationForm'; | |||
import { getMyOrganizations } from '../../../api/organizations'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { | |||
currentUser: { login: string, isLoggedIn: boolean }, | |||
open: boolean, | |||
onContinue: (organization: string) => void | |||
}; | |||
type State = { | |||
loading: boolean, | |||
newOrganization?: string, | |||
existingOrganization?: string, | |||
existingOrganizations: Array<string>, | |||
selection: 'personal' | 'existing' | 'new' | |||
}; | |||
export default class OrganizationStep extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State = { | |||
loading: true, | |||
existingOrganizations: [], | |||
selection: 'personal' | |||
}; | |||
componentDidMount() { | |||
this.mounted = true; | |||
this.fetchOrganizations(); | |||
} | |||
componentWillUnmount() { | |||
this.mounted = false; | |||
} | |||
fetchOrganizations = () => { | |||
getMyOrganizations().then( | |||
organizations => { | |||
if (this.mounted) { | |||
this.setState({ | |||
loading: false, | |||
existingOrganizations: sortBy( | |||
organizations.filter(organization => organization !== this.props.currentUser.login) | |||
) | |||
}); | |||
} | |||
}, | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
} | |||
); | |||
}; | |||
getSelectedOrganization = () => { | |||
switch (this.state.selection) { | |||
case 'personal': | |||
return this.props.currentUser.login; | |||
case 'existing': | |||
return this.state.existingOrganization; | |||
case 'new': | |||
return this.state.newOrganization; | |||
default: | |||
return null; | |||
} | |||
}; | |||
handlePersonalClick = (event: Event) => { | |||
event.preventDefault(); | |||
this.setState({ selection: 'personal' }); | |||
}; | |||
handleExistingClick = (event: Event) => { | |||
event.preventDefault(); | |||
this.setState({ selection: 'existing' }); | |||
}; | |||
handleNewClick = (event: Event) => { | |||
event.preventDefault(); | |||
this.setState({ selection: 'new' }); | |||
}; | |||
handleOrganizationCreate = (newOrganization: string) => { | |||
this.setState({ newOrganization }); | |||
}; | |||
handleOrganizationDelete = () => { | |||
this.setState({ newOrganization: undefined }); | |||
}; | |||
handleExistingOrganizationSelect = ({ value }: { value: string }) => { | |||
this.setState({ existingOrganization: value }); | |||
}; | |||
handleContinueClick = (event: Event) => { | |||
event.preventDefault(); | |||
const organization = this.getSelectedOrganization(); | |||
if (organization) { | |||
this.props.onContinue(organization); | |||
} | |||
}; | |||
renderPersonalOrganizationOption = () => ( | |||
<div> | |||
<a className="link-base-color link-no-underline" href="#" onClick={this.handlePersonalClick}> | |||
<i | |||
className={classNames('icon-radio', 'spacer-right', { | |||
'is-checked': this.state.selection === 'personal' | |||
})} | |||
/> | |||
{translate('onboarding.organization.my_personal_organization')} | |||
<span className="note spacer-left">{this.props.currentUser.login}</span> | |||
</a> | |||
</div> | |||
); | |||
renderExistingOrganizationOption = () => ( | |||
<div className="big-spacer-top"> | |||
<a | |||
className="js-existing link-base-color link-no-underline" | |||
href="#" | |||
onClick={this.handleExistingClick}> | |||
<i | |||
className={classNames('icon-radio', 'spacer-right', { | |||
'is-checked': this.state.selection === 'existing' | |||
})} | |||
/> | |||
{translate('onboarding.organization.exising_organization')} | |||
</a> | |||
{this.state.selection === 'existing' && | |||
<div className="big-spacer-top"> | |||
<Select | |||
className="input-super-large" | |||
clearable={false} | |||
onChange={this.handleExistingOrganizationSelect} | |||
options={this.state.existingOrganizations.map(organization => ({ | |||
label: organization, | |||
value: organization | |||
}))} | |||
value={this.state.existingOrganization} | |||
/> | |||
</div>} | |||
</div> | |||
); | |||
renderNewOrganizationOption = () => ( | |||
<div className="big-spacer-top"> | |||
<a | |||
className="js-new link-base-color link-no-underline" | |||
href="#" | |||
onClick={this.handleNewClick}> | |||
<i | |||
className={classNames('icon-radio', 'spacer-right', { | |||
'is-checked': this.state.selection === 'new' | |||
})} | |||
/> | |||
{translate('onboarding.organization.create_another_organization')} | |||
</a> | |||
{this.state.selection === 'new' && | |||
<div className="big-spacer-top"> | |||
<NewOrganizationForm | |||
onDelete={this.handleOrganizationDelete} | |||
onDone={this.handleOrganizationCreate} | |||
organization={this.state.newOrganization} | |||
/> | |||
</div>} | |||
</div> | |||
); | |||
renderForm = () => { | |||
return ( | |||
<div className="boxed-group-inner"> | |||
<div className="big-spacer-bottom width-50"> | |||
{translate('onboarding.organization.text')} | |||
</div> | |||
{this.renderPersonalOrganizationOption()} | |||
{this.state.existingOrganizations.length > 0 && this.renderExistingOrganizationOption()} | |||
{this.renderNewOrganizationOption()} | |||
{this.getSelectedOrganization() != null && | |||
<div className="big-spacer-top"> | |||
<button className="js-continue" onClick={this.handleContinueClick}> | |||
{translate('continue')} | |||
</button> | |||
</div>} | |||
</div> | |||
); | |||
}; | |||
renderResult = () => { | |||
const result = this.getSelectedOrganization(); | |||
return result != null | |||
? <div className="boxed-group-actions"> | |||
<i className="icon-check spacer-right" /> | |||
<strong>{result}</strong> | |||
</div> | |||
: null; | |||
}; | |||
render() { | |||
return ( | |||
<Step | |||
open={this.props.open} | |||
renderForm={this.renderForm} | |||
renderResult={this.renderResult} | |||
stepNumber={1} | |||
stepTitle={translate('onboarding.organization.header')} | |||
/> | |||
); | |||
} | |||
} |
@@ -0,0 +1,145 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { createProject, deleteProject } from '../../../api/components'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { | |||
onDelete: () => void, | |||
onDone: (projectKey: string) => void, | |||
organization?: string, | |||
projectKey?: string | |||
}; | |||
type State = { | |||
done: boolean, | |||
loading: boolean, | |||
projectKey: string | |||
}; | |||
export default class ProjectKeyStep extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
state: State; | |||
constructor(props: Props) { | |||
super(props); | |||
this.state = { | |||
done: props.projectKey != null, | |||
loading: false, | |||
projectKey: props.projectKey || '' | |||
}; | |||
} | |||
componentDidMount() { | |||
this.mounted = true; | |||
} | |||
componentWillUnmount() { | |||
this.mounted = false; | |||
} | |||
stopLoading = () => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
}; | |||
sanitizeProjectKey = (projectKey: string) => projectKey.replace(/[^a-zA-Z0-9-_\.:]/, ''); | |||
handleProjectKeyChange = (event: { target: HTMLInputElement }) => { | |||
this.setState({ projectKey: this.sanitizeProjectKey(event.target.value) }); | |||
}; | |||
handleProjectCreate = (event: Event) => { | |||
event.preventDefault(); | |||
const { projectKey } = this.state; | |||
const data: { [string]: string } = { | |||
name: projectKey, | |||
project: projectKey | |||
}; | |||
if (this.props.organization) { | |||
data.organization = this.props.organization; | |||
} | |||
this.setState({ loading: true }); | |||
createProject(data).then(() => { | |||
if (this.mounted) { | |||
this.setState({ done: true, loading: false }); | |||
this.props.onDone(projectKey); | |||
} | |||
}, this.stopLoading); | |||
}; | |||
handleProjectDelete = (event: Event) => { | |||
event.preventDefault(); | |||
const { projectKey } = this.state; | |||
this.setState({ loading: true }); | |||
deleteProject(projectKey).then(() => { | |||
if (this.mounted) { | |||
this.setState({ done: false, loading: false, projectKey: '' }); | |||
this.props.onDelete(); | |||
} | |||
}, this.stopLoading); | |||
}; | |||
render() { | |||
const { done, loading, projectKey } = this.state; | |||
const valid = projectKey.length > 0; | |||
const form = done | |||
? <form onSubmit={this.handleProjectDelete}> | |||
<span className="spacer-right text-middle">{projectKey}</span> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="button-clean"> | |||
<i className="icon-delete" /> | |||
</button>} | |||
</form> | |||
: <form onSubmit={this.handleProjectCreate}> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
minLength={1} | |||
maxLength={400} | |||
onChange={this.handleProjectKeyChange} | |||
required={true} | |||
type="text" | |||
value={projectKey} | |||
/> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="text-middle" disabled={!valid}>{translate('Done')}</button>} | |||
<div className="note spacer-top abs-width-300"> | |||
{translate('onboarding.project_key_requirement')} | |||
</div> | |||
</form>; | |||
return ( | |||
<div className="big-spacer-top"> | |||
<h4 className="spacer-bottom"> | |||
{translate('onboarding.language.project_key')} | |||
</h4> | |||
{form} | |||
</div> | |||
); | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import classNames from 'classnames'; | |||
type Props = { | |||
open: boolean, | |||
renderForm: () => React.Element<*>, | |||
renderResult: () => ?React.Element<*>, | |||
stepNumber: number, | |||
stepTitle: string | |||
}; | |||
export default function Step(props: Props) { | |||
const className = classNames('boxed-group', 'onboarding-step', { | |||
'onboarding-step-open': props.open | |||
}); | |||
return ( | |||
<div className={className}> | |||
<div className="onboarding-step-number">{props.stepNumber}</div> | |||
{!props.open && props.renderResult()} | |||
<div className="boxed-group-header"> | |||
<h2>{props.stepTitle}</h2> | |||
</div> | |||
{props.open ? props.renderForm() : <div className="boxed-group-inner" />} | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,180 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Step from './Step'; | |||
import { generateToken, revokeToken } from '../../../api/user-tokens'; | |||
import { translate } from '../../../helpers/l10n'; | |||
type Props = { | |||
open: boolean, | |||
onContinue: (token: string) => void, | |||
stepNumber: number | |||
}; | |||
type State = { | |||
loading: boolean, | |||
tokenName?: string, | |||
token?: string | |||
}; | |||
export default class TokenStep extends React.PureComponent { | |||
mounted: boolean; | |||
props: Props; | |||
static defaultProps = { | |||
stepNumber: 1 | |||
}; | |||
state: State = { | |||
loading: false | |||
}; | |||
componentDidMount() { | |||
this.mounted = true; | |||
} | |||
componentWillUnmount() { | |||
this.mounted = false; | |||
} | |||
handleTokenNameChange = (event: { target: HTMLInputElement }) => { | |||
this.setState({ tokenName: event.target.value }); | |||
}; | |||
handleTokenGenerate = (event: Event) => { | |||
event.preventDefault(); | |||
const { tokenName } = this.state; | |||
if (tokenName) { | |||
this.setState({ loading: true }); | |||
generateToken(tokenName).then( | |||
({ token }) => { | |||
if (this.mounted) { | |||
this.setState({ loading: false, token }); | |||
} | |||
}, | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
} | |||
); | |||
} | |||
}; | |||
handleTokenRevoke = (event: Event) => { | |||
event.preventDefault(); | |||
const { tokenName } = this.state; | |||
if (tokenName) { | |||
this.setState({ loading: true }); | |||
revokeToken(tokenName).then( | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false, token: undefined, tokenName: undefined }); | |||
} | |||
}, | |||
() => { | |||
if (this.mounted) { | |||
this.setState({ loading: false }); | |||
} | |||
} | |||
); | |||
} | |||
}; | |||
handleContinueClick = (event: Event) => { | |||
event.preventDefault(); | |||
if (this.state.token) { | |||
this.props.onContinue(this.state.token); | |||
} | |||
}; | |||
renderForm = () => { | |||
const { loading, token, tokenName } = this.state; | |||
return ( | |||
<div className="boxed-group-inner"> | |||
<div className="big-spacer-bottom width-50"> | |||
{translate('onboarding.token.text')} | |||
</div> | |||
{token != null | |||
? <form onSubmit={this.handleTokenRevoke}> | |||
{tokenName}{': '} | |||
<span className="monospaced spacer-right">{token}</span> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button className="button-clean" onClick={this.handleTokenRevoke}> | |||
<i className="icon-delete" /> | |||
</button>} | |||
</form> | |||
: <form onSubmit={this.handleTokenGenerate}> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
onChange={this.handleTokenNameChange} | |||
placeholder={translate('onboarding.token.placeholder')} | |||
required={true} | |||
type="text" | |||
value={tokenName || ''} | |||
/> | |||
{loading | |||
? <i className="spinner" /> | |||
: <button>{translate('onboarding.token.generate')}</button>} | |||
</form>} | |||
{token != null && | |||
<div className="big-spacer-top"> | |||
<button className="js-continue" onClick={this.handleContinueClick}> | |||
{translate('continue')} | |||
</button> | |||
</div>} | |||
</div> | |||
); | |||
}; | |||
renderResult = () => { | |||
const { token, tokenName } = this.state; | |||
if (!token) { | |||
return null; | |||
} | |||
return ( | |||
<div className="boxed-group-actions"> | |||
<i className="icon-check spacer-right" /> | |||
{tokenName}{': '} | |||
<strong className="monospaced">{token}</strong> | |||
</div> | |||
); | |||
}; | |||
render() { | |||
return ( | |||
<Step | |||
open={this.props.open} | |||
renderForm={this.renderForm} | |||
renderResult={this.renderResult} | |||
stepNumber={this.props.stepNumber} | |||
stepTitle={translate('onboarding.token.header')} | |||
/> | |||
); | |||
} | |||
} |
@@ -0,0 +1,106 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import LanguageStep from '../LanguageStep'; | |||
it('selects java', () => { | |||
const onDone = jest.fn(); | |||
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} />); | |||
wrapper.find('RadioToggle').prop('onCheck')('java'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('RadioToggle').at(1).prop('onCheck')('maven'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).lastCalledWith({ language: 'java', javaBuild: 'maven' }); | |||
wrapper.find('RadioToggle').at(1).prop('onCheck')('gradle'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).lastCalledWith({ language: 'java', javaBuild: 'gradle' }); | |||
}); | |||
it('selects c#', () => { | |||
const onDone = jest.fn(); | |||
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} />); | |||
wrapper.find('RadioToggle').prop('onCheck')('dotnet'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('NewProjectForm').prop('onDone')('project-foo'); | |||
expect(onDone).lastCalledWith({ language: 'dotnet', projectKey: 'project-foo' }); | |||
}); | |||
it('selects c-family', () => { | |||
const onDone = jest.fn(); | |||
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} sonarCloud={true} />); | |||
wrapper.find('RadioToggle').prop('onCheck')('c-family'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('RadioToggle').at(1).prop('onCheck')('msvc'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('NewProjectForm').prop('onDone')('project-foo'); | |||
expect(onDone).lastCalledWith({ | |||
language: 'c-family', | |||
cFamilyCompiler: 'msvc', | |||
projectKey: 'project-foo' | |||
}); | |||
wrapper.find('RadioToggle').at(1).prop('onCheck')('clang-gcc'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('RadioToggle').at(2).prop('onCheck')('linux'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('NewProjectForm').prop('onDone')('project-foo'); | |||
expect(onDone).lastCalledWith({ | |||
language: 'c-family', | |||
cFamilyCompiler: 'clang-gcc', | |||
os: 'linux', | |||
projectKey: 'project-foo' | |||
}); | |||
}); | |||
it('selects other', () => { | |||
const onDone = jest.fn(); | |||
const wrapper = shallow(<LanguageStep onDone={onDone} onReset={jest.fn()} />); | |||
wrapper.find('RadioToggle').prop('onCheck')('other'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('RadioToggle').at(1).prop('onCheck')('mac'); | |||
wrapper.update(); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.find('NewProjectForm').prop('onDone')('project-foo'); | |||
expect(onDone).lastCalledWith({ language: 'other', os: 'mac', projectKey: 'project-foo' }); | |||
}); |
@@ -0,0 +1,56 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import NewOrganizationForm from '../NewOrganizationForm'; | |||
import { change, doAsync, submit } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/organizations', () => ({ | |||
createOrganization: () => Promise.resolve(), | |||
deleteOrganization: () => Promise.resolve(), | |||
getOrganization: () => Promise.resolve(null) | |||
})); | |||
it('creates new organization', () => { | |||
const onDone = jest.fn(); | |||
const wrapper = mount(<NewOrganizationForm onDelete={jest.fn()} onDone={onDone} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'foo'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
}); | |||
it('deletes organization', () => { | |||
const onDelete = jest.fn(); | |||
const wrapper = mount(<NewOrganizationForm onDelete={onDelete} onDone={jest.fn()} />); | |||
wrapper.setState({ done: true, loading: false, organization: 'foo' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); | |||
}); |
@@ -0,0 +1,55 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import NewProjectForm from '../NewProjectForm'; | |||
import { change, doAsync, submit } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/components', () => ({ | |||
createProject: () => Promise.resolve(), | |||
deleteProject: () => Promise.resolve() | |||
})); | |||
it('creates new project', () => { | |||
const onDone = jest.fn(); | |||
const wrapper = mount(<NewProjectForm onDelete={jest.fn()} onDone={onDone} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'foo'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
}); | |||
it('deletes project', () => { | |||
const onDelete = jest.fn(); | |||
const wrapper = mount(<NewProjectForm onDelete={onDelete} onDone={jest.fn()} />); | |||
wrapper.setState({ done: true, loading: false, projectKey: 'foo' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); | |||
}); |
@@ -0,0 +1,63 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import OrganizationStep from '../OrganizationStep'; | |||
import { click, doAsync } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/organizations', () => ({ | |||
getMyOrganizations: () => Promise.resolve(['user', 'another']) | |||
})); | |||
const currentUser = { isLoggedIn: true, login: 'user' }; | |||
it('works with personal organization', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep currentUser={currentUser} onContinue={onContinue} open={true} /> | |||
); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('user'); | |||
}); | |||
it('works with existing organization', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep currentUser={currentUser} onContinue={onContinue} open={true} /> | |||
); | |||
return doAsync(() => { | |||
click(wrapper.find('.js-existing')); | |||
wrapper.find('Select').prop('onChange')({ value: 'another' }); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('another'); | |||
}); | |||
}); | |||
it('works with new organization', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount( | |||
<OrganizationStep currentUser={currentUser} onContinue={onContinue} open={true} /> | |||
); | |||
click(wrapper.find('.js-new')); | |||
wrapper.find('NewOrganizationForm').prop('onDone')('new'); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('new'); | |||
}); |
@@ -0,0 +1,55 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import ProjectKeyStep from '../ProjectKeyStep'; | |||
import { change, doAsync, submit } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/components', () => ({ | |||
createProject: () => Promise.resolve(), | |||
deleteProject: () => Promise.resolve() | |||
})); | |||
it('creates new project', () => { | |||
const onDone = jest.fn(); | |||
const wrapper = mount(<ProjectKeyStep onDelete={jest.fn()} onDone={onDone} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'foo'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDone).toBeCalledWith('foo'); | |||
}); | |||
}); | |||
it('deletes project', () => { | |||
const onDelete = jest.fn(); | |||
const wrapper = mount(<ProjectKeyStep onDelete={onDelete} onDone={jest.fn()} />); | |||
wrapper.setState({ done: true, loading: false, projectKey: 'foo' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => { | |||
expect(wrapper).toMatchSnapshot(); | |||
expect(onDelete).toBeCalled(); | |||
}); | |||
}); |
@@ -0,0 +1,38 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import Step from '../Step'; | |||
it('renders', () => { | |||
const wrapper = shallow( | |||
<Step | |||
open={true} | |||
renderForm={() => <div>form</div>} | |||
renderResult={() => <div>result</div>} | |||
stepNumber={1} | |||
stepTitle="First Step" | |||
/> | |||
); | |||
expect(wrapper).toMatchSnapshot(); | |||
wrapper.setProps({ open: false }); | |||
expect(wrapper).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,55 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { mount } from 'enzyme'; | |||
import TokenStep from '../TokenStep'; | |||
import { change, click, doAsync, submit } from '../../../../helpers/testUtils'; | |||
jest.mock('../../../../api/user-tokens', () => ({ | |||
generateToken: () => Promise.resolve({ token: 'abcd1234' }), | |||
revokeToken: () => Promise.resolve() | |||
})); | |||
it('generates token', () => { | |||
const wrapper = mount(<TokenStep open={true} onContinue={jest.fn()} />); | |||
expect(wrapper).toMatchSnapshot(); | |||
change(wrapper.find('input'), 'my token'); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => expect(wrapper).toMatchSnapshot()); | |||
}); | |||
it('revokes token', () => { | |||
const wrapper = mount(<TokenStep open={true} onContinue={jest.fn()} />); | |||
wrapper.setState({ token: 'abcd1234', tokenName: 'my token' }); | |||
expect(wrapper).toMatchSnapshot(); | |||
submit(wrapper.find('form')); | |||
expect(wrapper).toMatchSnapshot(); // spinner | |||
return doAsync(() => expect(wrapper).toMatchSnapshot()); | |||
}); | |||
it('continues', () => { | |||
const onContinue = jest.fn(); | |||
const wrapper = mount(<TokenStep open={true} onContinue={onContinue} />); | |||
wrapper.setState({ token: 'abcd1234', tokenName: 'my token' }); | |||
click(wrapper.find('.js-continue')); | |||
expect(onContinue).toBeCalledWith('abcd1234'); | |||
}); |
@@ -0,0 +1,687 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`selects c# 1`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="dotnet" | |||
/> | |||
</div> | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
/> | |||
</div> | |||
`; | |||
exports[`selects c-family 1`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family", | |||
"value": "c-family", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="c-family" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.c-family.compiler | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="c-family-compiler" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.msvc", | |||
"value": "msvc", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.clang-gcc", | |||
"value": "clang-gcc", | |||
}, | |||
] | |||
} | |||
value={null} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`selects c-family 2`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family", | |||
"value": "c-family", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="c-family" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.c-family.compiler | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="c-family-compiler" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.msvc", | |||
"value": "msvc", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.clang-gcc", | |||
"value": "clang-gcc", | |||
}, | |||
] | |||
} | |||
value="msvc" | |||
/> | |||
</div> | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
/> | |||
</div> | |||
`; | |||
exports[`selects c-family 3`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family", | |||
"value": "c-family", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="c-family" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.c-family.compiler | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="c-family-compiler" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.msvc", | |||
"value": "msvc", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.clang-gcc", | |||
"value": "clang-gcc", | |||
}, | |||
] | |||
} | |||
value="clang-gcc" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.os | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="os" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.os.linux", | |||
"value": "linux", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.win", | |||
"value": "win", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.mac", | |||
"value": "mac", | |||
}, | |||
] | |||
} | |||
value={null} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`selects c-family 4`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family", | |||
"value": "c-family", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="c-family" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.c-family.compiler | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="c-family-compiler" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.msvc", | |||
"value": "msvc", | |||
}, | |||
Object { | |||
"label": "onboarding.language.c-family.compiler.clang-gcc", | |||
"value": "clang-gcc", | |||
}, | |||
] | |||
} | |||
value="clang-gcc" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.os | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="os" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.os.linux", | |||
"value": "linux", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.win", | |||
"value": "win", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.mac", | |||
"value": "mac", | |||
}, | |||
] | |||
} | |||
value="linux" | |||
/> | |||
</div> | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
projectKey="project-foo" | |||
/> | |||
</div> | |||
`; | |||
exports[`selects java 1`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="java" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.java.build_technology | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="java-build" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java.build_technology.maven", | |||
"value": "maven", | |||
}, | |||
Object { | |||
"label": "onboarding.language.java.build_technology.gradle", | |||
"value": "gradle", | |||
}, | |||
] | |||
} | |||
value={null} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`selects java 2`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="java" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.java.build_technology | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="java-build" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java.build_technology.maven", | |||
"value": "maven", | |||
}, | |||
Object { | |||
"label": "onboarding.language.java.build_technology.gradle", | |||
"value": "gradle", | |||
}, | |||
] | |||
} | |||
value="maven" | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`selects java 3`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="java" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.java.build_technology | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="java-build" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java.build_technology.maven", | |||
"value": "maven", | |||
}, | |||
Object { | |||
"label": "onboarding.language.java.build_technology.gradle", | |||
"value": "gradle", | |||
}, | |||
] | |||
} | |||
value="gradle" | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`selects other 1`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="other" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.os | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="os" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.os.linux", | |||
"value": "linux", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.win", | |||
"value": "win", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.mac", | |||
"value": "mac", | |||
}, | |||
] | |||
} | |||
value={null} | |||
/> | |||
</div> | |||
</div> | |||
`; | |||
exports[`selects other 2`] = ` | |||
<div> | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="language" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.java", | |||
"value": "java", | |||
}, | |||
Object { | |||
"label": "onboarding.language.dotnet", | |||
"value": "dotnet", | |||
}, | |||
Object { | |||
"label": "onboarding.language.other", | |||
"value": "other", | |||
}, | |||
] | |||
} | |||
value="other" | |||
/> | |||
</div> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.os | |||
</h4> | |||
<RadioToggle | |||
disabled={false} | |||
name="os" | |||
onCheck={[Function]} | |||
options={ | |||
Array [ | |||
Object { | |||
"label": "onboarding.language.os.linux", | |||
"value": "linux", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.win", | |||
"value": "win", | |||
}, | |||
Object { | |||
"label": "onboarding.language.os.mac", | |||
"value": "mac", | |||
}, | |||
] | |||
} | |||
value="mac" | |||
/> | |||
</div> | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,168 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`creates new organization 1`] = ` | |||
<NewOrganizationForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-super-large spacer-right text-middle" | |||
maxLength={32} | |||
minLength={2} | |||
onChange={[Function]} | |||
placeholder="onboarding.organization.placeholder" | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button | |||
className="text-middle" | |||
disabled={true} | |||
> | |||
create | |||
</button> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.organization.key_requirement | |||
</div> | |||
</form> | |||
</NewOrganizationForm> | |||
`; | |||
exports[`creates new organization 2`] = ` | |||
<NewOrganizationForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-super-large spacer-right text-middle" | |||
maxLength={32} | |||
minLength={2} | |||
onChange={[Function]} | |||
placeholder="onboarding.organization.placeholder" | |||
required={true} | |||
type="text" | |||
value="foo" | |||
/> | |||
<i | |||
className="spinner" | |||
/> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.organization.key_requirement | |||
</div> | |||
</form> | |||
</NewOrganizationForm> | |||
`; | |||
exports[`creates new organization 3`] = ` | |||
<NewOrganizationForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
</NewOrganizationForm> | |||
`; | |||
exports[`deletes organization 1`] = ` | |||
<NewOrganizationForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
</NewOrganizationForm> | |||
`; | |||
exports[`deletes organization 2`] = ` | |||
<NewOrganizationForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<i | |||
className="spinner" | |||
/> | |||
</form> | |||
</NewOrganizationForm> | |||
`; | |||
exports[`deletes organization 3`] = ` | |||
<NewOrganizationForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-super-large spacer-right text-middle" | |||
maxLength={32} | |||
minLength={2} | |||
onChange={[Function]} | |||
placeholder="onboarding.organization.placeholder" | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button | |||
className="text-middle" | |||
disabled={true} | |||
> | |||
create | |||
</button> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.organization.key_requirement | |||
</div> | |||
</form> | |||
</NewOrganizationForm> | |||
`; |
@@ -0,0 +1,219 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`creates new project 1`] = ` | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
maxLength={400} | |||
minLength={1} | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button | |||
className="text-middle" | |||
disabled={true} | |||
> | |||
Done | |||
</button> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.project_key_requirement | |||
</div> | |||
</form> | |||
</div> | |||
</NewProjectForm> | |||
`; | |||
exports[`creates new project 2`] = ` | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
maxLength={400} | |||
minLength={1} | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="foo" | |||
/> | |||
<i | |||
className="spinner" | |||
/> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.project_key_requirement | |||
</div> | |||
</form> | |||
</div> | |||
</NewProjectForm> | |||
`; | |||
exports[`creates new project 3`] = ` | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
</div> | |||
</NewProjectForm> | |||
`; | |||
exports[`deletes project 1`] = ` | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
</div> | |||
</NewProjectForm> | |||
`; | |||
exports[`deletes project 2`] = ` | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<i | |||
className="spinner" | |||
/> | |||
</form> | |||
</div> | |||
</NewProjectForm> | |||
`; | |||
exports[`deletes project 3`] = ` | |||
<NewProjectForm | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
maxLength={400} | |||
minLength={1} | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button | |||
className="text-middle" | |||
disabled={true} | |||
> | |||
Done | |||
</button> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.project_key_requirement | |||
</div> | |||
</form> | |||
</div> | |||
</NewProjectForm> | |||
`; |
@@ -0,0 +1,219 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`creates new project 1`] = ` | |||
<ProjectKeyStep | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
maxLength={400} | |||
minLength={1} | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button | |||
className="text-middle" | |||
disabled={true} | |||
> | |||
Done | |||
</button> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.project_key_requirement | |||
</div> | |||
</form> | |||
</div> | |||
</ProjectKeyStep> | |||
`; | |||
exports[`creates new project 2`] = ` | |||
<ProjectKeyStep | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
maxLength={400} | |||
minLength={1} | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="foo" | |||
/> | |||
<i | |||
className="spinner" | |||
/> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.project_key_requirement | |||
</div> | |||
</form> | |||
</div> | |||
</ProjectKeyStep> | |||
`; | |||
exports[`creates new project 3`] = ` | |||
<ProjectKeyStep | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
</div> | |||
</ProjectKeyStep> | |||
`; | |||
exports[`deletes project 1`] = ` | |||
<ProjectKeyStep | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<button | |||
className="button-clean" | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
</div> | |||
</ProjectKeyStep> | |||
`; | |||
exports[`deletes project 2`] = ` | |||
<ProjectKeyStep | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<span | |||
className="spacer-right text-middle" | |||
> | |||
foo | |||
</span> | |||
<i | |||
className="spinner" | |||
/> | |||
</form> | |||
</div> | |||
</ProjectKeyStep> | |||
`; | |||
exports[`deletes project 3`] = ` | |||
<ProjectKeyStep | |||
onDelete={[Function]} | |||
onDone={[Function]} | |||
> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.language.project_key | |||
</h4> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right text-middle" | |||
maxLength={400} | |||
minLength={1} | |||
onChange={[Function]} | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button | |||
className="text-middle" | |||
disabled={true} | |||
> | |||
Done | |||
</button> | |||
<div | |||
className="note spacer-top abs-width-300" | |||
> | |||
onboarding.project_key_requirement | |||
</div> | |||
</form> | |||
</div> | |||
</ProjectKeyStep> | |||
`; |
@@ -0,0 +1,48 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders 1`] = ` | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
First Step | |||
</h2> | |||
</div> | |||
<div> | |||
form | |||
</div> | |||
</div> | |||
`; | |||
exports[`renders 2`] = ` | |||
<div | |||
className="boxed-group onboarding-step" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div> | |||
result | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
First Step | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,383 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`generates token 1`] = ` | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
stepNumber={1} | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.token.header | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
onChange={[Function]} | |||
placeholder="onboarding.token.placeholder" | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button> | |||
onboarding.token.generate | |||
</button> | |||
</form> | |||
</div> | |||
</div> | |||
</Step> | |||
</TokenStep> | |||
`; | |||
exports[`generates token 2`] = ` | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
stepNumber={1} | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.token.header | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
onChange={[Function]} | |||
placeholder="onboarding.token.placeholder" | |||
required={true} | |||
type="text" | |||
value="my token" | |||
/> | |||
<i | |||
className="spinner" | |||
/> | |||
</form> | |||
</div> | |||
</div> | |||
</Step> | |||
</TokenStep> | |||
`; | |||
exports[`generates token 3`] = ` | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
stepNumber={1} | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.token.header | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
my token | |||
: | |||
<span | |||
className="monospaced spacer-right" | |||
> | |||
abcd1234 | |||
</span> | |||
<button | |||
className="button-clean" | |||
onClick={[Function]} | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<button | |||
className="js-continue" | |||
onClick={[Function]} | |||
> | |||
continue | |||
</button> | |||
</div> | |||
</div> | |||
</div> | |||
</Step> | |||
</TokenStep> | |||
`; | |||
exports[`revokes token 1`] = ` | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
stepNumber={1} | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.token.header | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
my token | |||
: | |||
<span | |||
className="monospaced spacer-right" | |||
> | |||
abcd1234 | |||
</span> | |||
<button | |||
className="button-clean" | |||
onClick={[Function]} | |||
> | |||
<i | |||
className="icon-delete" | |||
/> | |||
</button> | |||
</form> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<button | |||
className="js-continue" | |||
onClick={[Function]} | |||
> | |||
continue | |||
</button> | |||
</div> | |||
</div> | |||
</div> | |||
</Step> | |||
</TokenStep> | |||
`; | |||
exports[`revokes token 2`] = ` | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
stepNumber={1} | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.token.header | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
my token | |||
: | |||
<span | |||
className="monospaced spacer-right" | |||
> | |||
abcd1234 | |||
</span> | |||
<i | |||
className="spinner" | |||
/> | |||
</form> | |||
<div | |||
className="big-spacer-top" | |||
> | |||
<button | |||
className="js-continue" | |||
onClick={[Function]} | |||
> | |||
continue | |||
</button> | |||
</div> | |||
</div> | |||
</div> | |||
</Step> | |||
</TokenStep> | |||
`; | |||
exports[`revokes token 3`] = ` | |||
<TokenStep | |||
onContinue={[Function]} | |||
open={true} | |||
stepNumber={1} | |||
> | |||
<Step | |||
open={true} | |||
renderForm={[Function]} | |||
renderResult={[Function]} | |||
stepNumber={1} | |||
stepTitle="onboarding.token.header" | |||
> | |||
<div | |||
className="boxed-group onboarding-step onboarding-step-open" | |||
> | |||
<div | |||
className="onboarding-step-number" | |||
> | |||
1 | |||
</div> | |||
<div | |||
className="boxed-group-header" | |||
> | |||
<h2> | |||
onboarding.token.header | |||
</h2> | |||
</div> | |||
<div | |||
className="boxed-group-inner" | |||
> | |||
<div | |||
className="big-spacer-bottom width-50" | |||
> | |||
onboarding.token.text | |||
</div> | |||
<form | |||
onSubmit={[Function]} | |||
> | |||
<input | |||
autoFocus={true} | |||
className="input-large spacer-right" | |||
onChange={[Function]} | |||
placeholder="onboarding.token.placeholder" | |||
required={true} | |||
type="text" | |||
value="" | |||
/> | |||
<button> | |||
onboarding.token.generate | |||
</button> | |||
</form> | |||
</div> | |||
</div> | |||
</Step> | |||
</TokenStep> | |||
`; |
@@ -0,0 +1,58 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = { | |||
className?: string, | |||
os: string | |||
}; | |||
const filenames = { | |||
linux: 'build-wrapper-win-x86.zip', | |||
win: 'build-wrapper-linux-x86.zip', | |||
mac: 'build-wrapper-macosx-x86.zip' | |||
}; | |||
export default function BuildWrapper(props: Props) { | |||
return ( | |||
<div className={props.className}> | |||
<h4 className="spacer-bottom"> | |||
{translate('onboarding.analysis.build_wrapper.header', props.os)} | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ | |||
__html: translate('onboarding.analysis.build_wrapper.text', props.os) | |||
}} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
download={filenames[props.os]} | |||
href={window.baseUrl + '/static/cpp/' + filenames[props.os]} | |||
target="_blank"> | |||
{translate('download_verb')} | |||
</a> | |||
</p> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,76 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Command from './Command'; | |||
import SQScanner from './SQScanner'; | |||
import BuildWrapper from './BuildWrapper'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = { | |||
host: string, | |||
os: string, | |||
organization?: string, | |||
projectKey: string, | |||
token: string | |||
}; | |||
const executables = { | |||
linux: 'build-wrapper-linux-x86-64', | |||
win: 'build-wrapper-win-x86-64.exe', | |||
mac: 'build-wrapper-macosx-x86' | |||
}; | |||
export default function ClangGCC(props: Props) { | |||
const command1 = `${executables[props.os]} --out-dir bw-output make clean all`; | |||
const command2 = [ | |||
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner', | |||
`-Dsonar.projectKey=${props.projectKey}`, | |||
props.organization && `-Dsonar.organization=${props.organization}`, | |||
'-Dsonar.sources=.', | |||
'-Dsonar.cfamily.build-wrapper-output=bw-output', | |||
`-Dsonar.host.url=${props.host}`, | |||
`-Dsonar.login=${props.token}` | |||
]; | |||
return ( | |||
<div> | |||
<SQScanner os={props.os} /> | |||
<BuildWrapper className="huge-spacer-top" os={props.os} /> | |||
<h4 className="huge-spacer-top spacer-bottom"> | |||
{translate('onboarding.analysis.sq_scanner.execute')} | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ | |||
__html: translate('onboarding.analysis.sq_scanner.execute.text') | |||
}} | |||
/> | |||
<Command command={command1} /> | |||
<Command command={command2} /> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.sq_scanner.docs') }} | |||
/> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,89 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Clipboard from 'clipboard'; | |||
import Tooltip from '../../../../components/controls/Tooltip'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = { | |||
command: string | Array<?string> | |||
}; | |||
type State = { | |||
tooltipShown: boolean | |||
}; | |||
const s = ' \\' + '\n '; | |||
export default class Command extends React.PureComponent { | |||
clipboard: Object; | |||
copyButton: HTMLButtonElement; | |||
mounted: boolean; | |||
props: Props; | |||
state: State = { tooltipShown: false }; | |||
componentDidMount() { | |||
this.mounted = true; | |||
this.clipboard = new Clipboard(this.copyButton); | |||
this.clipboard.on('success', this.showTooltip); | |||
} | |||
componentWillUnmount() { | |||
this.mounted = false; | |||
this.clipboard.destroy(); | |||
} | |||
showTooltip = () => { | |||
if (this.mounted) { | |||
this.setState({ tooltipShown: true }); | |||
setTimeout(this.hideTooltip, 1000); | |||
} | |||
}; | |||
hideTooltip = () => { | |||
if (this.mounted) { | |||
this.setState({ tooltipShown: false }); | |||
} | |||
}; | |||
render() { | |||
const { command } = this.props; | |||
const commandArray = Array.isArray(command) ? command.filter(line => line != null) : [command]; | |||
const finalCommand = commandArray.join(s); | |||
const button = ( | |||
<button data-clipboard-text={finalCommand} ref={node => (this.copyButton = node)}> | |||
{translate('copy')} | |||
</button> | |||
); | |||
return ( | |||
<div className="onboarding-command"> | |||
<pre>{finalCommand}</pre> | |||
{this.state.tooltipShown | |||
? <Tooltip defaultVisible={true} placement="top" overlay="Copied!" trigger="manual"> | |||
{button} | |||
</Tooltip> | |||
: button} | |||
</div> | |||
); | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Command from './Command'; | |||
import MSBuildScanner from './MSBuildScanner'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = {| | |||
host: string, | |||
organization?: string, | |||
projectKey: string, | |||
token: string | |||
|}; | |||
export default function DotNet(props: Props) { | |||
const command1 = [ | |||
'SonarQube.Scanner.MSBuild.exe begin', | |||
`/k:"${props.projectKey}"`, | |||
props.organization && `/d:"sonar.organization=${props.organization}"`, | |||
`/d:"sonar.host.url=${props.host}`, | |||
`/d:"sonar.login=${props.token}"` | |||
]; | |||
const command2 = 'MsBuild.exe /t:Rebuild'; | |||
const command3 = ['SonarQube.Scanner.MSBuild.exe end', `/d:"sonar.login=${props.token}"`]; | |||
return ( | |||
<div> | |||
<MSBuildScanner /> | |||
<h4 className="huge-spacer-top spacer-bottom"> | |||
{translate('onboarding.analysis.msbuild.execute')} | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ | |||
__html: translate('onboarding.analysis.msbuild.execute.text') | |||
}} | |||
/> | |||
<Command command={command1} /> | |||
<Command command={command2} /> | |||
<Command command={command3} /> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.msbuild.docs') }} | |||
/> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Command from './Command'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = {| | |||
host: string, | |||
organization?: string, | |||
token: string | |||
|}; | |||
export default function JavaGradle(props: Props) { | |||
const config = 'plugins {\n id "org.sonarqube" version "2.2"\n}'; | |||
const command = [ | |||
'./gradlew sonarqube', | |||
props.organization && `-Dsonar.organization=${props.organization}`, | |||
`-Dsonar.host.url=${props.host}`, | |||
`-Dsonar.login=${props.token}` | |||
]; | |||
return ( | |||
<div> | |||
<h4 className="spacer-bottom">{translate('onboarding.analysis.java.gradle.header')}</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.java.gradle.text.1') }} | |||
/> | |||
<Command command={config} /> | |||
<p className="spacer-top spacer-bottom markdown"> | |||
{translate('onboarding.analysis.java.gradle.text.2')} | |||
</p> | |||
<Command command={command} /> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.java.gradle.docs') }} | |||
/> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,50 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Command from './Command'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = {| | |||
host: string, | |||
organization?: string, | |||
token: string | |||
|}; | |||
export default function JavaMaven(props: Props) { | |||
const command = [ | |||
'mvn sonar:sonar', | |||
props.organization && `-Dsonar.organization=${props.organization}`, | |||
`-Dsonar.host.url=${props.host}`, | |||
`-Dsonar.login=${props.token}` | |||
]; | |||
return ( | |||
<div> | |||
<h4 className="spacer-bottom">{translate('onboarding.analysis.java.maven.header')}</h4> | |||
<p className="spacer-bottom markdown">{translate('onboarding.analysis.java.maven.text')}</p> | |||
<Command command={command} /> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.java.maven.docs') }} | |||
/> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = { | |||
className?: string | |||
}; | |||
export default function MSBuildScanner(props: Props) { | |||
return ( | |||
<div className={props.className}> | |||
<h4 className="spacer-bottom">{translate('onboarding.analysis.msbuild.header')}</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.msbuild.text') }} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" | |||
target="_blank"> | |||
{translate('download_verb')} | |||
</a> | |||
</p> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,71 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Command from './Command'; | |||
import MSBuildScanner from './MSBuildScanner'; | |||
import BuildWrapper from './BuildWrapper'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = {| | |||
host: string, | |||
organization?: string, | |||
projectKey: string, | |||
token: string | |||
|}; | |||
export default function Msvc(props: Props) { | |||
const command1 = [ | |||
'SonarQube.Scanner.MSBuild.exe begin', | |||
`/k:"${props.projectKey}"`, | |||
props.organization && `/d:"sonar.organization=${props.organization}"`, | |||
'/d:"sonar.cfamily.build-wrapper-output=bw-output"', | |||
`/d:"sonar.host.url=${props.host}`, | |||
`/d:"sonar.login=${props.token}"` | |||
]; | |||
const command2 = 'build-wrapper-win-x86-64.exe --out-dir bw-output MsBuild.exe /t:Rebuild'; | |||
const command3 = ['SonarQube.Scanner.MSBuild.exe end', `/d:"sonar.login=${props.token}"`]; | |||
return ( | |||
<div> | |||
<MSBuildScanner /> | |||
<BuildWrapper className="huge-spacer-top" os="win" /> | |||
<h4 className="huge-spacer-top spacer-bottom"> | |||
{translate('onboarding.analysis.msbuild.execute')} | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ | |||
__html: translate('onboarding.analysis.msbuild.execute.text') | |||
}} | |||
/> | |||
<Command command={command1} /> | |||
<Command command={command2} /> | |||
<Command command={command3} /> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.msbuild.docs') }} | |||
/> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,64 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import Command from './Command'; | |||
import SQScanner from './SQScanner'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = {| | |||
host: string, | |||
organization?: string, | |||
os: string, | |||
projectKey: string, | |||
token: string | |||
|}; | |||
export default function Other(props: Props) { | |||
const command = [ | |||
props.os === 'win' ? 'sonar-scanner.bat' : 'sonar-scanner', | |||
`-Dsonar.projectKey=${props.projectKey}`, | |||
props.organization && `-Dsonar.organization=${props.organization}`, | |||
'-Dsonar.sources=.', | |||
`-Dsonar.host.url=${props.host}`, | |||
`-Dsonar.login=${props.token}` | |||
]; | |||
return ( | |||
<div> | |||
<SQScanner os={props.os} /> | |||
<h4 className="huge-spacer-top spacer-bottom"> | |||
{translate('onboarding.analysis.sq_scanner.execute')} | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ | |||
__html: translate('onboarding.analysis.sq_scanner.execute.text') | |||
}} | |||
/> | |||
<Command command={command} /> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={{ __html: translate('onboarding.analysis.sq_scanner.docs') }} | |||
/> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,51 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { translate } from '../../../../helpers/l10n'; | |||
type Props = { | |||
className?: string, | |||
os: string | |||
}; | |||
export default function SQScanner(props: Props) { | |||
return ( | |||
<div className={props.className}> | |||
<h4 className="spacer-bottom"> | |||
{translate('onboarding.analysis.sq_scanner.header', props.os)} | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={{ | |||
__html: translate('onboarding.analysis.sq_scanner.text', props.os) | |||
}} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" | |||
target="_blank"> | |||
{translate('download_verb')} | |||
</a> | |||
</p> | |||
</div> | |||
); | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import BuildWrapper from '../BuildWrapper'; | |||
it('renders correctly', () => { | |||
expect(shallow(<BuildWrapper os="win" />)).toMatchSnapshot(); | |||
expect(shallow(<BuildWrapper os="linux" />)).toMatchSnapshot(); | |||
expect(shallow(<BuildWrapper os="mac" />)).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,45 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import ClangGCC from '../ClangGCC'; | |||
it('renders correctly', () => { | |||
expect( | |||
shallow(<ClangGCC host="host" os="win" projectKey="projectKey" token="token" />) | |||
).toMatchSnapshot(); | |||
expect( | |||
shallow(<ClangGCC host="host" os="linux" projectKey="projectKey" token="token" />) | |||
).toMatchSnapshot(); | |||
expect( | |||
shallow( | |||
<ClangGCC | |||
host="host" | |||
os="linux" | |||
organization="organization" | |||
projectKey="projectKey" | |||
token="token" | |||
/> | |||
) | |||
).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,27 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import Command from '../Command'; | |||
it('renders correctly', () => { | |||
expect(shallow(<Command command={'foo\nbar'} />)).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,32 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import DotNet from '../DotNet'; | |||
it('renders correctly', () => { | |||
expect(shallow(<DotNet host="host" projectKey="projectKey" token="token" />)).toMatchSnapshot(); | |||
expect( | |||
shallow( | |||
<DotNet host="host" organization="organization" projectKey="projectKey" token="token" /> | |||
) | |||
).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,30 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import JavaGradle from '../JavaGradle'; | |||
it('renders correctly', () => { | |||
expect(shallow(<JavaGradle host="host" token="token" />)).toMatchSnapshot(); | |||
expect( | |||
shallow(<JavaGradle host="host" organization="organization" token="token" />) | |||
).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,30 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import JavaMaven from '../JavaMaven'; | |||
it('renders correctly', () => { | |||
expect(shallow(<JavaMaven host="host" token="token" />)).toMatchSnapshot(); | |||
expect( | |||
shallow(<JavaMaven host="host" organization="organization" token="token" />) | |||
).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,27 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import MSBuildScanner from '../MSBuildScanner'; | |||
it('renders correctly', () => { | |||
expect(shallow(<MSBuildScanner />)).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,30 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import Msvc from '../Msvc'; | |||
it('renders correctly', () => { | |||
expect(shallow(<Msvc host="host" projectKey="projectKey" token="token" />)).toMatchSnapshot(); | |||
expect( | |||
shallow(<Msvc host="host" organization="organization" projectKey="projectKey" token="token" />) | |||
).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,45 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import Other from '../Other'; | |||
it('renders correctly', () => { | |||
expect( | |||
shallow(<Other host="host" os="win" projectKey="projectKey" token="token" />) | |||
).toMatchSnapshot(); | |||
expect( | |||
shallow(<Other host="host" os="linux" projectKey="projectKey" token="token" />) | |||
).toMatchSnapshot(); | |||
expect( | |||
shallow( | |||
<Other | |||
host="host" | |||
os="linux" | |||
organization="organization" | |||
projectKey="projectKey" | |||
token="token" | |||
/> | |||
) | |||
).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,29 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
// @flow | |||
import React from 'react'; | |||
import { shallow } from 'enzyme'; | |||
import SQScanner from '../SQScanner'; | |||
it('renders correctly', () => { | |||
expect(shallow(<SQScanner os="win" />)).toMatchSnapshot(); | |||
expect(shallow(<SQScanner os="linux" />)).toMatchSnapshot(); | |||
expect(shallow(<SQScanner os="mac" />)).toMatchSnapshot(); | |||
}); |
@@ -0,0 +1,85 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.build_wrapper.header.win | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.build_wrapper.text.win", | |||
} | |||
} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
download="build-wrapper-linux-x86.zip" | |||
href="/static/cpp/build-wrapper-linux-x86.zip" | |||
target="_blank" | |||
> | |||
download_verb | |||
</a> | |||
</p> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.build_wrapper.header.linux | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.build_wrapper.text.linux", | |||
} | |||
} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
download="build-wrapper-win-x86.zip" | |||
href="/static/cpp/build-wrapper-win-x86.zip" | |||
target="_blank" | |||
> | |||
download_verb | |||
</a> | |||
</p> | |||
</div> | |||
`; | |||
exports[`renders correctly 3`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.build_wrapper.header.mac | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.build_wrapper.text.mac", | |||
} | |||
} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
download="build-wrapper-macosx-x86.zip" | |||
href="/static/cpp/build-wrapper-macosx-x86.zip" | |||
target="_blank" | |||
> | |||
download_verb | |||
</a> | |||
</p> | |||
</div> | |||
`; |
@@ -0,0 +1,148 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<SQScanner | |||
os="win" | |||
/> | |||
<BuildWrapper | |||
className="huge-spacer-top" | |||
os="win" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command="build-wrapper-win-x86-64.exe --out-dir bw-output make clean all" | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"sonar-scanner.bat", | |||
"-Dsonar.projectKey=projectKey", | |||
undefined, | |||
"-Dsonar.sources=.", | |||
"-Dsonar.cfamily.build-wrapper-output=bw-output", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<SQScanner | |||
os="linux" | |||
/> | |||
<BuildWrapper | |||
className="huge-spacer-top" | |||
os="linux" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command="build-wrapper-linux-x86-64 --out-dir bw-output make clean all" | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"sonar-scanner", | |||
"-Dsonar.projectKey=projectKey", | |||
undefined, | |||
"-Dsonar.sources=.", | |||
"-Dsonar.cfamily.build-wrapper-output=bw-output", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 3`] = ` | |||
<div> | |||
<SQScanner | |||
os="linux" | |||
/> | |||
<BuildWrapper | |||
className="huge-spacer-top" | |||
os="linux" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command="build-wrapper-linux-x86-64 --out-dir bw-output make clean all" | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"sonar-scanner", | |||
"-Dsonar.projectKey=projectKey", | |||
"-Dsonar.organization=organization", | |||
"-Dsonar.sources=.", | |||
"-Dsonar.cfamily.build-wrapper-output=bw-output", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,18 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div | |||
className="onboarding-command" | |||
> | |||
<pre> | |||
foo | |||
bar | |||
</pre> | |||
<button | |||
data-clipboard-text="foo | |||
bar" | |||
> | |||
copy | |||
</button> | |||
</div> | |||
`; |
@@ -0,0 +1,99 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<MSBuildScanner /> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.msbuild.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe begin", | |||
"/k:\\"projectKey\\"", | |||
undefined, | |||
"/d:\\"sonar.host.url=host", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<Command | |||
command="MsBuild.exe /t:Rebuild" | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe end", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<MSBuildScanner /> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.msbuild.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe begin", | |||
"/k:\\"projectKey\\"", | |||
"/d:\\"sonar.organization=organization\\"", | |||
"/d:\\"sonar.host.url=host", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<Command | |||
command="MsBuild.exe /t:Rebuild" | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe end", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,93 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.java.gradle.header | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.java.gradle.text.1", | |||
} | |||
} | |||
/> | |||
<Command | |||
command="plugins { | |||
id \\"org.sonarqube\\" version \\"2.2\\" | |||
}" | |||
/> | |||
<p | |||
className="spacer-top spacer-bottom markdown" | |||
> | |||
onboarding.analysis.java.gradle.text.2 | |||
</p> | |||
<Command | |||
command={ | |||
Array [ | |||
"./gradlew sonarqube", | |||
undefined, | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.java.gradle.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.java.gradle.header | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.java.gradle.text.1", | |||
} | |||
} | |||
/> | |||
<Command | |||
command="plugins { | |||
id \\"org.sonarqube\\" version \\"2.2\\" | |||
}" | |||
/> | |||
<p | |||
className="spacer-top spacer-bottom markdown" | |||
> | |||
onboarding.analysis.java.gradle.text.2 | |||
</p> | |||
<Command | |||
command={ | |||
Array [ | |||
"./gradlew sonarqube", | |||
"-Dsonar.organization=organization", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.java.gradle.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,67 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.java.maven.header | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
> | |||
onboarding.analysis.java.maven.text | |||
</p> | |||
<Command | |||
command={ | |||
Array [ | |||
"mvn sonar:sonar", | |||
undefined, | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.java.maven.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.java.maven.header | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
> | |||
onboarding.analysis.java.maven.text | |||
</p> | |||
<Command | |||
command={ | |||
Array [ | |||
"mvn sonar:sonar", | |||
"-Dsonar.organization=organization", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.java.maven.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,28 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.msbuild.header | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.text", | |||
} | |||
} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" | |||
target="_blank" | |||
> | |||
download_verb | |||
</a> | |||
</p> | |||
</div> | |||
`; |
@@ -0,0 +1,109 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<MSBuildScanner /> | |||
<BuildWrapper | |||
className="huge-spacer-top" | |||
os="win" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.msbuild.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe begin", | |||
"/k:\\"projectKey\\"", | |||
undefined, | |||
"/d:\\"sonar.cfamily.build-wrapper-output=bw-output\\"", | |||
"/d:\\"sonar.host.url=host", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<Command | |||
command="build-wrapper-win-x86-64.exe --out-dir bw-output MsBuild.exe /t:Rebuild" | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe end", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<MSBuildScanner /> | |||
<BuildWrapper | |||
className="huge-spacer-top" | |||
os="win" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.msbuild.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe begin", | |||
"/k:\\"projectKey\\"", | |||
"/d:\\"sonar.organization=organization\\"", | |||
"/d:\\"sonar.cfamily.build-wrapper-output=bw-output\\"", | |||
"/d:\\"sonar.host.url=host", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<Command | |||
command="build-wrapper-win-x86-64.exe --out-dir bw-output MsBuild.exe /t:Rebuild" | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"SonarQube.Scanner.MSBuild.exe end", | |||
"/d:\\"sonar.login=token\\"", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.msbuild.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,124 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<SQScanner | |||
os="win" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"sonar-scanner.bat", | |||
"-Dsonar.projectKey=projectKey", | |||
undefined, | |||
"-Dsonar.sources=.", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<SQScanner | |||
os="linux" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"sonar-scanner", | |||
"-Dsonar.projectKey=projectKey", | |||
undefined, | |||
"-Dsonar.sources=.", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; | |||
exports[`renders correctly 3`] = ` | |||
<div> | |||
<SQScanner | |||
os="linux" | |||
/> | |||
<h4 | |||
className="huge-spacer-top spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.execute | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.execute.text", | |||
} | |||
} | |||
/> | |||
<Command | |||
command={ | |||
Array [ | |||
"sonar-scanner", | |||
"-Dsonar.projectKey=projectKey", | |||
"-Dsonar.organization=organization", | |||
"-Dsonar.sources=.", | |||
"-Dsonar.host.url=host", | |||
"-Dsonar.login=token", | |||
] | |||
} | |||
/> | |||
<p | |||
className="big-spacer-top markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.docs", | |||
} | |||
} | |||
/> | |||
</div> | |||
`; |
@@ -0,0 +1,82 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
exports[`renders correctly 1`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.header.win | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.text.win", | |||
} | |||
} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" | |||
target="_blank" | |||
> | |||
download_verb | |||
</a> | |||
</p> | |||
</div> | |||
`; | |||
exports[`renders correctly 2`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.header.linux | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.text.linux", | |||
} | |||
} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" | |||
target="_blank" | |||
> | |||
download_verb | |||
</a> | |||
</p> | |||
</div> | |||
`; | |||
exports[`renders correctly 3`] = ` | |||
<div> | |||
<h4 | |||
className="spacer-bottom" | |||
> | |||
onboarding.analysis.sq_scanner.header.mac | |||
</h4> | |||
<p | |||
className="spacer-bottom markdown" | |||
dangerouslySetInnerHTML={ | |||
Object { | |||
"__html": "onboarding.analysis.sq_scanner.text.mac", | |||
} | |||
} | |||
/> | |||
<p> | |||
<a | |||
className="button" | |||
href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" | |||
target="_blank" | |||
> | |||
download_verb | |||
</a> | |||
</p> | |||
</div> | |||
`; |
@@ -0,0 +1,59 @@ | |||
.onboarding-step { | |||
position: relative; | |||
padding-left: 34px; | |||
} | |||
.onboarding-step .boxed-group-actions { | |||
height: 24px; | |||
line-height: 24px; | |||
} | |||
.onboarding-step-number { | |||
position: absolute; | |||
top: 15px; | |||
left: 15px; | |||
width: 24px; | |||
height: 24px; | |||
line-height: 24px; | |||
border-radius: 24px; | |||
background-color: #cdcdcd; | |||
color: #fff; | |||
font-size: 14px; | |||
text-align: center; | |||
} | |||
.onboarding-step-open .onboarding-step-number { | |||
background-color: #236a97; | |||
} | |||
.onboarding-command { | |||
position: relative; | |||
margin: 8px 0; | |||
} | |||
.onboarding-command pre { | |||
padding: 15px; | |||
border-radius: 2px; | |||
background: #404040; | |||
color: #f0f0f0; | |||
overflow: auto; | |||
} | |||
.onboarding-command button { | |||
position: absolute; | |||
top: 15px; | |||
right: 15px; | |||
height: 20px; | |||
line-height: 18px; | |||
border: 1px solid #fff; | |||
color: #fff; | |||
font-size: 11px; | |||
font-weight: normal; | |||
} | |||
.onboarding-command button:hover, | |||
.onboarding-command button:focus, | |||
.onboarding-command button:active { | |||
background-color: #fff; | |||
color: #404040; | |||
} |
@@ -0,0 +1,31 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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. | |||
*/ | |||
const routes = [ | |||
{ | |||
path: 'onboarding', | |||
getComponent(_, callback) { | |||
require.ensure([], require => { | |||
callback(null, require('./onboarding/OnboardingContainer').default); | |||
}); | |||
} | |||
} | |||
]; | |||
export default routes; |
@@ -54,17 +54,13 @@ export default Modal.extend({ | |||
this.errors = []; | |||
this.newToken = null; | |||
const tokenName = this.$('.js-generate-token-form input').val(); | |||
generateToken(this.model.id, tokenName) | |||
.then(response => { | |||
generateToken(tokenName, this.model.id).then( | |||
response => { | |||
this.newToken = response; | |||
this.requestTokens(); | |||
}) | |||
.catch(error => { | |||
error.response.json().then(response => { | |||
this.errors = response.errors; | |||
this.render(); | |||
}); | |||
}); | |||
}, | |||
() => {} | |||
); | |||
}, | |||
onRevokeTokenFormSubmit(e) { | |||
@@ -73,7 +69,7 @@ export default Modal.extend({ | |||
const token = this.tokens.find(t => t.name === `${tokenName}`); | |||
if (token) { | |||
if (token.deleting) { | |||
revokeToken(this.model.id, tokenName).then(this.requestTokens.bind(this)); | |||
revokeToken(tokenName, this.model.id).then(this.requestTokens.bind(this), () => {}); | |||
} else { | |||
token.deleting = true; | |||
this.render(); |
@@ -54,3 +54,11 @@ export const elementKeydown = (element, keyCode) => { | |||
preventDefault() {} | |||
}); | |||
}; | |||
export const doAsync = fn => | |||
new Promise(resolve => { | |||
setTimeout(() => { | |||
fn(); | |||
resolve(); | |||
}, 0); | |||
}); |
@@ -43,6 +43,11 @@ | |||
opacity: 1; | |||
} | |||
.modal-medium { | |||
width: 800px; | |||
margin-left: -400px; | |||
} | |||
.modal-large { | |||
width: 90vw; | |||
margin-left: -45vw; |
@@ -0,0 +1,86 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2017 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 (reference) "../mixins"; | |||
@import (reference) "../variables"; | |||
.side-tabs-layout { | |||
display: flex; | |||
justify-content: space-between; | |||
align-items: stretch; | |||
.modal & { | |||
padding-left: 10px; | |||
background-color: @barBackgroundColor; | |||
} | |||
} | |||
.side-tabs-main { | |||
position: relative; | |||
z-index: 2; | |||
flex-grow: 1; | |||
padding: 15px 20px; | |||
border: 1px solid @barBorderColor; | |||
box-sizing: border-box; | |||
background-color: #fff; | |||
.modal & { | |||
border-top: none; | |||
border-bottom: none; | |||
border-right: none; | |||
} | |||
} | |||
.side-tabs-side { | |||
position: relative; | |||
z-index: 3; | |||
width: 160px; | |||
flex-shrink: 0; | |||
padding: 10px 0; | |||
box-sizing: border-box; | |||
transform: translateX(1px); | |||
} | |||
.side-tabs-menu > li { | |||
margin-bottom: 4px; | |||
} | |||
.side-tabs-menu > li > a { | |||
display: block; | |||
padding: 10px 10px; | |||
line-height: 1.5; | |||
border-top-left-radius: 3px; | |||
border-bottom-left-radius: 3px; | |||
border: 1px solid @barBorderColor; | |||
border-right: none; | |||
overflow: hidden; | |||
text-overflow: ellipsis; | |||
transition: color 0.3s ease, background-color 0.3s ease; | |||
} | |||
.side-tabs-menu > li > a:hover, | |||
.side-tabs-menu > li > a:focus, | |||
.side-tabs-menu > li > a.active { | |||
background-color: #fff; | |||
} | |||
.side-tabs-menu > li > a.active { | |||
color: #444; | |||
cursor: default; | |||
} |
@@ -114,6 +114,7 @@ small, | |||
.text-top { vertical-align: top; } | |||
.text-middle { vertical-align: middle; } | |||
.text-bottom { vertical-align: bottom; } | |||
.text-text-top { vertical-align: text-top !important; } | |||
// Overflow |
@@ -58,6 +58,7 @@ | |||
@import "components/search"; | |||
@import "components/pills"; | |||
@import "components/react-select"; | |||
@import "components/side-tabs"; | |||
@import "pages/coding-rules"; | |||
@import "pages/maintenance"; |
@@ -47,6 +47,7 @@ component=Component | |||
configurable=Configurable | |||
configure=Configure | |||
confirm=Confirm | |||
continue=Continue | |||
copy=Copy | |||
create=Create | |||
created=Created | |||
@@ -301,6 +302,7 @@ since_previous_version.short=\u0394 version | |||
since_previous_version_detailed=since previous version ({0} - {1}) | |||
since_previous_version_with_only_date=since previous version ({0}) | |||
since_previous_version_detailed.short=\u0394 version ({0}) | |||
this_name_is_already_taken=This name is already taken. | |||
time_changes=Time changes | |||
work_duration.x_days={0}d | |||
work_duration.x_hours={0}h | |||
@@ -1054,10 +1056,12 @@ search.placeholder=Search for projects, sub-projects and files... | |||
#------------------------------------------------------------------------------ | |||
# | |||
# SHORTCUTS | |||
# GLOBAL HELP | |||
# | |||
#------------------------------------------------------------------------------ | |||
shortcuts.modal_title=Shortcuts | |||
help.section.links=Links | |||
help.section.shortcuts=Shortcuts | |||
help.section.tutorials=Tutorials | |||
shortcuts.section.global=Global | |||
shortcuts.section.global.search=quickly open search bar | |||
@@ -2937,3 +2941,79 @@ footer.terms=Terms | |||
footer.twitter=Twitter | |||
footer.version_x=Version {0} | |||
footer.web_api=Web API | |||
#------------------------------------------------------------------------------ | |||
# | |||
# ONBOARDING | |||
# | |||
#------------------------------------------------------------------------------ | |||
onboarding.header=Welcome to SonarQube! | |||
onboarding.header.sonarcloud=Welcome to SonarCloud! | |||
onboarding.header.description=Let's learn how to analyze your first public project. | |||
onboarding.token.header=Generate a token | |||
onboarding.token.text=We'll use it as a replacement of the user login. This will increase the security of your installation by not letting your analysis user's password going through your network. | |||
onboarding.token.generate=Generate | |||
onboarding.token.placeholder=Enter a name for your token | |||
onboarding.organization.header=Choose an organization for your project | |||
onboarding.organization.text=Organizations are where your projects belong. You can add your team members to your organization later to allow them to contribute to your projects. | |||
onboarding.organization.placeholder=Enter a name for your organization | |||
onboarding.organization.my_personal_organization=My personal organization | |||
onboarding.organization.exising_organization=Existing organization | |||
onboarding.organization.create_another_organization=Create another organization | |||
onboarding.organization.key_requirement=2 to 32 characters. All chars must be lower-case letters (a to z), digits or dash (but dash can neither be trailing nor heading) | |||
onboarding.project_key_requirement=Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit. 400 characters max. | |||
onboarding.analysis.header=Run analysis on your project | |||
onboarding.language=What is your project's main language? | |||
onboarding.language.java=Java | |||
onboarding.language.java.build_technology=You are developing primarily in Java: what is your build technology? | |||
onboarding.language.java.build_technology.maven=Maven | |||
onboarding.language.java.build_technology.gradle=Gradle | |||
onboarding.language.dotnet=C# or VB.NET | |||
onboarding.language.c-family=C, C++, Objective-C | |||
onboarding.language.c-family.compiler=Which compiler are you using? | |||
onboarding.language.c-family.compiler.msvc=Microsoft Visual C++ | |||
onboarding.language.c-family.compiler.clang-gcc=CLang or GGC | |||
onboarding.language.other=Other (JS, Python, PHP, ...) | |||
onboarding.language.os=What is your OS? | |||
onboarding.language.os.linux=Linux | |||
onboarding.language.os.win=Windows | |||
onboarding.language.os.mac=macOS | |||
onboarding.language.project_key=Define a unique project key | |||
onboarding.analysis.java.maven.header=Execute the SonarQube Scanner for Maven from your computer | |||
onboarding.analysis.java.maven.text=Running a SonarQube analysis with Maven is straighforward. You just need to run the following command in your project's folder. | |||
onboarding.analysis.java.maven.docs=Please visit the <a href="http://redirect.sonarsource.com/doc/install-configure-scanner-maven.html" target="_blank">official documentation of the SonarQube Scanner for Maven</a> for more details. | |||
onboarding.analysis.java.gradle.header=Execute the SonarQube Scanner for Gradle from your computer | |||
onboarding.analysis.java.gradle.text.1=Running a SonarQube analysis with Gradle is straighforward. You just need to declare the <code>org.sonarqube</code> plugin in your <code>build.gradle</code> file: | |||
onboarding.analysis.java.gradle.text.2=and run the following command: | |||
onboarding.analysis.java.gradle.docs=Please visit the <a href="http://redirect.sonarsource.com/doc/gradle.html" target="_blank">official documentation of the SonarQube Scanner for Gradle</a> for more details. | |||
onboarding.analysis.msbuild.header=Download and unzip the SonarQube Scanner for MSBuild | |||
onboarding.analysis.msbuild.text=And add the executable's directory to the <code>%PATH%</code> environment variable | |||
onboarding.analysis.msbuild.execute=Execute the SonarQube Scanner for MSBuild from your computer | |||
onboarding.analysis.msbuild.execute.text=Running a SonarQube analysis is straighforward. You just need to execute the following commands at the root of your solution. | |||
onboarding.analysis.msbuild.docs=Please visit the <a href="http://redirect.sonarsource.com/doc/install-configure-scanner-msbuild.html" target="_blank">official documentation of the SonarQube Scanner for MSBuild</a> for more details. | |||
onboarding.analysis.build_wrapper.header.linux=Download and unzip the Build Wrapper for Linux | |||
onboarding.analysis.build_wrapper.header.win=Download and unzip the Build Wrapper for Windows | |||
onboarding.analysis.build_wrapper.header.mac=Download and unzip the Build Wrapper for macOS | |||
onboarding.analysis.build_wrapper.text.linux=And add the executable's directory to the <code>PATH</code> environment variable | |||
onboarding.analysis.build_wrapper.text.win=And add the executable's directory to the <code>%PATH%</code> environment variable | |||
onboarding.analysis.build_wrapper.text.mac=And add the executable's directory to the <code>PATH</code> environment variable | |||
onboarding.analysis.sq_scanner.header.linux=Download and unzip the SonarQube Scanner for Linux | |||
onboarding.analysis.sq_scanner.header.win=Download and unzip the SonarQube Scanner for Windows | |||
onboarding.analysis.sq_scanner.header.mac=Download and unzip the SonarQube Scanner for macOS | |||
onboarding.analysis.sq_scanner.text.linux=And add the <code>bin</code> directory to the <code>PATH</code> environment variable | |||
onboarding.analysis.sq_scanner.text.win=And add the <code>bin</code> directory to the <code>%PATH%</code> environment variable | |||
onboarding.analysis.sq_scanner.text.mac=And add the <code>bin</code> directory to the <code>PATH</code> environment variable | |||
onboarding.analysis.sq_scanner.execute=Execute the SonarQube Scanner from your computer | |||
onboarding.analysis.sq_scanner.execute.text=Running a SonarQube analysis is straighforward. You just need to execute the following commands in your project's folder. | |||
onboarding.analysis.sq_scanner.docs=Please visit the <a href="http://redirect.sonarsource.com/doc/install-configure-scanner.html" target="_blank">official documentation of the SonarQube Scanner</a> for more details. |