diff options
Diffstat (limited to 'server/sonar-web')
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')} <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')} <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')} <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')} <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> + + ); + } +}); |