]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5820 Ability to bulk "Activate In" or "Deactivate In" all rules matching some...
authorStas Vilchik <vilchiks@gmail.com>
Tue, 6 Jan 2015 13:32:44 +0000 (14:32 +0100)
committerStas Vilchik <vilchiks@gmail.com>
Tue, 6 Jan 2015 13:32:59 +0000 (14:32 +0100)
server/sonar-web/src/main/hbs/coding-rules/coding-rules-bulk-change-modal.hbs [new file with mode: 0644]
server/sonar-web/src/main/hbs/coding-rules/coding-rules-bulk-change-popup.hbs [new file with mode: 0644]
server/sonar-web/src/main/hbs/coding-rules/coding-rules-workspace-header.hbs
server/sonar-web/src/main/hbs/coding-rules/rule/coding-rules-manual-rule-creation.hbs
server/sonar-web/src/main/js/coding-rules/bulk-change-modal-view.js [new file with mode: 0644]
server/sonar-web/src/main/js/coding-rules/bulk-change-popup-view.js [new file with mode: 0644]
server/sonar-web/src/main/js/coding-rules/workspace-header-view.js
server/sonar-web/src/main/less/ui.less

diff --git a/server/sonar-web/src/main/hbs/coding-rules/coding-rules-bulk-change-modal.hbs b/server/sonar-web/src/main/hbs/coding-rules/coding-rules-bulk-change-modal.hbs
new file mode 100644 (file)
index 0000000..0ad2c90
--- /dev/null
@@ -0,0 +1,39 @@
+<form>
+  <div class="modal-head">
+    {{#eq action 'activate'}}
+      <h2>{{t 'coding_rules.activate_in_quality_profile'}} ({{state.total}} {{t 'coding_rules._rules'}})</h2>
+    {{/eq}}
+    {{#eq action 'deactivate'}}
+      <h2>{{t 'coding_rules.deactivate_in_quality_profile'}} ({{state.total}} {{t 'coding_rules._rules'}})</h2>
+    {{/eq}}
+  </div>
+
+  <div class="modal-body modal-body-select2">
+    <div class="js-modal-messages"></div>
+
+    <div class="modal-field">
+      <h3>
+        <label for="coding-rules-bulk-change-profile">
+          {{#eq action 'activate'}}{{t 'coding_rules.activate_in'}}{{/eq}}
+          {{#eq action 'deactivate'}}{{t 'coding_rules.deactivate_in'}}{{/eq}}
+        </label>
+      </h3>
+      {{#if qualityProfile}}
+        <h3 class="readonly-field">
+          {{qualityProfileName}}{{#notEq action 'change-severity'}} — {{t 'are_you_sure'}}{{/notEq}}
+        </h3>
+      {{else}}
+        <select id="coding-rules-bulk-change-profile">
+          {{#each availableQualityProfiles}}
+            <option value="{{key}}">{{name}} - {{language}}</option>
+          {{/each}}
+        </select>
+      {{/if}}
+    </div>
+  </div>
+
+  <div class="modal-foot">
+    <button id="coding-rules-submit-bulk-change">{{t 'apply'}}</button>
+    <a class="js-modal-close">{{t 'close'}}</a>
+  </div>
+</form>
diff --git a/server/sonar-web/src/main/hbs/coding-rules/coding-rules-bulk-change-popup.hbs b/server/sonar-web/src/main/hbs/coding-rules/coding-rules-bulk-change-popup.hbs
new file mode 100644 (file)
index 0000000..c5a4622
--- /dev/null
@@ -0,0 +1,41 @@
+<div class="bubble-popup-title">{{t 'bulk_change'}}</div>
+
+<ul class="bubble-popup-list">
+
+  {{! activation }}
+
+  <li>
+    <a class="js-bulk-change" data-action="activate">
+      {{t 'coding_rules.activate_in'}}&#8230;
+    </a>
+  </li>
+
+  {{#if allowActivateOnProfile}}
+    <li>
+      <a class="js-bulk-change" data-action="activate" data-param="{{qualityProfile}}">
+        {{t 'coding_rules.activate_in'}} <strong>{{qualityProfileName}}</strong>
+      </a>
+    </li>
+  {{/if}}
+
+
+
+  {{! deactivation }}
+
+  <li>
+    <a class="js-bulk-change" data-action="deactivate">
+      {{t 'coding_rules.deactivate_in'}}&#8230;
+    </a>
+  </li>
+
+  {{#if allowDeactivateOnProfile}}
+    <li>
+      <a class="js-bulk-change" data-action="deactivate" data-param="{{qualityProfile}}">
+        {{tp 'coding_rules.deactivate_in'}} <strong>{{qualityProfileName}}</strong>
+      </a>
+    </li>
+  {{/if}}
+</ul>
+
+
+<div class="bubble-popup-arrow"></div>
index e91dbcd736bacbcd45ff9d89b87485abd4251ce5..bcf70f5d3ab6fc1a77e096a3f7201c2000a7f01e 100644 (file)
@@ -12,7 +12,8 @@
     <div class="search-navigator-header-pagination">
       {{#gt state.total 0}}
         <a class="js-prev icon-prev" title="{{t 'paging_previous'}}"></a>
-        <span class="current">{{sum state.selectedIndex 1}} / <span id="coding-rules-total">{{state.total}}</span></span>
+        <span class="current">{{sum state.selectedIndex 1}} / <span
+            id="coding-rules-total">{{state.total}}</span></span>
         <a class="js-next icon-next" title="{{t 'paging_next'}}"></a>
       {{else}}
         <span class="current">0 / <span id="coding-rules-total">0</span></span>
     </div>
   {{/notNull}}
 
-
-  <div class="search-navigator-header-buttons button-group">
-    <button class="js-reload">{{t 'reload'}}</button>
-    {{#if state.canBulkChange}}
+  {{#if canWrite}}
+    <div class="search-navigator-header-buttons button-group">
       <button class="js-bulk-change">{{t 'bulk_change'}}</button>
-    {{/if}}
-  </div>
+    </div>
+  {{/if}}
 </div>
index 5a6e62a6c468250384e509d06bef6efaa305a40d..f413905f6363a89e96c1d08981683d75887c8725 100644 (file)
@@ -45,6 +45,6 @@
     <button id="coding-rules-manual-rule-creation-create">
       {{#if change}}{{t 'save'}}{{else}}{{t 'create'}}{{/if}}
     </button>
-    <a id="coding-rules-manual-rule-creation-cancel" class="action">{{t 'cancel'}}</a>
+    <a id="coding-rules-manual-rule-creation-cancel" class="js-modal-close">{{t 'cancel'}}</a>
   </div>
 </form>
diff --git a/server/sonar-web/src/main/js/coding-rules/bulk-change-modal-view.js b/server/sonar-web/src/main/js/coding-rules/bulk-change-modal-view.js
new file mode 100644 (file)
index 0000000..9375579
--- /dev/null
@@ -0,0 +1,74 @@
+define([
+    'common/modal-form',
+    'templates/coding-rules'
+], function (ModalFormView, Templates) {
+
+  var $ = jQuery;
+
+  return ModalFormView.extend({
+    template: Templates['coding-rules-bulk-change-modal'],
+
+    ui: function () {
+      return _.extend(ModalFormView.prototype.ui.apply(this, arguments), {
+        codingRulesSubmitBulkChange: '#coding-rules-submit-bulk-change'
+      });
+    },
+
+    showSuccessMessage: function (succeeded) {
+      var message = tp('coding_rules.bulk_change.success', succeeded);
+      this.ui.messagesContainer.html('<div class="message-notice">' + message + '</div>');
+    },
+
+    showWarnMessage: function (succeeded, failed) {
+      var message = tp('coding_rules.bulk_change.warning', succeeded, failed);
+      this.ui.messagesContainer.html('<div class="message-alert">' + message + '</div>');
+    },
+
+    onRender: function () {
+      ModalFormView.prototype.onRender.apply(this, arguments);
+      this.$('#coding-rules-bulk-change-profile').select2({
+        width: '250px',
+        minimumResultsForSearch: 1
+      });
+    },
+
+    onFormSubmit: function () {
+      ModalFormView.prototype.onFormSubmit.apply(this, arguments);
+      var that = this,
+          p = window.process.addBackgroundProcess(),
+          url = baseUrl + '/api/qualityprofiles/' + this.options.action + '_rules',
+          options = _.extend({}, this.options.app.state.get('query'), {
+            wsAction: this.options.action,
+            profile_key: this.$('#coding-rules-bulk-change-profile').val() || this.options.param
+          });
+      $.post(url, options).done(function (r) {
+        if (r.failed) {
+          that.showWarnMessage(r.succeeded, r.failed);
+        } else {
+          that.showSuccessMessage(r.succeeded, r.failed);
+        }
+        that.$(that.ui.codingRulesSubmitBulkChange.selector).hide();
+        window.process.finishBackgroundProcess(p);
+      }).fail(function () {
+        window.process.failBackgroundProcess(p);
+      });
+    },
+
+    getAvailableQualityProfiles: function () {
+      return this.options.app.qualityProfiles;
+    },
+
+    serializeData: function () {
+      var profile = _.findWhere(this.options.app.qualityProfiles, { key: this.options.param });
+      return _.extend(ModalFormView.prototype.serializeData.apply(this, arguments), {
+        action: this.options.action,
+        state: this.options.app.state.toJSON(),
+        qualityProfile: this.options.param,
+        qualityProfileName: profile != null ? profile.name : null,
+        qualityProfiles: this.options.app.qualityProfiles,
+        availableQualityProfiles: this.getAvailableQualityProfiles()
+      });
+    }
+  });
+
+});
diff --git a/server/sonar-web/src/main/js/coding-rules/bulk-change-popup-view.js b/server/sonar-web/src/main/js/coding-rules/bulk-change-popup-view.js
new file mode 100644 (file)
index 0000000..e373bd0
--- /dev/null
@@ -0,0 +1,41 @@
+define([
+    'common/popup',
+    'templates/coding-rules',
+    'coding-rules/bulk-change-modal-view'
+], function (PopupView, Templates, BulkChangeModalView) {
+
+  var $ = jQuery;
+
+  return PopupView.extend({
+    template: Templates['coding-rules-bulk-change-popup'],
+
+    events: {
+      'click .js-bulk-change': 'doAction'
+    },
+
+    doAction: function (e) {
+      var action = $(e.currentTarget).data('action'),
+          param = $(e.currentTarget).data('param');
+      new BulkChangeModalView({
+        app: this.options.app,
+        action: action,
+        param: param
+      }).render();
+    },
+
+    serializeData: function () {
+      var query = this.options.app.state.get('query'),
+          profileKey = query.qprofile,
+          profile = _.findWhere(this.options.app.qualityProfiles, { key: profileKey }),
+          activation = query.activation;
+
+      return {
+        qualityProfile: profileKey,
+        qualityProfileName: profile != null ? profile.name : null,
+        allowActivateOnProfile: profileKey != null && (activation === 'false' || activation === false),
+        allowDeactivateOnProfile: profileKey != null && (activation === 'true' || activation === true)
+      };
+    }
+  });
+
+});
index fae2372a8dc819e62c5c657f9f78b6f9a2e7c417..ef19ef289a9c9ce9a48975bd2be68512eb24e316 100644 (file)
@@ -1,19 +1,39 @@
 define([
   'components/navigator/workspace-header-view',
-  'templates/coding-rules'
-], function (WorkspaceHeaderView, Templates) {
+  'templates/coding-rules',
+  'coding-rules/bulk-change-popup-view'
+], function (WorkspaceHeaderView, Templates, BulkChangePopup) {
+
+  var $ = jQuery;
 
   return WorkspaceHeaderView.extend({
     template: Templates['coding-rules-workspace-header'],
 
     events: function () {
       return _.extend(WorkspaceHeaderView.prototype.events.apply(this, arguments), {
-        'click .js-back': 'onBackClick'
+        'click .js-back': 'onBackClick',
+        'click .js-bulk-change': 'onBulkChangeClick'
       });
     },
 
     onBackClick: function () {
       this.options.app.controller.hideDetails();
+    },
+
+    onBulkChangeClick: function (e) {
+      e.stopPropagation();
+      $('body').click();
+      new BulkChangePopup({
+        app: this.options.app,
+        triggerEl: $(e.currentTarget),
+        bottomRight: true
+      }).render();
+    },
+
+    serializeData: function () {
+      return _.extend(WorkspaceHeaderView.prototype.serializeData.apply(this, arguments), {
+        canWrite: this.options.app.canWrite
+      });
     }
   });
 
index f12a4f536e77be5adeeff2c52ef92d2bfeecd4e9..d0b840b128cee5b276d086ac77c5f2d86bbd42b0 100644 (file)
@@ -329,6 +329,12 @@ input[type=button] {
 }
 
 
+.message-notice {
+  display: block;
+  padding: 5px 8px;
+  border: 2px solid @blue;
+}
+
 .message-alert {
   display: block;
   padding: 5px 8px;