]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4884 Add metric filter
authorStas Vilchik <vilchiks@gmail.com>
Wed, 27 Nov 2013 11:52:39 +0000 (17:52 +0600)
committerStas Vilchik <vilchiks@gmail.com>
Wed, 27 Nov 2013 11:52:46 +0000 (17:52 +0600)
sonar-server/src/main/webapp/WEB-INF/app/views/layouts/_head.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/measures/search.html.erb
sonar-server/src/main/webapp/WEB-INF/app/views/navigator/_filter_templates.html.erb
sonar-server/src/main/webapp/javascripts/navigator/filters/metric-filters.js [new file with mode: 0644]
sonar-server/src/main/webapp/javascripts/navigator/measures-app.js
sonar-server/src/main/webapp/stylesheets/navigator.css
sonar-server/src/main/webapp/stylesheets/navigator.less
sonar-server/wro.xml

index 8d6cfb0f0f9b568a1c9a2e60f792cafdace7e88e..dceb971cd62efb6dbb6b2b290214db24378072e4 100644 (file)
@@ -58,9 +58,9 @@
     <%= javascript_include_tag 'navigator/filters/range-filters' %>
     <%= javascript_include_tag 'navigator/filters/checkbox-filters' %>
     <%= javascript_include_tag 'navigator/filters/string-filters' %>
+    <%= javascript_include_tag 'navigator/filters/metric-filters' %>
     <%= javascript_include_tag 'navigator/filters/favorite-filters' %>
     <%= javascript_include_tag 'navigator/filters/more-criteria-filters' %>
-    <%= javascript_include_tag 'navigator/filters/more-criteria-filters' %>
     <%= javascript_include_tag 'navigator/issues-app' %>
     <%= javascript_include_tag 'navigator/measures-app' %>
 
index fe2529c815577dfc0df988ce5354d0545f57c2b2..7ba067da273f7248e0cff7c0f8191789c3b4b724 100644 (file)
 
   _.extend(window.SS, {
     languages: <%= render :partial => 'measures/languages' -%>,
+    <% condition_metrics = Metric.all.select { |m| m.numeric? && !m.hidden } %>
+    metrics: <%= condition_metrics.to_json -%>,
+    metricPeriods: {
+      '1': '<%= Api::Utils.period_label(1) -%>',
+      '2': '<%= Api::Utils.period_label(2) -%>',
+      '3': '<%= Api::Utils.period_label(3) -%>'
+    },
     favorites: <%= render :partial => 'measures/favourites2' -%>
   });
 
     <% end %>
     { key: 'onFavourites', value: <%= @filter.criteria['onFavourites']=='true' -%> },
     { key: 'keySearch', value: '<%= h @filter.criteria['keySearch'] -%>' },
-    { key: 'languages[]', value: <%= @filter.criteria['languages'].to_json -%> }
+    { key: 'languages[]', value: <%= @filter.criteria['languages'].to_json -%> },
+
+    <% for i in 1..3 %>
+    { key: '<%= "c#{i}_metric" -%>', value: '<%= h @filter.criteria("c#{i}_metric") -%>' },
+    { key: '<%= "c#{i}_period" -%>', value: '<%= h @filter.criteria("c#{i}_period") -%>' },
+    { key: '<%= "c#{i}_op" -%>', value: '<%= h @filter.criteria("c#{i}_op") -%>' },
+    { key: '<%= "c#{i}_val" -%>', value: '<%= h @filter.criteria("c#{i}_val") -%>' },
+    <% end %>
+
   ];
 
   window.SS.MeasuresNavigatorApp.start();
index beedea8a1f763e4e6b5e284fb82f7cb817a21de0..bcdfc8c597ed42e6c14a2eae3f0edc9c0d2141d6 100644 (file)
   </div>
 </script>
 
+<script id="metricFilterTemplate" type="text/template">
+  <div class="navigator-filter-details-inner">
+    <select name="metric">
+      <option></option>
+      {[ _.each(groupedMetrics, function(group) { ]}
+      <optgroup label="{{ group.domain }}">
+        {[ _.each(group.metrics, function(metric) { ]}
+        <option value="{{ metric.name }}">{{ metric.short_name }}</option>
+        {[ }); ]}
+      </optgroup>
+      {[ }); ]}
+    </select>
+
+    <select name="period">
+      <option value="0">Value</option>
+      {[ _.each(periods, function(period, key) { ]}
+      <option value="{{ key }}">{{ period }}</option>
+      {[ }); ]}
+    </select>
+
+    <select name="op">
+      {[ _.each(operations, function(op, key) { ]}
+      <option value="{{ key }}">{{ op }}</option>
+      {[ }); ]}
+    </select>
+
+    <input type="text" name="val">
+  </div>
+</script>
+
 <script id="favoriteFilterTemplate" type="text/template">
   <div class="navigator-filter-favorite-toggle"></div>
 </script>
diff --git a/sonar-server/src/main/webapp/javascripts/navigator/filters/metric-filters.js b/sonar-server/src/main/webapp/javascripts/navigator/filters/metric-filters.js
new file mode 100644 (file)
index 0000000..e070a1c
--- /dev/null
@@ -0,0 +1,137 @@
+/* global _:false, $j:false */
+
+window.SS = typeof window.SS === 'object' ? window.SS : {};
+
+(function() {
+
+  var DetailsMetricFilterView = window.SS.DetailsFilterView.extend({
+    template: '#metricFilterTemplate',
+
+
+    events: {
+      'change :input': 'inputChanged'
+    },
+
+
+    inputChanged: function() {
+      var value = {
+        metric: this.$('[name=metric]').val(),
+        metricText: this.$('[name=metric] option:selected').text(),
+        period: this.$('[name=period]').val(),
+        periodText: this.$('[name=period] option:selected').text(),
+        op: this.$('[name=op]').val(),
+        opText: this.$('[name=op] option:selected').text(),
+        val: this.$('[name=val]').val()
+      };
+      this.model.set('value', value);
+    },
+
+
+    onRender: function() {
+      var value = this.model.get('value') || {};
+      this.$('[name=metric]').val(value.metric);
+      this.$('[name=period]').val(value.period);
+      this.$('[name=op]').val(value.op);
+      this.$('[name=val]').val(value.val);
+      this.inputChanged();
+    }
+
+  });
+
+
+
+  var MetricFilterView = window.SS.BaseFilterView.extend({
+
+    initialize: function() {
+      window.SS.BaseFilterView.prototype.initialize.call(this, {
+        detailsView: DetailsMetricFilterView
+      });
+
+      this.groupMetrics();
+    },
+
+
+    groupMetrics: function() {
+      var metrics = _.map(this.model.get('metrics'), function (metric) {
+            return metric.metric;
+          }),
+          groupedMetrics =
+              _.sortBy(
+                  _.map(
+                      _.groupBy(metrics, 'domain'),
+                      function (metrics, domain) {
+                        return {
+                          domain: domain,
+                          metrics: _.sortBy(metrics, 'short_name')
+                        };
+                      }),
+                  'domain'
+              );
+      this.model.set('groupedMetrics', groupedMetrics);
+    },
+
+
+    renderValue: function() {
+      return this.isDefaultValue() ?
+          'Not set' :
+          this.model.get('value').metricText + ' ' + this.model.get('value').opText + ' ' + this.model.get('value').val;
+    },
+
+
+    renderInput: function() {
+      var that = this,
+          value = this.model.get('value') || {};
+      _.each(value, function(v, k) {
+
+        $j('<input>')
+            .prop('name', that.model.get('property') + '_' + k)
+            .prop('type', 'hidden')
+            .css('display', 'none')
+            .val(v)
+            .appendTo(that.$el);
+      });
+    },
+
+
+    isDefaultValue: function() {
+      var value = this.model.get('value');
+      if (!_.isObject(value)) {
+        return true;
+      }
+      return !(value.metric && value.period && value.op && value.val);
+    },
+
+
+    restoreFromQuery: function(q) {
+      var that = this,
+          value = {};
+      _.each(['metric', 'period', 'op', 'val'], function(p) {
+        var property = that.model.get('property') + '_' + p,
+            pValue = _.findWhere(q, { key: property });
+
+        if (pValue.value) {
+          value[p] = pValue.value;
+        }
+      });
+
+      if (value && value.metric && value.period && value.op && value.val) {
+        this.model.set({
+          value: value,
+          enabled: true
+        });
+      }
+    }
+
+  });
+
+
+
+  /*
+   * Export public classes
+   */
+
+  _.extend(window.SS, {
+    MetricFilterView: MetricFilterView
+  });
+
+})();
index 4612850a6794dc8db6588fd0b0cf27792aaecfee..388a0089dea53796a20c917a2eac2c45bc7c7202 100644 (file)
@@ -116,6 +116,39 @@ window.SS = typeof window.SS === 'object' ? window.SS : {};
         type: window.SS.StringFilterView,
         enabled: false,
         optional: true
+      }),
+
+      new window.SS.Filter({
+        name: 'Metric',
+        property: 'c3',
+        type: window.SS.MetricFilterView,
+        metrics: window.SS.metrics,
+        periods: window.SS.metricPeriods,
+        operations: { 'eq': '=', 'lt': '<', 'lte': '≤', 'gt': '>', 'gte': '≥' },
+        enabled: false,
+        optional: true
+      }),
+
+      new window.SS.Filter({
+        name: 'Metric',
+        property: 'c2',
+        type: window.SS.MetricFilterView,
+        metrics: window.SS.metrics,
+        periods: window.SS.metricPeriods,
+        operations: { 'eq': '=', 'lt': '<', 'lte': '≤', 'gt': '>', 'gte': '≥' },
+        enabled: false,
+        optional: true
+      }),
+
+      new window.SS.Filter({
+        name: 'Metric',
+        property: 'c1',
+        type: window.SS.MetricFilterView,
+        metrics: window.SS.metrics,
+        periods: window.SS.metricPeriods,
+        operations: { 'eq': '=', 'lt': '<', 'lte': '≤', 'gt': '>', 'gte': '≥' },
+        enabled: false,
+        optional: true
       })
     ]);
 
index 023b57618bd576864bf48af098ee25171763581c..c029246d1eeb1a019dde03cb1413beb5e43cd241 100644 (file)
   display: block;
 }
 .navigator-filter-details-inner {
+  max-width: 300px;
   padding: 5px 10px;
 }
+.navigator-filter-details-inner select {
+  display: block;
+}
 .navigator-filter-select-list {
   min-width: 150px;
   max-width: 300px;
index 504733eb74bdf41565ed22346ca67c3adcd20f24..be4b6b921d3e2aa3da30fe118929cd5ecccbf6bd 100644 (file)
 }
 
 .navigator-filter-details-inner {
+  max-width: 300px;
   padding: 5px @navigatorFilterPadding;
+
+  select {
+    display: block;
+  }
 }
 
 .navigator-filter-select-list {
index 7ac0b8897e3b3aead985519ac761c6a16a1a7734..56640c1c029b2c53a36e73d3a8bdafb9774ffdc2 100644 (file)
@@ -38,6 +38,7 @@
     <js>/javascripts/navigator/filters/range-filters.js</js>
     <js>/javascripts/navigator/filters/checkbox-filters.js</js>
     <js>/javascripts/navigator/filters/string-filters.js</js>
+    <js>/javascripts/navigator/filters/metric-filters.js</js>
     <js>/javascripts/navigator/filters/favorite-filters.js</js>
     <js>/javascripts/navigator/filters/more-criteria-filters.js</js>
     <js>/javascripts/navigator/issues-app.js</js>