aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/app
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2016-12-08 17:35:26 +0100
committerGitHub <noreply@github.com>2016-12-08 17:35:26 +0100
commit621544af2b072e21e42b8d4c1c2bd800cbfdd696 (patch)
tree271306721ea30ca9549a4649eae6059ed5aa4ffa /server/sonar-web/src/main/js/app
parentfb9dd756d3e18058e13384b4119e220d3ae1a43d (diff)
downloadsonarqube-621544af2b072e21e42b8d4c1c2bd800cbfdd696.tar.gz
sonarqube-621544af2b072e21e42b8d4c1c2bd800cbfdd696.zip
SONAR-8505 Implement smooth transition between pages (#1440)
Diffstat (limited to 'server/sonar-web/src/main/js/app')
-rw-r--r--server/sonar-web/src/main/js/app/components/GlobalContainer.js4
-rw-r--r--server/sonar-web/src/main/js/app/components/GlobalFooter.js5
-rw-r--r--server/sonar-web/src/main/js/app/components/GlobalMessagesContainer.js5
-rw-r--r--server/sonar-web/src/main/js/app/components/NotFound.js3
-rw-r--r--server/sonar-web/src/main/js/app/components/ProjectContainer.js9
-rw-r--r--server/sonar-web/src/main/js/app/components/SimpleContainer.js5
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNav.js2
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/component/ComponentNavMenu.js151
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/global/GlobalNavBranding.js4
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.js46
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/global/GlobalNavUser.js3
-rw-r--r--server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.js87
12 files changed, 243 insertions, 81 deletions
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 da833189128..32b5f620145 100644
--- a/server/sonar-web/src/main/js/app/components/GlobalContainer.js
+++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.js
@@ -25,11 +25,13 @@ import GlobalMessagesContainer from './GlobalMessagesContainer';
export default class GlobalContainer extends React.Component {
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/>
+ <GlobalNav location={this.props.location}/>
<GlobalMessagesContainer/>
{this.props.children}
</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 e128246b69b..8d0e5472014 100644
--- a/server/sonar-web/src/main/js/app/components/GlobalFooter.js
+++ b/server/sonar-web/src/main/js/app/components/GlobalFooter.js
@@ -19,6 +19,7 @@
*/
// @flow
import React from 'react';
+import { Link } from 'react-router';
import { connect } from 'react-redux';
import { getAppState } from '../store/rootReducer';
@@ -64,9 +65,9 @@ class GlobalFooter extends React.Component {
{' - '}
<a href="http://redirect.sonarsource.com/doc/plugin-library.html">Plugins</a>
{' - '}
- <a href={window.baseUrl + '/web_api'}>Web API</a>
+ <Link to="/web_api">Web API</Link>
{' - '}
- <a href={window.baseUrl + '/about'}>About</a>
+ <Link to="/about">About</Link>
</div>
</div>
);
diff --git a/server/sonar-web/src/main/js/app/components/GlobalMessagesContainer.js b/server/sonar-web/src/main/js/app/components/GlobalMessagesContainer.js
index 0ee6c22edb5..6faf954d495 100644
--- a/server/sonar-web/src/main/js/app/components/GlobalMessagesContainer.js
+++ b/server/sonar-web/src/main/js/app/components/GlobalMessagesContainer.js
@@ -20,9 +20,12 @@
import { connect } from 'react-redux';
import GlobalMessages from '../../components/controls/GlobalMessages';
import { getGlobalMessages } from '../store/rootReducer';
+import { closeGlobalMessage } from '../../components/store/globalMessages';
const mapStateToProps = state => ({
messages: getGlobalMessages(state)
});
-export default connect(mapStateToProps)(GlobalMessages);
+const mapDispatchToProps = { closeGlobalMessage };
+
+export default connect(mapStateToProps, mapDispatchToProps)(GlobalMessages);
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 16b40224cef..85279ed1a14 100644
--- a/server/sonar-web/src/main/js/app/components/NotFound.js
+++ b/server/sonar-web/src/main/js/app/components/NotFound.js
@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
+import { Link } from 'react-router';
import SimpleContainer from './SimpleContainer';
export default class NotFound extends React.Component {
@@ -26,7 +27,7 @@ export default class NotFound extends React.Component {
<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><a href={window.baseUrl + '/'}>Go back to the homepage</a></p>
+ <p><Link to="/">Go back to the homepage</Link></p>
</SimpleContainer>
);
}
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 1a83c88e618..44d64f0cd9e 100644
--- a/server/sonar-web/src/main/js/app/components/ProjectContainer.js
+++ b/server/sonar-web/src/main/js/app/components/ProjectContainer.js
@@ -33,8 +33,15 @@ class ProjectContainer extends React.Component {
this.props.fetchProject();
}
+ componentDidUpdate (prevProps) {
+ if (prevProps.location.query.id !== this.props.location.query.id) {
+ this.props.fetchProject();
+ }
+ }
+
render () {
- if (!this.props.project) {
+ // check `canBeFavorite` to be sure that /api/navigation/component has been already called
+ if (!this.props.project || this.props.project.canBeFavorite == null) {
return null;
}
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 17d9c64cb69..342bffa2bc3 100644
--- a/server/sonar-web/src/main/js/app/components/SimpleContainer.js
+++ b/server/sonar-web/src/main/js/app/components/SimpleContainer.js
@@ -23,7 +23,10 @@ import GlobalFooter from './GlobalFooter';
export default class SimpleContainer extends React.Component {
static propTypes = {
- children: React.PropTypes.element.isRequired
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.element,
+ React.PropTypes.arrayOf(React.PropTypes.element)
+ ])
};
componentDidMount () {
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 b6dcd1c7359..5e3057b65ff 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
@@ -37,7 +37,7 @@ export default React.createClass({
},
loadStatus() {
- getTasksForComponent(this.props.component.uuid).then(r => {
+ getTasksForComponent(this.props.component.id).then(r => {
this.setState({
isPending: !!_.findWhere(r.queue, { status: STATUSES.PENDING }),
isInProgress: !!_.findWhere(r.queue, { status: STATUSES.IN_PROGRESS }),
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 52ed1e348a5..c348e186615 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
@@ -19,8 +19,8 @@
*/
import classNames from 'classnames';
import React from 'react';
+import { Link } from 'react-router';
import { translate } from '../../../../helpers/l10n';
-import { getComponentUrl } from '../../../../helpers/urls';
const SETTINGS_URLS = [
'/project/settings',
@@ -50,11 +50,6 @@ export default class ComponentNavMenu extends React.Component {
return qualifier === 'VW' || qualifier === 'SVW';
}
- isFixedDashboardActive () {
- const path = window.location.pathname;
- return path.indexOf(window.baseUrl + '/dashboard') === 0 || path.indexOf(window.baseUrl + '/governance') === 0;
- }
-
shouldShowAdministration () {
return Object.keys(this.props.conf).some(key => this.props.conf[key]);
}
@@ -73,12 +68,13 @@ export default class ComponentNavMenu extends React.Component {
}
renderDashboardLink () {
- const url = getComponentUrl(this.props.component.key);
- const name = <i className="icon-home"/>;
- const className = classNames({ active: this.isFixedDashboardActive() });
return (
- <li key="overview" className={className}>
- <a href={url}>{name}</a>
+ <li>
+ <Link
+ to={{ pathname: '/dashboard', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ <i className="icon-home"/>
+ </Link>
</li>
);
}
@@ -88,19 +84,39 @@ export default class ComponentNavMenu extends React.Component {
return null;
}
- const url = `/code/?id=${encodeURIComponent(this.props.component.key)}`;
- const header = this.isView() ? translate('view_projects.page') : translate('code.page');
- return this.renderLink(url, header, '/code');
+ 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>
+ );
}
renderComponentIssuesLink () {
- const url = `/component_issues?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('issues.page'), '/component_issues');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/component_issues', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('issues.page')}
+ </Link>
+ </li>
+ );
}
renderComponentMeasuresLink () {
- const url = `/component_measures/?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('layout.measures'), '/component_measures');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/component_measures', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('layout.measures')}
+ </Link>
+ </li>
+ );
}
renderAdministration () {
@@ -136,48 +152,90 @@ export default class ComponentNavMenu extends React.Component {
if (!this.props.conf.showSettings) {
return null;
}
- const url = `/project/settings?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('project_settings.page'), '/project/settings');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project/settings', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('project_settings.page')}
+ </Link>
+ </li>
+ );
}
renderProfilesLink () {
if (!this.props.conf.showQualityProfiles) {
return null;
}
- const url = `/project/quality_profiles?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('project_quality_profiles.page'), '/project/quality_profiles');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project/quality_profiles', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('project_quality_profiles.page')}
+ </Link>
+ </li>
+ );
}
renderQualityGateLink () {
if (!this.props.conf.showQualityGates) {
return null;
}
- const url = `/project/quality_gate?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('project_quality_gate.page'), '/project/quality_gate');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project/quality_gate', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('project_quality_gate.page')}
+ </Link>
+ </li>
+ );
}
renderCustomMeasuresLink () {
if (!this.props.conf.showManualMeasures) {
return null;
}
- const url = `/custom_measures?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('custom_measures.page'), '/custom_measures');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/custom_measures', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('custom_measures.page')}
+ </Link>
+ </li>
+ );
}
renderLinksLink () {
if (!this.props.conf.showLinks) {
return null;
}
- const url = `/project/links?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('project_links.page'), '/project/links');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project/links', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('project_links.page')}
+ </Link>
+ </li>
+ );
}
renderPermissionsLink () {
if (!this.props.conf.showPermissions) {
return null;
}
- const url = `/project_roles?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('permissions.page'), '/project_roles');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project_roles', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('permissions.page')}
+ </Link>
+ </li>
+ );
}
renderHistoryLink () {
@@ -199,16 +257,30 @@ export default class ComponentNavMenu extends React.Component {
if (!this.props.conf.showBackgroundTasks) {
return null;
}
- const url = `/project/background_tasks?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('background_tasks.page'), '/project/background_tasks');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project/background_tasks', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('background_tasks.page')}
+ </Link>
+ </li>
+ );
}
renderUpdateKeyLink () {
if (!this.props.conf.showUpdateKey) {
return null;
}
- const url = `/project/key?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('update_key.page'), '/project/key');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project/key', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('update_key.page')}
+ </Link>
+ </li>
+ );
}
renderDeletionLink () {
@@ -218,8 +290,15 @@ export default class ComponentNavMenu extends React.Component {
return null;
}
- const url = `/project/deletion?id=${encodeURIComponent(this.props.component.key)}`;
- return this.renderLink(url, translate('deletion.page'), '/project/deletion');
+ return (
+ <li>
+ <Link
+ to={{ pathname: '/project/deletion', query: { id: this.props.component.key } }}
+ activeClassName="active">
+ {translate('deletion.page')}
+ </Link>
+ </li>
+ );
}
renderExtensions () {
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 6542a9fb20b..b845eedfe58 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
@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
+import { Link } from 'react-router';
import { connect } from 'react-redux';
import { getSettingValue, getCurrentUser } from '../../../store/rootReducer';
import { translate } from '../../../../helpers/l10n';
@@ -40,11 +41,10 @@ class GlobalNavBranding extends React.Component {
render () {
const homeController = this.props.currentUser.isLoggedIn ? '/projects/favorite' : '/about';
- const homeUrl = window.baseUrl + homeController;
const homeLinkClassName = 'navbar-brand' + (this.props.customLogoUrl ? ' navbar-brand-custom' : '');
return (
<div className="navbar-header">
- <a className={homeLinkClassName} href={homeUrl}>{this.renderLogo()}</a>
+ <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 424ee074cef..d5c2f6402a8 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
@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
+import { Link } from 'react-router';
import { translate } from '../../../../helpers/l10n';
import { isUserAdmin } from '../../../../helpers/users';
@@ -36,48 +37,54 @@ export default class GlobalNavMenu extends React.Component {
}
renderProjects () {
- const controller = this.props.currentUser.isLoggedIn ? '/projects/favorite' : '/projects';
- const url = window.baseUrl + controller;
+ const pathname = this.props.currentUser.isLoggedIn ? '/projects/favorite' : '/projects';
return (
- <li className={this.activeLink('/projects')}>
- <a href={url}>{translate('projects.page')}</a>
+ <li>
+ <Link to={{ pathname }} activeClassName="active">
+ {translate('projects.page')}
+ </Link>
</li>
);
}
renderIssuesLink () {
const query = this.props.currentUser.isLoggedIn ? '#resolved=false|assigned_to_me=true' : '#resolved=false';
- const url = window.baseUrl + '/issues' + query;
+ const url = '/issues' + query;
return (
- <li className={this.activeLink('/issues')}>
- <a href={url}>{translate('issues.page')}</a>
+ <li>
+ <Link to={url} className={this.activeLink('/issues')}>
+ {translate('issues.page')}
+ </Link>
</li>
);
}
renderRulesLink () {
- const url = window.baseUrl + '/coding_rules';
return (
- <li className={this.activeLink('/coding_rules')}>
- <a href={url}>{translate('coding_rules.page')}</a>
+ <li>
+ <Link to="/coding_rules" className={this.activeLink('/coding_rules')}>
+ {translate('coding_rules.page')}
+ </Link>
</li>
);
}
renderProfilesLink () {
- const url = window.baseUrl + '/profiles';
return (
- <li className={this.activeLink('/profiles')}>
- <a href={url}>{translate('quality_profiles.page')}</a>
+ <li>
+ <Link to="/profiles" activeClassName="active">
+ {translate('quality_profiles.page')}
+ </Link>
</li>
);
}
renderQualityGatesLink () {
- const url = window.baseUrl + '/quality_gates';
return (
- <li className={this.activeLink('/quality_gates')}>
- <a href={url}>{translate('quality_gates.page')}</a>
+ <li>
+ <Link to="/quality_gates" activeClassName="active">
+ {translate('quality_gates.page')}
+ </Link>
</li>
);
}
@@ -86,10 +93,11 @@ export default class GlobalNavMenu extends React.Component {
if (!isUserAdmin(this.props.currentUser)) {
return null;
}
- const url = window.baseUrl + '/settings';
return (
- <li className={this.activeLink('/settings')}>
- <a className="navbar-admin-link" href={url}>{translate('layout.settings')}</a>
+ <li>
+ <Link to="/settings" className="navbar-admin-link" activeClassName="active">
+ {translate('layout.settings')}
+ </Link>
</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 11f633320c2..47eeb101a9b 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
@@ -18,6 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import React from 'react';
+import { Link } from 'react-router';
import Avatar from '../../../../components/ui/Avatar';
import RecentHistory from '../component/RecentHistory';
import { translate } from '../../../../helpers/l10n';
@@ -45,7 +46,7 @@ export default class GlobalNavUser extends React.Component {
</a>
<ul className="dropdown-menu dropdown-menu-right">
<li>
- <a href={`${window.baseUrl}/account/`}>{translate('my_account.page')}</a>
+ <Link to="/account">{translate('my_account.page')}</Link>
</li>
<li>
<a onClick={this.handleLogout} href="#">{translate('layout.logout')}</a>
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 afe8b25f1f2..6560e94f27c 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,6 +19,7 @@
*/
import React from 'react';
import classNames from 'classnames';
+import { IndexLink } from 'react-router';
import { translate } from '../../../../helpers/l10n';
export default class SettingsNav extends React.Component {
@@ -46,7 +47,7 @@ export default class SettingsNav extends React.Component {
return this.isSomethingActive(urls);
}
- renderLink(url, title, highlightUrl = url) {
+ renderLink (url, title, highlightUrl = url) {
const fullUrl = window.baseUrl + url;
const isActive = typeof highlightUrl === 'string' ?
window.location.pathname.indexOf(window.baseUrl + highlightUrl) === 0 :
@@ -76,7 +77,11 @@ export default class SettingsNav extends React.Component {
<div className="navbar-context-inner">
<div className="container">
<ul className="nav navbar-nav nav-crumbs">
- {this.renderLink('/settings', translate('layout.settings'))}
+ <li>
+ <IndexLink to="/settings">
+ {translate('layout.settings')}
+ </IndexLink>
+ </li>
</ul>
<ul className="nav navbar-nav nav-tabs">
@@ -85,11 +90,31 @@ export default class SettingsNav extends React.Component {
{translate('sidebar.project_settings')} <i className="icon-dropdown"/>
</a>
<ul className="dropdown-menu">
- {this.renderLink('/settings', translate('settings.page'), url => window.location.pathname === url)}
- {this.renderLink('/settings/licenses', translate('property.category.licenses'))}
- {this.renderLink('/settings/encryption', translate('property.category.security.encryption'))}
- {this.renderLink('/settings/server_id', translate('property.category.server_id'))}
- {this.renderLink('/metrics', 'Custom Metrics')}
+ <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(e => this.renderLink(e.url, e.name))}
</ul>
</li>
@@ -99,10 +124,26 @@ export default class SettingsNav extends React.Component {
{translate('sidebar.security')} <i className="icon-dropdown"/>
</a>
<ul className="dropdown-menu">
- {this.renderLink('/users', translate('users.page'))}
- {this.renderLink('/groups', translate('user_groups.page'))}
- {this.renderLink('/roles/global', translate('global_permissions.page'))}
- {this.renderLink('/permission_templates', translate('permission_templates'))}
+ <li>
+ <IndexLink to="/users" activeClassName="active">
+ {translate('users.page')}
+ </IndexLink>
+ </li>
+ <li>
+ <IndexLink to="/groups" activeClassName="active">
+ {translate('user_groups.page')}
+ </IndexLink>
+ </li>
+ <li>
+ <IndexLink to="/roles/global" activeClassName="active">
+ {translate('global_permissions.page')}
+ </IndexLink>
+ </li>
+ <li>
+ <IndexLink to="/permission_templates" activeClassName="active">
+ {translate('permission_templates')}
+ </IndexLink>
+ </li>
</ul>
</li>
@@ -111,8 +152,16 @@ export default class SettingsNav extends React.Component {
{translate('sidebar.projects')} <i className="icon-dropdown"/>
</a>
<ul className="dropdown-menu">
- {this.renderLink('/projects_admin', 'Management')}
- {this.renderLink('/background_tasks', translate('background_tasks.page'))}
+ <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>
@@ -121,8 +170,16 @@ export default class SettingsNav extends React.Component {
{translate('sidebar.system')} <i className="icon-dropdown"/>
</a>
<ul className="dropdown-menu">
- {this.renderLink('/updatecenter', translate('update_center.page'))}
- {this.renderLink('/system', translate('system_info.page'))}
+ <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>