diff options
Diffstat (limited to 'server/sonar-web/src/main/js/app')
47 files changed, 849 insertions, 788 deletions
diff --git a/server/sonar-web/src/main/js/app/components/AdminContainer.js b/server/sonar-web/src/main/js/app/components/AdminContainer.js index f0830c3b9a3..84ca940e53a 100644 --- a/server/sonar-web/src/main/js/app/components/AdminContainer.js +++ b/server/sonar-web/src/main/js/app/components/AdminContainer.js @@ -27,7 +27,7 @@ import { getSettingsNavigation } from '../../api/nav'; import { setAdminPages } from '../../store/appState/duck'; class AdminContainer extends React.Component { - componentDidMount () { + componentDidMount() { if (!isUserAdmin(this.props.currentUser)) { // workaround cyclic dependencies const handleRequiredAuthorization = require('../utils/handleRequiredAuthorization').default; @@ -36,23 +36,23 @@ class AdminContainer extends React.Component { this.loadData(); } - loadData () { + loadData() { getSettingsNavigation().then( r => this.props.setAdminPages(r.extensions), onFail(this.props.dispatch) ); } - render () { + render() { if (!isUserAdmin(this.props.currentUser) || !this.props.adminPages) { return null; } return ( - <div> - <SettingsNav location={this.props.location} extensions={this.props.adminPages}/> - {this.props.children} - </div> + <div> + <SettingsNav location={this.props.location} extensions={this.props.adminPages} /> + {this.props.children} + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/App.js b/server/sonar-web/src/main/js/app/components/App.js index db7f3aecaa2..647acffd144 100644 --- a/server/sonar-web/src/main/js/app/components/App.js +++ b/server/sonar-web/src/main/js/app/components/App.js @@ -45,32 +45,36 @@ class App extends React.Component { } }; - componentDidMount () { + componentDidMount() { this.mounted = true; - this.props.fetchCurrentUser() - .then(() => Promise.all([ + this.props + .fetchCurrentUser() + .then(() => + Promise.all([ this.props.fetchAppState(), this.props.fetchOrganizations(), this.props.fetchLanguages() ])) - .then(this.finishLoading, this.finishLoading); + .then(this.finishLoading, this.finishLoading); } - componentWillUnmount () { + componentWillUnmount() { this.mounted = false; } - render () { + render() { if (this.state.loading) { - return <GlobalLoading/>; + return <GlobalLoading />; } return this.props.children; } } -export default connect( - null, - { fetchAppState, fetchCurrentUser, fetchLanguages, fetchOrganizations } -)(App); +export default connect(null, { + fetchAppState, + fetchCurrentUser, + fetchLanguages, + fetchOrganizations +})(App); diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.js b/server/sonar-web/src/main/js/app/components/GlobalContainer.js index 05219392c0e..e59fd05b2c6 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.js +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.js @@ -24,20 +24,20 @@ import GlobalFooter from './GlobalFooter'; import GlobalMessagesContainer from './GlobalMessagesContainer'; export default class GlobalContainer extends React.Component { - render () { + render() { // it is important to pass `location` down to `GlobalNav` to trigger render on url change return ( - <div className="global-container"> - <div className="page-wrapper page-wrapper-global" id="container"> - <div className="page-container"> - <GlobalNav location={this.props.location}/> - <GlobalMessagesContainer/> - {this.props.children} - </div> + <div className="global-container"> + <div className="page-wrapper page-wrapper-global" id="container"> + <div className="page-container"> + <GlobalNav location={this.props.location} /> + <GlobalMessagesContainer /> + {this.props.children} </div> - <GlobalFooter/> </div> + <GlobalFooter /> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooter.js b/server/sonar-web/src/main/js/app/components/GlobalFooter.js index f28d36ac5f0..886de879bab 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalFooter.js +++ b/server/sonar-web/src/main/js/app/components/GlobalFooter.js @@ -25,43 +25,42 @@ import { getAppState } from '../../store/rootReducer'; import GlobalFooterBranding from './GlobalFooterBranding'; class GlobalFooter extends React.Component { - render () { + render() { const { sonarqubeVersion, productionDatabase } = this.props; return ( - <div id="footer" className="page-footer page-container"> - {productionDatabase === false && ( - <div className="alert alert-danger"> - <p className="big" id="evaluation_warning"> - Embedded database should be used for evaluation purpose only - </p> - <p> - The embedded database will not scale, it will not support upgrading to newer versions of SonarQube, - and there is no support for migrating your data out of it into a different database engine. - </p> - </div> - )} + <div id="footer" className="page-footer page-container"> + {productionDatabase === false && + <div className="alert alert-danger"> + <p className="big" id="evaluation_warning"> + Embedded database should be used for evaluation purpose only + </p> + <p> + The embedded database will not scale, it will not support upgrading to newer versions of SonarQube, + and there is no support for migrating your data out of it into a different database engine. + </p> + </div>} - <GlobalFooterBranding/> + <GlobalFooterBranding /> - <div> - Version {sonarqubeVersion} - {' - '} - <a href="http://www.gnu.org/licenses/lgpl-3.0.txt">LGPL v3</a> - {' - '} - <a href="http://www.sonarqube.org">Community</a> - {' - '} - <a href="https://redirect.sonarsource.com/doc/home.html">Documentation</a> - {' - '} - <a href="https://redirect.sonarsource.com/doc/community.html">Get Support</a> - {' - '} - <a href="https://redirect.sonarsource.com/doc/plugin-library.html">Plugins</a> - {' - '} - <Link to="/web_api">Web API</Link> - {' - '} - <Link to="/about">About</Link> - </div> + <div> + Version {sonarqubeVersion} + {' - '} + <a href="http://www.gnu.org/licenses/lgpl-3.0.txt">LGPL v3</a> + {' - '} + <a href="http://www.sonarqube.org">Community</a> + {' - '} + <a href="https://redirect.sonarsource.com/doc/home.html">Documentation</a> + {' - '} + <a href="https://redirect.sonarsource.com/doc/community.html">Get Support</a> + {' - '} + <a href="https://redirect.sonarsource.com/doc/plugin-library.html">Plugins</a> + {' - '} + <Link to="/web_api">Web API</Link> + {' - '} + <Link to="/about">About</Link> </div> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js b/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js index 1d80c194eaa..1ca8a72c20a 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js +++ b/server/sonar-web/src/main/js/app/components/GlobalFooterBranding.js @@ -21,17 +21,17 @@ import React from 'react'; export default class GlobalFooterBranding extends React.Component { - render () { + render() { return ( - <div> - This application is based on - {' '} - <a href="http://www.sonarqube.org/" title="SonarQube™">SonarQube™</a> - {' '} - but is <strong>not</strong> an official version provided by - {' '} - <a href="http://www.sonarsource.com" title="SonarSource SA">SonarSource SA</a>. - </div> + <div> + This application is based on + {' '} + <a href="http://www.sonarqube.org/" title="SonarQubeâ„¢">SonarQube™</a> + {' '} + but is <strong>not</strong> an official version provided by + {' '} + <a href="http://www.sonarsource.com" title="SonarSource SA">SonarSource SA</a>. + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/GlobalLoading.js b/server/sonar-web/src/main/js/app/components/GlobalLoading.js index 67d707e52ca..b5e45197357 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalLoading.js +++ b/server/sonar-web/src/main/js/app/components/GlobalLoading.js @@ -22,12 +22,12 @@ import React from 'react'; import './GlobalLoading.css'; export default class GlobalLoading extends React.Component { - render () { + render() { return ( - <div className="global-loading"> - <i className="spinner global-loading-spinner"/> - <span className="global-loading-text">Loading...</span> - </div> + <div className="global-loading"> + <i className="spinner global-loading-spinner" /> + <span className="global-loading-text">Loading...</span> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/Landing.js b/server/sonar-web/src/main/js/app/components/Landing.js index 7b4ba1721dc..5239df6f93b 100644 --- a/server/sonar-web/src/main/js/app/components/Landing.js +++ b/server/sonar-web/src/main/js/app/components/Landing.js @@ -25,10 +25,13 @@ import { getCurrentUser } from '../../store/rootReducer'; class Landing extends React.Component { static propTypes = { - currentUser: React.PropTypes.oneOfType([React.PropTypes.bool, React.PropTypes.object]).isRequired + currentUser: React.PropTypes.oneOfType([ + React.PropTypes.bool, + React.PropTypes.object + ]).isRequired }; - componentDidMount () { + componentDidMount() { const { currentUser, router } = this.props; if (currentUser.isLoggedIn) { router.replace('/projects'); @@ -37,7 +40,7 @@ class Landing extends React.Component { } } - render () { + render() { return null; } } diff --git a/server/sonar-web/src/main/js/app/components/LocalizationContainer.js b/server/sonar-web/src/main/js/app/components/LocalizationContainer.js index 21bd6c1a57b..8cbbec134be 100644 --- a/server/sonar-web/src/main/js/app/components/LocalizationContainer.js +++ b/server/sonar-web/src/main/js/app/components/LocalizationContainer.js @@ -34,16 +34,16 @@ export default class LocalizationContainer extends React.Component { } }; - componentDidMount () { + componentDidMount() { this.mounted = true; requestMessages().then(this.finishLoading, this.finishLoading); } - componentWillUnmount () { + componentWillUnmount() { this.mounted = false; } - render () { + render() { return this.state.loading ? null : this.props.children; } } diff --git a/server/sonar-web/src/main/js/app/components/MarkdownHelp.js b/server/sonar-web/src/main/js/app/components/MarkdownHelp.js index 70263175f0a..4502435d47e 100644 --- a/server/sonar-web/src/main/js/app/components/MarkdownHelp.js +++ b/server/sonar-web/src/main/js/app/components/MarkdownHelp.js @@ -21,7 +21,7 @@ import React from 'react'; export default class MarkdownHelp extends React.Component { - render () { + render() { return ( <div className="page page-limited"> <h2 className="spacer-bottom">Markdown Syntax</h2> @@ -50,7 +50,7 @@ export default class MarkdownHelp extends React.Component { </td> </tr> <tr> - <td className="text-top">* first item<br/> + <td className="text-top">* first item<br /> * second item </td> <td className="markdown"> @@ -61,7 +61,7 @@ export default class MarkdownHelp extends React.Component { </td> </tr> <tr> - <td className="text-top">1. first item<br/> + <td className="text-top">1. first item<br /> 1. second item </td> <td className="markdown text-top"> @@ -73,12 +73,12 @@ export default class MarkdownHelp extends React.Component { </tr> <tr> <td className="text-top"> - = Heading Level 1<br/> - == Heading Level 2<br/> - === Heading Level 3<br/> - ==== Heading Level 4<br/> - ===== Heading Level 5<br/> - ====== Heading Level 6<br/> + = Heading Level 1<br /> + == Heading Level 2<br /> + === Heading Level 3<br /> + ==== Heading Level 4<br /> + ===== Heading Level 5<br /> + ====== Heading Level 6<br /> </td> <td className="markdown text-top"> <h1>Heading Level 1</h1> @@ -95,11 +95,11 @@ export default class MarkdownHelp extends React.Component { </tr> <tr> <td className="text-top"> - ``<br/> - // code on multiple lines<br/> - {'public void foo() {'}<br/> - {'// do some logic here'}<br/> - {'}'}<br/> + ``<br /> + // code on multiple lines<br /> + {'public void foo() {'}<br /> + {'// do some logic here'}<br /> + {'}'}<br /> `` </td> <td className="markdown text-top"> @@ -113,14 +113,14 @@ export default class MarkdownHelp extends React.Component { </tr> <tr> <td className="text-top"> - Standard text<br/> - > Blockquoted text<br/> - > that spans multiple lines<br/> + Standard text<br /> + > Blockquoted text<br /> + > that spans multiple lines<br /> </td> <td className="markdown text-top"> <p>Standard text</p> - <blockquote>Blockquoted text<br/> - that spans multiple lines<br/></blockquote> + <blockquote>Blockquoted text<br /> + that spans multiple lines<br /></blockquote> </td> </tr> </tbody> diff --git a/server/sonar-web/src/main/js/app/components/MigrationContainer.js b/server/sonar-web/src/main/js/app/components/MigrationContainer.js index 46ed174a8c9..4441e3e8373 100644 --- a/server/sonar-web/src/main/js/app/components/MigrationContainer.js +++ b/server/sonar-web/src/main/js/app/components/MigrationContainer.js @@ -32,7 +32,7 @@ class MigrationContainer extends React.Component { loading: true }; - componentDidMount () { + componentDidMount() { getSystemStatus().then(r => { if (r.status === 'UP') { this.setState({ loading: false }); @@ -42,7 +42,7 @@ class MigrationContainer extends React.Component { }); } - render () { + render() { if (this.state.loading) { return null; } diff --git a/server/sonar-web/src/main/js/app/components/NotFound.js b/server/sonar-web/src/main/js/app/components/NotFound.js index 98e1e55aca4..2692a72a90d 100644 --- a/server/sonar-web/src/main/js/app/components/NotFound.js +++ b/server/sonar-web/src/main/js/app/components/NotFound.js @@ -22,13 +22,15 @@ import { Link } from 'react-router'; import SimpleContainer from './SimpleContainer'; export default class NotFound extends React.Component { - render () { + render() { return ( - <SimpleContainer> - <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2> - <p className="spacer-bottom">You may have mistyped the address or the page may have moved.</p> - <p><Link to="/">Go back to the homepage</Link></p> - </SimpleContainer> + <SimpleContainer> + <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2> + <p className="spacer-bottom"> + You may have mistyped the address or the page may have moved. + </p> + <p><Link to="/">Go back to the homepage</Link></p> + </SimpleContainer> ); } } diff --git a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js index 6c8f4418520..79c773e10af 100644 --- a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js +++ b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.js @@ -31,26 +31,26 @@ class ProjectAdminContainer extends React.Component { } }; - componentDidMount () { + componentDidMount() { this.checkPermissions(); } - componentDidUpdate () { + componentDidUpdate() { this.checkPermissions(); } - isProjectAdmin () { + isProjectAdmin() { const { configuration } = this.props.project; return configuration != null && configuration.showSettings; } - checkPermissions () { + checkPermissions() { if (!this.isProjectAdmin()) { handleRequiredAuthorization(); } } - render () { + render() { if (!this.isProjectAdmin()) { return null; } diff --git a/server/sonar-web/src/main/js/app/components/ProjectContainer.js b/server/sonar-web/src/main/js/app/components/ProjectContainer.js index 5e8c5e3738c..4dd98290d38 100644 --- a/server/sonar-web/src/main/js/app/components/ProjectContainer.js +++ b/server/sonar-web/src/main/js/app/components/ProjectContainer.js @@ -39,19 +39,18 @@ class ProjectContainer extends React.Component { qualifier: string }, fetchProject: (string) => Promise<*> - } - - componentDidMount () { + }; + componentDidMount() { this.fetchProject(); } - componentDidUpdate (prevProps) { + componentDidUpdate(prevProps) { if (prevProps.location.query.id !== this.props.location.query.id) { this.fetchProject(); } } - fetchProject () { + fetchProject() { this.props.fetchProject(this.props.location.query.id).catch(e => { if (e.response.status === 403) { handleRequiredAuthorization(); @@ -61,7 +60,7 @@ class ProjectContainer extends React.Component { }); } - render () { + render() { // check `breadcrumbs` to be sure that /api/navigation/component has been already called if (!this.props.project || this.props.project.breadcrumbs == null) { return null; @@ -73,12 +72,10 @@ class ProjectContainer extends React.Component { const configuration = this.props.project.configuration || {}; return ( - <div> - {!isFile && ( - <ComponentNav component={this.props.project} conf={configuration}/> - )} - {this.props.children} - </div> + <div> + {!isFile && <ComponentNav component={this.props.project} conf={configuration} />} + {this.props.children} + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/SimpleContainer.js b/server/sonar-web/src/main/js/app/components/SimpleContainer.js index 106a948c7a3..7fd30d02596 100644 --- a/server/sonar-web/src/main/js/app/components/SimpleContainer.js +++ b/server/sonar-web/src/main/js/app/components/SimpleContainer.js @@ -29,30 +29,30 @@ export default class SimpleContainer extends React.Component { ]) }; - componentDidMount () { + componentDidMount() { document.querySelector('html').classList.add('dashboard-page'); } - componentWillUnmount () { + componentWillUnmount() { document.querySelector('html').classList.remove('dashboard-page'); } - render () { + render() { return ( - <div className="global-container"> - <div className="page-wrapper page-wrapper-global" id="container"> - <nav className="navbar navbar-global page-container" id="global-navigation"> - <div className="navbar-header"/> - </nav> + <div className="global-container"> + <div className="page-wrapper page-wrapper-global" id="container"> + <nav className="navbar navbar-global page-container" id="global-navigation"> + <div className="navbar-header" /> + </nav> - <div id="bd" className="page-wrapper-simple"> - <div id="nonav" className="page-simple"> - {this.props.children} - </div> + <div id="bd" className="page-wrapper-simple"> + <div id="nonav" className="page-simple"> + {this.props.children} </div> </div> - <GlobalFooter/> </div> + <GlobalFooter /> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/Extension.js b/server/sonar-web/src/main/js/app/components/extensions/Extension.js index 1011c4bea2c..3889e58612d 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/Extension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/Extension.js @@ -42,18 +42,18 @@ class Extension extends React.Component { props: Props; stop: ?Function; - componentDidMount () { + componentDidMount() { this.startExtension(); } - componentDidUpdate (prevProps: Props) { + componentDidUpdate(prevProps: Props) { if (prevProps.extension !== this.props.extension) { this.stopExtension(); this.startExtension(); } } - componentWillUnmount () { + componentWillUnmount() { this.stopExtension(); } @@ -70,21 +70,21 @@ class Extension extends React.Component { this.props.onFail(translate('page_extension_failed')); }; - startExtension () { + startExtension() { const { extension } = this.props; getExtensionStart(extension.key).then(this.handleStart, this.handleFailure); } - stopExtension () { + stopExtension() { this.stop && this.stop(); this.stop = null; } - render () { + render() { return ( - <div> - <div ref={container => this.container = container}/> - </div> + <div> + <div ref={container => this.container = container} /> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js b/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js index 5ad30878ae3..077cd721366 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ExtensionNotFound.js @@ -22,23 +22,25 @@ import React from 'react'; import { Link } from 'react-router'; export default class ExtensionNotFound extends React.Component { - componentDidMount () { + componentDidMount() { document.querySelector('html').classList.add('dashboard-page'); } - componentWillUnmount () { + componentWillUnmount() { document.querySelector('html').classList.remove('dashboard-page'); } - render () { + render() { return ( - <div id="bd" className="page-wrapper-simple"> - <div id="nonav" className="page-simple"> - <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2> - <p className="spacer-bottom">You may have mistyped the address or the page may have moved.</p> - <p><Link to="/">Go back to the homepage</Link></p> - </div> + <div id="bd" className="page-wrapper-simple"> + <div id="nonav" className="page-simple"> + <h2 className="big-spacer-bottom">The page you were looking for does not exist.</h2> + <p className="spacer-bottom"> + You may have mistyped the address or the page may have moved. + </p> + <p><Link to="/">Go back to the homepage</Link></p> </div> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js index 4b8b26976a0..54f9f231b36 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/GlobalAdminPageExtension.js @@ -31,16 +31,11 @@ class GlobalAdminPageExtension extends React.Component { extensionKey: string, pluginKey: string } - } - - render () { + }; + render() { const { extensionKey, pluginKey } = this.props.params; const extension = this.props.adminPages.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension ? ( - <Extension extension={extension}/> - ) : ( - <ExtensionNotFound/> - ); + return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js index df0e56d3dbc..147564cf34a 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/GlobalPageExtension.js @@ -31,16 +31,11 @@ class GlobalPageExtension extends React.Component { extensionKey: string, pluginKey: string } - } - - render () { + }; + render() { const { extensionKey, pluginKey } = this.props.params; const extension = this.props.globalPages.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension ? ( - <Extension extension={extension}/> - ) : ( - <ExtensionNotFound/> - ); + return extension ? <Extension extension={extension} /> : <ExtensionNotFound />; } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js index 385c396ee05..4e753ae6459 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectAdminPageExtension.js @@ -41,16 +41,14 @@ type Props = { class ProjectAdminPageExtension extends React.Component { props: Props; - render () { + render() { const { extensionKey, pluginKey } = this.props.params; const { component } = this.props; const extension = component.configuration && - component.configuration.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension ? ( - <Extension extension={extension} options={{ component }}/> - ) : ( - <ExtensionNotFound/> - ); + component.configuration.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); + return extension + ? <Extension extension={extension} options={{ component }} /> + : <ExtensionNotFound />; } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js index b13d06a8029..3f2d684c04f 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ProjectPageExtension.js @@ -39,15 +39,13 @@ type Props = { class ProjectPageExtension extends React.Component { props: Props; - render () { + render() { const { extensionKey, pluginKey } = this.props.params; const { component } = this.props; const extension = component.extensions.find(p => p.key === `${pluginKey}/${extensionKey}`); - return extension ? ( - <Extension extension={extension} options={{ component }}/> - ) : ( - <ExtensionNotFound/> - ); + return extension + ? <Extension extension={extension} options={{ component }} /> + : <ExtensionNotFound />; } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js b/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js index 38041bdab3c..eb38960ee66 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js +++ b/server/sonar-web/src/main/js/app/components/extensions/ViewDashboard.js @@ -22,11 +22,12 @@ import React from 'react'; import ProjectPageExtension from './ProjectPageExtension'; export default class ViewDashboard extends React.Component { - render () { + render() { return ( - <ProjectPageExtension - location={this.props.location} - params={{ pluginKey: 'governance', extensionKey: 'governance' }}/> + <ProjectPageExtension + location={this.props.location} + params={{ pluginKey: 'governance', extensionKey: 'governance' }} + /> ); } } diff --git a/server/sonar-web/src/main/js/app/components/extensions/utils.js b/server/sonar-web/src/main/js/app/components/extensions/utils.js index 6bd8058fa85..7294bea0c83 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/utils.js +++ b/server/sonar-web/src/main/js/app/components/extensions/utils.js @@ -29,20 +29,19 @@ const installScript = (key: string) => { }); }; -export const getExtensionStart = (key: string) => ( - new Promise((resolve, reject) => { - const fromCache = getExtensionFromCache(key); - if (fromCache) { - return resolve(fromCache); - } +export const getExtensionStart = (key: string) => + new Promise((resolve, reject) => { + const fromCache = getExtensionFromCache(key); + if (fromCache) { + return resolve(fromCache); + } - installScript(key).then(() => { - const start = getExtensionFromCache(key); - if (start) { - resolve(start); - } else { - reject(); - } - }); - }) -); + installScript(key).then(() => { + const start = getExtensionFromCache(key); + if (start) { + resolve(start); + } else { + reject(); + } + }); + }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js index d0e02dcbae8..ed484f8453f 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js @@ -28,18 +28,18 @@ import { getTasksForComponent } from '../../../../api/ce'; import { STATUSES } from '../../../../apps/background-tasks/constants'; export default React.createClass({ - componentDidMount () { + componentDidMount() { this.mounted = true; this.loadStatus(); this.populateRecentHistory(); }, - componentWillUnmount () { + componentWillUnmount() { this.mounted = false; }, - loadStatus () { + loadStatus() { getTasksForComponent(this.props.component.id).then(r => { if (this.mounted) { this.setState({ @@ -51,7 +51,7 @@ export default React.createClass({ }); }, - populateRecentHistory () { + populateRecentHistory() { const { breadcrumbs } = this.props.component; const { qualifier } = breadcrumbs[breadcrumbs.length - 1]; if (['TRK', 'VW', 'DEV'].indexOf(qualifier) !== -1) { @@ -64,33 +64,34 @@ export default React.createClass({ } }, - render () { + render() { return ( - <nav className="navbar navbar-context page-container" id="context-navigation"> - <div className="navbar-context-inner"> - <div className="container"> - <ComponentNavFavorite - component={this.props.component.key} - favorite={this.props.component.isFavorite}/> + <nav className="navbar navbar-context page-container" id="context-navigation"> + <div className="navbar-context-inner"> + <div className="container"> + <ComponentNavFavorite + component={this.props.component.key} + favorite={this.props.component.isFavorite} + /> - <ComponentNavBreadcrumbs - component={this.props.component} - breadcrumbs={this.props.component.breadcrumbs}/> + <ComponentNavBreadcrumbs + component={this.props.component} + breadcrumbs={this.props.component.breadcrumbs} + /> - <TooltipsContainer options={{ delay: { show: 0, hide: 2000 } }}> - <ComponentNavMeta - {...this.props} - {...this.state} - version={this.props.component.version} - snapshotDate={this.props.component.snapshotDate}/> - </TooltipsContainer> + <TooltipsContainer options={{ delay: { show: 0, hide: 2000 } }}> + <ComponentNavMeta + {...this.props} + {...this.state} + version={this.props.component.version} + snapshotDate={this.props.component.snapshotDate} + /> + </TooltipsContainer> - <ComponentNavMenu - component={this.props.component} - conf={this.props.conf}/> - </div> + <ComponentNavMenu component={this.props.component} conf={this.props.conf} /> </div> - </nav> + </div> + </nav> ); } }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js index 1915257f6c4..05648e1bec5 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavBreadcrumbs.js @@ -29,7 +29,7 @@ class ComponentNavBreadcrumbs extends React.Component { breadcrumbs: React.PropTypes.array }; - render () { + render() { const { breadcrumbs, organization, shouldOrganizationBeDisplayed } = this.props; if (!breadcrumbs) { @@ -42,47 +42,46 @@ class ComponentNavBreadcrumbs extends React.Component { const items = breadcrumbs.map((item, index) => { return ( - <span key={item.key}> - {!displayOrganization && index === 0 && ( - <span className="navbar-context-title-qualifier little-spacer-right"> - <QualifierIcon qualifier={lastItem.qualifier}/> - </span> - )} - <Link to={{ pathname: '/dashboard', query: { id: item.key } }} className="link-base-color"> - {index === breadcrumbs.length - 1 ? ( - <strong>{item.name}</strong> - ) : ( - <span>{item.name}</span> - )} - </Link> - {index < breadcrumbs.length - 1 && ( - <span className="slash-separator"/> - )} - </span> + <span key={item.key}> + {!displayOrganization && + index === 0 && + <span className="navbar-context-title-qualifier little-spacer-right"> + <QualifierIcon qualifier={lastItem.qualifier} /> + </span>} + <Link + to={{ pathname: '/dashboard', query: { id: item.key } }} + className="link-base-color" + > + {index === breadcrumbs.length - 1 + ? <strong>{item.name}</strong> + : <span>{item.name}</span>} + </Link> + {index < breadcrumbs.length - 1 && <span className="slash-separator" />} + </span> ); }); return ( - <h2 className="navbar-context-title"> - {displayOrganization && ( - <span> - <span className="navbar-context-title-qualifier little-spacer-right"> - <QualifierIcon qualifier={lastItem.qualifier}/> - </span> - <OrganizationLink organization={organization} className="link-base-color"> - {organization.name} - </OrganizationLink> - <span className="slash-separator"/> - </span> - )} - {items} - </h2> + <h2 className="navbar-context-title"> + {displayOrganization && + <span> + <span className="navbar-context-title-qualifier little-spacer-right"> + <QualifierIcon qualifier={lastItem.qualifier} /> + </span> + <OrganizationLink organization={organization} className="link-base-color"> + {organization.name} + </OrganizationLink> + <span className="slash-separator" /> + </span>} + {items} + </h2> ); } } const mapStateToProps = (state, ownProps) => ({ - organization: ownProps.component.organization && getOrganizationByKey(state, ownProps.component.organization), + organization: ownProps.component.organization && + getOrganizationByKey(state, ownProps.component.organization), shouldOrganizationBeDisplayed: areThereCustomOrganizations(state) }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js index 20a96f79203..4ae31ef1fb7 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavFavorite.js @@ -27,17 +27,15 @@ class ComponentNavFavorite extends React.Component { currentUser: React.PropTypes.object.isRequired }; - render () { + render() { if (!this.props.currentUser.isLoggedIn) { return null; } return ( - <div className="navbar-context-favorite"> - <Favorite - component={this.props.component} - favorite={this.props.favorite}/> - </div> + <div className="navbar-context-favorite"> + <Favorite component={this.props.component} favorite={this.props.favorite} /> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js index c6203fb9017..6d3cc006dc3 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js @@ -41,241 +41,256 @@ export default class ComponentNavMenu extends React.Component { conf: React.PropTypes.object.isRequired }; - isProject () { + isProject() { return this.props.component.qualifier === 'TRK'; } - isDeveloper () { + isDeveloper() { return this.props.component.qualifier === 'DEV'; } - isView () { + isView() { const { qualifier } = this.props.component; return qualifier === 'VW' || qualifier === 'SVW'; } - shouldShowAdministration () { + shouldShowAdministration() { return Object.keys(this.props.conf).some(key => this.props.conf[key]); } - renderDashboardLink () { + renderDashboardLink() { const pathname = this.isView() ? '/view' : '/dashboard'; return ( - <li> - <Link - to={{ pathname, query: { id: this.props.component.key } }} - activeClassName="active"> - <i className="icon-home"/> - </Link> - </li> + <li> + <Link to={{ pathname, query: { id: this.props.component.key } }} activeClassName="active"> + <i className="icon-home" /> + </Link> + </li> ); } - renderCodeLink () { + renderCodeLink() { if (this.isDeveloper()) { return null; } return ( - <li> - <Link - to={{ pathname: '/code', query: { id: this.props.component.key } }} - activeClassName="active"> - {this.isView() ? translate('view_projects.page') : translate('code.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/code', query: { id: this.props.component.key } }} + activeClassName="active" + > + {this.isView() ? translate('view_projects.page') : translate('code.page')} + </Link> + </li> ); } - renderActivityLink () { + renderActivityLink() { if (!this.isProject()) { return null; } return ( - <li> - <Link to={{ pathname: '/project/activity', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('project_activity.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/activity', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('project_activity.page')} + </Link> + </li> ); } - renderComponentIssuesLink () { + renderComponentIssuesLink() { return ( - <li> - <Link - to={{ pathname: '/component_issues', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('issues.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/component_issues', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('issues.page')} + </Link> + </li> ); } - renderComponentMeasuresLink () { + renderComponentMeasuresLink() { return ( - <li> - <Link - to={{ pathname: '/component_measures', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('layout.measures')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/component_measures', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('layout.measures')} + </Link> + </li> ); } - renderAdministration () { + renderAdministration() { if (!this.shouldShowAdministration()) { return null; } const isSettingsActive = SETTINGS_URLS.some(url => window.location.href.indexOf(url) !== -1); const className = 'dropdown' + (isSettingsActive ? ' active' : ''); return ( - <li className={className}> - <a className="dropdown-toggle navbar-admin-link" - id="component-navigation-admin" data-toggle="dropdown" href="#"> - {translate('layout.settings')} - <i className="icon-dropdown"/> - </a> - <ul className="dropdown-menu"> - {this.renderSettingsLink()} - {this.renderProfilesLink()} - {this.renderQualityGateLink()} - {this.renderCustomMeasuresLink()} - {this.renderLinksLink()} - {this.renderPermissionsLink()} - {this.renderBackgroundTasksLink()} - {this.renderUpdateKeyLink()} - {this.renderAdminExtensions()} - {this.renderDeletionLink()} - </ul> - </li> + <li className={className}> + <a + className="dropdown-toggle navbar-admin-link" + id="component-navigation-admin" + data-toggle="dropdown" + href="#" + > + {translate('layout.settings')} + <i className="icon-dropdown" /> + </a> + <ul className="dropdown-menu"> + {this.renderSettingsLink()} + {this.renderProfilesLink()} + {this.renderQualityGateLink()} + {this.renderCustomMeasuresLink()} + {this.renderLinksLink()} + {this.renderPermissionsLink()} + {this.renderBackgroundTasksLink()} + {this.renderUpdateKeyLink()} + {this.renderAdminExtensions()} + {this.renderDeletionLink()} + </ul> + </li> ); } - renderSettingsLink () { + renderSettingsLink() { if (!this.props.conf.showSettings) { return null; } return ( - <li> - <Link - to={{ pathname: '/project/settings', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('project_settings.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/settings', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('project_settings.page')} + </Link> + </li> ); } - renderProfilesLink () { + renderProfilesLink() { if (!this.props.conf.showQualityProfiles) { return null; } return ( - <li> - <Link - to={{ pathname: '/project/quality_profiles', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('project_quality_profiles.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/quality_profiles', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('project_quality_profiles.page')} + </Link> + </li> ); } - renderQualityGateLink () { + renderQualityGateLink() { if (!this.props.conf.showQualityGates) { return null; } return ( - <li> - <Link - to={{ pathname: '/project/quality_gate', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('project_quality_gate.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/quality_gate', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('project_quality_gate.page')} + </Link> + </li> ); } - renderCustomMeasuresLink () { + renderCustomMeasuresLink() { if (!this.props.conf.showManualMeasures) { return null; } return ( - <li> - <Link - to={{ pathname: '/custom_measures', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('custom_measures.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/custom_measures', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('custom_measures.page')} + </Link> + </li> ); } - renderLinksLink () { + renderLinksLink() { if (!this.props.conf.showLinks) { return null; } return ( - <li> - <Link - to={{ pathname: '/project/links', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('project_links.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/links', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('project_links.page')} + </Link> + </li> ); } - renderPermissionsLink () { + renderPermissionsLink() { if (!this.props.conf.showPermissions) { return null; } return ( - <li> - <Link - to={{ pathname: '/project_roles', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('permissions.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project_roles', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('permissions.page')} + </Link> + </li> ); } - renderBackgroundTasksLink () { + renderBackgroundTasksLink() { if (!this.props.conf.showBackgroundTasks) { return null; } return ( - <li> - <Link - to={{ pathname: '/project/background_tasks', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('background_tasks.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/background_tasks', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('background_tasks.page')} + </Link> + </li> ); } - renderUpdateKeyLink () { + renderUpdateKeyLink() { if (!this.props.conf.showUpdateKey) { return null; } return ( - <li> - <Link - to={{ pathname: '/project/key', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('update_key.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/key', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('update_key.page')} + </Link> + </li> ); } - renderDeletionLink () { + renderDeletionLink() { const { qualifier } = this.props.component; if (!this.props.conf.showSettings) { @@ -287,33 +302,34 @@ export default class ComponentNavMenu extends React.Component { } return ( - <li> - <Link - to={{ pathname: '/project/deletion', query: { id: this.props.component.key } }} - activeClassName="active"> - {translate('deletion.page')} - </Link> - </li> + <li> + <Link + to={{ pathname: '/project/deletion', query: { id: this.props.component.key } }} + activeClassName="active" + > + {translate('deletion.page')} + </Link> + </li> ); } renderExtension = ({ key, name }, isAdmin = false) => { const pathname = isAdmin ? `/project/admin/extension/${key}` : `/project/extension/${key}`; return ( - <li key={key}> - <Link to={{ pathname, query: { id: this.props.component.key } }} activeClassName="active"> - {name} - </Link> - </li> + <li key={key}> + <Link to={{ pathname, query: { id: this.props.component.key } }} activeClassName="active"> + {name} + </Link> + </li> ); }; - renderAdminExtensions () { + renderAdminExtensions() { const extensions = this.props.conf.extensions || []; return extensions.map(e => this.renderExtension(e, true)); } - renderExtensions () { + renderExtensions() { const extensions = this.props.component.extensions || []; const withoutGovernance = extensions.filter(ext => ext.name !== 'Governance'); if (!withoutGovernance.length) { @@ -321,29 +337,34 @@ export default class ComponentNavMenu extends React.Component { } return ( - <li className="dropdown"> - <a className="dropdown-toggle" id="component-navigation-more" data-toggle="dropdown" href="#"> - {translate('more')} - <i className="icon-dropdown"/> - </a> - <ul className="dropdown-menu"> - {withoutGovernance.map(this.renderExtension)} - </ul> - </li> + <li className="dropdown"> + <a + className="dropdown-toggle" + id="component-navigation-more" + data-toggle="dropdown" + href="#" + > + {translate('more')} + <i className="icon-dropdown" /> + </a> + <ul className="dropdown-menu"> + {withoutGovernance.map(this.renderExtension)} + </ul> + </li> ); } - render () { + render() { return ( - <ul className="nav navbar-nav nav-tabs"> - {this.renderDashboardLink()} - {this.renderComponentIssuesLink()} - {this.renderComponentMeasuresLink()} - {this.renderCodeLink()} - {this.renderActivityLink()} - {this.renderAdministration()} - {this.renderExtensions()} - </ul> + <ul className="nav navbar-nav nav-tabs"> + {this.renderDashboardLink()} + {this.renderComponentIssuesLink()} + {this.renderComponentMeasuresLink()} + {this.renderCodeLink()} + {this.renderActivityLink()} + {this.renderAdministration()} + {this.renderExtensions()} + </ul> ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js index bd2273f9662..21fc78a5de4 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMeta.js @@ -23,40 +23,43 @@ import PendingIcon from '../../../../components/shared/pending-icon'; import { translate, translateWithParameters } from '../../../../helpers/l10n'; export default React.createClass({ - render () { + render() { const metaList = []; const canSeeBackgroundTasks = this.props.conf.showBackgroundTasks; - const backgroundTasksUrl = - `${window.baseUrl}/project/background_tasks?id=${encodeURIComponent(this.props.component.key)}`; + const backgroundTasksUrl = window.baseUrl + + `/project/background_tasks?id=${encodeURIComponent(this.props.component.key)}`; if (this.props.isInProgress) { - const tooltip = canSeeBackgroundTasks ? - translateWithParameters('component_navigation.status.in_progress.admin', backgroundTasksUrl) : - translate('component_navigation.status.in_progress'); + const tooltip = canSeeBackgroundTasks + ? translateWithParameters( + 'component_navigation.status.in_progress.admin', + backgroundTasksUrl + ) + : translate('component_navigation.status.in_progress'); metaList.push( <li key="isInProgress" data-toggle="tooltip" title={tooltip}> - <i className="spinner" style={{ marginTop: '-1px' }}/> - {' '} - <span className="text-info">{translate('background_task.status.IN_PROGRESS')}</span> - </li> + <i className="spinner" style={{ marginTop: '-1px' }} /> + {' '} + <span className="text-info">{translate('background_task.status.IN_PROGRESS')}</span> + </li> ); } else if (this.props.isPending) { - const tooltip = canSeeBackgroundTasks ? - translateWithParameters('component_navigation.status.pending.admin', backgroundTasksUrl) : - translate('component_navigation.status.pending'); + const tooltip = canSeeBackgroundTasks + ? translateWithParameters('component_navigation.status.pending.admin', backgroundTasksUrl) + : translate('component_navigation.status.pending'); metaList.push( <li key="isPending" data-toggle="tooltip" title={tooltip}> - <PendingIcon/> <span>{translate('background_task.status.PENDING')}</span> - </li> + <PendingIcon /> <span>{translate('background_task.status.PENDING')}</span> + </li> ); } else if (this.props.isFailed) { - const tooltip = canSeeBackgroundTasks ? - translateWithParameters('component_navigation.status.failed.admin', backgroundTasksUrl) : - translate('component_navigation.status.failed'); + const tooltip = canSeeBackgroundTasks + ? translateWithParameters('component_navigation.status.failed.admin', backgroundTasksUrl) + : translate('component_navigation.status.failed'); metaList.push( <li key="isFailed" data-toggle="tooltip" title={tooltip}> - <span className="badge badge-danger">{translate('background_task.status.FAILED')}</span> - </li> + <span className="badge badge-danger">{translate('background_task.status.FAILED')}</span> + </li> ); } @@ -69,9 +72,9 @@ export default React.createClass({ } return ( - <div className="navbar-context-meta"> - <ul className="list-inline">{metaList}</ul> - </div> + <div className="navbar-context-meta"> + <ul className="list-inline">{metaList}</ul> + </div> ); } }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/RecentHistory.js b/server/sonar-web/src/main/js/app/components/nav/component/RecentHistory.js index a783c0344ff..6cd25ac4072 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/RecentHistory.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/RecentHistory.js @@ -29,7 +29,7 @@ type History = Array<{ }>; export default class RecentHistory { - static get (): History { + static get(): History { let history = localStorage.getItem(STORAGE_KEY); if (history == null) { history = []; @@ -44,15 +44,20 @@ export default class RecentHistory { return history; } - static set (newHistory: History): void { + static set(newHistory: History): void { localStorage.setItem(STORAGE_KEY, JSON.stringify(newHistory)); } - static clear (): void { + static clear(): void { localStorage.removeItem(STORAGE_KEY); } - static add (componentKey: string, componentName: string, icon: string, organization?: string): void { + static add( + componentKey: string, + componentName: string, + icon: string, + organization?: string + ): void { const sonarHistory = RecentHistory.get(); const newEntry = { key: componentKey, name: componentName, icon, organization }; let newHistory = sonarHistory.filter(entry => entry.key !== newEntry.key); @@ -61,7 +66,7 @@ export default class RecentHistory { RecentHistory.set(newHistory); } - static remove (componentKey: string): void { + static remove(componentKey: string): void { const history = RecentHistory.get(); const newHistory = history.filter(entry => entry.key !== componentKey); RecentHistory.set(newHistory); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavBreadcrumbs-test.js b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavBreadcrumbs-test.js index e8c6e930bd0..6fce85f2d97 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavBreadcrumbs-test.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavBreadcrumbs-test.js @@ -23,7 +23,7 @@ import { Unconnected } from '../ComponentNavBreadcrumbs'; it('should not render breadcrumbs with one element', () => { const breadcrumbs = [{ key: 'my-project', name: 'My Project', qualifier: 'TRK' }]; - const result = shallow(<Unconnected breadcrumbs={breadcrumbs}/>); + const result = shallow(<Unconnected breadcrumbs={breadcrumbs} />); expect(result).toMatchSnapshot(); }); @@ -32,8 +32,10 @@ it('should render organization', () => { const organization = { key: 'foo', name: 'The Foo Organization' }; const result = shallow( <Unconnected - breadcrumbs={breadcrumbs} - organization={organization} - shouldOrganizationBeDisplayed={true}/>); + breadcrumbs={breadcrumbs} + organization={organization} + shouldOrganizationBeDisplayed={true} + /> + ); expect(result).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.js b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.js index 257d3c9f02e..024f2a4a7a0 100644 --- a/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.js +++ b/server/sonar-web/src/main/js/app/components/nav/component/__tests__/ComponentNavMenu-test.js @@ -30,6 +30,6 @@ it('should work with extensions', () => { showSettings: true, extensions: [{ key: 'foo', name: 'Foo' }] }; - const wrapper = shallow(<ComponentNavMenu component={component} conf={conf}/>); + const wrapper = shallow(<ComponentNavMenu component={component} conf={conf} />); expect(wrapper).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js index d4a04a25860..ef83aed3921 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.js @@ -27,11 +27,11 @@ import ShortcutsHelpView from './ShortcutsHelpView'; import { getCurrentUser, getAppState } from '../../../../store/rootReducer'; class GlobalNav extends React.Component { - componentDidMount () { + componentDidMount() { window.addEventListener('keypress', this.onKeyPress); } - componentWillUnmount () { + componentWillUnmount() { window.removeEventListener('keypress', this.onKeyPress); } @@ -53,25 +53,25 @@ class GlobalNav extends React.Component { new ShortcutsHelpView().render(); }; - render () { + render() { return ( - <nav className="navbar navbar-global page-container" id="global-navigation"> - <div className="container"> - <GlobalNavBranding/> + <nav className="navbar navbar-global page-container" id="global-navigation"> + <div className="container"> + <GlobalNavBranding /> - <GlobalNavMenu {...this.props}/> + <GlobalNavMenu {...this.props} /> - <ul className="nav navbar-nav navbar-right"> - <GlobalNavUser {...this.props}/> - <GlobalNavSearch {...this.props}/> - <li> - <a onClick={this.openHelp} href="#"> - <i className="icon-help navbar-icon"/> - </a> - </li> - </ul> - </div> - </nav> + <ul className="nav navbar-nav navbar-right"> + <GlobalNavUser {...this.props} /> + <GlobalNavSearch {...this.props} /> + <li> + <a onClick={this.openHelp} href="#"> + <i className="icon-help navbar-icon" /> + </a> + </li> + </ul> + </div> + </nav> ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js index a1f73443ea2..8e6dd891305 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js @@ -29,23 +29,22 @@ class GlobalNavBranding extends React.Component { customLogoWidth: React.PropTypes.oneOfType([React.PropTypes.string, React.PropTypes.number]) }; - renderLogo () { + renderLogo() { const url = this.props.customLogoUrl || `${window.baseUrl}/images/logo.svg`; const width = this.props.customLogoWidth || 100; const height = 30; const title = translate('layout.sonar.slogan'); - return ( - <img src={url} width={width} height={height} alt={title} title={title}/> - ); + return <img src={url} width={width} height={height} alt={title} title={title} />; } - render () { + render() { const homeController = this.props.currentUser.isLoggedIn ? '/projects' : '/about'; - const homeLinkClassName = 'navbar-brand' + (this.props.customLogoUrl ? ' navbar-brand-custom' : ''); + const homeLinkClassName = 'navbar-brand' + + (this.props.customLogoUrl ? ' navbar-brand-custom' : ''); return ( - <div className="navbar-header"> - <Link to={homeController} className={homeLinkClassName}>{this.renderLogo()}</Link> - </div> + <div className="navbar-header"> + <Link to={homeController} className={homeLinkClassName}>{this.renderLogo()}</Link> + </div> ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js index 3693e493fcf..b1e556af9d0 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js @@ -33,112 +33,114 @@ export default class GlobalNavMenu extends React.Component { globalPages: [] }; - activeLink (url) { + activeLink(url) { return window.location.pathname.indexOf(window.baseUrl + url) === 0 ? 'active' : null; } - renderProjects () { + renderProjects() { return ( - <li> - <Link to="/projects" activeClassName="active"> - {translate('projects.page')} - </Link> - </li> + <li> + <Link to="/projects" activeClassName="active"> + {translate('projects.page')} + </Link> + </li> ); } - renderIssuesLink () { - const query = this.props.currentUser.isLoggedIn ? '#resolved=false|assigned_to_me=true' : '#resolved=false'; + renderIssuesLink() { + const query = this.props.currentUser.isLoggedIn + ? '#resolved=false|assigned_to_me=true' + : '#resolved=false'; const url = '/issues' + query; return ( - <li> - <Link to={url} className={this.activeLink('/issues')}> - {translate('issues.page')} - </Link> - </li> + <li> + <Link to={url} className={this.activeLink('/issues')}> + {translate('issues.page')} + </Link> + </li> ); } - renderRulesLink () { + renderRulesLink() { return ( - <li> - <Link to="/coding_rules" className={this.activeLink('/coding_rules')}> - {translate('coding_rules.page')} - </Link> - </li> + <li> + <Link to="/coding_rules" className={this.activeLink('/coding_rules')}> + {translate('coding_rules.page')} + </Link> + </li> ); } - renderProfilesLink () { + renderProfilesLink() { return ( - <li> - <Link to="/profiles" activeClassName="active"> - {translate('quality_profiles.page')} - </Link> - </li> + <li> + <Link to="/profiles" activeClassName="active"> + {translate('quality_profiles.page')} + </Link> + </li> ); } - renderQualityGatesLink () { + renderQualityGatesLink() { return ( - <li> - <Link to="/quality_gates" activeClassName="active"> - {translate('quality_gates.page')} - </Link> - </li> + <li> + <Link to="/quality_gates" activeClassName="active"> + {translate('quality_gates.page')} + </Link> + </li> ); } - renderAdministrationLink () { + renderAdministrationLink() { if (!isUserAdmin(this.props.currentUser)) { return null; } return ( - <li> - <Link to="/settings" className="navbar-admin-link" activeClassName="active"> - {translate('layout.settings')} - </Link> - </li> + <li> + <Link to="/settings" className="navbar-admin-link" activeClassName="active"> + {translate('layout.settings')} + </Link> + </li> ); } renderGlobalPageLink = ({ key, name }) => { return ( - <li key={key}> - <Link to={`/extension/${key}`}>{name}</Link> - </li> + <li key={key}> + <Link to={`/extension/${key}`}>{name}</Link> + </li> ); }; - renderMore () { + renderMore() { const { globalPages } = this.props.appState; if (globalPages.length === 0) { return null; } return ( - <li className="dropdown"> - <a className="dropdown-toggle" id="global-navigation-more" data-toggle="dropdown" href="#"> - {translate('more')} - <span className="icon-dropdown"/> - </a> - <ul className="dropdown-menu"> - {globalPages.map(this.renderGlobalPageLink)} - </ul> - </li> + <li className="dropdown"> + <a className="dropdown-toggle" id="global-navigation-more" data-toggle="dropdown" href="#"> + {translate('more')} + <span className="icon-dropdown" /> + </a> + <ul className="dropdown-menu"> + {globalPages.map(this.renderGlobalPageLink)} + </ul> + </li> ); } - render () { + render() { return ( - <ul className="nav navbar-nav"> - {this.renderProjects()} - {this.renderIssuesLink()} - {this.renderRulesLink()} - {this.renderProfilesLink()} - {this.renderQualityGatesLink()} - {this.renderAdministrationLink()} - {this.renderMore()} - </ul> + <ul className="nav navbar-nav"> + {this.renderProjects()} + {this.renderIssuesLink()} + {this.renderRulesLink()} + {this.renderProfilesLink()} + {this.renderQualityGatesLink()} + {this.renderAdministrationLink()} + {this.renderMore()} + </ul> ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js index fdcb24c2881..2b5aa6ccf63 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavSearch.js @@ -23,7 +23,7 @@ import { connect } from 'react-redux'; import SearchView from './SearchView'; import { getCurrentUser } from '../../../../store/rootReducer'; -function contains (root, node) { +function contains(root, node) { while (node) { if (node === root) { return true; @@ -36,7 +36,7 @@ function contains (root, node) { class GlobalNavSearch extends React.Component { state = { open: false }; - componentDidMount () { + componentDidMount() { key('s', () => { const isModalOpen = document.querySelector('html').classList.contains('modal-open'); if (!isModalOpen) { @@ -46,7 +46,7 @@ class GlobalNavSearch extends React.Component { }); } - componentWillUnmount () { + componentWillUnmount() { this.closeSearch(); key.unbind('s'); } @@ -92,15 +92,18 @@ class GlobalNavSearch extends React.Component { } }; - render () { + render() { const dropdownClassName = 'dropdown' + (this.state.open ? ' open' : ''); return ( - <li ref="dropdown" className={dropdownClassName}> - <a className="navbar-search-dropdown" href="#" onClick={this.onClick}> - <i className="icon-search navbar-icon"/> <i className="icon-dropdown"/> - </a> - <div ref="container" className="dropdown-menu dropdown-menu-right global-navbar-search-dropdown"/> - </li> + <li ref="dropdown" className={dropdownClassName}> + <a className="navbar-search-dropdown" href="#" onClick={this.onClick}> + <i className="icon-search navbar-icon" /> <i className="icon-dropdown" /> + </a> + <div + ref="container" + className="dropdown-menu dropdown-menu-right global-navbar-search-dropdown" + /> + </li> ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js index b8a5fe7c1df..57fda1a1492 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js @@ -49,35 +49,35 @@ class GlobalNavUser extends React.Component { this.props.router.push('/sessions/logout'); }; - renderAuthenticated () { + renderAuthenticated() { const { currentUser } = this.props; return ( - <li className="dropdown js-user-authenticated"> - <a className="dropdown-toggle" data-toggle="dropdown" href="#"> - <Avatar email={currentUser.email} size={20}/> - {currentUser.name} <i className="icon-dropdown"/> - </a> - <ul className="dropdown-menu dropdown-menu-right"> - <li> - <Link to="/account">{translate('my_account.page')}</Link> - </li> - <li> - <a onClick={this.handleLogout} href="#">{translate('layout.logout')}</a> - </li> - </ul> - </li> + <li className="dropdown js-user-authenticated"> + <a className="dropdown-toggle" data-toggle="dropdown" href="#"> + <Avatar email={currentUser.email} size={20} /> + {currentUser.name} <i className="icon-dropdown" /> + </a> + <ul className="dropdown-menu dropdown-menu-right"> + <li> + <Link to="/account">{translate('my_account.page')}</Link> + </li> + <li> + <a onClick={this.handleLogout} href="#">{translate('layout.logout')}</a> + </li> + </ul> + </li> ); } - renderAnonymous () { + renderAnonymous() { return ( - <li> - <a onClick={this.handleLogin} href="#">{translate('layout.login')}</a> - </li> + <li> + <a onClick={this.handleLogin} href="#">{translate('layout.login')}</a> + </li> ); } - render () { + render() { return this.props.currentUser.isLoggedIn ? this.renderAuthenticated() : this.renderAnonymous(); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/global/SearchView.js b/server/sonar-web/src/main/js/app/components/nav/global/SearchView.js index cf711c889e8..e98a0397a3a 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/SearchView.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/SearchView.js @@ -31,7 +31,10 @@ import { translate } from '../../../../helpers/l10n'; import { isUserAdmin } from '../../../../helpers/users'; import { getFavorites } from '../../../../api/favorites'; import { getSuggestions } from '../../../../api/components'; -import { getOrganization, areThereCustomOrganizations } from '../../../../store/organizations/utils'; +import { + getOrganization, + areThereCustomOrganizations +} from '../../../../store/organizations/utils'; type Finding = { name: string, @@ -45,19 +48,19 @@ const SearchItemView = Marionette.ItemView.extend({ tagName: 'li', template: SearchItemTemplate, - select () { + select() { this.$el.addClass('active'); }, - deselect () { + deselect() { this.$el.removeClass('active'); }, - submit () { + submit() { this.$('a')[0].click(); }, - onRender () { + onRender() { this.$('[data-toggle="tooltip"]').tooltip({ container: 'body', html: true, @@ -66,11 +69,11 @@ const SearchItemView = Marionette.ItemView.extend({ }); }, - onDestroy () { + onDestroy() { this.$('[data-toggle="tooltip"]').tooltip('destroy'); }, - serializeData () { + serializeData() { return { ...Marionette.ItemView.prototype.serializeData.apply(this, arguments), index: this.options.index @@ -105,7 +108,7 @@ export default Marionette.LayoutView.extend({ 'keyup .js-search-input': 'onKeyUp' }, - initialize () { + initialize() { this.results = new Backbone.Collection(); this.favorite = []; if (this.model.get('currentUser').isLoggedIn) { @@ -121,15 +124,18 @@ export default Marionette.LayoutView.extend({ this._bufferedValue = ''; }, - onRender () { + onRender() { const that = this; this.resultsRegion.show(this.resultsView); - setTimeout(() => { - that.$('.js-search-input').focus(); - }, 0); + setTimeout( + () => { + that.$('.js-search-input').focus(); + }, + 0 + ); }, - onKeyDown (e) { + onKeyDown(e) { if (e.keyCode === 38) { this.resultsView.selectPrev(); return false; @@ -149,7 +155,7 @@ export default Marionette.LayoutView.extend({ } }, - onKeyUp () { + onKeyUp() { const value = this.$('.js-search-input').val(); if (value === this._bufferedValue) { return; @@ -158,18 +164,21 @@ export default Marionette.LayoutView.extend({ this.searchRequest = this.debouncedSearch(value); }, - onSubmit () { + onSubmit() { return false; }, - fetchFavorite (): Promise<*> { + fetchFavorite(): Promise<*> { const customOrganizations = areThereCustomOrganizations(); return getFavorites().then(r => { this.favorite = r.favorites.map(f => { const showOrganization = customOrganizations && f.organization != null; const organization = showOrganization ? getOrganization(f.organization) : null; return { - url: window.baseUrl + '/dashboard/index?id=' + encodeURIComponent(f.key) + window.dashboardParameters(true), + url: window.baseUrl + + '/dashboard/index?id=' + + encodeURIComponent(f.key) + + window.dashboardParameters(true), name: f.name, icon: 'favorite', organization @@ -179,12 +188,14 @@ export default Marionette.LayoutView.extend({ }); }, - resetResultsToDefault () { + resetResultsToDefault() { const recentHistory = RecentHistory.get(); const customOrganizations = areThereCustomOrganizations(); const history = recentHistory.map((historyItem, index) => { - const url = window.baseUrl + '/dashboard/index?id=' + encodeURIComponent(historyItem.key) + - window.dashboardParameters(true); + const url = window.baseUrl + + '/dashboard/index?id=' + + encodeURIComponent(historyItem.key) + + window.dashboardParameters(true); const showOrganization = customOrganizations && historyItem.organization != null; // $FlowFixMe flow doesn't check the above condition on `historyItem.organization != null` const organization = showOrganization ? getOrganization(historyItem.organization) : null; @@ -202,7 +213,7 @@ export default Marionette.LayoutView.extend({ this.results.reset([].concat(history, favorite)); }, - search (q) { + search(q) { if (q.length < 2) { this.resetResultsToDefault(); return; @@ -219,8 +230,9 @@ export default Marionette.LayoutView.extend({ const collection = []; r.results.forEach(({ items, q }) => { items.forEach((item, index) => { - const showOrganization = customOrganizations && item.organization != null && - SHOW_ORGANIZATION_FOR_QUALIFIERS.includes(q); + const showOrganization = customOrganizations && + item.organization != null && + SHOW_ORGANIZATION_FOR_QUALIFIERS.includes(q); const organization = showOrganization ? getOrganization(item.organization) : null; collection.push({ ...item, @@ -240,10 +252,13 @@ export default Marionette.LayoutView.extend({ }); }, - getNavigationFindings (q) { + getNavigationFindings(q) { const DEFAULT_ITEMS = [ { name: translate('issues.page'), url: window.baseUrl + '/issues/search' }, - { name: translate('layout.measures'), url: window.baseUrl + '/measures/search?qualifiers[]=TRK' }, + { + name: translate('layout.measures'), + url: window.baseUrl + '/measures/search?qualifiers[]=TRK' + }, { name: translate('coding_rules.page'), url: window.baseUrl + '/coding_rules' }, { name: translate('quality_profiles.page'), url: window.baseUrl + '/profiles' }, { name: translate('quality_gates.page'), url: window.baseUrl + '/quality_gates' } @@ -261,10 +276,13 @@ export default Marionette.LayoutView.extend({ return findings.slice(0, 6); }, - getGlobalDashboardFindings (q) { + getGlobalDashboardFindings(q) { const dashboards = this.model.get('globalDashboards') || []; const items = dashboards.map(d => { - return { name: d.name, url: window.baseUrl + '/dashboard/index?did=' + encodeURIComponent(d.key) }; + return { + name: d.name, + url: window.baseUrl + '/dashboard/index?did=' + encodeURIComponent(d.key) + }; }); const findings = items.filter(f => { return f.name.match(new RegExp(q, 'i')); @@ -275,7 +293,7 @@ export default Marionette.LayoutView.extend({ return findings.slice(0, 6); }, - getFavoriteFindings (q) { + getFavoriteFindings(q) { const findings = this.favorite.filter(f => { return f.name.match(new RegExp(q, 'i')); }); diff --git a/server/sonar-web/src/main/js/app/components/nav/global/ShortcutsHelpView.js b/server/sonar-web/src/main/js/app/components/nav/global/ShortcutsHelpView.js index 6c9f8cbc4b1..893e4930ad6 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/ShortcutsHelpView.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/ShortcutsHelpView.js @@ -24,4 +24,3 @@ export default ModalView.extend({ className: 'modal modal-large', template: ShortcutsHelpTemplate }); - diff --git a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js index 43e5359b962..8631913e07f 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js +++ b/server/sonar-web/src/main/js/app/components/nav/global/__tests__/GlobalNavMenu-test.js @@ -29,6 +29,6 @@ it('should work with extensions', () => { isLoggedIn: false, permissions: { global: [] } }; - const wrapper = shallow(<GlobalNavMenu appState={appState} currentUser={currentUser}/>); + const wrapper = shallow(<GlobalNavMenu appState={appState} currentUser={currentUser} />); expect(wrapper).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js index 38ee2cef480..b82a5e22a60 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js +++ b/server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js @@ -29,35 +29,35 @@ class SettingsNav extends React.Component { extensions: [] }; - isSomethingActive (urls) { + isSomethingActive(urls) { const path = window.location.pathname; return urls.some(url => path.indexOf(window.baseUrl + url) === 0); } - isSecurityActive () { + isSecurityActive() { const urls = ['/users', '/groups', '/roles/global', '/permission_templates']; return this.isSomethingActive(urls); } - isProjectsActive () { + isProjectsActive() { const urls = ['/projects_admin', '/background_tasks']; return this.isSomethingActive(urls); } - isSystemActive () { + isSystemActive() { const urls = ['/updatecenter', '/system']; return this.isSomethingActive(urls); } renderExtension = ({ key, name }) => { return ( - <li key={key}> - <Link to={`/admin/extension/${key}`} activeClassName="active">{name}</Link> - </li> + <li key={key}> + <Link to={`/admin/extension/${key}`} activeClassName="active">{name}</Link> + </li> ); }; - render () { + render() { const isSecurity = this.isSecurityActive(); const isProjects = this.isProjectsActive(); const isSystem = this.isSystemActive(); @@ -70,127 +70,128 @@ class SettingsNav extends React.Component { }); return ( - <nav className="navbar navbar-context page-container" id="context-navigation"> - <div className="navbar-context-inner"> - <div className="container"> - <ul className="nav navbar-nav nav-crumbs"> - <li> - <IndexLink to="/settings"> - {translate('layout.settings')} - </IndexLink> - </li> - </ul> - - <ul className="nav navbar-nav nav-tabs"> - <li className={configurationClassNames}> - <a className="dropdown-toggle" data-toggle="dropdown" id="settings-navigation-configuration" href="#"> - {translate('sidebar.project_settings')} <i className="icon-dropdown"/> - </a> - <ul className="dropdown-menu"> + <nav className="navbar navbar-context page-container" id="context-navigation"> + <div className="navbar-context-inner"> + <div className="container"> + <ul className="nav navbar-nav nav-crumbs"> + <li> + <IndexLink to="/settings"> + {translate('layout.settings')} + </IndexLink> + </li> + </ul> + + <ul className="nav navbar-nav nav-tabs"> + <li className={configurationClassNames}> + <a + className="dropdown-toggle" + data-toggle="dropdown" + id="settings-navigation-configuration" + href="#" + > + {translate('sidebar.project_settings')} <i className="icon-dropdown" /> + </a> + <ul className="dropdown-menu"> + <li> + <IndexLink to="/settings" activeClassName="active"> + {translate('settings.page')} + </IndexLink> + </li> + <li> + <IndexLink to="/settings/licenses" activeClassName="active"> + {translate('property.category.licenses')} + </IndexLink> + </li> + <li> + <IndexLink to="/settings/encryption" activeClassName="active"> + {translate('property.category.security.encryption')} + </IndexLink> + </li> + <li> + <IndexLink to="/settings/server_id" activeClassName="active"> + {translate('property.category.server_id')} + </IndexLink> + </li> + <li> + <IndexLink to="/metrics" activeClassName="active"> + Custom Metrics + </IndexLink> + </li> + {this.props.extensions.map(this.renderExtension)} + </ul> + </li> + + <li className={securityClassName}> + <a className="dropdown-toggle" data-toggle="dropdown" href="#"> + {translate('sidebar.security')} <i className="icon-dropdown" /> + </a> + <ul className="dropdown-menu"> + <li> + <IndexLink to="/users" activeClassName="active"> + {translate('users.page')} + </IndexLink> + </li> + {!this.props.customOrganizations && <li> - <IndexLink to="/settings" activeClassName="active"> - {translate('settings.page')} + <IndexLink to="/groups" activeClassName="active"> + {translate('user_groups.page')} </IndexLink> - </li> + </li>} + {!this.props.customOrganizations && <li> - <IndexLink to="/settings/licenses" activeClassName="active"> - {translate('property.category.licenses')} + <IndexLink to="/roles/global" activeClassName="active"> + {translate('global_permissions.page')} </IndexLink> - </li> + </li>} + {!this.props.customOrganizations && <li> - <IndexLink to="/settings/encryption" activeClassName="active"> - {translate('property.category.security.encryption')} + <IndexLink to="/permission_templates" activeClassName="active"> + {translate('permission_templates')} </IndexLink> - </li> + </li>} + </ul> + </li> + + <li className={projectsClassName}> + <a className="dropdown-toggle" data-toggle="dropdown" href="#"> + {translate('sidebar.projects')} <i className="icon-dropdown" /> + </a> + <ul className="dropdown-menu"> + {!this.props.customOrganizations && <li> - <IndexLink to="/settings/server_id" activeClassName="active"> - {translate('property.category.server_id')} + <IndexLink to="/projects_admin" activeClassName="active"> + Management </IndexLink> - </li> - <li> - <IndexLink to="/metrics" activeClassName="active"> - Custom Metrics - </IndexLink> - </li> - {this.props.extensions.map(this.renderExtension)} - </ul> - </li> - - <li className={securityClassName}> - <a className="dropdown-toggle" data-toggle="dropdown" href="#"> - {translate('sidebar.security')} <i className="icon-dropdown"/> - </a> - <ul className="dropdown-menu"> - <li> - <IndexLink to="/users" activeClassName="active"> - {translate('users.page')} - </IndexLink> - </li> - {!this.props.customOrganizations && ( - <li> - <IndexLink to="/groups" activeClassName="active"> - {translate('user_groups.page')} - </IndexLink> - </li> - )} - {!this.props.customOrganizations && ( - <li> - <IndexLink to="/roles/global" activeClassName="active"> - {translate('global_permissions.page')} - </IndexLink> - </li> - )} - {!this.props.customOrganizations && ( - <li> - <IndexLink to="/permission_templates" activeClassName="active"> - {translate('permission_templates')} - </IndexLink> - </li> - )} - </ul> - </li> - - <li className={projectsClassName}> - <a className="dropdown-toggle" data-toggle="dropdown" href="#"> - {translate('sidebar.projects')} <i className="icon-dropdown"/> - </a> - <ul className="dropdown-menu"> - {!this.props.customOrganizations && ( - <li> - <IndexLink to="/projects_admin" activeClassName="active"> - Management - </IndexLink> - </li> - )} - <li> - <IndexLink to="/background_tasks" activeClassName="active"> - {translate('background_tasks.page')} - </IndexLink> - </li> - </ul> - </li> - - <li className={systemClassName}> - <a className="dropdown-toggle" data-toggle="dropdown" href="#"> - {translate('sidebar.system')} <i className="icon-dropdown"/> - </a> - <ul className="dropdown-menu"> - <li> - <IndexLink to="/updatecenter" activeClassName="active"> - {translate('update_center.page')} - </IndexLink> - </li> - <li> - <IndexLink to="/system" activeClassName="active"> - {translate('system_info.page')} - </IndexLink> - </li> - </ul> - </li> - </ul> - </div> + </li>} + <li> + <IndexLink to="/background_tasks" activeClassName="active"> + {translate('background_tasks.page')} + </IndexLink> + </li> + </ul> + </li> + + <li className={systemClassName}> + <a className="dropdown-toggle" data-toggle="dropdown" href="#"> + {translate('sidebar.system')} <i className="icon-dropdown" /> + </a> + <ul className="dropdown-menu"> + <li> + <IndexLink to="/updatecenter" activeClassName="active"> + {translate('update_center.page')} + </IndexLink> + </li> + <li> + <IndexLink to="/system" activeClassName="active"> + {translate('system_info.page')} + </IndexLink> + </li> + </ul> + </li> + </ul> </div> - </nav> + </div> + </nav> ); } } diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/SettingsNav-test.js b/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/SettingsNav-test.js index 2477ccb58a4..48f8539f415 100644 --- a/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/SettingsNav-test.js +++ b/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/SettingsNav-test.js @@ -23,6 +23,6 @@ import { UnconnectedSettingsNav } from '../SettingsNav'; it('should work with extensions', () => { const extensions = [{ key: 'foo', name: 'Foo' }]; - const wrapper = shallow(<UnconnectedSettingsNav extensions={extensions}/>); + const wrapper = shallow(<UnconnectedSettingsNav extensions={extensions} />); expect(wrapper).toMatchSnapshot(); }); diff --git a/server/sonar-web/src/main/js/app/utils/configureLocale.js b/server/sonar-web/src/main/js/app/utils/configureLocale.js index 077a768d108..3b5346d2c59 100644 --- a/server/sonar-web/src/main/js/app/utils/configureLocale.js +++ b/server/sonar-web/src/main/js/app/utils/configureLocale.js @@ -19,9 +19,8 @@ */ import moment from 'moment'; -const getPreferredLanguage = () => ( - window.navigator.languages ? window.navigator.languages[0] : window.navigator.language -); +const getPreferredLanguage = () => + window.navigator.languages ? window.navigator.languages[0] : window.navigator.language; const configureLocale = () => { moment.locale(getPreferredLanguage()); diff --git a/server/sonar-web/src/main/js/app/utils/getHistory.js b/server/sonar-web/src/main/js/app/utils/getHistory.js index 263245a61b0..3a0f42b0d5d 100644 --- a/server/sonar-web/src/main/js/app/utils/getHistory.js +++ b/server/sonar-web/src/main/js/app/utils/getHistory.js @@ -30,6 +30,4 @@ const ensureHistory = () => { return history; }; -export default () => ( - history ? history : ensureHistory() -); +export default () => history ? history : ensureHistory(); diff --git a/server/sonar-web/src/main/js/app/utils/getStore.js b/server/sonar-web/src/main/js/app/utils/getStore.js index 03596f06dab..16796124e8f 100644 --- a/server/sonar-web/src/main/js/app/utils/getStore.js +++ b/server/sonar-web/src/main/js/app/utils/getStore.js @@ -28,6 +28,4 @@ const createStore = () => { return store; }; -export default () => ( - store ? store : createStore() -); +export default () => store ? store : createStore(); diff --git a/server/sonar-web/src/main/js/app/utils/handleRequiredAuthentication.js b/server/sonar-web/src/main/js/app/utils/handleRequiredAuthentication.js index 80771d448c4..ccd6899e88e 100644 --- a/server/sonar-web/src/main/js/app/utils/handleRequiredAuthentication.js +++ b/server/sonar-web/src/main/js/app/utils/handleRequiredAuthentication.js @@ -25,6 +25,6 @@ export default () => { const returnTo = window.location.pathname + window.location.search + window.location.hash; history.replace({ pathname: '/sessions/new', - query: { 'return_to': returnTo } + query: { return_to: returnTo } }); }; diff --git a/server/sonar-web/src/main/js/app/utils/handleRequiredAuthorization.js b/server/sonar-web/src/main/js/app/utils/handleRequiredAuthorization.js index 8637db51dc1..efb0deaecbd 100644 --- a/server/sonar-web/src/main/js/app/utils/handleRequiredAuthorization.js +++ b/server/sonar-web/src/main/js/app/utils/handleRequiredAuthorization.js @@ -31,6 +31,6 @@ export default () => { store.dispatch(requireAuthorization()); history.replace({ pathname: '/sessions/new', - query: { 'return_to': returnTo } + query: { return_to: returnTo } }); }; diff --git a/server/sonar-web/src/main/js/app/utils/startAjaxMonitoring.js b/server/sonar-web/src/main/js/app/utils/startAjaxMonitoring.js index 5b08fa4fc51..c60f3bca742 100644 --- a/server/sonar-web/src/main/js/app/utils/startAjaxMonitoring.js +++ b/server/sonar-web/src/main/js/app/utils/startAjaxMonitoring.js @@ -36,27 +36,27 @@ const Process = Backbone.Model.extend({ state: 'ok' }, - timeout () { + timeout() { this.set({ state: 'timeout', message: 'Still Working...' }); }, - finish (options) { + finish(options) { const finalOptions = { force: false, ...options }; if (this.get('state') !== 'failed' || finalOptions.force) { this.trigger('destroy', this, this.collection, finalOptions); } }, - fail (message) { + fail(message) { const that = this; let msg = message || translate('process.fail'); if (msg === 'process.fail') { // no translation msg = 'An error happened, some parts of the page might not render correctly. ' + - 'Please contact the administrator if you keep on experiencing this error.'; + 'Please contact the administrator if you keep on experiencing this error.'; } clearInterval(this.get('timer')); this.set({ @@ -64,9 +64,12 @@ const Process = Backbone.Model.extend({ message: msg }); this.set('state', 'failed'); - setTimeout(() => { - that.finish({ force: true }); - }, 5000); + setTimeout( + () => { + that.finish({ force: true }); + }, + 5000 + ); } }); @@ -79,28 +82,28 @@ const ProcessesView = Marionette.ItemView.extend({ className: 'processes-container', collectionEvents: { - 'all': 'render' + all: 'render' }, - render () { + render() { const failed = this.collection.findWhere({ state: 'failed' }); const timeout = this.collection.findWhere({ state: 'timeout' }); let el; this.$el.empty(); if (failed != null) { el = $('<li></li>') - .html(failed.get('message')) - .addClass('process-spinner process-spinner-failed shown'); - const close = $('<button></button>').html('<i class="icon-close"></i>').addClass('process-spinner-close'); + .html(failed.get('message')) + .addClass('process-spinner process-spinner-failed shown'); + const close = $('<button></button>') + .html('<i class="icon-close"></i>') + .addClass('process-spinner-close'); close.appendTo(el); close.on('click', () => { failed.finish({ force: true }); }); el.appendTo(this.$el); } else if (timeout != null) { - el = $('<li></li>') - .html(timeout.get('message')) - .addClass('process-spinner shown'); + el = $('<li></li>').html(timeout.get('message')).addClass('process-spinner shown'); el.appendTo(this.$el); } return this; @@ -116,13 +119,16 @@ const processesView = new ProcessesView({ * Add background process * @returns {number} */ -function addBackgroundProcess () { +function addBackgroundProcess() { const uid = uniqueId('process'); const process = new Process({ id: uid, - timer: setTimeout(() => { - process.timeout(); - }, defaults.timeout) + timer: setTimeout( + () => { + process.timeout(); + }, + defaults.timeout + ) }); processes.add(process); return uid; @@ -132,7 +138,7 @@ function addBackgroundProcess () { * Finish background process * @param {number} uid */ -function finishBackgroundProcess (uid) { +function finishBackgroundProcess(uid) { const process = processes.get(uid); if (process != null) { process.finish(); @@ -144,7 +150,7 @@ function finishBackgroundProcess (uid) { * @param {number} uid * @param {string} message */ -function failBackgroundProcess (uid, message) { +function failBackgroundProcess(uid, message) { const process = processes.get(uid); if (process != null) { process.fail(message); @@ -155,7 +161,7 @@ function failBackgroundProcess (uid, message) { * Handle ajax error * @param jqXHR */ -function handleAjaxError (jqXHR) { +function handleAjaxError(jqXHR) { if (jqXHR != null && jqXHR.processId != null) { let message = null; if (jqXHR.responseJSON != null && jqXHR.responseJSON.errors != null) { @@ -165,18 +171,18 @@ function handleAjaxError (jqXHR) { } } -function handleNotAuthenticatedError () { +function handleNotAuthenticatedError() { // workaround cyclic dependencies const handleRequiredAuthentication = require('./handleRequiredAuthentication').default; handleRequiredAuthentication(); } $.ajaxSetup({ - beforeSend (jqXHR) { + beforeSend(jqXHR) { jqXHR.setRequestHeader(getCSRFTokenName(), getCSRFTokenValue()); jqXHR.processId = addBackgroundProcess(); }, - complete (jqXHR) { + complete(jqXHR) { if (jqXHR.processId != null) { finishBackgroundProcess(jqXHR.processId); } diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.js b/server/sonar-web/src/main/js/app/utils/startReactApp.js index 594e906ff12..71f53ddfe0f 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.js +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.js @@ -69,7 +69,7 @@ import { globalPermissionsRoutes, projectPermissionsRoutes } from '../../apps/pe import getStore from './getStore'; import getHistory from './getHistory'; -function handleUpdate () { +function handleUpdate() { const { action } = this.state.location; if (action === 'PUSH') { @@ -83,14 +83,17 @@ const startReactApp = () => { const history = getHistory(); const store = getStore(); - render(( + render( <Provider store={store}> <Router history={history} onUpdate={handleUpdate}> - <Route path="/dashboard/index/:key" onEnter={(nextState, replace) => { - replace({ pathname: '/dashboard', query: { id: nextState.params.key } }); - }}/> + <Route + path="/dashboard/index/:key" + onEnter={(nextState, replace) => { + replace({ pathname: '/dashboard', query: { id: nextState.params.key } }); + }} + /> - <Route path="markdown/help" component={MarkdownHelp}/> + <Route path="markdown/help" component={MarkdownHelp} /> <Route component={LocalizationContainer}> <Route component={SimpleContainer}> @@ -105,17 +108,20 @@ const startReactApp = () => { <Route path="/" component={App}> - <IndexRoute component={Landing}/> + <IndexRoute component={Landing} /> <Route component={GlobalContainer}> <Route path="about">{aboutRoutes}</Route> <Route path="account">{accountRoutes}</Route> - <Route path="codingrules" onEnter={(nextState, replace) => { - replace('/coding_rules' + window.location.hash); - }}/> + <Route + path="codingrules" + onEnter={(nextState, replace) => { + replace('/coding_rules' + window.location.hash); + }} + /> <Route path="coding_rules">{codingRulesRoutes}</Route> <Route path="component">{componentRoutes}</Route> - <Route path="extension/:pluginKey/:extensionKey" component={GlobalPageExtension}/> + <Route path="extension/:pluginKey/:extensionKey" component={GlobalPageExtension} /> <Route path="issues">{issuesRoutes}</Route> <Route path="organizations">{organizationsRouters}</Route> <Route path="projects">{projectsRoutes}</Route> @@ -129,24 +135,33 @@ const startReactApp = () => { <Route path="component_measures">{componentMeasuresRoutes}</Route> <Route path="custom_measures">{customMeasuresRoutes}</Route> <Route path="dashboard">{overviewRoutes}</Route> - <Redirect from="governance" to="/view"/> + <Redirect from="governance" to="/view" /> <Route path="project"> <Route path="activity">{projectActivityRoutes}</Route> <Route path="admin" component={ProjectAdminContainer}> - <Route path="extension/:pluginKey/:extensionKey" component={ProjectAdminPageExtension}/> + <Route + path="extension/:pluginKey/:extensionKey" + component={ProjectAdminPageExtension} + /> </Route> - <Redirect from="extension/governance/governance" to="/view"/> - <Route path="extension/:pluginKey/:extensionKey" component={ProjectPageExtension}/> + <Redirect from="extension/governance/governance" to="/view" /> + <Route + path="extension/:pluginKey/:extensionKey" + component={ProjectPageExtension} + /> <Route path="background_tasks">{backgroundTasksRoutes}</Route> <Route path="settings">{settingsRoutes}</Route> {projectAdminRoutes} </Route> <Route path="project_roles">{projectPermissionsRoutes}</Route> - <Route path="view" component={ViewDashboard}/> + <Route path="view" component={ViewDashboard} /> </Route> <Route component={AdminContainer}> - <Route path="admin/extension/:pluginKey/:extensionKey" component={GlobalAdminPageExtension}/> + <Route + path="admin/extension/:pluginKey/:extensionKey" + component={GlobalAdminPageExtension} + /> <Route path="background_tasks">{backgroundTasksRoutes}</Route> <Route path="groups">{groupsRoutes}</Route> <Route path="metrics">{metricsRoutes}</Route> @@ -160,14 +175,15 @@ const startReactApp = () => { </Route> </Route> - <Route path="not_found" component={NotFound}/> - <Route path="*" component={NotFound}/> + <Route path="not_found" component={NotFound} /> + <Route path="*" component={NotFound} /> </Route> </Route> </Route> </Router> - </Provider> - ), el); + </Provider>, + el + ); }; export default startReactApp; |