diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2016-12-20 16:28:58 +0100 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2016-12-20 16:35:14 +0100 |
commit | 0d37b8a966e1f1ebf6f38524da8ec1e0a0e06813 (patch) | |
tree | afbeabfac1648420922dd28ae4d58cd582222fe7 | |
parent | 8c9d3d5bb674a0ea9a8dcff2fef5a1eeb70537a8 (diff) | |
download | sonarqube-0d37b8a966e1f1ebf6f38524da8ec1e0a0e06813.tar.gz sonarqube-0d37b8a966e1f1ebf6f38524da8ec1e0a0e06813.zip |
SONAR-8552 fix settings navigation
4 files changed, 243 insertions, 13 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 728118fac90..26da1f1be44 100644 --- a/server/sonar-web/src/main/js/app/components/AdminContainer.js +++ b/server/sonar-web/src/main/js/app/components/AdminContainer.js @@ -22,24 +22,46 @@ import { connect } from 'react-redux'; import SettingsNav from './nav/settings/SettingsNav'; import { getCurrentUser } from '../../store/rootReducer'; import { isUserAdmin } from '../../helpers/users'; +import { onFail } from '../../store/rootActions'; +import { getSettingsNavigation } from '../../api/nav'; class AdminContainer extends React.Component { + state = { + loading: true + }; + componentDidMount () { if (!isUserAdmin(this.props.currentUser)) { // workaround cyclic dependencies const handleRequiredAuthorization = require('../utils/handleRequiredAuthorization').default; handleRequiredAuthorization(); } + + this.mounted = true; + this.loadData(); + } + + componentWillUnmount () { + this.mounted = false; + } + + loadData () { + getSettingsNavigation().then( + r => this.setState({ extensions: r.extensions, loading: false }), + onFail(this.props.dispatch) + ); } render () { - if (!isUserAdmin(this.props.currentUser)) { + if (!isUserAdmin(this.props.currentUser) || this.state.loading) { return null; } return ( <div> - <SettingsNav/> + <SettingsNav + location={this.props.location} + extensions={this.state.extensions}/> {this.props.children} </div> ); 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 6560e94f27c..f65a2b8050e 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 @@ -19,7 +19,7 @@ */ import React from 'react'; import classNames from 'classnames'; -import { IndexLink } from 'react-router'; +import { IndexLink, Link } from 'react-router'; import { translate } from '../../../../helpers/l10n'; export default class SettingsNav extends React.Component { @@ -47,18 +47,13 @@ export default class SettingsNav extends React.Component { return this.isSomethingActive(urls); } - renderLink (url, title, highlightUrl = url) { - const fullUrl = window.baseUrl + url; - const isActive = typeof highlightUrl === 'string' ? - window.location.pathname.indexOf(window.baseUrl + highlightUrl) === 0 : - highlightUrl(fullUrl); - + renderExtension = ({ id, name }) => { return ( - <li key={url} className={classNames({ 'active': isActive })}> - <a href={fullUrl}>{title}</a> + <li key={id}> + <Link to={`/admin/extension/${id}`} activeClassName="active">{name}</Link> </li> ); - } + }; render () { const isSecurity = this.isSecurityActive(); @@ -115,7 +110,7 @@ export default class SettingsNav extends React.Component { Custom Metrics </IndexLink> </li> - {this.props.extensions.map(e => this.renderLink(e.url, e.name))} + {this.props.extensions.map(this.renderExtension)} </ul> </li> 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 new file mode 100644 index 00000000000..c00d2b102ce --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/SettingsNav-test.js @@ -0,0 +1,29 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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 React from 'react'; +import { shallow } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import SettingsNav from '../SettingsNav'; + +it('should work with extensions', () => { + const extensions = [{ id: 'foo', name: 'Foo' }]; + const wrapper = shallow(<SettingsNav extensions={extensions}/>); + expect(toJSON(wrapper)).toMatchSnapshot(); +}); diff --git a/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/SettingsNav-test.js.snap b/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/SettingsNav-test.js.snap new file mode 100644 index 00000000000..2173a8f054f --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/nav/settings/__tests__/__snapshots__/SettingsNav-test.js.snap @@ -0,0 +1,184 @@ +exports[`test should work with extensions 1`] = ` +<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"> + layout.settings + </IndexLink> + </li> + </ul> + <ul + className="nav navbar-nav nav-tabs"> + <li + className="dropdown active"> + <a + className="dropdown-toggle" + data-toggle="dropdown" + href="#"> + sidebar.project_settings + + <i + className="icon-dropdown" /> + </a> + <ul + className="dropdown-menu"> + <li> + <IndexLink + activeClassName="active" + to="/settings"> + settings.page + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/settings/licenses"> + property.category.licenses + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/settings/encryption"> + property.category.security.encryption + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/settings/server_id"> + property.category.server_id + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/metrics"> + Custom Metrics + </IndexLink> + </li> + <li> + <Link + activeClassName="active" + onlyActiveOnIndex={false} + style={Object {}} + to="/admin/extension/foo"> + Foo + </Link> + </li> + </ul> + </li> + <li + className="dropdown"> + <a + className="dropdown-toggle" + data-toggle="dropdown" + href="#"> + sidebar.security + + <i + className="icon-dropdown" /> + </a> + <ul + className="dropdown-menu"> + <li> + <IndexLink + activeClassName="active" + to="/users"> + users.page + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/groups"> + user_groups.page + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/roles/global"> + global_permissions.page + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/permission_templates"> + permission_templates + </IndexLink> + </li> + </ul> + </li> + <li + className="dropdown"> + <a + className="dropdown-toggle" + data-toggle="dropdown" + href="#"> + sidebar.projects + + <i + className="icon-dropdown" /> + </a> + <ul + className="dropdown-menu"> + <li> + <IndexLink + activeClassName="active" + to="/projects_admin"> + Management + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/background_tasks"> + background_tasks.page + </IndexLink> + </li> + </ul> + </li> + <li + className="dropdown"> + <a + className="dropdown-toggle" + data-toggle="dropdown" + href="#"> + sidebar.system + + <i + className="icon-dropdown" /> + </a> + <ul + className="dropdown-menu"> + <li> + <IndexLink + activeClassName="active" + to="/updatecenter"> + update_center.page + </IndexLink> + </li> + <li> + <IndexLink + activeClassName="active" + to="/system"> + system_info.page + </IndexLink> + </li> + </ul> + </li> + </ul> + </div> + </div> +</nav> +`; |