From: Stas Vilchik Date: Wed, 7 Jan 2015 12:46:47 +0000 (+0100) Subject: resolve SONAR-6041 New global layout X-Git-Tag: latest-silver-master-#65~219 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=d79cc0b5eae85a5d3e59fe149b4ba538db8f35e7;p=sonarqube.git resolve SONAR-6041 New global layout --- diff --git a/server/sonar-web/.jshintrc b/server/sonar-web/.jshintrc index 2d6820a4d4c..5b2eb1b387b 100644 --- a/server/sonar-web/.jshintrc +++ b/server/sonar-web/.jshintrc @@ -82,7 +82,9 @@ "baseUrl": true, "key": true, "Backbone": true, + "Marionette": true, "Handlebars": true, + "Templates": true, "t": true, "tp": true, "moment": true, diff --git a/server/sonar-web/Gruntfile.coffee b/server/sonar-web/Gruntfile.coffee index 60b9b6b3e87..809f748df89 100644 --- a/server/sonar-web/Gruntfile.coffee +++ b/server/sonar-web/Gruntfile.coffee @@ -14,6 +14,7 @@ module.exports = (grunt) -> '<%= pkg.sources %>less/select2.less' '<%= pkg.sources %>less/select2-sonar.less' '<%= pkg.sources %>less/layout.less' + '<%= pkg.sources %>less/layout-new.less' '<%= pkg.sources %>less/style.less' '<%= pkg.sources %>less/icons.less' '<%= pkg.sources %>less/ui.less' @@ -33,6 +34,7 @@ module.exports = (grunt) -> '<%= pkg.sources %>less/select2.less' '<%= pkg.sources %>less/select2-sonar.less' '<%= pkg.sources %>less/layout.less' + '<%= pkg.sources %>less/layout-new.less' '<%= pkg.sources %>less/style.less' '<%= pkg.sources %>less/icons.less' '<%= pkg.sources %>less/ui.less' @@ -91,6 +93,7 @@ module.exports = (grunt) -> '<%= pkg.assets %>js/third-party/numeral.js' '<%= pkg.assets %>js/third-party/numeral-languages.js' '<%= pkg.assets %>js/third-party/bootstrap/tooltip.js' + '<%= pkg.assets %>js/third-party/bootstrap/dropdown.js' '<%= pkg.assets %>js/select2-jquery-ui-fix.js' '<%= pkg.assets %>js/widgets/base.js' '<%= pkg.assets %>js/widgets/widget.js' @@ -134,6 +137,7 @@ module.exports = (grunt) -> '<%= pkg.assets %>js/third-party/numeral.js' '<%= pkg.assets %>js/third-party/numeral-languages.js' '<%= pkg.assets %>js/third-party/bootstrap/tooltip.js' + '<%= pkg.assets %>js/third-party/bootstrap/dropdown.js' '<%= pkg.assets %>js/select2-jquery-ui-fix.js' '<%= pkg.assets %>js/widgets/base.js' '<%= pkg.assets %>js/widgets/widget.js' @@ -235,6 +239,10 @@ module.exports = (grunt) -> name: 'analysis-reports/app' out: '<%= pkg.assets %>build/js/analysis-reports/app.js' + nav: options: + name: 'nav/app' + out: '<%= pkg.assets %>build/js/nav/app.js' + handlebars: options: @@ -285,6 +293,9 @@ module.exports = (grunt) -> '<%= pkg.assets %>js/templates/analysis-reports.js': [ '<%= pkg.sources %>hbs/analysis-reports/**/*.hbs' ] + '<%= pkg.assets %>js/templates/nav.js': [ + '<%= pkg.sources %>hbs/nav/**/*.hbs' + ] clean: diff --git a/server/sonar-web/src/main/coffee/issues/facets/severity-facet.coffee b/server/sonar-web/src/main/coffee/issues/facets/severity-facet.coffee index b0b605c6a09..17d1fabaa9e 100644 --- a/server/sonar-web/src/main/coffee/issues/facets/severity-facet.coffee +++ b/server/sonar-web/src/main/coffee/issues/facets/severity-facet.coffee @@ -11,6 +11,6 @@ define [ sortValues: (values) -> - order = ['BLOCKER', 'MINOR', 'CRITICAL', 'INFO', 'MAJOR'] + order = ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'] _.sortBy values, (v) -> order.indexOf v.val diff --git a/server/sonar-web/src/main/coffee/issues/facets/status-facet.coffee b/server/sonar-web/src/main/coffee/issues/facets/status-facet.coffee index 8b35191eabf..e3f4d0015b4 100644 --- a/server/sonar-web/src/main/coffee/issues/facets/status-facet.coffee +++ b/server/sonar-web/src/main/coffee/issues/facets/status-facet.coffee @@ -11,5 +11,5 @@ define [ sortValues: (values) -> - order = ['OPEN', 'RESOLVED', 'REOPENED', 'CLOSED', 'CONFIRMED'] + order = ['OPEN', 'REOPENED', 'CONFIRMED', 'RESOLVED', 'CLOSED'] _.sortBy values, (v) -> order.indexOf v.val diff --git a/server/sonar-web/src/main/coffee/issues/layout.coffee b/server/sonar-web/src/main/coffee/issues/layout.coffee index 6d2a60fe82b..2b57dbf22b6 100644 --- a/server/sonar-web/src/main/coffee/issues/layout.coffee +++ b/server/sonar-web/src/main/coffee/issues/layout.coffee @@ -26,10 +26,6 @@ define [ $(window).off 'scroll.issues-layout' - onRender: -> - @$('.search-navigator-side').isolatedScroll() - - onScroll: -> scrollTop = $(window).scrollTop() $('.search-navigator').toggleClass 'sticky', scrollTop >= @topOffset diff --git a/server/sonar-web/src/main/hbs/coding-rules/coding-rules-layout.hbs b/server/sonar-web/src/main/hbs/coding-rules/coding-rules-layout.hbs index 8f46e4f8fb1..7a107af3688 100644 --- a/server/sonar-web/src/main/hbs/coding-rules/coding-rules-layout.hbs +++ b/server/sonar-web/src/main/hbs/coding-rules/coding-rules-layout.hbs @@ -1,10 +1,14 @@ -
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
diff --git a/server/sonar-web/src/main/hbs/issues/facets/issues-creation-date-facet.hbs b/server/sonar-web/src/main/hbs/issues/facets/issues-creation-date-facet.hbs index c5b3e5dd47e..b5a65ed7145 100644 --- a/server/sonar-web/src/main/hbs/issues/facets/issues-creation-date-facet.hbs +++ b/server/sonar-web/src/main/hbs/issues/facets/issues-creation-date-facet.hbs @@ -6,7 +6,7 @@ {{dt createdAt}} ({{fromNow createdAt}})
{{else}} -
+
to diff --git a/server/sonar-web/src/main/hbs/issues/issues-layout.hbs b/server/sonar-web/src/main/hbs/issues/issues-layout.hbs index f60fecfb03f..fb22d724577 100644 --- a/server/sonar-web/src/main/hbs/issues/issues-layout.hbs +++ b/server/sonar-web/src/main/hbs/issues/issues-layout.hbs @@ -1,10 +1,14 @@ -
-
-
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
diff --git a/server/sonar-web/src/main/hbs/nav/_nav-logo.hbs b/server/sonar-web/src/main/hbs/nav/_nav-logo.hbs new file mode 100644 index 00000000000..fcb273a09ae --- /dev/null +++ b/server/sonar-web/src/main/hbs/nav/_nav-logo.hbs @@ -0,0 +1,18 @@ + diff --git a/server/sonar-web/src/main/hbs/nav/_nav-navbar-label.hbs b/server/sonar-web/src/main/hbs/nav/_nav-navbar-label.hbs new file mode 100644 index 00000000000..df44ac06af2 --- /dev/null +++ b/server/sonar-web/src/main/hbs/nav/_nav-navbar-label.hbs @@ -0,0 +1 @@ +{{#if labelLocalized}}{{labelLocalized}}{{else}}{{t label}}{{/if}} diff --git a/server/sonar-web/src/main/hbs/nav/nav-navbar.hbs b/server/sonar-web/src/main/hbs/nav/nav-navbar.hbs new file mode 100644 index 00000000000..af4a71bb884 --- /dev/null +++ b/server/sonar-web/src/main/hbs/nav/nav-navbar.hbs @@ -0,0 +1,87 @@ +
+ + + + + + +
diff --git a/server/sonar-web/src/main/hbs/nav/nav-search-empty.hbs b/server/sonar-web/src/main/hbs/nav/nav-search-empty.hbs new file mode 100644 index 00000000000..ccac4831661 --- /dev/null +++ b/server/sonar-web/src/main/hbs/nav/nav-search-empty.hbs @@ -0,0 +1 @@ +{{t 'no_results'}} diff --git a/server/sonar-web/src/main/hbs/nav/nav-search-item.hbs b/server/sonar-web/src/main/hbs/nav/nav-search-item.hbs new file mode 100644 index 00000000000..b9e1c60b016 --- /dev/null +++ b/server/sonar-web/src/main/hbs/nav/nav-search-item.hbs @@ -0,0 +1,6 @@ + + {{#if extra}} + {{extra}} + {{/if}} + {{#if q}}{{qualifierIcon q}} {{/if}}{{name}} + diff --git a/server/sonar-web/src/main/hbs/nav/nav-search.hbs b/server/sonar-web/src/main/hbs/nav/nav-search.hbs new file mode 100644 index 00000000000..a5059642f99 --- /dev/null +++ b/server/sonar-web/src/main/hbs/nav/nav-search.hbs @@ -0,0 +1,6 @@ + + + + +
diff --git a/server/sonar-web/src/main/js/application.js b/server/sonar-web/src/main/js/application.js index a1c209a82b6..ca0bf4dab29 100644 --- a/server/sonar-web/src/main/js/application.js +++ b/server/sonar-web/src/main/js/application.js @@ -21,13 +21,13 @@ function toggleFav(resourceId, elt) { }}); } -function dashboardParameters() { +function dashboardParameters (urlHasSomething) { var queryString = window.location.search; - var parameters = ''; + var parameters = []; var matchDashboard = queryString.match(/did=\d+/); if (matchDashboard && $j('#is-project-dashboard').length === 1) { - parameters += (matchDashboard[0] + '&'); + parameters.push(matchDashboard[0]); } var matchPeriod = queryString.match(/period=\d+/); @@ -35,14 +35,15 @@ function dashboardParameters() { // If we have a match for period, check that it is not project-specific var period = parseInt(/period=(\d+)/.exec(queryString)[1]); if (period <= 3) { - parameters += matchPeriod[0] + '&'; + parameters.push(matchPeriod[0]); } } - if (parameters !== '') { - parameters = '?' + parameters; + var query = parameters.join('&'); + if (query !== '') { + query = (urlHasSomething ? '&' : '?') + query; } - return parameters; + return query; } @@ -340,11 +341,7 @@ jQuery(function () { // Define global shortcuts key('s', function () { - jQuery('#searchInput').focus().on('keydown', function (e) { - if (e.keyCode === 27) { - jQuery('#searchInput').blur(); - } - }); + jQuery('.js-search-dropdown-toggle').dropdown('toggle'); return false; }); }); diff --git a/server/sonar-web/src/main/js/coding-rules/facets/severity-facet.js b/server/sonar-web/src/main/js/coding-rules/facets/severity-facet.js index 219a5e67c85..360d5677fa9 100644 --- a/server/sonar-web/src/main/js/coding-rules/facets/severity-facet.js +++ b/server/sonar-web/src/main/js/coding-rules/facets/severity-facet.js @@ -5,7 +5,7 @@ define([ return BaseFacet.extend({ template: Templates['coding-rules-severity-facet'], - severities: ['BLOCKER', 'MINOR', 'CRITICAL', 'INFO', 'MAJOR'], + severities: ['BLOCKER', 'CRITICAL', 'MAJOR', 'MINOR', 'INFO'], sortValues: function (values) { var order = this.severities; diff --git a/server/sonar-web/src/main/js/coding-rules/layout.js b/server/sonar-web/src/main/js/coding-rules/layout.js index 412b832f9b9..c9fa76c5769 100644 --- a/server/sonar-web/src/main/js/coding-rules/layout.js +++ b/server/sonar-web/src/main/js/coding-rules/layout.js @@ -27,10 +27,6 @@ define([ $(window).off('scroll.search-navigator-layout'); }, - onRender: function () { - this.$('.search-navigator-side').isolatedScroll(); - }, - onScroll: function () { var scrollTop = $(window).scrollTop(); $('.search-navigator').toggleClass('sticky', scrollTop >= this.topOffset); diff --git a/server/sonar-web/src/main/js/common/selectable-collection-view.js b/server/sonar-web/src/main/js/common/selectable-collection-view.js new file mode 100644 index 00000000000..6ddce02f574 --- /dev/null +++ b/server/sonar-web/src/main/js/common/selectable-collection-view.js @@ -0,0 +1,62 @@ +define(function () { + + return Marionette.CollectionView.extend({ + + initialize: function () { + this.resetSelectedIndex(); + this.listenTo(this.collection, 'reset', this.resetSelectedIndex); + }, + + resetSelectedIndex: function () { + this.selectedIndex = 0; + }, + + onRender: function () { + this.selectCurrent(); + }, + + submitCurrent: function () { + var view = this.children.findByIndex(this.selectedIndex); + if (view != null) { + view.submit(); + } + }, + + selectCurrent: function () { + this.selectItem(this.selectedIndex); + }, + + selectNext: function () { + if (this.selectedIndex < this.collection.length - 1) { + this.deselectItem(this.selectedIndex); + this.selectedIndex++; + this.selectItem(this.selectedIndex); + } + }, + + selectPrev: function () { + if (this.selectedIndex > 0) { + this.deselectItem(this.selectedIndex); + this.selectedIndex--; + this.selectItem(this.selectedIndex); + } + }, + + selectItem: function (index) { + if (index >= 0 && index < this.collection.length) { + var view = this.children.findByIndex(index); + if (view != null) { + view.select(); + } + } + }, + + deselectItem: function (index) { + var view = this.children.findByIndex(index); + if (view != null) { + view.deselect(); + } + } + }); + +}); diff --git a/server/sonar-web/src/main/js/nav/app.js b/server/sonar-web/src/main/js/nav/app.js new file mode 100644 index 00000000000..f6295eea637 --- /dev/null +++ b/server/sonar-web/src/main/js/nav/app.js @@ -0,0 +1,21 @@ +define([ + 'nav/navbar' +], function (NavbarView) { + + var $ = jQuery, + App = new Marionette.Application(); + + App.addInitializer(function () { + this.navbarView = new NavbarView({ + app: App, + el: $('.navbar'), + collection: new Backbone.Collection(window.navbarItems) + }); + this.navbarView.render(); + }); + + window.requestMessages().done(function () { + App.start(); + }); + +}); diff --git a/server/sonar-web/src/main/js/nav/navbar.js b/server/sonar-web/src/main/js/nav/navbar.js new file mode 100644 index 00000000000..7ab37245391 --- /dev/null +++ b/server/sonar-web/src/main/js/nav/navbar.js @@ -0,0 +1,95 @@ +define([ + 'nav/search-view', + 'templates/nav' +], function (SearchView) { + + var $ = jQuery; + + return Marionette.Layout.extend({ + tagName: 'nav', + template: Templates['nav-navbar'], + + 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' + }, + + initialize: function () { + $(window).on('scroll.nav-layout', this.onScroll); + this.projectName = window.navbarProject; + this.isProjectFavorite = window.navbarProjectFavorite; + }, + + onClose: function () { + $(window).off('scroll.nav-layout'); + }, + + onScroll: function () { + var scrollTop = $(window).scrollTop(), + isInTheMiddle = scrollTop > 0; + $('.navbar-sticky').toggleClass('middle', isInTheMiddle); + }, + + onRender: function () { + var that = this; + this.$el.addClass('navbar-' + window.navbarSpace); + 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; + }, + + onFavoriteClick: function () { + var that = this, + p = window.process.addBackgroundProcess(), + url = baseUrl + '/favourites/toggle/' + window.navbarProjectId; + return $.post(url).done(function () { + that.isProjectFavorite = !that.isProjectFavorite; + that.render(); + window.process.finishBackgroundProcess(p); + }).fail(function () { + window.process.failBackgroundProcess(p); + }); + }, + + onSearchDropdownShow: function () { + var that = this; + this.searchRegion.show(new SearchView({ + hide: function () { + that.$('.js-search-dropdown-toggle').dropdown('toggle'); + } + })); + }, + + onSearchDropdownHidden: function () { + this.searchRegion.reset(); + }, + + serializeData: function () { + return _.extend(Marionette.Layout.prototype.serializeData.apply(this, arguments), { + user: window.SS.user, + userName: window.SS.userName, + isUserAdmin: window.SS.isUserAdmin, + + space: window.navbarSpace, + + projectName: this.projectName, + projectFavorite: this.isProjectFavorite, + navbarCanFavoriteProject: window.navbarCanFavoriteProject + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/nav/search-view.js b/server/sonar-web/src/main/js/nav/search-view.js new file mode 100644 index 00000000000..fa092a71b8d --- /dev/null +++ b/server/sonar-web/src/main/js/nav/search-view.js @@ -0,0 +1,156 @@ +define([ + 'common/selectable-collection-view', + 'templates/nav' +], 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(); + } + }), + + 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 () { + this.results = new Backbone.Collection(); + 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(); + this.search(value); + }, + + onSubmit: function () { + return false; + }, + + resetResultsToDefault: function () { + var recentHistory = JSON.parse(localStorage.getItem('sonar_recent_history')), + history = recentHistory.map(function (historyItem) { + return { + url: baseUrl + '/dashboard/index?id=' + encodeURIComponent(historyItem.key) + dashboardParameters(true), + name: historyItem.name, + q: historyItem.icon + }; + }), + qualifiers = window.navbarQualifiers.map(function (q) { + return { + url: baseUrl + '/all_projects?qualifier=' + encodeURIComponent(q), + name: t('qualifiers.all', q) + }; + }); + this.results.reset(history.concat(qualifiers)); + }, + + open: function () { + this.$el.addClass('open'); + }, + + disableOpen: function () { + this.$el.removeClass('open'); + }, + + search: function (q) { + if (q.length < 2) { + this.resetResultsToDefault(); + this.disableOpen(); + return; + } + var that = this, + url = baseUrl + '/api/components/suggestions', + options = { s: q }, + p = window.process.addBackgroundProcess(); + this.open(); + 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 : ' ', + url: baseUrl + '/dashboard/index?id=' + encodeURIComponent(item.key) + dashboardParameters(true) + })); + }); + }); + that.results.reset(collection); + window.process.finishBackgroundProcess(p); + }).fail(function() { + window.process.failBackgroundProcess(p); + }); + } + }); + +}); diff --git a/server/sonar-web/src/main/js/third-party/bootstrap/dropdown.js b/server/sonar-web/src/main/js/third-party/bootstrap/dropdown.js new file mode 100644 index 00000000000..980424d635e --- /dev/null +++ b/server/sonar-web/src/main/js/third-party/bootstrap/dropdown.js @@ -0,0 +1,161 @@ +/* ======================================================================== + * Bootstrap: dropdown.js v3.3.1 + * http://getbootstrap.com/javascript/#dropdowns + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // DROPDOWN CLASS DEFINITION + // ========================= + + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle="dropdown"]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } + + Dropdown.VERSION = '3.3.1' + + Dropdown.prototype.toggle = function (e) { + var $this = $(this) + + if ($this.is('.disabled, :disabled')) return + + var $parent = getParent($this) + var isActive = $parent.hasClass('open') + + clearMenus() + + if (!isActive) { + if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { + // if mobile we use a backdrop because click events don't delegate + $(' <% elsif displayed_resource %> + <% + resource_link = {:controller => params[:controller], :action => params[:action]} + if display_only_root + resource_link = {:controller => 'dashboard', :action => 'index'} + end -
-
    - <% if displayed_resource && !display_only_root %> -
  • - <%= link_to_favourite(displayed_resource) -%> -
  • - <% if (has_role?(:admin, displayed_resource) || profiles_administrator?) && !displayed_resource.entity? %> - <%= render 'layouts/menu_resource_settings' -%> - <% end %> - <% end %> -
-
    - <% - resource_link = {:controller => params[:controller], :action => params[:action]} - if display_only_root - resource_link = {:controller => 'dashboard', :action => 'index'} - end + # ======== Path for resources ======== - # ======== Path for resources ======== + if displayed_resource + if displayed_resource.last_snapshot + resources=[] + s=displayed_resource.last_snapshot + while (s!=nil) do + resources.insert(0, s.project) + s=s.parent + end + else + resources = [displayed_resource] + end + %> - if displayed_resource - if displayed_resource.last_snapshot - resources=[] - s=displayed_resource.last_snapshot - while (s!=nil) do - resources.insert(0, s.project) - s=s.parent - end - else - resources = [displayed_resource] - end - %> - <% - resources.each do |resource| - %> -
  • - <%= qualifier_icon(resource) -%> -   - <%= - root = "#{ApplicationController.root_context}/#{u resource_link[:controller]}/#{u resource_link[:action]}?" - path = '' - query = request.query_parameters - query[:id] = resource.key - query.each do |key, value| - path += '&' unless path.empty? - path += "#{u key}=#{u value}" - end - "#{h(resource.name)}" - -%> -
  • - <% - end - end + <% if resources.length > 1 %> +
    +
    +
      + <% + resources.each do |resource| + %> +
    • + <%= qualifier_icon(resource) -%> +   + <%= + root = "#{ApplicationController.root_context}/#{u resource_link[:controller]}/#{u resource_link[:action]}?" + path = '' + query = request.query_parameters + query[:id] = resource.key + query.each do |key, value| + path += '&' unless path.empty? + path += "#{u key}=#{u value}" + end + "#{h(resource.name)}" + -%> +
    • + <% + end + end # ======== Path for issue ======== if @issue %> -
    • - <%= link_to message('issue') + ' #' + @issue.key.to_s -%> -
    • - <% - end - %> +
    • + <%= link_to message('issue') + ' #' + @issue.key.to_s -%> +
    • + <% + end + %>
    -
    +
    +
+ <% end %> <% end %> diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb index fb83ec46c99..9b6c269c74c 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_layout.html.erb @@ -6,198 +6,46 @@ @project=@resource unless @project || selected_section==Navigation::SECTION_HOME period_param = "period=#{u(params[:period])}" if params[:period] %> -
- <%= yield :header -%> -
- -
- -
- <%= render 'layouts/breadcrumb' if @breadcrumbs || selected_section==Navigation::SECTION_RESOURCE -%> -
- <% if selected_section && selected_section.show_sidebar && !@hide_sidebar %> - - <% end %> - <% - html_id_class = '' - html_id_class = "id='content' class='with_sidebar'" if selected_section && selected_section.show_sidebar - html_id_class = "id='content'" if @hide_sidebar || (selected_section && !selected_section.show_sidebar) - %> -
> - <% if @project %> -

<%= h @project.name() %>

- <% end %> - - - @@ -225,7 +73,8 @@

The embedded database will not scale, it will not support upgrading to newer versions of SonarQube, and there is no support for migrating your data out of it into a different database engine. <% end %>
- +
<% end %> diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_logo.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_logo.html.erb new file mode 100644 index 00000000000..51f0c126f18 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_logo.html.erb @@ -0,0 +1,18 @@ + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_menu_projects.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_menu_projects.html.erb deleted file mode 100644 index 4d18b7b330c..00000000000 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_menu_projects.html.erb +++ /dev/null @@ -1,46 +0,0 @@ - - -
  • - - <%= message('layout.projects') -%> - - - - - -
  • - - diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar.html.erb new file mode 100644 index 00000000000..fd8d74e7348 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar.html.erb @@ -0,0 +1,5 @@ +<%= render 'layouts/navbar_conf' -%> +<%= render 'layouts/recent_history' -%> + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf.html.erb new file mode 100644 index 00000000000..d2a4eca1461 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf.html.erb @@ -0,0 +1,29 @@ +<% + selected_section = controller.class::SECTION if defined?(controller.class::SECTION) + if selected_section==Navigation::SECTION_RESOURCE && !@project && !@resource + selected_section = Navigation::SECTION_HOME + end + @project=@resource unless @project || selected_section==Navigation::SECTION_HOME + period_param = "period=#{u(params[:period])}" if params[:period] + displayed_resource = @resource || @project + display_only_root = @issue + resource_id=displayed_resource ? (displayed_resource.is_a?(Fixnum) ? displayed_resource : displayed_resource.permanent_id) : nil +%> + +<% if selected_section==Navigation::SECTION_RESOURCE %> + <%= render :partial => 'layouts/navbar_conf_project' %> +<% elsif selected_section==Navigation::SECTION_CONFIGURATION %> + <%= render :partial => 'layouts/navbar_conf_settings' %> +<% else %> + <%= render :partial => 'layouts/navbar_conf_global' %> +<% end %> + + + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_global.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_global.html.erb new file mode 100644 index 00000000000..b3c48d945b6 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_global.html.erb @@ -0,0 +1,76 @@ +<% + selected_section = controller.class::SECTION if defined?(controller.class::SECTION) + if selected_section==Navigation::SECTION_RESOURCE && !@project && !@resource + selected_section = Navigation::SECTION_HOME + end +%> + + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_project.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_project.html.erb new file mode 100644 index 00000000000..5abfc35c7ca --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_project.html.erb @@ -0,0 +1,166 @@ +<% + @project=@resource unless @project || selected_section==Navigation::SECTION_HOME + period_param = "period=#{u(params[:period])}" if params[:period] + displayed_resource = @resource || @project + display_only_root = @issue + resource_id=displayed_resource ? (displayed_resource.is_a?(Fixnum) ? displayed_resource : displayed_resource.permanent_id) : nil +%> + + + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_settings.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_settings.html.erb new file mode 100644 index 00000000000..084f8159718 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_navbar_conf_settings.html.erb @@ -0,0 +1,109 @@ +<% + selected_section = controller.class::SECTION if defined?(controller.class::SECTION) + if selected_section==Navigation::SECTION_RESOURCE && !@project && !@resource + selected_section = Navigation::SECTION_HOME + end +%> + + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_recent_history.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_recent_history.html.erb new file mode 100644 index 00000000000..51b81a44d3f --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_recent_history.html.erb @@ -0,0 +1,9 @@ + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_small_logo.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_small_logo.html.erb new file mode 100644 index 00000000000..a7029b5ae50 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/_small_logo.html.erb @@ -0,0 +1,9 @@ + diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/application.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/application.html.erb index 3c67adf30b2..52e8974dc14 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/application.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/layouts/application.html.erb @@ -10,9 +10,10 @@ end %> <%= render :partial => 'layouts/head' unless params[:hd]=='false' %> +<%= render :partial => 'layouts/navbar' %> <% if params[:layout]=='false' %> <%= render :partial => 'layouts/nolayout' %> <% else %> <%= render :partial => 'layouts/layout' %> <% end %> -<%= render :partial => 'layouts/footer' unless params[:hd]=='false' %> \ No newline at end of file +<%= render :partial => 'layouts/footer' unless params[:hd]=='false' %> diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index ef44688c9c8..7db54b195d9 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -427,6 +427,7 @@ layout.sonar.slogan=Embrace Quality layout.dashboards=Dashboards layout.configuration=Project Configuration layout.projects=Projects +layout.tools=Tools layout.recent_projects=Recent Projects layout.user_panel.my_profile=My profile