]> source.dussan.org Git - sonarqube.git/commitdiff
Quality Gates: new layout, some other improvements
authorStas Vilchik <vilchiks@gmail.com>
Fri, 28 Feb 2014 14:48:21 +0000 (15:48 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Fri, 28 Feb 2014 14:48:29 +0000 (15:48 +0100)
41 files changed:
plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
sonar-server/src/main/webapp/WEB-INF/app/controllers/quality_gates_controller.rb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/index.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_actions_template.hbs.erb [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_condition_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_conditions_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_header_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_projects_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_renaming_template.hbs.erb [deleted file]
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_edit_template.hbs.erb [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_sidebar_list_item_template.hbs.erb
sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_sidebar_list_template.hbs.erb [deleted file]
sonar-server/src/main/webapp/javascripts/issues/app.js
sonar-server/src/main/webapp/javascripts/quality-gate/app.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/app.js
sonar-server/src/main/webapp/javascripts/quality-gate/router.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/router.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-actions-view.coffee [new file with mode: 0644]
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-condition-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-header-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-header-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-projects-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-projects-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-renaming-view.coffee [deleted file]
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-renaming-view.js [deleted file]
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-edit-view.coffee [new file with mode: 0644]
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-edit-view.js [new file with mode: 0644]
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-sidebar-list-item-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-sidebar-list-item-view.js
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-sidebar-list-view.coffee
sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-sidebar-list-view.js
sonar-server/src/main/webapp/stylesheets/navigator.css
sonar-server/src/main/webapp/stylesheets/navigator/base.css
sonar-server/src/main/webapp/stylesheets/navigator/base.less
sonar-server/src/main/webapp/stylesheets/quality-gates.css
sonar-server/src/main/webapp/stylesheets/quality-gates.less
sonar-server/src/main/webapp/stylesheets/style.css

index 255913424d825f0b397d95709b8375545e295686..b7df17c848540f32c07f8c06cc79fe0cba2a4b02 100644 (file)
@@ -1641,11 +1641,13 @@ quality_profiles.copy_new_name=New name
 #
 #------------------------------------------------------------------------------
 
+quality_gates.add=Add Quality Gate
 quality_gates.conditions=Conditions
 quality_gates.projects=Projects
 quality_gates.add_condition=Add Condition
 quality_gates.introduction=Only project measures are checked against thresholds. Modules, packages and classes are ignored.
 quality_gates.health_icons=Project health icons represent:
+quality_gates.projects_for_default=You must not select specific projects for the default quality gate
 quality_gates.projects.with=With
 quality_gates.projects.without=Without
 quality_gates.projects.all=All
index 3f7922b851a04e8eb4f67d920e08953c9bd1db22..c960a35c3de426d45cb9cbd23369763a607c37a2 100644 (file)
@@ -20,6 +20,8 @@
 
 class QualityGatesController < ApplicationController
 
+  SECTION=Navigation::SECTION_QUALITY_GATES
+
   # GET /quality_gates/index
   def index
 
index 04f2917d7f3b3f9a35624053aacdf2fd0068eefb..673ec7b1976360b1772ae25c06a074a3a1262834 100644 (file)
@@ -2,17 +2,19 @@
   <script data-main="<%= ApplicationController.root_context -%>/javascripts/quality-gate/app" src="<%= ApplicationController.root_context -%>/javascripts/third-party/require.js"></script>
 <% end %>
 
-<div class="quality-gate-page-loader"></div>
+<div class="navigator quality-gates-navigator">
+  <div class="navigator-header"></div>
+  <div class="navigator-results"><i class="spinner"></i></div>
+  <div class="navigator-details"></div>
+  <div class="navigator-actions"></div>
+</div>
 
-<div id="sidebar"></div>
-<div id="content"></div>
-
-<%= render :partial => '/quality_gates/templates/quality_gate_sidebar_list_template.hbs' -%>
 <%= render :partial => '/quality_gates/templates/quality_gate_sidebar_list_item_template.hbs' -%>
+<%= render :partial => '/quality_gates/templates/quality_gate_actions_template.hbs' -%>
 <%= render :partial => '/quality_gates/templates/quality_gate_new_template.hbs' -%>
+<%= render :partial => '/quality_gates/templates/quality_gate_edit_template.hbs' -%>
 <%= render :partial => '/quality_gates/templates/quality_gate_detail_template.hbs' -%>
 <%= render :partial => '/quality_gates/templates/quality_gate_detail_header_template.hbs' -%>
-<%= render :partial => '/quality_gates/templates/quality_gate_detail_renaming_template.hbs' -%>
 <%= render :partial => '/quality_gates/templates/quality_gate_detail_conditions_template.hbs' -%>
 <%= render :partial => '/quality_gates/templates/quality_gate_detail_condition_template.hbs' -%>
 <%= render :partial => '/quality_gates/templates/quality_gate_detail_projects_template.hbs' -%>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_actions_template.hbs.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_actions_template.hbs.erb
new file mode 100644 (file)
index 0000000..552d9e2
--- /dev/null
@@ -0,0 +1,7 @@
+<script id="quality-gate-actions-template" type="text/x-handlebars-template">
+  <h1 class="navigator-header-title"><%= message('quality_gates.page') -%></h1>
+
+  <div class="navigator-header-actions">
+    <button id="quality-gate-add"><%= message('add_verb') -%></button>
+  </div>
+</script>
index 5380fe6094afdb76e9b5f73a05d23f91b6bc7346..bf7f19f389bb72e9d057b45e58888c38b4cd1375 100644 (file)
@@ -25,7 +25,7 @@
   </td>
   <td class="quality-gate-condition-actions" width="120px" nowrap>
     {{#if id}}
-      <button class="update-condition"><%= message('update_verb') -%></button>
+      <button class="update-condition" disabled><%= message('update_verb') -%></button>
       <a class="action link-red delete-condition"><%= message('delete') -%></a>
     {{else}}
       <button class="add-condition"><%= message('add_verb') -%></button>
index 9efb723be3871a12de1889ed60bf24cf2b3ceb80..b3a3ae04cf3d04e102a689248f0c51de587107fd 100644 (file)
@@ -1,4 +1,6 @@
 <script id="quality-gate-detail-conditions-template" type="text/x-handlebars-template">
+  <div class="quality-gate-section-name"><%= message('quality_gates.conditions') -%></div>
+
   <div class="quality-gate-introduction">
     <p><%= message('quality_gates.introduction') -%>
       <a class="link-action quality-gate-introduction-show-more"><%= message('more') -%></a>
@@ -41,7 +43,7 @@
     </select>
   </div>
 
-  <table class="data width100 marginbottom10 spaced quality-gate-conditions">
+  <table class="data zebra width100 marginbottom10 spaced quality-gate-conditions">
     <thead><tr></tr></thead>
     <tbody></tbody>
   </table>
index 9788d0e913bae6c0192a1aefb10176043003315e..718a6de2ef436c4deacb2a49576dfc640f7cec67 100644 (file)
@@ -1,7 +1,5 @@
 <script id="quality-gate-detail-header-template" type="text/x-handlebars-template">
-  <h1 class="navigator-header-title">
-    {{#if default}}<i class="icon-default"></i>{{/if}} {{name}}
-  </h1>
+  <h1 class="navigator-header-title">{{name}}</h1>
 
   <div class="navigator-header-actions">
     <button id="quality-gate-rename"><%= message('rename') -%></button>
index 0091e6b5ec4d2aac23415f725cdd00e88e59fe3a..64e599cdb4c6924166b2cea78dddfb22e36e27a1 100644 (file)
@@ -1,3 +1,9 @@
 <script id="quality-gate-detail-projects-template" type="text/x-handlebars-template">
-  <div id="select-list-projects"></div>
+  <div class="quality-gate-section-name"><%= message('quality_gates.projects') -%></div>
+
+  {{#if default}}
+    <p><%= message('quality_gates.projects_for_default') -%></p>
+  {{else}}
+    <div id="select-list-projects"></div>
+  {{/if}}
 </script>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_renaming_template.hbs.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_detail_renaming_template.hbs.erb
deleted file mode 100644 (file)
index fe09a66..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<script id="quality-gate-detail-renaming-template" type="text/x-handlebars-template">
-  <div class="quality-gate-header-rename">
-    <input id="quality-gate-renaming-input" type="text" value="{{name}}">
-
-    <div class="navigator-header-actions">
-      <button id="quality-gate-rename"><%= message('rename') -%></button>
-      <button id="quality-gate-cancel-rename"><%= message('cancel') -%></button>
-    </div>
-  </div>
-</script>
index 9290cc89df8152cfc495409c4e72a99036d39c4d..02742bf3f6b1c0e35116fa4f957e9da340b25e74 100644 (file)
@@ -1,11 +1,4 @@
 <script id="quality-gate-detail-template" type="text/x-handlebars-template">
-  <div class="quality-gate-header"></div>
-
-  <div class="quality-gate-details">
-    <ul class="tabs quality-gate-tabs">
-      <li><a id="quality-gate-tab-conditions"><%= message('quality_gates.conditions') -%></a></li>
-      <li><a id="quality-gate-tab-projects"><%= message('quality_gates.projects') -%></a></li>
-    </ul>
-    <div class="quality-gate-details-tab"></div>
-  </div>
+  <div id="quality-gate-conditions" class="quality-gate-section"></div>
+  <div id="quality-gate-projects" class="quality-gate-section"></div>
 </script>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_edit_template.hbs.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_edit_template.hbs.erb
new file mode 100644 (file)
index 0000000..6ebe5db
--- /dev/null
@@ -0,0 +1,22 @@
+<script id="quality-gate-edit-template" type="text/x-handlebars-template">
+  <div class="modal-head">
+    <h2><%= message('quality_gates.add') -%></h2>
+  </div>
+
+  <div class="modal-body">
+    <div class="modal-error"></div>
+    <div class="modal-field">
+      <label for="quality-gate-edit-name"><%= message('name') -%> <em class="mandatory">*</em></label>
+      <input id="quality-gate-edit-name" value="{{name}}" type="text" size="50" maxlength="100">
+    </div>
+  </div>
+
+  <div class="modal-foot">
+    {{#if id}}
+      <button id="quality-gate-save"><%= message('save') -%></button>
+    {{else}}
+      <button id="quality-gate-create"><%= message('create') -%></button>
+    {{/if}}
+    <a id="quality-gate-cancel-create" class="action"><%= message('cancel') -%></a>
+  </div>
+</script>
index 81b80c07b02eb0475b9da311b8444dd67cb5f60f..eafcd7dfd26f03882c3b260504a4c443ed3961ba 100644 (file)
@@ -1,3 +1,3 @@
 <script id="quality-gate-sidebar-list-item-template" type="text/x-handlebars-template">
-  {{#if default}}<i class="icon-default"></i>{{/if}} <a>{{name}}</a>
+  <div class="line">{{name}} {{#if default}}<span class="subtitle"><%= message('default') -%></span>{{/if}}</div>
 </script>
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_sidebar_list_template.hbs.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/quality_gates/templates/_quality_gate_sidebar_list_template.hbs.erb
deleted file mode 100644 (file)
index 484b4fd..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-<script id="quality-gate-sidebar-list-template" type="text/x-handlebars-template">
-  <li class="spacer"></li>
-  <li><a id="quality-gate-add">Add Quality Gate</a></li>
-</script>
index 98faddb280ec722aabdbf831990e6e5c4b71ab3e..84d6fbadfed92d29b261e8090f487e4c810d3921 100644 (file)
@@ -63,7 +63,7 @@ requirejs(
 
 
       NavigatorApp.addInitializer(function () {
-        jQuery('html').addClass('issues-page');
+        jQuery('html').addClass('navigator-page issues-page');
 
         this.appState = new Extra.AppState();
         window.SS.appState = this.appState;
index bc434b0fee9635cf9cd504cefef61a629d91f8b8..9346cb288c0e50acb8d3ba73df99d48789d20d7c 100644 (file)
@@ -27,6 +27,8 @@ requirejs [
   'quality-gate/collections/quality-gates',
   'quality-gate/collections/metrics',
   'quality-gate/views/quality-gate-sidebar-list-view',
+  'quality-gate/views/quality-gate-actions-view',
+  'quality-gate/views/quality-gate-edit-view',
   'quality-gate/router'
   'common/handlebars-extensions'
 ], (
@@ -34,6 +36,8 @@ requirejs [
   QualityGates,
   Metrics,
   QualityGateSidebarListItemView,
+  QualityGateActionsView,
+  QualityGateEditView,
   QualityGateRouter
 ) ->
 
@@ -45,6 +49,9 @@ requirejs [
       else
         alert jqXHR.responseText
 
+  # 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
 
@@ -67,15 +74,28 @@ requirejs [
 
   # Define page regions
   App.addRegions
-    sidebarRegion: '#sidebar'
-    contentRegion: '#content'
+    headerRegion: '.navigator-header'
+    actionsRegion: '.navigator-actions'
+    listRegion: '.navigator-results'
+    detailsRegion: '.navigator-details'
+
+  # Construct actions bar
+  App.addInitializer ->
+    @qualityGateActionsView = new QualityGateActionsView
+      app: @
+    @actionsRegion.show @qualityGateActionsView
 
   # Construct sidebar
   App.addInitializer ->
     @qualityGateSidebarListView = new QualityGateSidebarListItemView
       collection: @qualityGates
       app: @
-    @sidebarRegion.show @qualityGateSidebarListView
+    @listRegion.show @qualityGateSidebarListView
+
+  # Construct edit view
+  App.addInitializer ->
+    @qualityGateEditView = new QualityGateEditView app: @
+    @qualityGateEditView.render()
 
   # Start router
   App.addInitializer ->
index 0267a75dce9688c0e570f167006fd06575659aa2..98e67daedfeb13a43e973d8c2e8b28238181c1e8 100644 (file)
@@ -29,7 +29,7 @@
     }
   });
 
-  requirejs(['backbone', 'backbone.marionette', 'handlebars', 'quality-gate/collections/quality-gates', 'quality-gate/collections/metrics', 'quality-gate/views/quality-gate-sidebar-list-view', 'quality-gate/router', 'common/handlebars-extensions'], function(Backbone, Marionette, Handlebars, QualityGates, Metrics, QualityGateSidebarListItemView, QualityGateRouter) {
+  requirejs(['backbone', 'backbone.marionette', 'handlebars', 'quality-gate/collections/quality-gates', 'quality-gate/collections/metrics', 'quality-gate/views/quality-gate-sidebar-list-view', 'quality-gate/views/quality-gate-actions-view', 'quality-gate/views/quality-gate-edit-view', 'quality-gate/router', 'common/handlebars-extensions'], function(Backbone, Marionette, Handlebars, QualityGates, Metrics, QualityGateSidebarListItemView, QualityGateActionsView, QualityGateEditView, QualityGateRouter) {
     var App;
     jQuery.ajaxSetup({
       error: function(jqXHR) {
@@ -41,6 +41,7 @@
         }
       }
     });
+    jQuery('html').addClass('navigator-page quality-gates-page');
     App = new Marionette.Application;
     App.metrics = new Metrics;
     App.qualityGates = new QualityGates;
       });
     };
     App.addRegions({
-      sidebarRegion: '#sidebar',
-      contentRegion: '#content'
+      headerRegion: '.navigator-header',
+      actionsRegion: '.navigator-actions',
+      listRegion: '.navigator-results',
+      detailsRegion: '.navigator-details'
+    });
+    App.addInitializer(function() {
+      this.qualityGateActionsView = new QualityGateActionsView({
+        app: this
+      });
+      return this.actionsRegion.show(this.qualityGateActionsView);
     });
     App.addInitializer(function() {
       this.qualityGateSidebarListView = new QualityGateSidebarListItemView({
         collection: this.qualityGates,
         app: this
       });
-      return this.sidebarRegion.show(this.qualityGateSidebarListView);
+      return this.listRegion.show(this.qualityGateSidebarListView);
+    });
+    App.addInitializer(function() {
+      this.qualityGateEditView = new QualityGateEditView({
+        app: this
+      });
+      return this.qualityGateEditView.render();
     });
     App.addInitializer(function() {
       this.router = new QualityGateRouter({
index d4b29732854fd5fd2255488db407a8282d981294..010c084bff85d86c35de0215da67f4fc33096a14 100644 (file)
@@ -2,11 +2,13 @@ define [
   'backbone',
   'quality-gate/models/quality-gate',
   'quality-gate/views/quality-gate-detail-view',
+  'quality-gate/views/quality-gate-detail-header-view',
   'quality-gate/views/quality-gate-new-view'
 ], (
   Backbone,
   QualityGate,
   QualityGateDetailView,
+  QualityGateDetailHeaderView,
   QualityGateNewView
 ) ->
 
@@ -14,7 +16,6 @@ define [
 
     routes:
       'show/:id': 'show'
-      'new': 'new'
 
 
     initialize: (options) ->
@@ -25,17 +26,19 @@ define [
       qualityGate = @app.qualityGates.get id
       if qualityGate
         @app.qualityGateSidebarListView.highlight id
-        qualityGateDetailView = new QualityGateDetailView
+
+        qualityGateDetailHeaderView = new QualityGateDetailHeaderView
           app: @app
           model: qualityGate
-        @app.contentRegion.show qualityGateDetailView
-        qualityGateDetailView.$el.addClass 'navigator-fetching'
-        qualityGate.fetch().done ->
-          qualityGateDetailView.$el.removeClass 'navigator-fetching'
+        @app.headerRegion.show qualityGateDetailHeaderView
 
+        qualityGateDetailView = new QualityGateDetailView
+          app: @app
+          model: qualityGate
+        @app.detailsRegion.show qualityGateDetailView
+        qualityGateDetailView.$el.hide()
 
-    new: ->
-      qualityGateNewView = new QualityGateNewView
-        app: @app
-        model: new QualityGate
-      @app.contentRegion.show qualityGateNewView
+        qualityGateDetailHeaderView.showSpinner()
+        qualityGate.fetch().done ->
+          qualityGateDetailView.$el.show()
+          qualityGateDetailHeaderView.hideSpinner()
index d2c1b41e6ce97c3e0a694422396bb968668a2254..881ceb6c8b656acf671f0edcf7cbe8fc53f066f2 100644 (file)
@@ -3,7 +3,7 @@
   var __hasProp = {}.hasOwnProperty,
     __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
 
-  define(['backbone', 'quality-gate/models/quality-gate', 'quality-gate/views/quality-gate-detail-view', 'quality-gate/views/quality-gate-new-view'], function(Backbone, QualityGate, QualityGateDetailView, QualityGateNewView) {
+  define(['backbone', 'quality-gate/models/quality-gate', 'quality-gate/views/quality-gate-detail-view', 'quality-gate/views/quality-gate-detail-header-view', 'quality-gate/views/quality-gate-new-view'], function(Backbone, QualityGate, QualityGateDetailView, QualityGateDetailHeaderView, QualityGateNewView) {
     var QualityGateRouter, _ref;
     return QualityGateRouter = (function(_super) {
       __extends(QualityGateRouter, _super);
@@ -14,8 +14,7 @@
       }
 
       QualityGateRouter.prototype.routes = {
-        'show/:id': 'show',
-        'new': 'new'
+        'show/:id': 'show'
       };
 
       QualityGateRouter.prototype.initialize = function(options) {
       };
 
       QualityGateRouter.prototype.show = function(id) {
-        var qualityGate, qualityGateDetailView;
+        var qualityGate, qualityGateDetailHeaderView, qualityGateDetailView;
         qualityGate = this.app.qualityGates.get(id);
         if (qualityGate) {
           this.app.qualityGateSidebarListView.highlight(id);
+          qualityGateDetailHeaderView = new QualityGateDetailHeaderView({
+            app: this.app,
+            model: qualityGate
+          });
+          this.app.headerRegion.show(qualityGateDetailHeaderView);
           qualityGateDetailView = new QualityGateDetailView({
             app: this.app,
             model: qualityGate
           });
-          this.app.contentRegion.show(qualityGateDetailView);
-          qualityGateDetailView.$el.addClass('navigator-fetching');
+          this.app.detailsRegion.show(qualityGateDetailView);
+          qualityGateDetailView.$el.hide();
+          qualityGateDetailHeaderView.showSpinner();
           return qualityGate.fetch().done(function() {
-            return qualityGateDetailView.$el.removeClass('navigator-fetching');
+            qualityGateDetailView.$el.show();
+            return qualityGateDetailHeaderView.hideSpinner();
           });
         }
       };
 
-      QualityGateRouter.prototype["new"] = function() {
-        var qualityGateNewView;
-        qualityGateNewView = new QualityGateNewView({
-          app: this.app,
-          model: new QualityGate
-        });
-        return this.app.contentRegion.show(qualityGateNewView);
-      };
-
       return QualityGateRouter;
 
     })(Backbone.Router);
diff --git a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-actions-view.coffee b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-actions-view.coffee
new file mode 100644 (file)
index 0000000..0210c3e
--- /dev/null
@@ -0,0 +1,22 @@
+define [
+  'backbone.marionette',
+  'handlebars',
+  'quality-gate/models/quality-gate'
+], (
+  Marionette,
+  Handlebars,
+  QualityGate
+) ->
+
+  class QualityGateActionsView extends Marionette.ItemView
+    template: Handlebars.compile jQuery('#quality-gate-actions-template').html()
+
+
+    events:
+      'click #quality-gate-add': 'add'
+
+
+    add: ->
+      qualityGate = new QualityGate()
+      @options.app.qualityGateEditView.model = qualityGate
+      @options.app.qualityGateEditView.show()
index 5cf922fcfe0ab34ef65abcb00764a2937e6d8bea..7467feaa6e59f2c54d8589948eb8b7ef41ffc624 100644 (file)
@@ -9,6 +9,7 @@ define [
   class QualityGateDetailConditionView extends Marionette.ItemView
     tagName: 'tr'
     template: Handlebars.compile jQuery('#quality-gate-detail-condition-template').html()
+    spinner: '<i class="spinner"></i>'
 
 
     modelEvents:
@@ -21,13 +22,15 @@ define [
       warningInput: '[name=warning]'
       errorInput: '[name=error]'
       actionsBox: '.quality-gate-condition-actions'
+      updateButton: '.update-condition'
 
 
     events:
-      'click .update-condition': 'saveCondition'
+      'click @ui.updateButton': 'saveCondition'
       'click .delete-condition': 'deleteCondition'
       'click .add-condition': 'saveCondition'
       'click .cancel-add-condition': 'cancelAddCondition'
+      'change :input': 'enableUpdate'
 
 
     initialize: ->
@@ -63,11 +66,13 @@ define [
 
 
     showSpinner: ->
-      @ui.actionsBox.addClass 'navigator-fetching'
+      jQuery(@spinner).prependTo @ui.actionsBox
+      @ui.actionsBox.find(':not(.spinner)').hide()
 
 
     hideSpinner: ->
-      @ui.actionsBox.removeClass 'navigator-fetching'
+      @ui.actionsBox.find('.spinner').remove()
+      @ui.actionsBox.children().show()
 
 
     saveCondition: ->
@@ -79,6 +84,7 @@ define [
         error: @ui.errorInput.val()
       @model.save()
         .always =>
+          @ui.updateButton.prop 'disabled', true
           @hideSpinner()
         .done =>
           @options.collectionView.updateConditions()
@@ -94,3 +100,7 @@ define [
 
     cancelAddCondition: ->
       @close()
+
+
+    enableUpdate: ->
+      @ui.updateButton.prop 'disabled', false
index 2c61f70392f907f9c1d2be20cba6dc8003ab45a3..5a15393ba6e4b0e36799d07ff7806f48666d044b 100644 (file)
@@ -17,6 +17,8 @@
 
       QualityGateDetailConditionView.prototype.template = Handlebars.compile(jQuery('#quality-gate-detail-condition-template').html());
 
+      QualityGateDetailConditionView.prototype.spinner = '<i class="spinner"></i>';
+
       QualityGateDetailConditionView.prototype.modelEvents = {
         'change:id': 'render'
       };
         operatorSelect: '[name=operator]',
         warningInput: '[name=warning]',
         errorInput: '[name=error]',
-        actionsBox: '.quality-gate-condition-actions'
+        actionsBox: '.quality-gate-condition-actions',
+        updateButton: '.update-condition'
       };
 
       QualityGateDetailConditionView.prototype.events = {
-        'click .update-condition': 'saveCondition',
+        'click @ui.updateButton': 'saveCondition',
         'click .delete-condition': 'deleteCondition',
         'click .add-condition': 'saveCondition',
-        'click .cancel-add-condition': 'cancelAddCondition'
+        'click .cancel-add-condition': 'cancelAddCondition',
+        'change :input': 'enableUpdate'
       };
 
       QualityGateDetailConditionView.prototype.initialize = function() {
       };
 
       QualityGateDetailConditionView.prototype.showSpinner = function() {
-        return this.ui.actionsBox.addClass('navigator-fetching');
+        jQuery(this.spinner).prependTo(this.ui.actionsBox);
+        return this.ui.actionsBox.find(':not(.spinner)').hide();
       };
 
       QualityGateDetailConditionView.prototype.hideSpinner = function() {
-        return this.ui.actionsBox.removeClass('navigator-fetching');
+        this.ui.actionsBox.find('.spinner').remove();
+        return this.ui.actionsBox.children().show();
       };
 
       QualityGateDetailConditionView.prototype.saveCondition = function() {
           error: this.ui.errorInput.val()
         });
         return this.model.save().always(function() {
+          _this.ui.updateButton.prop('disabled', true);
           return _this.hideSpinner();
         }).done(function() {
           return _this.options.collectionView.updateConditions();
         return this.close();
       };
 
+      QualityGateDetailConditionView.prototype.enableUpdate = function() {
+        return this.ui.updateButton.prop('disabled', false);
+      };
+
       return QualityGateDetailConditionView;
 
     })(Marionette.ItemView);
index e8401a75442b8f8488fa211b14c4176c448c7547..6406d065420411d7a5ca517f4a77c49b374a2e4c 100644 (file)
@@ -8,6 +8,11 @@ define [
 
   class QualityGateDetailHeaderView extends Marionette.ItemView
     template: Handlebars.compile jQuery('#quality-gate-detail-header-template').html()
+    spinner: '<i class="spinner"></i>'
+
+
+    modelEvents:
+      'change': 'render'
 
 
     events:
@@ -18,22 +23,25 @@ define [
 
 
     renameQualityGate: ->
-      @options.detailView.showRenaming()
+      @options.app.qualityGateEditView.model = @model
+      @options.app.qualityGateEditView.show()
 
 
     deleteQualityGate: ->
       if confirm window.SS.phrases.areYouSure
-        @options.detailView.showHeaderSpinner()
-        jQuery.ajax({
+        @showSpinner()
+        jQuery.ajax
           type: 'POST'
           url: "#{baseUrl}/api/qualitygates/destroy"
           data: id: @model.id
-        }).done =>
+        .always =>
+          @hideSpinner()
+        .done =>
           @options.app.deleteQualityGate @model.id
 
 
     changeDefault: (set) ->
-      @options.detailView.showHeaderSpinner()
+      @showSpinner()
       data = if set then { id: @model.id } else {}
       method = if set then 'set_as_default' else 'unset_default'
       jQuery.ajax
@@ -41,7 +49,7 @@ define [
         url: "#{baseUrl}/api/qualitygates/#{method}"
         data: data
       .always =>
-        @options.detailView.hideHeaderSpinner()
+        @hideSpinner()
       .done =>
         @options.app.unsetDefaults @model.id
         @model.set 'default', !@model.get('default')
@@ -53,3 +61,13 @@ define [
 
     unsetAsDefault: ->
       @changeDefault false
+
+
+    showSpinner: ->
+      @$el.hide()
+      jQuery(@spinner).insertBefore @$el
+
+
+    hideSpinner: ->
+      @$el.prev().remove()
+      @$el.show()
index 760b0f487de706a52829bbbdcba993da5ed7c8a2..f60d30a04ddf9b002a2e82749c84ca5099377060 100644 (file)
 
       QualityGateDetailHeaderView.prototype.template = Handlebars.compile(jQuery('#quality-gate-detail-header-template').html());
 
+      QualityGateDetailHeaderView.prototype.spinner = '<i class="spinner"></i>';
+
+      QualityGateDetailHeaderView.prototype.modelEvents = {
+        'change': 'render'
+      };
+
       QualityGateDetailHeaderView.prototype.events = {
         'click #quality-gate-rename': 'renameQualityGate',
         'click #quality-gate-delete': 'deleteQualityGate',
       };
 
       QualityGateDetailHeaderView.prototype.renameQualityGate = function() {
-        return this.options.detailView.showRenaming();
+        this.options.app.qualityGateEditView.model = this.model;
+        return this.options.app.qualityGateEditView.show();
       };
 
       QualityGateDetailHeaderView.prototype.deleteQualityGate = function() {
         var _this = this;
         if (confirm(window.SS.phrases.areYouSure)) {
-          this.options.detailView.showHeaderSpinner();
+          this.showSpinner();
           return jQuery.ajax({
             type: 'POST',
             url: "" + baseUrl + "/api/qualitygates/destroy",
             data: {
               id: this.model.id
             }
+          }).always(function() {
+            return _this.hideSpinner();
           }).done(function() {
             return _this.options.app.deleteQualityGate(_this.model.id);
           });
@@ -45,7 +54,7 @@
       QualityGateDetailHeaderView.prototype.changeDefault = function(set) {
         var data, method,
           _this = this;
-        this.options.detailView.showHeaderSpinner();
+        this.showSpinner();
         data = set ? {
           id: this.model.id
         } : {};
@@ -55,7 +64,7 @@
           url: "" + baseUrl + "/api/qualitygates/" + method,
           data: data
         }).always(function() {
-          return _this.options.detailView.hideHeaderSpinner();
+          return _this.hideSpinner();
         }).done(function() {
           _this.options.app.unsetDefaults(_this.model.id);
           return _this.model.set('default', !_this.model.get('default'));
         return this.changeDefault(false);
       };
 
+      QualityGateDetailHeaderView.prototype.showSpinner = function() {
+        this.$el.hide();
+        return jQuery(this.spinner).insertBefore(this.$el);
+      };
+
+      QualityGateDetailHeaderView.prototype.hideSpinner = function() {
+        this.$el.prev().remove();
+        return this.$el.show();
+      };
+
       return QualityGateDetailHeaderView;
 
     })(Marionette.ItemView);
index 1b8366cd55d172a49ab277a21401e935608fe4d1..353074e6e3a2676bfa42666faea43c6660628d79 100644 (file)
@@ -12,22 +12,23 @@ define [
 
 
     onRender: ->
-      @$el.css 'max-width', 600
-      new SelectList
-        el: @$('#select-list-projects')
-        width: '100%'
-        format: (item) -> item.name
-        searchUrl: "#{baseUrl}/api/qualitygates/search?gateId=#{@options.gateId}"
-        selectUrl: "#{baseUrl}/api/qualitygates/select"
-        deselectUrl: "#{baseUrl}/api/qualitygates/deselect"
-        extra:
-          gateId: @options.gateId
-        selectParameter: 'projectId'
-        selectParameterValue: 'id'
-        labels:
-          selected: window.SS.phrases.projects.with
-          deselected: window.SS.phrases.projects.without
-          all: window.SS.phrases.projects.all
-        tooltips:
-          select: window.SS.phrases.projects.select_hint
-          deselect: window.SS.phrases.projects.deselect_hint
+      unless @model.get('default')
+        @$el.css 'max-width', 600
+        new SelectList
+          el: @$('#select-list-projects')
+          width: '100%'
+          format: (item) -> item.name
+          searchUrl: "#{baseUrl}/api/qualitygates/search?gateId=#{@options.gateId}"
+          selectUrl: "#{baseUrl}/api/qualitygates/select"
+          deselectUrl: "#{baseUrl}/api/qualitygates/deselect"
+          extra:
+            gateId: @options.gateId
+          selectParameter: 'projectId'
+          selectParameterValue: 'id'
+          labels:
+            selected: window.SS.phrases.projects.with
+            deselected: window.SS.phrases.projects.without
+            all: window.SS.phrases.projects.all
+          tooltips:
+            select: window.SS.phrases.projects.select_hint
+            deselect: window.SS.phrases.projects.deselect_hint
index 008b0bbc63303da7f869977d3015df552d1b3ff6..ea37af52df2528558df3c1632bf08fa35585823a 100644 (file)
       QualityGateDetailProjectsView.prototype.template = Handlebars.compile(jQuery('#quality-gate-detail-projects-template').html());
 
       QualityGateDetailProjectsView.prototype.onRender = function() {
-        this.$el.css('max-width', 600);
-        return new SelectList({
-          el: this.$('#select-list-projects'),
-          width: '100%',
-          format: function(item) {
-            return item.name;
-          },
-          searchUrl: "" + baseUrl + "/api/qualitygates/search?gateId=" + this.options.gateId,
-          selectUrl: "" + baseUrl + "/api/qualitygates/select",
-          deselectUrl: "" + baseUrl + "/api/qualitygates/deselect",
-          extra: {
-            gateId: this.options.gateId
-          },
-          selectParameter: 'projectId',
-          selectParameterValue: 'id',
-          labels: {
-            selected: window.SS.phrases.projects["with"],
-            deselected: window.SS.phrases.projects.without,
-            all: window.SS.phrases.projects.all
-          },
-          tooltips: {
-            select: window.SS.phrases.projects.select_hint,
-            deselect: window.SS.phrases.projects.deselect_hint
-          }
-        });
+        if (!this.model.get('default')) {
+          this.$el.css('max-width', 600);
+          return new SelectList({
+            el: this.$('#select-list-projects'),
+            width: '100%',
+            format: function(item) {
+              return item.name;
+            },
+            searchUrl: "" + baseUrl + "/api/qualitygates/search?gateId=" + this.options.gateId,
+            selectUrl: "" + baseUrl + "/api/qualitygates/select",
+            deselectUrl: "" + baseUrl + "/api/qualitygates/deselect",
+            extra: {
+              gateId: this.options.gateId
+            },
+            selectParameter: 'projectId',
+            selectParameterValue: 'id',
+            labels: {
+              selected: window.SS.phrases.projects["with"],
+              deselected: window.SS.phrases.projects.without,
+              all: window.SS.phrases.projects.all
+            },
+            tooltips: {
+              select: window.SS.phrases.projects.select_hint,
+              deselect: window.SS.phrases.projects.deselect_hint
+            }
+          });
+        }
       };
 
       return QualityGateDetailProjectsView;
diff --git a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-renaming-view.coffee b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-renaming-view.coffee
deleted file mode 100644 (file)
index e5b7785..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-define [
-  'backbone.marionette',
-  'handlebars'
-], (
-  Marionette,
-  Handlebars,
-) ->
-
-  class QualityGateDetailRenamingView extends Marionette.ItemView
-    template: Handlebars.compile jQuery('#quality-gate-detail-renaming-template').html()
-
-
-    ui:
-      input: '#quality-gate-renaming-input'
-
-
-    events:
-      'click #quality-gate-rename': 'rename'
-      'click #quality-gate-cancel-rename': 'cancel'
-
-
-    onDomRefresh: ->
-      @ui.input.focus()
-
-
-    rename: ->
-      @options.detailView.showHeaderSpinner()
-      newName = @ui.input.val()
-      jQuery.ajax
-        url: "#{baseUrl}/api/qualitygates/rename"
-        type: 'POST'
-        data:
-          id: @model.id
-          name: newName
-      .always =>
-        @options.detailView.hideHeaderSpinner()
-      .done =>
-        @model.set 'name', newName
-        @options.detailView.showHeader()
-
-
-    cancel: ->
-      @options.detailView.showHeader()
diff --git a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-renaming-view.js b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-detail-renaming-view.js
deleted file mode 100644 (file)
index 983f29a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-// Generated by CoffeeScript 1.6.3
-(function() {
-  var __hasProp = {}.hasOwnProperty,
-    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
-
-  define(['backbone.marionette', 'handlebars'], function(Marionette, Handlebars) {
-    var QualityGateDetailRenamingView, _ref;
-    return QualityGateDetailRenamingView = (function(_super) {
-      __extends(QualityGateDetailRenamingView, _super);
-
-      function QualityGateDetailRenamingView() {
-        _ref = QualityGateDetailRenamingView.__super__.constructor.apply(this, arguments);
-        return _ref;
-      }
-
-      QualityGateDetailRenamingView.prototype.template = Handlebars.compile(jQuery('#quality-gate-detail-renaming-template').html());
-
-      QualityGateDetailRenamingView.prototype.ui = {
-        input: '#quality-gate-renaming-input'
-      };
-
-      QualityGateDetailRenamingView.prototype.events = {
-        'click #quality-gate-rename': 'rename',
-        'click #quality-gate-cancel-rename': 'cancel'
-      };
-
-      QualityGateDetailRenamingView.prototype.onDomRefresh = function() {
-        return this.ui.input.focus();
-      };
-
-      QualityGateDetailRenamingView.prototype.rename = function() {
-        var newName,
-          _this = this;
-        this.options.detailView.showHeaderSpinner();
-        newName = this.ui.input.val();
-        return jQuery.ajax({
-          url: "" + baseUrl + "/api/qualitygates/rename",
-          type: 'POST',
-          data: {
-            id: this.model.id,
-            name: newName
-          }
-        }).always(function() {
-          return _this.options.detailView.hideHeaderSpinner();
-        }).done(function() {
-          _this.model.set('name', newName);
-          return _this.options.detailView.showHeader();
-        });
-      };
-
-      QualityGateDetailRenamingView.prototype.cancel = function() {
-        return this.options.detailView.showHeader();
-      };
-
-      return QualityGateDetailRenamingView;
-
-    })(Marionette.ItemView);
-  });
-
-}).call(this);
index 3f999d9957619690557381b02bc719dad52120c0..475b25fb4e56638f49f8dd347be6a438fb5b8cfb 100644 (file)
@@ -3,7 +3,6 @@ define [
   'handlebars',
   'quality-gate/collections/conditions',
   'quality-gate/views/quality-gate-detail-header-view',
-  'quality-gate/views/quality-gate-detail-renaming-view',
   'quality-gate/views/quality-gate-detail-conditions-view',
   'quality-gate/views/quality-gate-detail-projects-view'
 ], (
@@ -11,81 +10,41 @@ define [
   Handlebars,
   Conditions,
   QualityGateDetailHeaderView,
-  QualityGateDetailRenamingView,
   QualityGateDetailConditionsView,
   QualityGateDetailProjectsView
 ) ->
 
   class QualityGateDetailView extends Marionette.Layout
-    className: 'quality-gate'
     template: Handlebars.compile jQuery('#quality-gate-detail-template').html()
 
 
     regions:
-      headerRegion: '.quality-gate-header'
-      tabRegion: '.quality-gate-details-tab'
-
-
-    ui:
-      tabs: '.quality-gate-tabs'
-      conditionsTab: '#quality-gate-tab-conditions'
-      projectsTab: '#quality-gate-tab-projects'
+      conditionsRegion: '#quality-gate-conditions'
+      projectsRegion: '#quality-gate-projects'
 
 
     modelEvents:
       'change': 'render'
 
 
-    events:
-      'click @ui.conditionsTab': 'showConditions'
-      'click @ui.projectsTab': 'showProjects'
-
-
     onRender: ->
-      @showHeader()
       @showConditions()
-
-
-    showHeader: ->
-      view = new QualityGateDetailHeaderView
-        app: @options.app
-        detailView: @
-        model: @model
-      @headerRegion.show view
-
-
-    showRenaming: ->
-      view = new QualityGateDetailRenamingView
-        app: @options.app
-        detailView: @
-        model: @model
-      @headerRegion.show view
+      @showProjects()
 
 
     showConditions: ->
-      @ui.tabs.find('a').removeClass 'selected'
-      @ui.conditionsTab.addClass 'selected'
       conditions = new Conditions @model.get('conditions')
       view = new QualityGateDetailConditionsView
         app: @options.app
         collection: conditions
         gateId: @model.id
         qualityGate: @model
-      @tabRegion.show view
+      @conditionsRegion.show view
 
 
     showProjects: ->
-      @ui.tabs.find('a').removeClass 'selected'
-      @ui.projectsTab.addClass 'selected'
       view = new QualityGateDetailProjectsView
         app: @options.app
+        model: @model
         gateId: @model.id
-      @tabRegion.show view
-
-
-    showHeaderSpinner: ->
-      @$(@headerRegion.el).addClass 'navigator-fetching'
-
-
-    hideHeaderSpinner: ->
-      @$(@headerRegion.el).removeClass 'navigator-fetching'
+      @projectsRegion.show view
index e3e30f6e07e01318409fbbd48aa3b404bdc6ebb8..6df657a234b4d730456d4cf491b5afdca00d975c 100644 (file)
@@ -3,7 +3,7 @@
   var __hasProp = {}.hasOwnProperty,
     __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
 
-  define(['backbone.marionette', 'handlebars', 'quality-gate/collections/conditions', 'quality-gate/views/quality-gate-detail-header-view', 'quality-gate/views/quality-gate-detail-renaming-view', 'quality-gate/views/quality-gate-detail-conditions-view', 'quality-gate/views/quality-gate-detail-projects-view'], function(Marionette, Handlebars, Conditions, QualityGateDetailHeaderView, QualityGateDetailRenamingView, QualityGateDetailConditionsView, QualityGateDetailProjectsView) {
+  define(['backbone.marionette', 'handlebars', 'quality-gate/collections/conditions', 'quality-gate/views/quality-gate-detail-header-view', 'quality-gate/views/quality-gate-detail-conditions-view', 'quality-gate/views/quality-gate-detail-projects-view'], function(Marionette, Handlebars, Conditions, QualityGateDetailHeaderView, QualityGateDetailConditionsView, QualityGateDetailProjectsView) {
     var QualityGateDetailView, _ref;
     return QualityGateDetailView = (function(_super) {
       __extends(QualityGateDetailView, _super);
         return _ref;
       }
 
-      QualityGateDetailView.prototype.className = 'quality-gate';
-
       QualityGateDetailView.prototype.template = Handlebars.compile(jQuery('#quality-gate-detail-template').html());
 
       QualityGateDetailView.prototype.regions = {
-        headerRegion: '.quality-gate-header',
-        tabRegion: '.quality-gate-details-tab'
-      };
-
-      QualityGateDetailView.prototype.ui = {
-        tabs: '.quality-gate-tabs',
-        conditionsTab: '#quality-gate-tab-conditions',
-        projectsTab: '#quality-gate-tab-projects'
+        conditionsRegion: '#quality-gate-conditions',
+        projectsRegion: '#quality-gate-projects'
       };
 
       QualityGateDetailView.prototype.modelEvents = {
         'change': 'render'
       };
 
-      QualityGateDetailView.prototype.events = {
-        'click @ui.conditionsTab': 'showConditions',
-        'click @ui.projectsTab': 'showProjects'
-      };
-
       QualityGateDetailView.prototype.onRender = function() {
-        this.showHeader();
-        return this.showConditions();
-      };
-
-      QualityGateDetailView.prototype.showHeader = function() {
-        var view;
-        view = new QualityGateDetailHeaderView({
-          app: this.options.app,
-          detailView: this,
-          model: this.model
-        });
-        return this.headerRegion.show(view);
-      };
-
-      QualityGateDetailView.prototype.showRenaming = function() {
-        var view;
-        view = new QualityGateDetailRenamingView({
-          app: this.options.app,
-          detailView: this,
-          model: this.model
-        });
-        return this.headerRegion.show(view);
+        this.showConditions();
+        return this.showProjects();
       };
 
       QualityGateDetailView.prototype.showConditions = function() {
         var conditions, view;
-        this.ui.tabs.find('a').removeClass('selected');
-        this.ui.conditionsTab.addClass('selected');
         conditions = new Conditions(this.model.get('conditions'));
         view = new QualityGateDetailConditionsView({
           app: this.options.app,
           gateId: this.model.id,
           qualityGate: this.model
         });
-        return this.tabRegion.show(view);
+        return this.conditionsRegion.show(view);
       };
 
       QualityGateDetailView.prototype.showProjects = function() {
         var view;
-        this.ui.tabs.find('a').removeClass('selected');
-        this.ui.projectsTab.addClass('selected');
         view = new QualityGateDetailProjectsView({
           app: this.options.app,
+          model: this.model,
           gateId: this.model.id
         });
-        return this.tabRegion.show(view);
-      };
-
-      QualityGateDetailView.prototype.showHeaderSpinner = function() {
-        return this.$(this.headerRegion.el).addClass('navigator-fetching');
-      };
-
-      QualityGateDetailView.prototype.hideHeaderSpinner = function() {
-        return this.$(this.headerRegion.el).removeClass('navigator-fetching');
+        return this.projectsRegion.show(view);
       };
 
       return QualityGateDetailView;
diff --git a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-edit-view.coffee b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-edit-view.coffee
new file mode 100644 (file)
index 0000000..34d94fe
--- /dev/null
@@ -0,0 +1,65 @@
+define [
+  'backbone.marionette',
+  'handlebars'
+], (
+  Marionette,
+  Handlebars,
+) ->
+
+  class QualityGateEditView extends Marionette.ItemView
+    className: 'modal'
+    template: Handlebars.compile jQuery('#quality-gate-edit-template').html()
+
+
+    ui:
+      nameInput: '#quality-gate-edit-name'
+
+
+    events:
+      'click #quality-gate-create': 'createQualityGate'
+      'click #quality-gate-save': 'saveQualityGate'
+      'click #quality-gate-cancel-create': 'hide'
+
+
+    onRender: ->
+      @$el.dialog
+        dialogClass: 'no-close',
+        width: '600px',
+        draggable: false,
+        autoOpen: false,
+        modal: true,
+        minHeight: 50,
+        resizable: false,
+        title: null
+
+
+    show: ->
+      @render()
+      @$el.dialog 'open'
+      @ui.nameInput.focus()
+
+
+    hide: ->
+      @$el.dialog 'close'
+
+
+    saveRequest: (method, data) ->
+      jQuery.ajax
+        type: 'POST'
+        url: "#{baseUrl}/api/qualitygates/#{method}"
+        data: data
+      .done => @hide()
+
+
+    createQualityGate: ->
+      data = name: @ui.nameInput.val()
+      @saveRequest('create', data).done (r) =>
+        @model.set id: r.id, name: r.name
+        @options.app.qualityGates.add @model
+        @options.app.router.navigate "show/#{r.id}", trigger: true
+
+
+    saveQualityGate: ->
+      data = id: @model.id, name: @ui.nameInput.val()
+      @saveRequest('rename', data).done (r) =>
+        @model.set name: r.name
diff --git a/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-edit-view.js b/sonar-server/src/main/webapp/javascripts/quality-gate/views/quality-gate-edit-view.js
new file mode 100644 (file)
index 0000000..6b4c397
--- /dev/null
@@ -0,0 +1,101 @@
+// Generated by CoffeeScript 1.6.3
+(function() {
+  var __hasProp = {}.hasOwnProperty,
+    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+  define(['backbone.marionette', 'handlebars'], function(Marionette, Handlebars) {
+    var QualityGateEditView, _ref;
+    return QualityGateEditView = (function(_super) {
+      __extends(QualityGateEditView, _super);
+
+      function QualityGateEditView() {
+        _ref = QualityGateEditView.__super__.constructor.apply(this, arguments);
+        return _ref;
+      }
+
+      QualityGateEditView.prototype.className = 'modal';
+
+      QualityGateEditView.prototype.template = Handlebars.compile(jQuery('#quality-gate-edit-template').html());
+
+      QualityGateEditView.prototype.ui = {
+        nameInput: '#quality-gate-edit-name'
+      };
+
+      QualityGateEditView.prototype.events = {
+        'click #quality-gate-create': 'createQualityGate',
+        'click #quality-gate-save': 'saveQualityGate',
+        'click #quality-gate-cancel-create': 'hide'
+      };
+
+      QualityGateEditView.prototype.onRender = function() {
+        return this.$el.dialog({
+          dialogClass: 'no-close',
+          width: '600px',
+          draggable: false,
+          autoOpen: false,
+          modal: true,
+          minHeight: 50,
+          resizable: false,
+          title: null
+        });
+      };
+
+      QualityGateEditView.prototype.show = function() {
+        this.render();
+        this.$el.dialog('open');
+        return this.ui.nameInput.focus();
+      };
+
+      QualityGateEditView.prototype.hide = function() {
+        return this.$el.dialog('close');
+      };
+
+      QualityGateEditView.prototype.saveRequest = function(method, data) {
+        var _this = this;
+        return jQuery.ajax({
+          type: 'POST',
+          url: "" + baseUrl + "/api/qualitygates/" + method,
+          data: data
+        }).done(function() {
+          return _this.hide();
+        });
+      };
+
+      QualityGateEditView.prototype.createQualityGate = function() {
+        var data,
+          _this = this;
+        data = {
+          name: this.ui.nameInput.val()
+        };
+        return this.saveRequest('create', data).done(function(r) {
+          _this.model.set({
+            id: r.id,
+            name: r.name
+          });
+          _this.options.app.qualityGates.add(_this.model);
+          return _this.options.app.router.navigate("show/" + r.id, {
+            trigger: true
+          });
+        });
+      };
+
+      QualityGateEditView.prototype.saveQualityGate = function() {
+        var data,
+          _this = this;
+        data = {
+          id: this.model.id,
+          name: this.ui.nameInput.val()
+        };
+        return this.saveRequest('rename', data).done(function(r) {
+          return _this.model.set({
+            name: r.name
+          });
+        });
+      };
+
+      return QualityGateEditView;
+
+    })(Marionette.ItemView);
+  });
+
+}).call(this);
index 4ddd64318df0aa1d27498c6dbeef673f676db796..458736751db61fac6f56496901a743a4be3d1452 100644 (file)
@@ -16,7 +16,7 @@ define [
 
 
     events:
-      'click a': 'showQualityGate'
+      'click': 'showQualityGate'
 
 
     onRender: ->
index 1ebd667ed8fccb93521ffd404e0be5fdf5fefc22..05b6798c7beb1b58aa5bcda3bf5088ddf1104e8a 100644 (file)
@@ -22,7 +22,7 @@
       };
 
       QualityGateSidebarListItemView.prototype.events = {
-        'click a': 'showQualityGate'
+        'click': 'showQualityGate'
       };
 
       QualityGateSidebarListItemView.prototype.onRender = function() {
index f8832dc8aae279ef7b8e908c2b6216d8d45f4488..e8e8cb961691904378d9659b098b888a12a823a9 100644 (file)
@@ -10,34 +10,17 @@ define [
   QualityGateSidebarListItemView
 ) ->
 
-  class QualityGateSidebarListView extends Marionette.CompositeView
-    tagName: 'ul'
-    className: 'sidebar blue-sidebar'
-    template: Handlebars.compile jQuery('#quality-gate-sidebar-list-template').html()
+  class QualityGateSidebarListView extends Marionette.CollectionView
+    tagName: 'ol'
+    className: 'navigator-results-list'
     itemView: QualityGateSidebarListItemView
 
 
-    ui:
-      spacer: '.spacer'
-
-
-    events:
-      'click #quality-gate-add': 'addQualityGate'
-
-
     itemViewOptions: (model) ->
       app: @options.app
       highlighted: model.get('id') == +@highlighted
 
 
-    appendHtml: (compositeView, itemView) ->
-      itemView.$el.insertBefore @ui.spacer
-
-
     highlight: (id) ->
       @highlighted = id
       @render()
-
-
-    addQualityGate: ->
-      @options.app.router.navigate 'new', trigger: true
index 2ae45f78051446b900c56c658b8624672b978011..d2ac9a4393d8bd10b725aa38d1aada16f44e1d00 100644 (file)
         return _ref;
       }
 
-      QualityGateSidebarListView.prototype.tagName = 'ul';
+      QualityGateSidebarListView.prototype.tagName = 'ol';
 
-      QualityGateSidebarListView.prototype.className = 'sidebar blue-sidebar';
-
-      QualityGateSidebarListView.prototype.template = Handlebars.compile(jQuery('#quality-gate-sidebar-list-template').html());
+      QualityGateSidebarListView.prototype.className = 'navigator-results-list';
 
       QualityGateSidebarListView.prototype.itemView = QualityGateSidebarListItemView;
 
-      QualityGateSidebarListView.prototype.ui = {
-        spacer: '.spacer'
-      };
-
-      QualityGateSidebarListView.prototype.events = {
-        'click #quality-gate-add': 'addQualityGate'
-      };
-
       QualityGateSidebarListView.prototype.itemViewOptions = function(model) {
         return {
           app: this.options.app,
         };
       };
 
-      QualityGateSidebarListView.prototype.appendHtml = function(compositeView, itemView) {
-        return itemView.$el.insertBefore(this.ui.spacer);
-      };
-
       QualityGateSidebarListView.prototype.highlight = function(id) {
         this.highlighted = id;
         return this.render();
       };
 
-      QualityGateSidebarListView.prototype.addQualityGate = function() {
-        return this.options.app.router.navigate('new', {
-          trigger: true
-        });
-      };
-
       return QualityGateSidebarListView;
 
-    })(Marionette.CompositeView);
+    })(Marionette.CollectionView);
   });
 
 }).call(this);
index c7cf3231b8ee012032f4bb167da079c62d02d8dd..a341ca6b61596982424bff38e347664a1aca220c 100644 (file)
   font-size: 16px;
   text-decoration: none;
 }
-.issues-page #footer {
+.navigator-page #footer {
   position: fixed;
   z-index: 2;
   -moz-box-sizing: border-box;
   margin: 0;
   border-top: 1px solid #e1e1e1;
 }
-.issues-page #ftlinks {
+.navigator-page #ftlinks {
   margin-top: 0;
 }
 .navigator-filters {
index a7e8f306461489e6bbb5e9c8dd11f0b5719c0268..4e062c3ebe6bfd265b0934b183ecb5f46028a6a3 100644 (file)
   font-size: 16px;
   text-decoration: none;
 }
-.issues-page #footer {
+.navigator-page #footer {
   position: fixed;
   z-index: 2;
   -moz-box-sizing: border-box;
   margin: 0;
   border-top: 1px solid #e1e1e1;
 }
-.issues-page #ftlinks {
+.navigator-page #ftlinks {
   margin-top: 0;
 }
index e53cb36e61215bd2f72fac7b846e52d5102e689a..2456f8a51a0fc722879f1eed7d36410ea0513677 100644 (file)
 
 
 // Footer
-.issues-page #footer {
+.navigator-page #footer {
   .navigator-element;
   bottom: 0;
   left: @navigatorResultsWidth;
   border-top: 1px solid @navigatorBorderLightColor;
 }
 
-.issues-page #ftlinks {
+.navigator-page #ftlinks {
   margin-top: 0;
 }
index 9dbfa1ec4e6fd8346149daadbde95fca5590b78b..303502edf916ebae1575963efd1116bcbd19e3f0 100644 (file)
   font-size: 16px;
   text-decoration: none;
 }
-.issues-page #footer {
+.navigator-page #footer {
   position: fixed;
   z-index: 2;
   -moz-box-sizing: border-box;
   margin: 0;
   border-top: 1px solid #e1e1e1;
 }
-.issues-page #ftlinks {
+.navigator-page #ftlinks {
   margin-top: 0;
 }
-.quality-gate {
-  position: relative;
-  padding: 0 10px;
-  overflow: hidden;
-}
-.quality-gate-page-loader {
-  position: relative;
-  width: 24px;
-  height: 24px;
-}
-.quality-gate-page-loader:before {
-  content: " ";
-  position: absolute;
-  z-index: 3;
-  top: 0;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  background: #ffffff url(../images/loading.gif) no-repeat 4px 4px;
-}
-.quality-gate-page-loader#tab-issue-rule {
-  position: relative;
-}
-.quality-gate-page-loader#tab-issue-rule:before {
-  z-index: 3;
-  background-color: #EFEFEF;
+.quality-gates-navigator .navigator-header {
+  left: 320px;
+  border-bottom-color: #e1e1e1;
 }
-.quality-gate-page-loader.code-issue-actions {
-  position: relative;
+.quality-gates-navigator .navigator-header .spinner {
+  margin-top: 9px;
 }
-.quality-gate-page-loader.code-issue-actions:before {
-  z-index: 3;
-  background-color: #E4ECF3;
-}
-.quality-gate-header {
-  position: relative;
+.quality-gates-navigator .navigator-actions {
+  top: 30px;
+  height: 37px;
   padding: 0 10px;
-  border-left: 1px solid #cdcdcd;
-  border-right: 1px solid #cdcdcd;
-  border-bottom: 1px solid #cdcdcd;
-  background-color: #efefef;
-  font-size: 0;
-}
-.quality-gate-header.navigator-fetching:before {
-  background-color: #efefef;
-  background-position: 10px center;
+  border-right-color: #cdcdcd;
 }
-.quality-gate-header-rename {
-  padding: 8px 0 7px;
+.quality-gates-navigator .navigator-results {
+  top: 67px;
 }
-.quality-gate-header-rename input {
-  vertical-align: middle;
-  width: 200px;
-  font-size: 13px;
+.quality-gates-navigator .navigator-details {
+  top: 67px;
+  padding: 10px;
 }
-.quality-gate-details {
+.quality-gate-section + .quality-gate-section {
   margin-top: 10px;
+  padding-top: 20px;
 }
-.quality-gate-tabs {
-  margin-bottom: 10px;
+.quality-gate-section-empty + .quality-gate-section {
+  border-top: 1px solid #e1e1e1;
 }
-.quality-gate-new-condition {
-  margin: 20px 0 10px;
+.quality-gate-section-name {
+  margin-bottom: 10px;
+  font-weight: bold;
 }
-.quality-gate-new-condition label {
-  vertical-align: middle;
+.quality-gate-introduction {
+  margin-bottom: 20px;
 }
-.quality-gate-conditions img,
-.quality-gate-conditions input,
-.quality-gate-conditions button,
-.quality-gate-conditions .action {
-  vertical-align: middle !important;
+.quality-gate-new-condition {
+  margin-bottom: 10px;
 }
 .quality-gate-condition-actions {
   position: relative;
 }
-.quality-gate-condition-actions.navigator-fetching:before {
-  background-position: center left;
-}
index 15a2517806fcf632801660b5d2bf0db58411dacb..5bd981b339219f54352800b8ca70d90e977f4754 100644 (file)
@@ -2,70 +2,58 @@
 @import "mixins";
 @import "navigator/base";
 
-.quality-gate {
-  position: relative;
-  padding: 0 10px;
-  overflow: hidden;
-}
+.quality-gates-navigator {
 
-.quality-gate-page-loader {
-  position: relative;
-  .square(24px);
-  .navigator-fetching;
-}
+  .navigator-header {
+    left: @navigatorResultsWidth;
+    border-bottom-color: @navigatorBorderLightColor;
 
-.quality-gate-header {
-  position: relative;
-  padding: 0 10px;
-  border-left: 1px solid @darkGrey;
-  border-right: 1px solid @darkGrey;
-  border-bottom: 1px solid @darkGrey;
-  background-color: @grey;
-  font-size: 0;
-
-  &.navigator-fetching:before {
-    background-color: @grey;
-    background-position: 10px center;
+    .spinner { margin-top: 9px; }
   }
-}
 
-.quality-gate-header-rename {
-  padding: 8px 0 7px;
+  .navigator-actions {
+    top: @navigatorTopOffset;
+    height: @navigatorHeaderHeight;
+    padding: 0 @navigatorPadding;
+    border-right-color: @navigatorBorderColor;
+  }
 
-  input {
-    vertical-align: middle;
-    width: 200px;
-    font-size: @baseFontSize;
+  .navigator-results {
+    top: @navigatorTopOffset + @navigatorHeaderHeight;
   }
+
+  .navigator-details {
+    top: @navigatorTopOffset + @navigatorHeaderHeight;
+    padding: @navigatorPadding;
+  }
+
 }
 
-.quality-gate-details {
-  margin-top: 10px;
+
+.quality-gate-section + .quality-gate-section {
+  margin-top: @navigatorPadding;
+  padding-top: 2 * @navigatorPadding;
 }
 
-.quality-gate-tabs {
-  margin-bottom: 10px;
+.quality-gate-section-empty + .quality-gate-section {
+  border-top: 1px solid @navigatorBorderLightColor;
 }
 
-.quality-gate-new-condition {
-  margin: 20px 0 10px;
-  
-  label {
-    vertical-align: middle;
-  }
+.quality-gate-section-name {
+  margin-bottom: @navigatorPadding;
+  font-weight: bold;
 }
 
-.quality-gate-conditions {
 
-  img, input, button, .action {
-    vertical-align: middle !important;
-  }
+.quality-gate-introduction {
+  margin-bottom: 2 * @navigatorPadding;
+}
+
+
+.quality-gate-new-condition {
+  margin-bottom: @navigatorPadding;
 }
 
 .quality-gate-condition-actions {
   position: relative;
-
-  &.navigator-fetching:before {
-    background-position: center left;
-  }
 }
index 4b96a84cce71a9cb61001816cdb715e8a94dade9..be6f6eadeab6fcb445b1fe178a232603cda89479 100644 (file)
@@ -406,6 +406,10 @@ table.data th img, table.data td img {
   vertical-align: sub;
 }
 
+table.data.zebra tr:nth-child(odd) {
+  background-color: #EFEFEF;
+}
+
 .data thead tr.total {
   background-color: #EFEFEF;
   font-weight: normal;