diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-05-18 16:29:19 +0200 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-05-19 18:20:09 +0200 |
commit | e59e4aa2c06a57566f148f4217d286461231ae58 (patch) | |
tree | ad0918eb06b2474a6c71997b7ff573bbb93e0170 /server/sonar-web/src/main/js/apps/nav | |
parent | 8d82c9cf9ba88c1517604b4063ad0fc2a9a1bb9a (diff) | |
download | sonarqube-e59e4aa2c06a57566f148f4217d286461231ae58.tar.gz sonarqube-e59e4aa2c06a57566f148f4217d286461231ae58.zip |
change web structure: separate components
Diffstat (limited to 'server/sonar-web/src/main/js/apps/nav')
16 files changed, 1026 insertions, 0 deletions
diff --git a/server/sonar-web/src/main/js/apps/nav/app.js b/server/sonar-web/src/main/js/apps/nav/app.js new file mode 100644 index 00000000000..5d45dd82f97 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/app.js @@ -0,0 +1,79 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +define([ + './state', + './global-navbar-view', + './context-navbar-view', + './settings-navbar-view', + 'components/workspace/main' +], function (State, GlobalNavbarView, ContextNavbarView, SettingsNavbarView) { + + var $ = jQuery, + App = new Marionette.Application(), + state = new State(); + + state.set(window.navbarOptions.toJSON()); + + App.on('start', function () { + state.fetchGlobal(); + + this.navbarView = new GlobalNavbarView({ + app: App, + el: $('.navbar-global'), + model: state + }); + this.navbarView.render(); + + if (state.get('space') === 'component') { + state.fetchComponent(); + this.contextNavbarView = new ContextNavbarView({ + app: App, + el: $('.navbar-context'), + model: state + }); + this.contextNavbarView.render(); + } + + if (state.get('space') === 'settings') { + state.fetchSettings(); + this.settingsNavbarView = new SettingsNavbarView({ + app: App, + el: $('.navbar-context'), + model: state + }); + this.settingsNavbarView.render(); + } + + $(window).on('keypress', function (e) { + var tagName = e.target.tagName; + if (tagName !== 'INPUT' && tagName !== 'SELECT' && tagName !== 'TEXTAREA') { + var code = e.keyCode || e.which; + if (code === 63) { + App.navbarView.showShortcutsHelp(); + } + } + }); + }); + + window.requestMessages().done(function () { + App.start(); + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/nav/context-navbar-view.js b/server/sonar-web/src/main/js/apps/nav/context-navbar-view.js new file mode 100644 index 00000000000..07eb0cd159a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/context-navbar-view.js @@ -0,0 +1,82 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +define([ + './templates' +], function () { + + var $ = jQuery, + MORE_URLS = [ + '/dashboards', '/plugins/resource' + ], + SETTINGS_URLS = [ + '/project/settings', '/project/profile', '/project/qualitygate', '/manual_measures/index', + '/action_plans/index', '/project/links', '/project_roles/index', '/project/history', '/project/key', + '/project/deletion' + ]; + + return Marionette.ItemView.extend({ + template: Templates['nav-context-navbar'], + + modelEvents: { + 'change:component': 'render' + }, + + events: { + 'click .js-favorite': 'onFavoriteClick' + }, + + onRender: function () { + this.$('[data-toggle="tooltip"]').tooltip({ + container: 'body' + }); + }, + + onFavoriteClick: function () { + var that = this, + url = baseUrl + '/favourites/toggle/' + this.model.get('contextId'), + isContextFavorite = this.model.get('isContextFavorite'); + this.model.set({ isContextFavorite: !isContextFavorite }); + return $.post(url).fail(function () { + that.model.set({ isContextFavorite: isContextFavorite }); + }); + }, + + serializeData: function () { + var href = window.location.href, + search = window.location.search, + isMoreActive = _.some(MORE_URLS, function (url) { + return href.indexOf(url) !== -1; + }) || (href.indexOf('/dashboard') !== -1 && search.indexOf('did=') !== -1), + isSettingsActive = _.some(SETTINGS_URLS, function (url) { + return href.indexOf(url) !== -1; + }), + isOverviewActive = !isMoreActive && href.indexOf('/dashboard') !== -1 && search.indexOf('did=') === -1; + return _.extend(Marionette.Layout.prototype.serializeData.apply(this, arguments), { + canManageContextDashboards: !!window.SS.user, + contextKeyEncoded: encodeURIComponent(this.model.get('componentKey')), + + isOverviewActive: isOverviewActive, + isSettingsActive: isSettingsActive, + isMoreActive: isMoreActive + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/nav/global-navbar-view.js b/server/sonar-web/src/main/js/apps/nav/global-navbar-view.js new file mode 100644 index 00000000000..9ee43d9fdfe --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/global-navbar-view.js @@ -0,0 +1,97 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +define([ + './search-view', + './shortcuts-help-view', + './templates' +], function (SearchView, ShortcutsHelpView) { + + return Marionette.Layout.extend({ + template: Templates['nav-global-navbar'], + + modelEvents: { + 'change': 'render' + }, + + regions: { + searchRegion: '.js-search-region' + }, + + events: { + 'click .js-login': 'onLoginClick', + 'click .js-favorite': 'onFavoriteClick', + 'show.bs.dropdown .js-search-dropdown': 'onSearchDropdownShow', + 'hidden.bs.dropdown .js-search-dropdown': 'onSearchDropdownHidden', + 'click .js-shortcuts': 'onShortcutsClick' + }, + + onRender: function () { + var that = this; + if (this.model.has('space')) { + this.$el.addClass('navbar-' + this.model.get('space')); + } + this.$el.addClass('navbar-fade'); + setTimeout(function () { + that.$el.addClass('in'); + }, 0); + }, + + onLoginClick: function () { + var returnTo = window.location.pathname + window.location.search; + window.location = baseUrl + '/sessions/new?return_to=' + encodeURIComponent(returnTo) + window.location.hash; + return false; + }, + + onSearchDropdownShow: function () { + var that = this; + this.searchRegion.show(new SearchView({ + model: this.model, + hide: function () { + that.$('.js-search-dropdown-toggle').dropdown('toggle'); + } + })); + }, + + onSearchDropdownHidden: function () { + this.searchRegion.reset(); + }, + + onShortcutsClick: function () { + this.showShortcutsHelp(); + }, + + showShortcutsHelp: function () { + new ShortcutsHelpView({ shortcuts: this.model.get('shortcuts') }).render(); + }, + + serializeData: function () { + return _.extend(Marionette.Layout.prototype.serializeData.apply(this, arguments), { + user: window.SS.user, + userName: window.SS.userName, + isUserAdmin: window.SS.isUserAdmin, + + canManageGlobalDashboards: !!window.SS.user, + canManageIssueFilters: !!window.SS.user, + canManageMeasureFilters: !!window.SS.user + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/nav/search-view.js b/server/sonar-web/src/main/js/apps/nav/search-view.js new file mode 100644 index 00000000000..57daa695031 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/search-view.js @@ -0,0 +1,250 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +define([ + 'components/common/selectable-collection-view', + './templates' +], function (SelectableCollectionView) { + + var $ = jQuery, + + SearchItemView = Marionette.ItemView.extend({ + tagName: 'li', + template: Templates['nav-search-item'], + + select: function () { + this.$el.addClass('active'); + }, + + deselect: function () { + this.$el.removeClass('active'); + }, + + submit: function () { + this.$('a')[0].click(); + }, + + serializeData: function () { + return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), { + index: this.options.index + }); + } + }), + + SearchEmptyView = Marionette.ItemView.extend({ + tagName: 'li', + template: Templates['nav-search-empty'] + }), + + SearchResultsView = SelectableCollectionView.extend({ + className: 'menu', + tagName: 'ul', + itemView: SearchItemView, + emptyView: SearchEmptyView + }); + + return Marionette.Layout.extend({ + className: 'navbar-search', + tagName: 'form', + template: Templates['nav-search'], + + regions: { + resultsRegion: '.js-search-results' + }, + + events: { + 'submit': 'onSubmit', + 'keydown .js-search-input': 'onKeyDown', + 'keyup .js-search-input': 'debouncedOnKeyUp' + }, + + initialize: function () { + var that = this; + this.results = new Backbone.Collection(); + this.favorite = []; + if (window.SS.user) { + this.fetchFavorite().always(function () { + that.resetResultsToDefault(); + }); + } else { + this.resetResultsToDefault(); + } + this.resultsView = new SearchResultsView({ collection: this.results }); + this.debouncedOnKeyUp = _.debounce(this.onKeyUp, 400); + this._bufferedValue = ''; + }, + + onRender: function () { + var that = this; + this.resultsRegion.show(this.resultsView); + setTimeout(function () { + that.$('.js-search-input').focus(); + }, 0); + }, + + onKeyDown: function (e) { + if (e.keyCode === 38) { + this.resultsView.selectPrev(); + return false; + } + if (e.keyCode === 40) { + this.resultsView.selectNext(); + return false; + } + if (e.keyCode === 13) { + this.resultsView.submitCurrent(); + return false; + } + if (e.keyCode === 27) { + this.options.hide(); + return false; + } + }, + + onKeyUp: function () { + var value = this.$('.js-search-input').val(); + if (value === this._bufferedValue) { + return; + } + this._bufferedValue = this.$('.js-search-input').val(); + if (this.searchRequest != null) { + this.searchRequest.abort(); + } + this.searchRequest = this.search(value); + }, + + onSubmit: function () { + return false; + }, + + fetchFavorite: function () { + var that = this; + return $.get(baseUrl + '/api/favourites').done(function (r) { + that.favorite = r.map(function (f) { + var isFile = ['FIL', 'UTS'].indexOf(f.qualifier) !== -1; + return { + url: baseUrl + '/dashboard/index?id=' + encodeURIComponent(f.key) + dashboardParameters(true), + name: isFile ? window.collapsedDirFromPath(f.lname) + window.fileFromPath(f.lname) : f.name, + icon: 'favorite' + }; + }); + that.favorite = _.sortBy(that.favorite, 'name'); + }); + }, + + resetResultsToDefault: function () { + var recentHistory = JSON.parse(localStorage.getItem('sonar_recent_history')), + history = (recentHistory || []).map(function (historyItem, index) { + return { + url: baseUrl + '/dashboard/index?id=' + encodeURIComponent(historyItem.key) + dashboardParameters(true), + name: historyItem.name, + q: historyItem.icon, + extra: index === 0 ? t('browsed_recently') : null + }; + }), + favorite = _.first(this.favorite, 6).map(function (f, index) { + return _.extend(f, { extra: index === 0 ? t('favorite') : null }); + }), + qualifiers = this.model.get('qualifiers').map(function (q, index) { + return { + url: baseUrl + '/all_projects?qualifier=' + encodeURIComponent(q), + name: t('qualifiers.all', q), + extra: index === 0 ? '' : null + }; + }); + this.results.reset([].concat(history, favorite, qualifiers)); + }, + + search: function (q) { + if (q.length < 2) { + this.resetResultsToDefault(); + return; + } + var that = this, + url = baseUrl + '/api/components/suggestions', + options = { s: q }; + return $.get(url, options).done(function (r) { + var collection = []; + r.results.forEach(function (domain) { + domain.items.forEach(function (item, index) { + collection.push(_.extend(item, { + q: domain.q, + extra: index === 0 ? domain.name : null, + url: baseUrl + '/dashboard/index?id=' + encodeURIComponent(item.key) + dashboardParameters(true) + })); + }); + }); + that.results.reset([].concat( + that.getNavigationFindings(q), + that.getGlobalDashboardFindings(q), + that.getFavoriteFindings(q), + collection + )); + }); + }, + + getNavigationFindings: function (q) { + var DEFAULT_ITEMS = [ + { name: t('issues.page'), url: baseUrl + '/issues/search' }, + { name: t('layout.measures'), url: baseUrl + '/measures/search?qualifiers[]=TRK' }, + { name: t('coding_rules.page'), url: baseUrl + '/coding_rules' }, + { name: t('quality_profiles.page'), url: baseUrl + '/profiles' }, + { name: t('quality_gates.page'), url: baseUrl + '/quality_gates' }, + { name: t('comparison_global.page'), url: baseUrl + '/comparison' }, + { name: t('dependencies.page'), url: baseUrl + '/dependencies' } + ], + customItems = []; + if (window.SS.isUserAdmin) { + customItems.push({ name: t('layout.settings'), url: baseUrl + '/settings' }); + } + var findings = [].concat(DEFAULT_ITEMS, customItems).filter(function (f) { + return f.name.match(new RegExp(q, 'i')); + }); + if (findings.length > 0) { + findings[0].extra = t('navigation'); + } + return _.first(findings, 6); + }, + + getGlobalDashboardFindings: function (q) { + var dashboards = this.model.get('globalDashboards') || [], + items = dashboards.map(function (d) { + return { name: d.name, url: baseUrl + '/dashboard/index?did=' + encodeURIComponent(d.key) }; + }); + var findings = items.filter(function (f) { + return f.name.match(new RegExp(q, 'i')); + }); + if (findings.length > 0) { + findings[0].extra = t('dashboard.global_dashboards'); + } + return _.first(findings, 6); + }, + + getFavoriteFindings: function (q) { + var findings = this.favorite.filter(function (f) { + return f.name.match(new RegExp(q, 'i')); + }); + if (findings.length > 0) { + findings[0].extra = t('favorite'); + } + return _.first(findings, 6); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/nav/settings-navbar-view.js b/server/sonar-web/src/main/js/apps/nav/settings-navbar-view.js new file mode 100644 index 00000000000..6134e229fd1 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/settings-navbar-view.js @@ -0,0 +1,32 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +define([ + './templates' +], function () { + + return Marionette.ItemView.extend({ + template: Templates['nav-settings-navbar'], + + modelEvents: { + 'change:settings': 'render' + } + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/nav/shortcuts-help-view.js b/server/sonar-web/src/main/js/apps/nav/shortcuts-help-view.js new file mode 100644 index 00000000000..b054b7c6150 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/shortcuts-help-view.js @@ -0,0 +1,30 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +define([ + 'components/common/modals', + './templates' +], function (ModalView) { + + return ModalView.extend({ + className: 'modal modal-large', + template: Templates['nav-shortcuts-help'] + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/nav/state.js b/server/sonar-web/src/main/js/apps/nav/state.js new file mode 100644 index 00000000000..f41557663ee --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/state.js @@ -0,0 +1,51 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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. + */ +define(function () { + + var $ = jQuery; + + return Backbone.Model.extend({ + + fetchGlobal: function () { + var that = this; + return $.get(baseUrl + '/api/navigation/global').done(function (r) { + that.set(r); + }); + }, + + fetchComponent: function () { + var that = this, + url = baseUrl + '/api/navigation/component', + data = { componentKey: this.get('componentKey') }; + return $.get(url, data).done(function (r) { + that.set({ component: r }); + }); + }, + + fetchSettings: function () { + var that = this; + return $.get(baseUrl + '/api/navigation/settings').done(function (r) { + that.set({ settings: r }); + }); + } + + }); + +}); diff --git a/server/sonar-web/src/main/js/apps/nav/templates/_nav-logo.hbs b/server/sonar-web/src/main/js/apps/nav/templates/_nav-logo.hbs new file mode 100644 index 00000000000..fcc91b8f24b --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/_nav-logo.hbs @@ -0,0 +1 @@ +<img src="{{link '/images/logo.svg'}}" alt="{{t 'layout.sonar.slogan'}}" title="{{t 'layout.sonar.slogan'}}"> diff --git a/server/sonar-web/src/main/js/apps/nav/templates/_nav-navbar-label.hbs b/server/sonar-web/src/main/js/apps/nav/templates/_nav-navbar-label.hbs new file mode 100644 index 00000000000..df44ac06af2 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/_nav-navbar-label.hbs @@ -0,0 +1 @@ +{{#if labelLocalized}}{{labelLocalized}}{{else}}{{t label}}{{/if}} diff --git a/server/sonar-web/src/main/js/apps/nav/templates/nav-context-navbar.hbs b/server/sonar-web/src/main/js/apps/nav/templates/nav-context-navbar.hbs new file mode 100644 index 00000000000..11ef4f53ad7 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/nav-context-navbar.hbs @@ -0,0 +1,124 @@ +<div class="container"> + {{#if component.canBeFavorite}} + <div class="navbar-context-favorite"> + <a class="js-favorite {{#if component.isFavorite}}icon-favorite{{else}}icon-not-favorite{{/if}}"></a> + </div> + {{/if}} + <ul class="nav navbar-nav nav-crumbs"> + {{#each component.breadcrumbs}} + <li> + <a href="{{componentPermalink key}}"> + {{qualifierIcon qualifier}} {{name}} + </a> + </li> + {{/each}} + </ul> + + <div class="navbar-right navbar-context-meta"> + {{#if component.version}}Version {{component.version}}{{/if}} + {{#all component.version component.snapshotDate}}/{{/all}} + {{#if component.snapshotDate}}{{dt component.snapshotDate}}{{/if}} + </div> + + <ul class="nav navbar-nav nav-tabs"> + <li {{#if isOverviewActive}}class="active"{{/if}}> + <a href="{{componentPermalink component.key}}">{{t 'overview.page'}}</a> + </li> + <li {{#isActiveLink '/components'}}class="active"{{/isActiveLink}}> + <a href="{{componentBrowsePermalink component.key}}">{{t 'components.page'}}</a> + </li> + <li {{#isActiveLink '/component_issues'}}class="active"{{/isActiveLink}}> + <a href="{{componentIssuesPermalink component.key}}">{{t 'issues.page'}}</a> + </li> + {{#if component.configuration.showSettings}} + <li class="dropdown {{#if isSettingsActive}}active{{/if}}"> + <a class="dropdown-toggle navbar-admin-link" data-toggle="dropdown" href="#">{{t 'layout.settings'}} <i + class="icon-dropdown"></i></a> + <ul class="dropdown-menu"> + <li> + <a href="{{link '/project/settings?id=' contextKeyEncoded}}">{{t 'project_settings.page'}}</a> + </li> + {{#if component.configuration.showQualityProfiles}} + <li> + <a href="{{link '/project/profile?id=' contextKeyEncoded}}">{{t 'project_quality_profiles.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showQualityGates}} + <li> + <a href="{{link '/project/qualitygate?id=' contextKeyEncoded}}">{{t 'project_quality_gate.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showManualMeasures}} + <li> + <a href="{{link '/manual_measures/index?id=' contextKeyEncoded}}">{{t 'manual_measures.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showActionPlans}} + <li> + <a href="{{link '/action_plans/index?id=' contextKeyEncoded}}">{{t 'action_plans.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showLinks}} + <li> + <a href="{{link '/project/links?id=' contextKeyEncoded}}">{{t 'project_links.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showPermissions}} + <li> + <a href="{{link '/project_roles/index?id=' contextKeyEncoded}}">{{t 'permissions.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showHistory}} + <li> + <a href="{{link '/project/history?id=' contextKeyEncoded}}">{{t 'project_history.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showUpdateKey}} + <li> + <a href="{{link '/project/key?id=' contextKeyEncoded}}">{{t 'update_key.page'}}</a> + </li> + {{/if}} + {{#if component.configuration.showDeletion}} + <li> + <a href="{{link '/project/deletion?id=' contextKeyEncoded}}">{{t 'deletion.page'}}</a> + </li> + {{/if}} + {{#each component.configuration.extensions}} + <li> + <a href="{{link url}}">{{name}}</a> + </li> + {{/each}} + </ul> + </li> + {{/if}} + <li class="dropdown {{#if isMoreActive}}active{{/if}}"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#">{{t 'more'}} <i class="icon-dropdown"></i></a> + <ul class="dropdown-menu"> + <li class="dropdown-header">{{t 'layout.dashboards'}}</li> + {{#withoutFirst component.dashboards}} + <li> + <a href="{{componentDashboardPermalink ../component.key key}}">{{dashboardL10n name}}</a> + </li> + {{/withoutFirst}} + {{#if canManageContextDashboards}} + <li class="small-divider"></li> + <li> + <a href="{{link '/dashboards?resource=' contextKeyEncoded}}">{{t 'dashboard.manage_dashboards'}}</a> + </li> + {{/if}} + <li class="divider"></li> + <li class="dropdown-header">Tools</li> + {{#if component.isComparable}} + <li> + <a href="{{link '/comparison/index?resource=' contextKeyEncoded}}">{{t 'comparison.page'}}</a> + </li> + {{/if}} + {{#each component.extensions}} + <li> + <a href="{{link url}}">{{name}}</a> + </li> + {{/each}} + </ul> + </li> + </ul> +</div> diff --git a/server/sonar-web/src/main/js/apps/nav/templates/nav-global-navbar.hbs b/server/sonar-web/src/main/js/apps/nav/templates/nav-global-navbar.hbs new file mode 100644 index 00000000000..fcaf9cc2672 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/nav-global-navbar.hbs @@ -0,0 +1,105 @@ +<div class="container"> + <div class="navbar-header"> + <a class="navbar-brand {{#if logoUrl}}navbar-brand-custom{{/if}}" href="{{link '/'}}"> + {{#if logoUrl}} + <img src="{{logoUrl}}" {{#if logoWidth}}width="{{logoWidth}}"{{/if}} height="30" + alt="{{t 'layout.sonar.slogan'}}" title="{{t 'layout.sonar.slogan'}}"> + {{else}} + {{> '_nav-logo'}} + {{/if}} + </a> + </div> + + <ul class="nav navbar-nav"> + <li class="dropdown t-dashboards"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#"> + {{t 'layout.dashboards'}} <span class="icon-dropdown"></span> + </a> + <ul class="dropdown-menu"> + {{#each globalDashboards}} + <li> + <a href="{{link '/dashboard/index?did=' key}}">{{dashboardL10n name}}</a> + </li> + {{/each}} + {{#if canManageGlobalDashboards}} + <li class="divider"></li> + <li> + <a href="{{link '/dashboards'}}">{{t 'dashboard.manage_dashboards'}}</a> + </li> + {{/if}} + </ul> + </li> + <li {{#isActiveLink '/issues'}}class="active"{{/isActiveLink}}> + <a href="{{link '/issues/search'}}">{{t 'issues.page'}}</a> + </li> + <li {{#isActiveLink '/measures'}}class="active"{{/isActiveLink}}> + <a href="{{link '/measures/search?qualifiers[]=TRK'}}">{{t 'layout.measures'}}</a> + </li> + <li {{#isActiveLink '/coding_rules'}}class="active"{{/isActiveLink}}> + <a href="{{link '/coding_rules'}}">{{t 'coding_rules.page'}}</a> + </li> + <li {{#isActiveLink '/profiles'}}class="active"{{/isActiveLink}}> + <a href="{{link '/profiles'}}">{{t 'quality_profiles.page'}}</a> + </li> + <li {{#isActiveLink '/quality_gates'}}class="active"{{/isActiveLink}}> + <a href="{{link '/quality_gates'}}">{{t 'quality_gates.page'}}</a> + </li> + {{#if isUserAdmin}} + <li {{#isActiveLink '/settings'}}class="active"{{/isActiveLink}}> + <a class="navbar-admin-link" href="{{link '/settings'}}">{{t 'layout.settings'}}</a> + </li> + {{/if}} + <li class="dropdown t-more"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#">{{t 'more'}} <i class="icon-dropdown"></i></a> + <ul class="dropdown-menu"> + <li> + <a href="{{link '/comparison'}}">{{t 'comparison_global.page'}}</a> + </li> + <li> + <a href="{{link '/dependencies'}}">{{t 'dependencies.page'}}</a> + </li> + {{#each globalPages}} + <li> + <a href="{{link url}}">{{name}}</a> + </li> + {{/each}} + </ul> + </li> + </ul> + + <ul class="nav navbar-nav navbar-right"> + {{#if user}} + <li class="dropdown"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#"> + {{userName}} <span class="icon-dropdown"></span> + </a> + <ul class="dropdown-menu dropdown-menu-right"> + <li> + <a href="{{link '/account/index'}}">{{t 'layout.user_panel.my_profile'}}</a> + </li> + <li> + <a href="{{link '/sessions/logout'}}" + onclick="if (sonarRecentHistory) { sonarRecentHistory.clear(); }">{{t 'layout.logout'}}</a> + </li> + </ul> + </li> + {{else}} + <li> + <a class="js-login" href="{{link '/sessions/new'}}">{{t 'layout.login'}}</a> + </li> + {{/if}} + <li class="dropdown js-search-dropdown"> + <a class="dropdown-toggle navbar-search-dropdown js-search-dropdown-toggle" data-toggle="dropdown" href="#"> + <i class="icon-search navbar-icon"></i> <span class="icon-dropdown"></span> + </a> + + <div class="js-search-region dropdown-menu dropdown-menu-right"></div> + </li> + <li> + <a class="js-shortcuts" href="#"> + <i class="icon-help navbar-icon"></i> + </a> + </li> + </ul> + +</div> diff --git a/server/sonar-web/src/main/js/apps/nav/templates/nav-search-empty.hbs b/server/sonar-web/src/main/js/apps/nav/templates/nav-search-empty.hbs new file mode 100644 index 00000000000..fb76e686612 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/nav-search-empty.hbs @@ -0,0 +1 @@ +<span class="note">{{t 'no_results'}}</span> diff --git a/server/sonar-web/src/main/js/apps/nav/templates/nav-search-item.hbs b/server/sonar-web/src/main/js/apps/nav/templates/nav-search-item.hbs new file mode 100644 index 00000000000..855b5175187 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/nav-search-item.hbs @@ -0,0 +1,22 @@ +{{#notNull extra}} + {{#gt index 0}} + <div class="divider"></div> + {{/gt}} + {{#if extra}} + <div class="dropdown-header">{{extra}}</div> + {{/if}} +{{/notNull}} + +<a href="{{url}}" title="{{name}}"> + {{#if icon}}<i class="icon-{{icon}} text-text-bottom"></i>{{/if}} + {{#if q}}{{qualifierIcon q}}{{/if}} + {{#eq q 'FIL'}} + {{collapsedDirFromPath name}}{{fileFromPath name}} + {{else}} + {{#eq q 'UTS'}} + {{collapsedDirFromPath name}}{{fileFromPath name}} + {{else}} + {{name}} + {{/eq}} + {{/eq}} +</a> diff --git a/server/sonar-web/src/main/js/apps/nav/templates/nav-search.hbs b/server/sonar-web/src/main/js/apps/nav/templates/nav-search.hbs new file mode 100644 index 00000000000..68e1f3ad168 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/nav-search.hbs @@ -0,0 +1,8 @@ +<i class="navbar-search-icon icon-search"></i> + +<input class="navbar-search-input js-search-input" type="search" name="q" placeholder="{{t 'search_verb'}}" + maxlength="30" autocomplete="off"> + +<div class="js-search-results"></div> + +<div class="note navbar-search-subtitle">{{t 'search.shortcut'}}</div> diff --git a/server/sonar-web/src/main/js/apps/nav/templates/nav-settings-navbar.hbs b/server/sonar-web/src/main/js/apps/nav/templates/nav-settings-navbar.hbs new file mode 100644 index 00000000000..5cc7dbbc1ed --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/nav-settings-navbar.hbs @@ -0,0 +1,86 @@ +<div class="container"> + <ul class="nav navbar-nav nav-crumbs"> + <li> + <a href="{{link '/settings'}}">{{t 'layout.settings'}}</a> + </li> + </ul> + + <ul class="nav navbar-nav nav-tabs"> + <li class="dropdown"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#"> + {{t 'sidebar.project_settings'}} <i class="icon-dropdown"></i> + </a> + <ul class="dropdown-menu"> + <li> + <a href="{{link '/settings/index'}}">{{t 'settings.page'}}</a> + </li> + <li> + <a href="{{link '/metrics/index'}}">{{t 'manual_metrics.page'}}</a> + </li> + <li> + <a href="{{link '/admin_dashboards/index'}}">{{t 'default_dashboards.page'}}</a> + </li> + {{#each settings.extensions}} + <li> + <a href="{{link url}}">{{name}}</a> + </li> + {{/each}} + </ul> + </li> + + <li class="dropdown"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#"> + {{t 'sidebar.security'}} <i class="icon-dropdown"></i> + </a> + <ul class="dropdown-menu"> + <li> + <a href="{{link '/users'}}">{{t 'users.page'}}</a> + </li> + <li> + <a href="{{link '/groups/index'}}">{{t 'user_groups.page'}}</a> + </li> + <li> + <a href="{{link '/roles/global'}}">{{t 'global_permissions.page'}}</a> + </li> + <li> + <a href="{{link '/roles/projects'}}">{{t 'roles.page'}}</a> + </li> + </ul> + </li> + + <li class="dropdown"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#"> + {{t 'sidebar.projects'}} <i class="icon-dropdown"></i> + </a> + <ul class="dropdown-menu"> + {{#if settings.showProvisioning}} + <li> + <a href="{{link '/provisioning'}}">{{t 'provisioning.page'}}</a> + </li> + {{/if}} + <li> + <a href="{{link '/bulk_deletion'}}">{{t 'bulk_deletion.page'}}</a> + </li> + <li> + <a href="{{link '/analysis_reports'}}">{{t 'analysis_reports.page'}}</a> + </li> + </ul> + </li> + + <li class="dropdown"> + <a class="dropdown-toggle" data-toggle="dropdown" href="#"> + {{t 'sidebar.system'}} <i class="icon-dropdown"></i> + </a> + <ul class="dropdown-menu"> + {{#if settings.showUpdateCenter}} + <li> + <a href="{{link '/updatecenter'}}">{{t 'update_center.page'}}</a> + </li> + {{/if}} + <li> + <a href="{{link '/system'}}">{{t 'system_info.page'}}</a> + </li> + </ul> + </li> + </ul> +</div> diff --git a/server/sonar-web/src/main/js/apps/nav/templates/nav-shortcuts-help.hbs b/server/sonar-web/src/main/js/apps/nav/templates/nav-shortcuts-help.hbs new file mode 100644 index 00000000000..9457d1b7762 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/nav/templates/nav-shortcuts-help.hbs @@ -0,0 +1,57 @@ +<div class="modal-head"> + <h2>{{t 'help'}}</h2> +</div> + +<div class="modal-body modal-container"> + <div class="spacer-bottom"> + <a href="http://www.sonarqube.org" target="sonar">Community</a> - + <a href="http://www.sonarqube.org/documentation" target="sonar_doc">Documentation</a> - + <a href="http://www.sonarqube.org/support" target="support">Get Support</a> - + <a href="http://redirect.sonarsource.com/doc/plugin-library.html" target="plugins">Plugins</a> - + <a href="{{link '/api_documentation'}}">Web Service API</a> + </div> + + <h2 class="spacer-top spacer-bottom">{{t 'shortcuts.modal_title'}}</h2> + + <div class="columns"> + <div class="column-half"> + <div class="spacer-bottom"> + <h3 class="shortcuts-section-title">{{t 'shortcuts.section.global'}}</h3> + <ul class="shortcuts-list"> + <li><span class="shortcut-button">s</span> {{t 'shortcuts.section.global.search'}}</li> + <li><span class="shortcut-button">?</span> {{t 'shortcuts.section.global.shortcuts'}}</li> + </ul> + </div> + + <h3 class="shortcuts-section-title">{{t 'shortcuts.section.rules'}}</h3> + <ul class="shortcuts-list"> + <li><span class="shortcut-button">↑</span> <span + class="shortcut-button">↓</span> {{t 'shortcuts.section.rules.navigate_between_rules'}}</li> + <li><span class="shortcut-button">→</span> {{t 'shortcuts.section.rules.open_details'}}</li> + <li><span class="shortcut-button">←</span> {{t 'shortcuts.section.rules.return_to_list'}}</li> + </ul> + </div> + + <div class="column-half"> + <h3 class="shortcuts-section-title">{{t 'shortcuts.section.issues'}}</h3> + <ul class="shortcuts-list"> + <li><span class="shortcut-button">↑</span> <span + class="shortcut-button">↓</span> {{t 'shortcuts.section.issues.navigate_between_issues'}} + </li> + <li><span class="shortcut-button">→</span> {{t 'shortcuts.section.issues.open_details'}}</li> + <li><span class="shortcut-button">←</span> {{t 'shortcuts.section.issues.return_to_list'}}</li> + <li><span class="shortcut-button">f</span> {{t 'shortcuts.section.issue.do_transition'}}</li> + <li><span class="shortcut-button">a</span> {{t 'shortcuts.section.issue.assign'}}</li> + <li><span class="shortcut-button">m</span> {{t 'shortcuts.section.issue.assign_to_me'}}</li> + <li><span class="shortcut-button">p</span> {{t 'shortcuts.section.issue.plan'}}</li> + <li><span class="shortcut-button">i</span> {{t 'shortcuts.section.issue.change_severity'}}</li> + <li><span class="shortcut-button">c</span> {{t 'shortcuts.section.issue.comment'}}</li> + <li><span class="shortcut-button">t</span> {{t 'shortcuts.section.issue.change_tags'}}</li> + </ul> + </div> + </div> +</div> + +<div class="modal-foot"> + <a class="js-modal-close" href="#">{{t 'close'}}</a> +</div> |