aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/apps/nav/app.jsx7
-rw-r--r--server/sonar-web/src/main/js/apps/nav/component/component-nav-menu.jsx16
-rw-r--r--server/sonar-web/src/main/js/apps/nav/global/global-nav-menu.jsx7
-rw-r--r--server/sonar-web/src/main/js/apps/nav/global/global-nav.jsx17
-rw-r--r--server/sonar-web/src/main/js/apps/nav/links-mixin.jsx16
-rw-r--r--server/sonar-web/src/main/js/apps/nav/settings/settings-nav.jsx78
6 files changed, 121 insertions, 20 deletions
diff --git a/server/sonar-web/src/main/js/apps/nav/app.jsx b/server/sonar-web/src/main/js/apps/nav/app.jsx
index 48a708e321b..4b0b6ed5fa0 100644
--- a/server/sonar-web/src/main/js/apps/nav/app.jsx
+++ b/server/sonar-web/src/main/js/apps/nav/app.jsx
@@ -1,12 +1,14 @@
import React from 'react';
import GlobalNav from './global/global-nav';
import ComponentNav from './component/component-nav';
+import SettingsNav from './settings/settings-nav';
export default {
start(options) {
window.requestMessages().done(() => {
this.renderGlobalNav(options);
options.space === 'component' && this.renderComponentNav(options);
+ options.space === 'settings' && this.renderSettingsNav(options);
});
},
@@ -18,5 +20,10 @@ export default {
renderComponentNav(options) {
const el = document.getElementById('context-navigation');
React.render(<ComponentNav {...options}/>, el);
+ },
+
+ renderSettingsNav(options) {
+ const el = document.getElementById('context-navigation');
+ React.render(<SettingsNav {...options}/>, el);
}
};
diff --git a/server/sonar-web/src/main/js/apps/nav/component/component-nav-menu.jsx b/server/sonar-web/src/main/js/apps/nav/component/component-nav-menu.jsx
index 03e1c28f7ee..9201916e690 100644
--- a/server/sonar-web/src/main/js/apps/nav/component/component-nav-menu.jsx
+++ b/server/sonar-web/src/main/js/apps/nav/component/component-nav-menu.jsx
@@ -1,5 +1,6 @@
import React from 'react';
import DashboardNameMixin from '../dashboard-name-mixin';
+import LinksMixin from '../links-mixin';
const SETTINGS_URLS = [
'/project/settings', '/project/profile', '/project/qualitygate', '/manual_measures/index',
@@ -10,20 +11,7 @@ const SETTINGS_URLS = [
const MORE_URLS = ['/dashboards', '/dashboard', '/plugins/resource'];
export default React.createClass({
- mixins: [DashboardNameMixin],
-
- activeLink(url) {
- return window.location.pathname.indexOf(window.baseUrl + url) === 0 ? 'active' : null;
- },
-
- renderLink(url, title, highlightUrl = url) {
- let fullUrl = window.baseUrl + url;
- return (
- <li key={highlightUrl} className={this.activeLink(highlightUrl)}>
- <a href={fullUrl}>{title}</a>
- </li>
- );
- },
+ mixins: [DashboardNameMixin, LinksMixin],
renderOverviewLink() {
const url = `/overview/index?id=${encodeURIComponent(this.props.component.key)}`;
diff --git a/server/sonar-web/src/main/js/apps/nav/global/global-nav-menu.jsx b/server/sonar-web/src/main/js/apps/nav/global/global-nav-menu.jsx
index 037b0231210..6249b8b11fb 100644
--- a/server/sonar-web/src/main/js/apps/nav/global/global-nav-menu.jsx
+++ b/server/sonar-web/src/main/js/apps/nav/global/global-nav-menu.jsx
@@ -1,17 +1,14 @@
import React from 'react';
import DashboardNameMixin from '../dashboard-name-mixin';
+import LinksMixin from '../links-mixin';
export default React.createClass({
- mixins: [DashboardNameMixin],
+ mixins: [DashboardNameMixin, LinksMixin],
getDefaultProps: function () {
return { globalDashboards: [], globalPages: [] };
},
- activeLink(url) {
- return window.location.pathname.indexOf(window.baseUrl + url) === 0 ? 'active' : null;
- },
-
renderDashboardLink(dashboard) {
const url = `${window.baseUrl}/dashboard/index?did=${encodeURIComponent(dashboard.key)}`;
const name = this.getLocalizedDashboardName(dashboard.name);
diff --git a/server/sonar-web/src/main/js/apps/nav/global/global-nav.jsx b/server/sonar-web/src/main/js/apps/nav/global/global-nav.jsx
index b7d8782268a..908033c73bf 100644
--- a/server/sonar-web/src/main/js/apps/nav/global/global-nav.jsx
+++ b/server/sonar-web/src/main/js/apps/nav/global/global-nav.jsx
@@ -14,6 +14,11 @@ export default React.createClass({
componentDidMount() {
this.loadGlobalNavDetails();
+ window.addEventListener('keypress', this.onKeyPress);
+ },
+
+ componentWillUnmount() {
+ window.removeEventListener('keypress', this.onKeyPress);
},
loadGlobalNavDetails() {
@@ -22,8 +27,18 @@ export default React.createClass({
});
},
+ onKeyPress(e) {
+ var tagName = e.target.tagName;
+ if (tagName !== 'INPUT' && tagName !== 'SELECT' && tagName !== 'TEXTAREA') {
+ var code = e.keyCode || e.which;
+ if (code === 63) {
+ this.openHelp();
+ }
+ }
+ },
+
openHelp(e) {
- e.preventDefault();
+ e && e.preventDefault();
new ShortcutsHelpView().render();
},
diff --git a/server/sonar-web/src/main/js/apps/nav/links-mixin.jsx b/server/sonar-web/src/main/js/apps/nav/links-mixin.jsx
new file mode 100644
index 00000000000..e807c5a26d0
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/nav/links-mixin.jsx
@@ -0,0 +1,16 @@
+import React from 'react';
+
+export default {
+ activeLink(url) {
+ return window.location.pathname.indexOf(window.baseUrl + url) === 0 ? 'active' : null;
+ },
+
+ renderLink(url, title, highlightUrl = url) {
+ let fullUrl = window.baseUrl + url;
+ return (
+ <li key={highlightUrl} className={this.activeLink(highlightUrl)}>
+ <a href={fullUrl}>{title}</a>
+ </li>
+ );
+ }
+};
diff --git a/server/sonar-web/src/main/js/apps/nav/settings/settings-nav.jsx b/server/sonar-web/src/main/js/apps/nav/settings/settings-nav.jsx
new file mode 100644
index 00000000000..20f1ce5a08d
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/nav/settings/settings-nav.jsx
@@ -0,0 +1,78 @@
+import React from 'react';
+import LinksMixin from '../links-mixin';
+
+let $ = jQuery;
+
+export default React.createClass({
+ mixins: [LinksMixin],
+
+ getInitialState() {
+ return { extensions: [] };
+ },
+
+ componentDidMount() {
+ this.loadDetails();
+ },
+
+ loadDetails() {
+ $.get(`${window.baseUrl}/api/navigation/settings`).done(r => this.setState(r));
+ },
+
+ render() {
+ return (
+ <div className="container">
+ <ul className="nav navbar-nav nav-crumbs">
+ {this.renderLink('/settings', window.t('layout.settings'))}
+ </ul>
+
+ <ul className="nav navbar-nav nav-tabs">
+ <li className="dropdown">
+ <a className="dropdown-toggle" data-toggle="dropdown" href="#">
+ {window.t('sidebar.project_settings')}&nbsp;<i className="icon-dropdown"></i>
+ </a>
+ <ul className="dropdown-menu">
+ {this.renderLink('/settings', window.t('settings.page'))}
+ {this.renderLink('/metrics', 'Custom Metrics')}
+ {this.renderLink('/admin_dashboards', window.t('default_dashboards.page'))}
+ {this.state.extensions.map(e => this.renderLink(e.url, e.name))}
+ </ul>
+ </li>
+
+ <li className="dropdown">
+ <a className="dropdown-toggle" data-toggle="dropdown" href="#">
+ {window.t('sidebar.security')}&nbsp;<i className="icon-dropdown"></i>
+ </a>
+ <ul className="dropdown-menu">
+ {this.renderLink('/users', window.t('users.page'))}
+ {this.renderLink('/groups', window.t('user_groups.page'))}
+ {this.renderLink('/roles/global', window.t('global_permissions.page'))}
+ {this.renderLink('/roles/projects', window.t('roles.page'))}
+ </ul>
+ </li>
+
+ <li className="dropdown">
+ <a className="dropdown-toggle" data-toggle="dropdown" href="#">
+ {window.t('sidebar.projects')}&nbsp;<i className="icon-dropdown"></i>
+ </a>
+ <ul className="dropdown-menu">
+ {this.state.showProvisioning ? this.renderLink('/provisioning', window.t('provisioning.page')) : null}
+ {this.renderLink('/bulk_deletion', window.t('bulk_deletion.page'))}
+ {this.renderLink('/computation', window.t('analysis_reports.page'))}
+ </ul>
+ </li>
+
+ <li className="dropdown">
+ <a className="dropdown-toggle" data-toggle="dropdown" href="#">
+ {window.t('sidebar.system')}&nbsp;<i className="icon-dropdown"></i>
+ </a>
+ <ul className="dropdown-menu">
+ {this.renderLink('/updatecenter', window.t('update_center.page'))}
+ {this.renderLink('/system', window.t('system_info.page'))}
+ </ul>
+ </li>
+ </ul>
+ </div>
+
+ );
+ }
+});