diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-02-18 15:08:54 +0100 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-02-18 15:16:42 +0100 |
commit | 8640ce8dee1ff1f515d8c8b8564e0c53e5d6b5ec (patch) | |
tree | 157e6087c28e54363e209fac2c35aabf1469e606 | |
parent | 53bb31e599534ccf81a757ff30cbf79bd52bb3f8 (diff) | |
download | sonarqube-8640ce8dee1ff1f515d8c8b8564e0c53e5d6b5ec.tar.gz sonarqube-8640ce8dee1ff1f515d8c8b8564e0c53e5d6b5ec.zip |
SONAR-5855 Update UI of quality gates page
17 files changed, 257 insertions, 281 deletions
diff --git a/server/sonar-web/src/main/coffee/quality-gate/app.coffee b/server/sonar-web/src/main/coffee/quality-gate/app.coffee index 28cf9daf416..1e376e3b2b5 100644 --- a/server/sonar-web/src/main/coffee/quality-gate/app.coffee +++ b/server/sonar-web/src/main/coffee/quality-gate/app.coffee @@ -18,10 +18,6 @@ requirejs [ QualityGateLayout ) -> - # Add html class to mark the page as navigator page - jQuery('html').addClass('navigator-page quality-gates-page'); - - # Create a Quality Gate Application App = new Marionette.Application @@ -49,8 +45,8 @@ requirejs [ # Construct layout App.addInitializer -> @layout = new QualityGateLayout app: @ - jQuery('#content').append @layout.render().el - @layout.onResize() + jQuery('#quality-gates').append @layout.render().el + jQuery('#footer').addClass 'search-navigator-footer' # Construct actions bar @@ -101,8 +97,5 @@ requirejs [ jQuery.when(qualityGatesXHR, appXHR, l10nXHR) .done -> - # Remove the initial spinner - jQuery('#quality-gate-page-loader').remove() - # Start the application App.start() diff --git a/server/sonar-web/src/main/coffee/quality-gate/layout.coffee b/server/sonar-web/src/main/coffee/quality-gate/layout.coffee index 9a982cf1e02..4e58fa172e8 100644 --- a/server/sonar-web/src/main/coffee/quality-gate/layout.coffee +++ b/server/sonar-web/src/main/coffee/quality-gate/layout.coffee @@ -2,45 +2,21 @@ define [ 'templates/quality-gates' ], -> + $ = jQuery + class AppLayout extends Marionette.Layout - className: 'navigator quality-gates-navigator' template: Templates['quality-gates-layout'] regions: - headerRegion: '.navigator-header' - actionsRegion: '.navigator-actions' - resultsRegion: '.navigator-results' - detailsRegion: '.navigator-details' - - - initialize: (options) -> - @listenTo options.app.qualityGates, 'all', @updateLayout - jQuery(window).on 'resize', => @onResize() - - - updateLayout: -> - empty = @options.app.qualityGates.length == 0 - @$(@headerRegion.el).toggle !empty - @$(@detailsRegion.el).toggle !empty - - - onResize: -> - footerEl = jQuery('#footer') - footerHeight = footerEl.outerHeight true - - resultsEl = jQuery('.navigator-results') - resultsHeight = jQuery(window).height() - resultsEl.offset().top - - parseInt(resultsEl.css('margin-bottom'), 10) - footerHeight - resultsEl.height resultsHeight - - detailsEl = jQuery('.navigator-details') - detailsWidth = jQuery(window).width() - detailsEl.offset().left - - parseInt(detailsEl.css('margin-right'), 10) - detailsHeight = jQuery(window).height() - detailsEl.offset().top - - parseInt(detailsEl.css('margin-bottom'), 10) - footerHeight - detailsEl.width(detailsWidth).height detailsHeight + headerRegion: '.search-navigator-workspace-header' + actionsRegion: '.search-navigator-filters' + resultsRegion: '.quality-gates-results' + detailsRegion: '.search-navigator-workspace-list' onRender: -> - @updateLayout() + $('.search-navigator').addClass 'sticky' + top = $('.search-navigator').offset().top + @$('.search-navigator-workspace-header').css top: top + @$('.search-navigator-side').css({ top: top }).isolatedScroll() diff --git a/server/sonar-web/src/main/coffee/quality-gate/router.coffee b/server/sonar-web/src/main/coffee/quality-gate/router.coffee index 9bb56410f9a..e185428a51b 100644 --- a/server/sonar-web/src/main/coffee/quality-gate/router.coffee +++ b/server/sonar-web/src/main/coffee/quality-gate/router.coffee @@ -34,7 +34,5 @@ define [ @app.layout.detailsRegion.show qualityGateDetailView qualityGateDetailView.$el.hide() - qualityGateDetailHeaderView.showSpinner() qualityGate.fetch().done -> qualityGateDetailView.$el.show() - qualityGateDetailHeaderView.hideSpinner() diff --git a/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-detail-header-view.coffee b/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-detail-header-view.coffee index 3bcc07e9eaf..a90b5580f2a 100644 --- a/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-detail-header-view.coffee +++ b/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-detail-header-view.coffee @@ -49,26 +49,21 @@ define [ yesLabel: t 'delete' noLabel: t 'cancel' yesHandler: => - @showSpinner() jQuery.ajax type: 'POST' url: "#{baseUrl}/api/qualitygates/destroy" data: id: @model.id - .always => @hideSpinner() .done => @options.app.deleteQualityGate @model.id always: => @ui.deleteButton.blur() changeDefault: (set) -> - @showSpinner() data = if set then { id: @model.id } else {} method = if set then 'set_as_default' else 'unset_default' jQuery.ajax type: 'POST' url: "#{baseUrl}/api/qualitygates/#{method}" data: data - .always => - @hideSpinner() .done => @options.app.unsetDefaults @model.id @model.set 'default', !@model.get('default') @@ -82,15 +77,5 @@ define [ @changeDefault false - showSpinner: -> - @$el.hide() - jQuery(@spinner).insertBefore @$el - - - hideSpinner: -> - @$el.prev().remove() - @$el.show() - - serializeData: -> _.extend super, canEdit: @options.app.canEdit diff --git a/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-item-view.coffee b/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-item-view.coffee index d2c618fa745..4f2e3eaa14c 100644 --- a/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-item-view.coffee +++ b/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-item-view.coffee @@ -3,7 +3,7 @@ define [ ], -> class QualityGateSidebarListItemView extends Marionette.ItemView - tagName: 'li' + className: 'facet search-navigator-facet' template: Templates['quality-gate-sidebar-list-item'] diff --git a/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-view.coffee b/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-view.coffee index 063fd569a2c..7cdfbe4a14e 100644 --- a/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-view.coffee +++ b/server/sonar-web/src/main/coffee/quality-gate/views/quality-gate-sidebar-list-view.coffee @@ -7,8 +7,7 @@ define [ ) -> class QualityGateSidebarListView extends Marionette.CollectionView - tagName: 'ol' - className: 'navigator-results-list' + className: 'search-navigator-facet-list' itemView: QualityGateSidebarListItemView emptyView: QualityGateSidebarListEmptyView diff --git a/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-condition.hbs b/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-condition.hbs index 79973fe9a38..9be26807f78 100644 --- a/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-condition.hbs +++ b/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-condition.hbs @@ -27,19 +27,19 @@ {{t 'quality_gates.operator' op}} {{/if}} </td> -<td width="15%" nowrap="nowrap"> +<td width="1" class="nowrap"> <i class="icon-alert-warn" title="{{t 'quality_gates.warning_tooltip'}}"></i> {{#if canEdit}} - <input name="warning" class="measure-input" data-type="{{metric.type}}" placeholder="{{metric.placeholder}}" + <input name="warning" class="input-small" data-type="{{metric.type}}" placeholder="{{metric.placeholder}}" type="text"> {{else}} {{warning}} {{/if}} </td> -<td width="15%" nowrap="nowrap"> +<td width="1" class="nowrap"> <i class="icon-alert-error" title="{{t 'quality_gates.error_tooltip'}}"></i> {{#if canEdit}} - <input name="error" class="measure-input" data-type="{{metric.type}}" placeholder="{{metric.placeholder}}" + <input name="error" class="input-small" data-type="{{metric.type}}" placeholder="{{metric.placeholder}}" type="text"> {{else}} {{error}} diff --git a/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-header.hbs b/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-header.hbs index e84a730d379..71f7e3b06de 100644 --- a/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-header.hbs +++ b/server/sonar-web/src/main/hbs/quality-gates/quality-gate-detail-header.hbs @@ -1,14 +1,16 @@ -<h1 class="navigator-header-title">{{name}}</h1> +<h2 class="search-navigator-header-component">{{name}}</h2> {{#if canEdit}} - <div class="navigator-header-actions button-group"> - <button id="quality-gate-rename">{{t 'rename'}}</button> - <button id="quality-gate-copy">{{t 'copy'}}</button> - {{#if default}} - <button id="quality-gate-unset-as-default">{{t 'unset_as_default'}}</button> - {{else}} - <button id="quality-gate-set-as-default">{{t 'set_as_default'}}</button> - {{/if}} - <button id="quality-gate-delete" class="button-red">{{t 'delete'}}</button> + <div class="search-navigator-header-actions"> + <div class="button-group"> + <button id="quality-gate-rename">{{t 'rename'}}</button> + <button id="quality-gate-copy">{{t 'copy'}}</button> + {{#if default}} + <button id="quality-gate-unset-as-default">{{t 'unset_as_default'}}</button> + {{else}} + <button id="quality-gate-set-as-default">{{t 'set_as_default'}}</button> + {{/if}} + <button id="quality-gate-delete" class="button-red">{{t 'delete'}}</button> + </div> </div> -{{/if}}
\ No newline at end of file +{{/if}} diff --git a/server/sonar-web/src/main/hbs/quality-gates/quality-gate-sidebar-list-item.hbs b/server/sonar-web/src/main/hbs/quality-gates/quality-gate-sidebar-list-item.hbs index af8d93ae07b..2b8f1089eb7 100644 --- a/server/sonar-web/src/main/hbs/quality-gates/quality-gate-sidebar-list-item.hbs +++ b/server/sonar-web/src/main/hbs/quality-gates/quality-gate-sidebar-list-item.hbs @@ -1 +1,7 @@ -<div class="line line-nowrap">{{name}} {{#if default}}<span class="subtitle">({{t 'default'}})</span>{{/if}}</div>
\ No newline at end of file +<span class="facet-name"> + {{name}} +</span> + +{{#if default}} + <span class="facet-stat">{{t 'default'}}</span> +{{/if}} diff --git a/server/sonar-web/src/main/hbs/quality-gates/quality-gates-layout.hbs b/server/sonar-web/src/main/hbs/quality-gates/quality-gates-layout.hbs index 22f6fba05e7..d596459b6a7 100644 --- a/server/sonar-web/src/main/hbs/quality-gates/quality-gates-layout.hbs +++ b/server/sonar-web/src/main/hbs/quality-gates/quality-gates-layout.hbs @@ -1,10 +1,9 @@ -<div class="navigator-content"> - <div class="navigator-side"> - <div class="navigator-actions"></div> - <div class="navigator-results quality-gates-nav"></div> - </div> - <div class="navigator-main"> - <div class="navigator-header"></div> - <div class="navigator-details"></div> - </div> -</div>
\ No newline at end of file +<div class="search-navigator-side quality-gates-side"> + <div class="search-navigator-filters"></div> + <div class="quality-gates-results"></div> +</div> + +<div class="search-navigator-workspace"> + <div class="search-navigator-workspace-header"></div> + <div class="search-navigator-workspace-list"></div> +</div> diff --git a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec.js b/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec.js index f068858dd67..6655b4eb9ac 100644 --- a/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec.js +++ b/server/sonar-web/src/main/js/tests/e2e/tests/quality-gates-spec.js @@ -1,36 +1,42 @@ +/* global casper:false */ + var lib = require('../lib'); lib.initMessages(); lib.changeWorkingDirectory('quality-gates-spec'); -casper.test.begin('Quality Gates', function suite(test) { - casper.start(lib.buildUrl('quality-gates'), function() { - lib.setDefaultViewport(); - - lib.mockRequest('/api/l10n/index', '{}'); - lib.mockRequestFromFile('/api/qualitygates/app', 'app.json'); - lib.mockRequestFromFile('/api/qualitygates/list', 'list.json'); - lib.mockRequestFromFile('/api/qualitygates/show?id=1', 'show.json'); - }); - - casper.waitWhileSelector("div#quality-gates-loader", function() { - - casper.waitForSelector('li.active', function() { - test.assertElementCount('li.active', 1); - test.assertSelectorHasText('ol.navigator-results-list li', 'Default Gate'); - }); - - casper.waitForSelector('div.navigator-header', function() { - test.assertSelectorHasText('div.navigator-header h1', 'Default Gate'); - }); - - casper.waitForSelector('table.quality-gate-conditions tbody tr:nth-child(9)', function() { - test.assertElementCount('table.quality-gate-conditions tbody tr', 9); - }); - }); - - casper.run(function() { - test.done(); - }); +casper.test.begin('Quality Gates', function suite (test) { + casper + .start(lib.buildUrl('quality-gates'), function () { + lib.setDefaultViewport(); + + lib.mockRequest('/api/l10n/index', '{}'); + lib.mockRequestFromFile('/api/qualitygates/app', 'app.json'); + lib.mockRequestFromFile('/api/qualitygates/list', 'list.json'); + lib.mockRequestFromFile('/api/qualitygates/show?id=1', 'show.json'); + }) + + .then(function () { + casper.waitForSelector('.active', function () { + test.assertElementCount('.active', 1); + test.assertSelectorHasText('.search-navigator-side .active', 'Default Gate'); + }); + }) + + .then(function () { + casper.waitForSelector('.search-navigator-workspace-header', function () { + test.assertSelectorHasText('.search-navigator-workspace-header', 'Default Gate'); + }); + }) + + .then(function () { + casper.waitForSelector('table.quality-gate-conditions tbody tr:nth-child(9)', function () { + test.assertElementCount('table.quality-gate-conditions tbody tr', 9); + }); + }) + + .run(function () { + test.done(); + }); }); diff --git a/server/sonar-web/src/main/js/tests/e2e/views/quality-gates.jade b/server/sonar-web/src/main/js/tests/e2e/views/quality-gates.jade index 1a10f0b5b34..ac1a4871c1b 100644 --- a/server/sonar-web/src/main/js/tests/e2e/views/quality-gates.jade +++ b/server/sonar-web/src/main/js/tests/e2e/views/quality-gates.jade @@ -7,5 +7,4 @@ block header block body #content - #quality-gate-page-loader.navigator-page-loader - i.spinner + .search-navigator#quality-gates diff --git a/server/sonar-web/src/main/less/components/ui.less b/server/sonar-web/src/main/less/components/ui.less index 5ebfed40fa8..418fe0a7896 100644 --- a/server/sonar-web/src/main/less/components/ui.less +++ b/server/sonar-web/src/main/less/components/ui.less @@ -101,164 +101,6 @@ a.active-link { -/* - * Inputs - */ - -input[type=text], -input[type=password], -input[type=email], -input[type=search], -textarea { - border: 1px solid @darkGrey; - .box-sizing(border-box); - background: #fff; - color: @baseFontColor; - .trans(border-color); - - &:active, - &:focus { - border-color: @highlighted; - box-shadow: none; - outline: none; - } - - &.invalid { border-color: @red; } -} - -input[type=text], -input[type=password], -input[type=email], -input[type=search] { - height: @formControlHeight; - padding: 0 3px; -} - -input[type=search] { - -webkit-appearance: none; -} - -textarea { - padding: 3px; -} - -button, -.button, -input[type=submit], -input[type=button] { - display: inline-block; - vertical-align: baseline; - height: @formControlHeight; - margin: 0 1px; - padding: 0 10px; - - border: 1px solid @darkGrey; - .box-sizing(border-box); - - background: #f4f4f4; - - color: @baseFontColor; - font-weight: bold; - font-size: @baseFontSize; - text-align: center; - text-decoration: none; - - cursor: pointer; - outline: none; - .trans(border-color); - - &:hover, &.active { - border-color: #5281a0; - background: #4b9fd5; - color: #fff; - } - - &:active { - border-color: #2790c0; - background: #78bdea; - color: #fff; - } - - &:focus { - border-color: @highlighted; - } - - &[disabled], - &[disabled]:hover, - &[disabled]:active, - &[disabled]:focus { - color: #bbb; - border-color: #ddd; - background: #ebebeb; - cursor: default; - } -} - -.button { line-height: @formControlHeight; } - -.button-red { - &:hover, &:focus { - border-color: #900; - background: lighten(#900, 10%); - color: #fff; - } - - &:active { - border-color: #900; - background: lighten(#900, 20%); - } -} - -.button-clean, -.button-clean:hover, -.button-clean:focus { - margin: 0; - padding: 0; - border: none; - background: transparent; - color: @baseFontColor; -} - -.button-group { - display: inline-block; - vertical-align: middle; - font-size: 0; - white-space: nowrap; - - & > button, - & > .button { - position: relative; - z-index: 2; - display: inline-block; - vertical-align: middle; - margin: 0; - padding: 2px 8px; - font-size: @smallFontSize; - font-weight: normal; - cursor: pointer; - - &:hover, &:focus, &:active, &.active { - z-index: 3; - } - } - - & > .button { line-height: 16px; } - - & > button + button, - & > button + .button, - & > .button + button, - & > .button + .button { - margin-left: -1px; - } - - & > a:not(.button) { - vertical-align: middle; - margin: 0 8px; - font-size: @smallFontSize; - } -} - - .message-notice { display: block; padding: 5px 8px; diff --git a/server/sonar-web/src/main/less/init.less b/server/sonar-web/src/main/less/init.less index 86dd9fc5b3a..c2fe9052204 100644 --- a/server/sonar-web/src/main/less/init.less +++ b/server/sonar-web/src/main/less/init.less @@ -3,5 +3,6 @@ @import "init/links"; @import "init/tables"; @import "init/lists"; +@import "init/forms"; @import "init/icons"; @import "init/misc"; diff --git a/server/sonar-web/src/main/less/init/forms.less b/server/sonar-web/src/main/less/init/forms.less new file mode 100644 index 00000000000..9f8be907f17 --- /dev/null +++ b/server/sonar-web/src/main/less/init/forms.less @@ -0,0 +1,164 @@ +@import (reference) "../variables"; +@import (reference) "../mixins"; +@import (reference) "../components/ui"; + +/* + * Inputs + */ + +input[type=text], +input[type=password], +input[type=email], +input[type=search], +textarea { + border: 1px solid @darkGrey; + .box-sizing(border-box); + background: #fff; + color: @baseFontColor; + .trans(border-color); + + &:active, + &:focus { + border-color: @highlighted; + box-shadow: none; + outline: none; + } + + &.invalid { border-color: @red; } +} + +input[type=text], +input[type=password], +input[type=email], +input[type=search] { + height: @formControlHeight; + padding: 0 3px; +} + +input[type=search] { + -webkit-appearance: none; +} + +textarea { + padding: 3px; +} + +button, +.button, +input[type=submit], +input[type=button] { + display: inline-block; + vertical-align: baseline; + height: @formControlHeight; + margin: 0 1px; + padding: 0 10px; + + border: 1px solid @darkGrey; + .box-sizing(border-box); + + background: #f4f4f4; + + color: @baseFontColor; + font-weight: bold; + font-size: @baseFontSize; + text-align: center; + text-decoration: none; + + cursor: pointer; + outline: none; + .trans(border-color); + + &:hover, &.active { + border-color: #5281a0; + background: #4b9fd5; + color: #fff; + } + + &:active { + border-color: #2790c0; + background: #78bdea; + color: #fff; + } + + &:focus { + border-color: @highlighted; + } + + &[disabled], + &[disabled]:hover, + &[disabled]:active, + &[disabled]:focus { + color: #bbb; + border-color: #ddd; + background: #ebebeb; + cursor: default; + } +} + +.button { line-height: @formControlHeight; } + +.button-red { + &:hover, &:focus { + border-color: #900; + background: lighten(#900, 10%); + color: #fff; + } + + &:active { + border-color: #900; + background: lighten(#900, 20%); + } +} + +.button-clean, +.button-clean:hover, +.button-clean:focus { + margin: 0; + padding: 0; + border: none; + background: transparent; + color: @baseFontColor; +} + +.button-group { + display: inline-block; + vertical-align: middle; + font-size: 0; + white-space: nowrap; + + & > button, + & > .button { + position: relative; + z-index: 2; + display: inline-block; + vertical-align: middle; + margin: 0; + padding: 2px 8px; + font-size: @smallFontSize; + font-weight: normal; + cursor: pointer; + + &:hover, &:focus, &:active, &.active { + z-index: 3; + } + } + + & > .button { line-height: 16px; } + + & > button + button, + & > button + .button, + & > .button + button, + & > .button + .button { + margin-left: -1px; + } + + & > a:not(.button) { + vertical-align: middle; + margin: 0 8px; + font-size: @smallFontSize; + } +} + +.input-small { + width: 80px; +} diff --git a/server/sonar-web/src/main/less/pages/quality-gates.less b/server/sonar-web/src/main/less/pages/quality-gates.less index 9734d8f5b8e..eea7e0bf0d0 100644 --- a/server/sonar-web/src/main/less/pages/quality-gates.less +++ b/server/sonar-web/src/main/less/pages/quality-gates.less @@ -2,6 +2,14 @@ @import (reference) "../mixins"; @import (reference) "../components/navigator/config"; +.quality-gates-side { + background-color: @barBackgroundColor; +} + +.quality-gates-results { + padding: 5px 0; +} + @qualityGateSidebarWidth: 230px; .quality-gates-navigator { diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/quality_gates/index.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/quality_gates/index.html.erb index 4a1ee1605e2..181ab0efae2 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/quality_gates/index.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/quality_gates/index.html.erb @@ -2,6 +2,4 @@ <script>require(['quality-gate/app']);</script> <% end %> -<div id="quality-gate-page-loader" class="navigator-page-loader"> - <i class="spinner"></i> -</div> +<div class="search-navigator" id="quality-gates"></div> |