]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6668 update issue filters widgets to display the technical debt
authorStas Vilchik <vilchiks@gmail.com>
Mon, 29 Jun 2015 11:21:37 +0000 (13:21 +0200)
committerStas Vilchik <vilchiks@gmail.com>
Mon, 29 Jun 2015 12:49:35 +0000 (14:49 +0200)
18 files changed:
server/sonar-server/src/main/java/org/sonar/server/dashboard/widget/IssueFilterWidget.java
server/sonar-server/src/main/java/org/sonar/server/dashboard/widget/ProjectIssueFilterWidget.java
server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/issue_filter.html.erb
server/sonar-server/src/main/resources/org/sonar/server/dashboard/widget/project_issue_filter.html.erb
server/sonar-web/src/main/js/widgets/issue-filter/templates/_widget-issue-filter-total.hbs
server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-action-plans.hbs
server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-assignees.hbs
server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-resolutions.hbs
server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-severities.hbs
server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter-statuses.hbs
server/sonar-web/src/main/js/widgets/issue-filter/templates/widget-issue-filter.hbs
server/sonar-web/src/main/js/widgets/issue-filter/widget.js
server/sonar-web/src/test/js/global-issue-filter-widget.js
server/sonar-web/src/test/js/project-issue-filter-widget.js
server/sonar-web/src/test/json/global-issues-filter-widget/messages.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-debt.json [new file with mode: 0644]
server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity-debt.json [new file with mode: 0644]
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index d3bc92a44a5d7c542b73f23ac8628fdf95c3486d..f8042223c79866d0f32cbcc76a568c34a29b8ed5 100644 (file)
@@ -34,13 +34,15 @@ import static org.sonar.api.web.WidgetScope.GLOBAL;
   @WidgetProperty(key = IssueFilterWidget.DISTRIBUTION_AXIS_PROPERTY, type = WidgetPropertyType.SINGLE_SELECT_LIST, defaultValue = "severities",
     options = {"severities", "resolutions", "statuses", "rules", "tags", "projectUuids", "assignees", "reporters",
       "authors", "languages", "actionPlans", "createdAt"}),
-  @WidgetProperty(key = IssueFilterWidget.DISPLAY_FILTER_DESCRIPTION, type = WidgetPropertyType.BOOLEAN, defaultValue = "false")
+  @WidgetProperty(key = IssueFilterWidget.DISPLAY_FILTER_DESCRIPTION, type = WidgetPropertyType.BOOLEAN, defaultValue = "false"),
+  @WidgetProperty(key = IssueFilterWidget.DISPLAY_MODE, type = WidgetPropertyType.SINGLE_SELECT_LIST, defaultValue = "count", options = {"count", "debt"})
 })
 public class IssueFilterWidget extends CoreWidget {
 
   public static final String FILTER_PROPERTY = "filter";
   public static final String DISTRIBUTION_AXIS_PROPERTY = "distributionAxis";
   public static final String DISPLAY_FILTER_DESCRIPTION = "displayFilterDescription";
+  public static final String DISPLAY_MODE = "displayMode";
   public static final String ID = "issue_filter";
 
   public IssueFilterWidget() {
index 3f4f1ff9275b296cf3162a6eaa525605f579c4ad..6ac66e77d0a7f23fc955e424f71a04cfcf6891fb 100644 (file)
@@ -34,13 +34,15 @@ import static org.sonar.api.web.WidgetScope.PROJECT;
   @WidgetProperty(key = ProjectIssueFilterWidget.DISTRIBUTION_AXIS_PROPERTY, type = WidgetPropertyType.SINGLE_SELECT_LIST, defaultValue = "severities",
     options = {"severities", "resolutions", "statuses", "rules", "tags", "assignees", "reporters", "authors",
       "languages", "actionPlans", "createdAt"}),
-  @WidgetProperty(key = ProjectIssueFilterWidget.DISPLAY_FILTER_DESCRIPTION, type = WidgetPropertyType.BOOLEAN, defaultValue = "false")
+  @WidgetProperty(key = ProjectIssueFilterWidget.DISPLAY_FILTER_DESCRIPTION, type = WidgetPropertyType.BOOLEAN, defaultValue = "false"),
+  @WidgetProperty(key = ProjectIssueFilterWidget.DISPLAY_MODE, type = WidgetPropertyType.SINGLE_SELECT_LIST, defaultValue = "count", options = {"count", "debt"})
 })
 public class ProjectIssueFilterWidget extends CoreWidget {
 
   public static final String FILTER_PROPERTY = "filter";
   public static final String DISTRIBUTION_AXIS_PROPERTY = "distributionAxis";
   public static final String DISPLAY_FILTER_DESCRIPTION = "displayFilterDescription";
+  public static final String DISPLAY_MODE = "displayMode";
   public static final String ID = "project_issue_filter";
 
   public ProjectIssueFilterWidget() {
index f70e79ec85ba72f64f592f9d016e6b16ff2db870..5523fbfd11e6e82d96835818326d2df1703db0ad 100644 (file)
@@ -3,6 +3,7 @@
    filter_id = widget_properties['filter']
    filter = Internal.issues.findIssueFilterById(filter_id.to_i)
    distribution_axis = widget_properties['distributionAxis']
+   display_mode = widget_properties['displayMode']
    is_enough_permissions = filter.shared || (current_user && filter.userLogin == current_user.login)
 %>
 
@@ -32,7 +33,8 @@
             new IssueFilter({
               el: '#<%= container_id -%>',
               query: query,
-              distributionAxis: '<%= distribution_axis -%>'
+              distributionAxis: '<%= distribution_axis -%>',
+              displayMode: '<%= display_mode -%>'
             });
           });
         });
index 16edb8192d11e78e60d10cf11da92e91b4267f7c..0815b95e88e150bc1b17495ca2a2c5fe1f6a89ee 100644 (file)
@@ -3,6 +3,7 @@
    filter_id = widget_properties['filter']
    filter = Internal.issues.findIssueFilterById(filter_id.to_i)
    distribution_axis = widget_properties['distributionAxis']
+   display_mode = widget_properties['displayMode']
    is_enough_permissions = filter.shared || (current_user && filter.userLogin == current_user.login)
 
    if @dashboard_configuration.selected_period?
@@ -39,6 +40,7 @@
               el: '#<%= container_id -%>',
               query: query,
               distributionAxis: '<%= distribution_axis -%>',
+              displayMode: '<%= display_mode -%>',
               <% if period_date %>
               periodDate: '<%= period_date -%>',
               <% end %>
index 03fb4134f4a42dca04a14f92103def907b57c72e..376ea5611dec12e56c354f8515481cfe7bbc7f70 100644 (file)
@@ -1,8 +1,10 @@
 <tr>
   <td>
-    <a href="{{issueFilterTotalLink parsedQuery}}"><strong>{{t 'total'}}</strong></a>
+    <a href="{{issueFilterTotalLink parsedQuery displayMode}}"><strong>{{t 'total'}}</strong></a>
+  </td>
+  <td class="text-right nowrap">
+    <strong>{{#notNull periodDate}}+{{/notNull}}{{issueFilterValue total displayMode}}</strong>
   </td>
-  <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{numberShort total}}</strong></td>
   <td class="barchart">
     <div class="barchart" style="width: 100%;">
       <div style="width: 100%;"></div>
index 07c9b17f40cc0278a8dbbad43612fe24bb02c9ef..b5c932831940aaa2d510d6863b5029684e469315 100644 (file)
@@ -4,13 +4,13 @@
     <tr>
       <td>
         {{#eq val ''}}
-          <a href="{{issueFilterItemLink ../../parsedQuery 'planned' 'false'}}">{{t 'issue.unplanned'}}</a>
+          <a href="{{issueFilterItemLink ../../parsedQuery 'planned' 'false' ../../displayMode}}">{{t 'issue.unplanned'}}</a>
         {{else}}
-          <a href="{{issueFilterItemLink ../../parsedQuery 'actionPlans' val}}">{{default label val}}</a>
+          <a href="{{issueFilterItemLink ../../parsedQuery 'actionPlans' val ../../displayMode}}">{{default label val}}</a>
         {{/eq}}
       </td>
       <td class="text-right nowrap">
-        {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+        {{#notNull ../periodDate}}+{{/notNull}}{{issueFilterValue count ../displayMode}}
       </td>
       <td class="barchart">
         <div class="barchart" style="width: 100%;">
index 494104f3ee93deabbed3639a20a54335ad2aafbd..aef7f8fc9f6088d1e19ad12570ddb85248bbde99 100644 (file)
@@ -4,13 +4,13 @@
     <tr>
       <td>
         {{#eq val ''}}
-          <a href="{{issueFilterItemLink ../../parsedQuery 'assigned' 'false'}}">{{t 'unassigned'}}</a>
+          <a href="{{issueFilterItemLink ../../parsedQuery 'assigned' 'false' ../../displayMode}}">{{t 'unassigned'}}</a>
         {{else}}
-          <a href="{{issueFilterItemLink ../../parsedQuery 'assignees' val}}">{{default label val}}</a>
+          <a href="{{issueFilterItemLink ../../parsedQuery 'assignees' val ../../displayMode}}">{{default label val}}</a>
         {{/eq}}
       </td>
       <td class="text-right nowrap">
-        {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+        {{#notNull ../periodDate}}+{{/notNull}}{{issueFilterValue count ../displayMode}}
       </td>
       <td class="barchart">
         <div class="barchart" style="width: 100%;">
index 50827ba41bbcc209f11f15c32e8749f9a51b5f1b..5d8d6c2554d2b32cda18e84795e9cdbf59110689 100644 (file)
@@ -4,13 +4,13 @@
     <tr>
       <td>
         {{#eq val ''}}
-          <a href="{{issueFilterItemLink ../../parsedQuery 'resolved' 'false'}}">{{t 'unresolved'}}</a>
+          <a href="{{issueFilterItemLink ../../parsedQuery 'resolved' 'false' ../../displayMode}}">{{t 'unresolved'}}</a>
         {{else}}
-          <a href="{{issueFilterItemLink ../../parsedQuery 'resolutions' val}}">{{t 'issue.resolution' val}}</a>
+          <a href="{{issueFilterItemLink ../../parsedQuery 'resolutions' val ../../displayMode}}">{{t 'issue.resolution' val}}</a>
         {{/eq}}
       </td>
       <td class="text-right nowrap">
-        {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+        {{#notNull ../periodDate}}+{{/notNull}}{{issueFilterValue count ../displayMode}}
       </td>
       <td class="barchart">
         <div class="barchart" style="width: 100%;">
index 3ca50c03da560f8dae8086d9c2b0b4ea401aba25..a292b57e2b90a232a09fd8a8c859c6191aa3c03c 100644 (file)
@@ -1,18 +1,18 @@
 <table class="data zebra">
   <tr>
     <td>
-      <a href="{{issueFilterTotalLink parsedQuery}}"><strong>{{t 'total'}}</strong></a>
+      <a href="{{issueFilterTotalLink parsedQuery displayMode}}"><strong>{{t 'total'}}</strong></a>
     </td>
-    <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{numberShort total}}</strong></td>
+    <td class="text-right"><strong>{{#notNull periodDate}}+{{/notNull}}{{issueFilterValue total displayMode}}</strong></td>
   </tr>
   {{#each items}}
     <tr>
       <td>
         {{severityIcon val}}
-        <a href="{{issueFilterItemLink ../parsedQuery ../property val}}">{{t 'severity' val}}</a>
+        <a href="{{issueFilterItemLink ../parsedQuery ../property val ../displayMode}}">{{t 'severity' val}}</a>
       </td>
       <td class="text-right nowrap">
-        {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+        {{#notNull ../periodDate}}+{{/notNull}}{{issueFilterValue count ../displayMode}}
       </td>
     </tr>
   {{/each}}
index 70d5a57c76524d9169ba584c9adfae487ef17ec4..a661cd7ff3d764afe212a62dac99de54e023199d 100644 (file)
@@ -4,10 +4,10 @@
     <tr>
       <td>
         {{statusIcon val}}
-        <a href="{{issueFilterItemLink ../parsedQuery ../property val}}">{{t 'issue.status' val}}</a>
+        <a href="{{issueFilterItemLink ../parsedQuery ../property val ../displayMode}}">{{t 'issue.status' val}}</a>
       </td>
       <td class="text-right nowrap">
-        {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+        {{#notNull ../periodDate}}+{{/notNull}}{{issueFilterValue count ../displayMode}}
       </td>
       <td class="barchart">
         <div class="barchart" style="width: 100%;">
index dc78bba0232ba732a08321824f6052866ad3da20..b92cf91f9958c1850c394c8acc97bcafd0b3f82c 100644 (file)
@@ -6,7 +6,7 @@
         <a href="{{searchLink}}">{{default label val}}</a>
       </td>
       <td class="text-right nowrap">
-        {{#notNull ../periodDate}}+{{/notNull}}{{numberShort count}}
+        {{#notNull ../periodDate}}+{{/notNull}}{{issueFilterValue count ../displayMode}}
       </td>
       <td class="barchart">
         <div class="barchart" style="width: 100%;">
index 2fb96c7d2e70ba6e63b804b3140f13349da15eb0..97c72ca75a16b9fe033514d50f8ce18dc5a8c4d1 100644 (file)
@@ -32,10 +32,13 @@ define(['./templates'], function () {
       defaultLabel = function (item) {
         return item.val;
       },
-      defaultLink = function (item, property, query) {
+      defaultLink = function (item, property, query, index, items, mode) {
         var criterion = {};
         criterion[property] = item.val;
         var r = _.extend({}, query, criterion);
+        if (mode === 'debt') {
+          r.facetMode = 'debt';
+        }
         if (r.componentKey != null) {
           return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
               '#' + getQuery(_.omit(r, 'componentKey'));
@@ -164,7 +167,7 @@ define(['./templates'], function () {
                 isSameDay = ending.diff(beginning, 'days') <= 1;
             return beginning.format('LL') + (isSameDay ? '' : (' â€“ ' + ending.format('LL')));
           },
-          link: function (item, property, query, index, items) {
+          link: function (item, property, query, index, items, mode) {
             var createdAfter = moment(item.val),
                 endDate = query.createdBefore != null ? moment(query.createdBefore) : moment(),
                 createdBefore = index < items.length - 1 ? moment(items[index + 1].val).subtract(1, 'days') : endDate,
@@ -176,6 +179,9 @@ define(['./templates'], function () {
               createdAfter: createdAfter.format('YYYY-MM-DD'),
               createdBefore: createdBefore.format('YYYY-MM-DD')
             });
+            if (mode === 'debt') {
+              r.facetMode = 'debt';
+            }
             if (r.componentKey != null) {
               return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
                   '#' + getQuery(_.omit(r, 'componentKey'));
@@ -195,10 +201,13 @@ define(['./templates'], function () {
     return route.join(separator);
   }
 
-  Handlebars.registerHelper('issueFilterItemLink', function (query, property, value) {
+  Handlebars.registerHelper('issueFilterItemLink', function (query, property, value, mode) {
     var criterion = {};
     criterion[property] = value;
     var r = _.extend({}, query, criterion);
+    if (mode === 'debt') {
+      r.facetMode = 'debt';
+    }
     if (r.componentKey != null) {
       return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
           '#' + getQuery(_.omit(r, 'componentKey'));
@@ -207,8 +216,11 @@ define(['./templates'], function () {
     }
   });
 
-  Handlebars.registerHelper('issueFilterTotalLink', function (query) {
+  Handlebars.registerHelper('issueFilterTotalLink', function (query, mode) {
     var r = _.extend({}, query);
+    if (mode === 'debt') {
+      r.facetMode = 'debt';
+    }
     if (r.componentKey != null) {
       return baseUrl + '/component_issues/index?id=' + encodeURIComponent(r.componentKey) +
           '#' + getQuery(_.omit(r, 'componentKey'));
@@ -217,6 +229,11 @@ define(['./templates'], function () {
     }
   });
 
+  Handlebars.registerHelper('issueFilterValue', function (value, mode) {
+    var formatter = mode === 'debt' ? 'SHORT_WORK_DUR' : 'SHORT_INT';
+    return window.formatMeasure(value, formatter);
+  });
+
   return Marionette.ItemView.extend({
 
     getTemplate: function () {
@@ -284,9 +301,10 @@ define(['./templates'], function () {
     withLink: function (items) {
       var link = this.conf != null && this.conf.link != null ? this.conf.link : defaultLink,
           property = this.options.distributionAxis,
+          mode = this.options.displayMode,
           query = this.model.get('parsedQuery');
       return items.map(function (item, index) {
-        return _.extend(item, { searchLink: link(item, property, query, index, items) });
+        return _.extend(item, { searchLink: link(item, property, query, index, items, mode) });
       });
     },
 
@@ -301,10 +319,12 @@ define(['./templates'], function () {
 
     requestIssues: function () {
       var that = this,
+          facetMode = this.options.displayMode,
           url = baseUrl + '/api/issues/search',
           options = _.extend({}, this.query, {
             ps: 1,
-            facets: this.options.distributionAxis
+            facets: this.options.distributionAxis,
+            facetMode: facetMode
           });
       if (this.options.componentUuid != null) {
         _.extend(options, { componentUuids: this.options.componentUuid });
@@ -321,10 +341,14 @@ define(['./templates'], function () {
             items: items,
             maxResultsReached: items.length >= FACET_LIMIT,
             maxResults: items.length,
-            total: r.total
+            total: facetMode === 'debt' ? r.debtTotal : r.total
           });
         }
       });
+    },
+
+    serializeData: function () {
+      return _.extend(this._super(), { displayMode: this.options.displayMode });
     }
   });
 
index 5cf3863ccdb2a319951e8a20f49f71fce40211e6..eedd5f275fcb693a275bf40b454f9c9a95f94baa 100644 (file)
@@ -61,12 +61,12 @@ casper.test.begin(testName('Unresolved Issues By Severity'), 13, function (test)
         test.assertElementCount('tr', 6);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
         test.assertSelectorContains('tr:nth-child(2)', '1');
         test.assertSelectorContains('tr:nth-child(3)', '105');
-        test.assertSelectorContains('tr:nth-child(4)', '5,027');
+        test.assertSelectorContains('tr:nth-child(4)', '5k');
         test.assertSelectorContains('tr:nth-child(5)', '540');
-        test.assertSelectorContains('tr:nth-child(6)', '1,178');
+        test.assertSelectorContains('tr:nth-child(6)', '1.2k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
@@ -120,10 +120,10 @@ casper.test.begin(testName('Red Issues By Severity'), 9, function (test) {
         test.assertElementCount('tr', 4);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
         test.assertSelectorContains('tr:nth-child(2)', '1');
         test.assertSelectorContains('tr:nth-child(3)', '105');
-        test.assertSelectorContains('tr:nth-child(4)', '5,027');
+        test.assertSelectorContains('tr:nth-child(4)', '5k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|severities=BLOCKER%2CCRITICAL%2CMAJOR"]');
@@ -174,12 +174,12 @@ casper.test.begin(testName('All Issues By Status'), 9, function (test) {
         test.assertElementCount('tr', 6);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '71.6k');
+        test.assertSelectorContains('tr:nth-child(1)', '72k');
         test.assertSelectorContains('tr:nth-child(2)', '238');
         test.assertSelectorContains('tr:nth-child(3)', '4');
-        test.assertSelectorContains('tr:nth-child(4)', '6,609');
-        test.assertSelectorContains('tr:nth-child(5)', '1,307');
-        test.assertSelectorContains('tr:nth-child(6)', '63.4k');
+        test.assertSelectorContains('tr:nth-child(4)', '6.6k');
+        test.assertSelectorContains('tr:nth-child(5)', '1.3k');
+        test.assertSelectorContains('tr:nth-child(6)', '63k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#"]');
@@ -229,10 +229,10 @@ casper.test.begin(testName('Unresolved Issues By Status'), 9, function (test) {
         test.assertElementCount('tr', 4);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '71.6k');
+        test.assertSelectorContains('tr:nth-child(1)', '72k');
         test.assertSelectorContains('tr:nth-child(2)', '238');
         test.assertSelectorContains('tr:nth-child(3)', '4');
-        test.assertSelectorContains('tr:nth-child(4)', '6,609');
+        test.assertSelectorContains('tr:nth-child(4)', '6.6k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
@@ -283,12 +283,12 @@ casper.test.begin(testName('All Issues By Resolution'), 10, function (test) {
         test.assertElementCount('tr', 6);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '71.6k');
-        test.assertSelectorContains('tr:nth-child(2)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '72k');
+        test.assertSelectorContains('tr:nth-child(2)', '6.9k');
         test.assertSelectorContains('tr:nth-child(3)', '752');
         test.assertSelectorContains('tr:nth-child(4)', '550');
-        test.assertSelectorContains('tr:nth-child(5)', '47.1k');
-        test.assertSelectorContains('tr:nth-child(6)', '16.3k');
+        test.assertSelectorContains('tr:nth-child(5)', '47k');
+        test.assertSelectorContains('tr:nth-child(6)', '16k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#"]');
@@ -339,8 +339,8 @@ casper.test.begin(testName('Unresolved Issues By Resolution'), 5, function (test
         test.assertElementCount('tr', 2);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
-        test.assertSelectorContains('tr:nth-child(2)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
+        test.assertSelectorContains('tr:nth-child(2)', '6.9k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false"]');
@@ -390,7 +390,7 @@ casper.test.begin(testName('Unresolved Issues By Rule'), 15, function (test) {
         test.assertElementCount('tr', 16);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
         test.assertSelectorContains('tr:nth-child(2)', '879');
         test.assertSelectorContains('tr:nth-child(3)', '571');
         test.assertSelectorContains('tr:nth-child(15)', '113');
@@ -453,8 +453,8 @@ casper.test.begin(testName('Unresolved Issues By Project'), 15, function (test)
         test.assertElementCount('tr', 5);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '2,598');
-        test.assertSelectorContains('tr:nth-child(2)', '1,766');
+        test.assertSelectorContains('tr:nth-child(1)', '2.6k');
+        test.assertSelectorContains('tr:nth-child(2)', '1.8k');
         test.assertSelectorContains('tr:nth-child(3)', '442');
         test.assertSelectorContains('tr:nth-child(4)', '283');
         test.assertSelectorContains('tr:nth-child(5)', '107');
@@ -516,8 +516,8 @@ casper.test.begin(testName('Unresolved Issues By Assignee'), 15, function (test)
         test.assertElementCount('tr', 5);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
-        test.assertSelectorContains('tr:nth-child(2)', '4,134');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
+        test.assertSelectorContains('tr:nth-child(2)', '4.1k');
         test.assertSelectorContains('tr:nth-child(3)', '698');
         test.assertSelectorContains('tr:nth-child(4)', '504');
         test.assertSelectorContains('tr:nth-child(5)', '426');
@@ -579,8 +579,8 @@ casper.test.begin(testName('Unresolved Unassigned Issues By Assignee'), 6, funct
         test.assertElementCount('tr', 2);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '4,134');
-        test.assertSelectorContains('tr:nth-child(2)', '4,134');
+        test.assertSelectorContains('tr:nth-child(1)', '4.1k');
+        test.assertSelectorContains('tr:nth-child(2)', '4.1k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|assigned=false"]');
@@ -633,7 +633,7 @@ casper.test.begin(testName('Unresolved Issues By Reporter'), 12, function (test)
         test.assertElementCount('tr', 4);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
         test.assertSelectorContains('tr:nth-child(2)', '698');
         test.assertSelectorContains('tr:nth-child(3)', '504');
         test.assertSelectorContains('tr:nth-child(4)', '426');
@@ -693,8 +693,8 @@ casper.test.begin(testName('Unresolved Issues By Language'), 15, function (test)
         test.assertElementCount('tr', 5);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
-        test.assertSelectorContains('tr:nth-child(2)', '6,336');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
+        test.assertSelectorContains('tr:nth-child(2)', '6.3k');
         test.assertSelectorContains('tr:nth-child(3)', '444');
         test.assertSelectorContains('tr:nth-child(4)', '22');
         test.assertSelectorContains('tr:nth-child(5)', '15');
@@ -756,8 +756,8 @@ casper.test.begin(testName('Unresolved Issues By Action Plan'), 15, function (te
         test.assertElementCount('tr', 5);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
-        test.assertSelectorContains('tr:nth-child(2)', '5,877');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
+        test.assertSelectorContains('tr:nth-child(2)', '5.9k');
         test.assertSelectorContains('tr:nth-child(3)', '532');
         test.assertSelectorContains('tr:nth-child(4)', '56');
         test.assertSelectorContains('tr:nth-child(5)', '52');
@@ -819,8 +819,8 @@ casper.test.begin(testName('Unresolved Unplanned Issues By Action Plan'), 6, fun
         test.assertElementCount('tr', 2);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '5,877');
-        test.assertSelectorContains('tr:nth-child(2)', '5,877');
+        test.assertSelectorContains('tr:nth-child(1)', '5.9k');
+        test.assertSelectorContains('tr:nth-child(2)', '5.9k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|planned=false"]');
@@ -873,10 +873,10 @@ casper.test.begin(testName('Unresolved Issues By Date'), 18, function (test) {
         test.assertElementCount('tr', 6);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
-        test.assertSelectorContains('tr:nth-child(2)', '1,724');
-        test.assertSelectorContains('tr:nth-child(3)', '3,729');
-        test.assertSelectorContains('tr:nth-child(4)', '1,262');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
+        test.assertSelectorContains('tr:nth-child(2)', '1.7k');
+        test.assertSelectorContains('tr:nth-child(3)', '3.7k');
+        test.assertSelectorContains('tr:nth-child(4)', '1.3k');
         test.assertSelectorContains('tr:nth-child(5)', '64');
         test.assertSelectorContains('tr:nth-child(6)', '72');
 
@@ -941,7 +941,7 @@ casper.test.begin(testName('Unresolved Issues on a Limited Period By Date'), 12,
         test.assertElementCount('tr', 4);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
         test.assertSelectorContains('tr:nth-child(2)', '47');
         test.assertSelectorContains('tr:nth-child(3)', '48');
         test.assertSelectorContains('tr:nth-child(4)', '49');
@@ -966,3 +966,125 @@ casper.test.begin(testName('Unresolved Issues on a Limited Period By Date'), 12,
         test.done();
       });
 });
+
+
+casper.test.begin(testName('Unresolved Issues By Severity Displaying Debt'), 13, function (test) {
+  casper
+      .start(lib.buildUrl('base'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequestFromFile('/api/l10n/index', 'messages.json');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-severity-debt.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['widgets/issue-filter/widget'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#content',
+                query: 'resolved=false',
+                distributionAxis: 'severities',
+                displayMode: 'debt'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#content > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        test.assertSelectorContains('tr:nth-child(1)', '~ 14d');
+        test.assertSelectorContains('tr:nth-child(2)', '1min');
+        test.assertSelectorContains('tr:nth-child(3)', '~ 1h');
+        test.assertSelectorContains('tr:nth-child(4)', '~ 10d');
+        test.assertSelectorContains('tr:nth-child(5)', '~ 1d');
+        test.assertSelectorContains('tr:nth-child(6)', '~ 2d');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|facetMode=debt"]');
+        test.assertExists('tr:nth-child(2) a[href="/issues/search#resolved=false|severities=BLOCKER|facetMode=debt"]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|severities=CRITICAL|facetMode=debt"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|severities=MAJOR|facetMode=debt"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|severities=MINOR|facetMode=debt"]');
+        test.assertExists('tr:nth-child(6) a[href="/issues/search#resolved=false|severities=INFO|facetMode=debt"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
+
+
+casper.test.begin(testName('Unresolved Issues By Date Displaying Debt'), 13, function (test) {
+  casper
+      .start(lib.buildUrl('base'), function () {
+        lib.setDefaultViewport();
+
+        lib.mockRequestFromFile('/api/l10n/index', 'messages.json');
+        lib.mockRequestFromFile('/api/issues/search', 'unresolved-issues-by-date-debt.json',
+            { data: { resolved: 'false' } });
+      })
+
+      .then(function () {
+        casper.evaluate(function () {
+          require(['widgets/issue-filter/widget'], function (IssueFilter) {
+            window.requestMessages().done(function () {
+              new IssueFilter({
+                el: '#content',
+                query: 'resolved=false',
+                distributionAxis: 'createdAt',
+                displayMode: 'debt'
+              });
+            });
+          });
+        });
+      })
+
+      .then(function () {
+        casper.waitForSelector('#content > table');
+      })
+
+      .then(function () {
+        // check count
+        test.assertElementCount('tr', 6);
+
+        // check order and values
+        lib.capture();
+        test.assertSelectorContains('tr:nth-child(1)', '~ 14d');
+        test.assertSelectorContains('tr:nth-child(2)', '1min');
+        test.assertSelectorContains('tr:nth-child(3)', '~ 1h');
+        test.assertSelectorContains('tr:nth-child(4)', '~ 1d');
+        test.assertSelectorContains('tr:nth-child(5)', '~ 2d');
+        test.assertSelectorContains('tr:nth-child(6)', '~ 10d');
+
+        // check links
+        test.assertExists('tr:nth-child(1) a[href="/issues/search#resolved=false|facetMode=debt"]');
+        // do not check createdBefore value, because it is set dynamically to *now*
+        test.assertExists('tr:nth-child(2) a[href^="/issues/search#resolved=false|createdAfter=2015-01-01|createdBefore="]');
+        test.assertExists('tr:nth-child(3) a[href="/issues/search#resolved=false|createdAfter=2014-01-01|createdBefore=2014-12-31|facetMode=debt"]');
+        test.assertExists('tr:nth-child(4) a[href="/issues/search#resolved=false|createdAfter=2013-01-01|createdBefore=2013-12-31|facetMode=debt"]');
+        test.assertExists('tr:nth-child(5) a[href="/issues/search#resolved=false|createdAfter=2012-01-01|createdBefore=2012-12-31|facetMode=debt"]');
+        test.assertExists('tr:nth-child(6) a[href="/issues/search#resolved=false|createdAfter=2011-01-01|createdBefore=2011-12-31|facetMode=debt"]');
+      })
+
+      .then(function () {
+        lib.sendCoverage();
+      })
+
+      .run(function () {
+        test.done();
+      });
+});
index 8ec0127a1ad3cc1991368d9e730aff0c36c37617..2637edad29b8767d0f8a25a92b0e7bf4be553491 100644 (file)
@@ -63,12 +63,12 @@ casper.test.begin(testName('Unresolved Issues By Severity'), 13, function (test)
         test.assertElementCount('tr', 6);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
         test.assertSelectorContains('tr:nth-child(2)', '1');
         test.assertSelectorContains('tr:nth-child(3)', '105');
-        test.assertSelectorContains('tr:nth-child(4)', '5,027');
+        test.assertSelectorContains('tr:nth-child(4)', '5k');
         test.assertSelectorContains('tr:nth-child(5)', '540');
-        test.assertSelectorContains('tr:nth-child(6)', '1,178');
+        test.assertSelectorContains('tr:nth-child(6)', '1.2k');
 
         // check links
         test.assertExists('tr:nth-child(1) a[href="/component_issues/index?id=org.codehaus.sonar%3Asonar#resolved=false"]');
@@ -124,10 +124,10 @@ casper.test.begin(testName('Unresolved Issues By Date'), 18, function (test) {
         test.assertElementCount('tr', 6);
 
         // check order and values
-        test.assertSelectorContains('tr:nth-child(1)', '6,851');
-        test.assertSelectorContains('tr:nth-child(2)', '1,724');
-        test.assertSelectorContains('tr:nth-child(3)', '3,729');
-        test.assertSelectorContains('tr:nth-child(4)', '1,262');
+        test.assertSelectorContains('tr:nth-child(1)', '6.9k');
+        test.assertSelectorContains('tr:nth-child(2)', '1.7k');
+        test.assertSelectorContains('tr:nth-child(3)', '3.7k');
+        test.assertSelectorContains('tr:nth-child(4)', '1.3k');
         test.assertSelectorContains('tr:nth-child(5)', '64');
         test.assertSelectorContains('tr:nth-child(6)', '72');
 
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/messages.json b/server/sonar-web/src/test/json/global-issues-filter-widget/messages.json
new file mode 100644 (file)
index 0000000..4b2848c
--- /dev/null
@@ -0,0 +1,6 @@
+{
+  "work_duration.x_days": "{0}d",
+  "work_duration.x_hours": "{0}h",
+  "work_duration.x_minutes": "{0}min",
+  "work_duration.about": "~ {0}"
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-debt.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-date-debt.json
new file mode 100644 (file)
index 0000000..c1eb80c
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  "total": 6851,
+  "debtTotal": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "createdAt",
+      "values": [
+        {
+          "val": "2011-01-01T01:00:00+0000",
+          "count": 5027
+        },
+        {
+          "val": "2012-01-01T01:00:00+0000",
+          "count": 1178
+        },
+        {
+          "val": "2013-01-01T01:00:00+0000",
+          "count": 540
+        },
+        {
+          "val": "2014-01-01T01:00:00+0000",
+          "count": 105
+        },
+        {
+          "val": "2015-01-01T01:00:00+0000",
+          "count": 1
+        }
+      ]
+    }
+  ]
+}
diff --git a/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity-debt.json b/server/sonar-web/src/test/json/global-issues-filter-widget/unresolved-issues-by-severity-debt.json
new file mode 100644 (file)
index 0000000..15a51ee
--- /dev/null
@@ -0,0 +1,33 @@
+{
+  "total": 6851,
+  "debtTotal": 6851,
+  "p": 1,
+  "ps": 1,
+  "facets": [
+    {
+      "property": "severities",
+      "values": [
+        {
+          "val": "MAJOR",
+          "count": 5027
+        },
+        {
+          "val": "INFO",
+          "count": 1178
+        },
+        {
+          "val": "MINOR",
+          "count": 540
+        },
+        {
+          "val": "CRITICAL",
+          "count": 105
+        },
+        {
+          "val": "BLOCKER",
+          "count": 1
+        }
+      ]
+    }
+  ]
+}
index 0e762b376cc64ffdfdbc11654b2117e7485baa5b..4a98a79471eb8fe9d4f99090f8e41a3c16790369 100644 (file)
@@ -1338,6 +1338,7 @@ widget.issue_filter.description=Displays the result of a pre-configured issue fi
 widget.issue_filter.property.filter.name=Filter
 widget.issue_filter.property.distributionAxis.name=Distribution Axis
 widget.issue_filter.property.displayFilterDescription.name=Display Filter Description
+widget.issue_filter.property.displayMode.name=Display Mode
 widget.issue_filter.unknown_filter_warning=This widget is configured to display an issue filter that doesn't exist anymore.
 widget.issue_filter.insufficient_privileges_warning=Widget cannot be displayed: insufficient privileges.
 widget.issue_filter.property.distributionAxis.option.severities.name=By Severity
@@ -1352,12 +1353,15 @@ widget.issue_filter.property.distributionAxis.option.resolutions.name=By Resolut
 widget.issue_filter.property.distributionAxis.option.languages.name=By Language
 widget.issue_filter.property.distributionAxis.option.reporters.name=By Reporter
 widget.issue_filter.property.distributionAxis.option.authors.name=By Author
+widget.issue_filter.property.displayMode.option.count.name=Issues
+widget.issue_filter.property.displayMode.option.debt.name=Technical Debt
 
 widget.project_issue_filter.name=Project Issue Filter
 widget.project_issue_filter.description=Displays the result of a pre-configured issue filter applied to the project.
 widget.project_issue_filter.property.filter.name=Filter
 widget.project_issue_filter.property.distributionAxis.name=Distribution Axis
 widget.project_issue_filter.property.displayFilterDescription.name=Display Filter Description
+widget.project_issue_filter.property.displayMode.name=Display Mode
 widget.project_issue_filter.unknown_filter_warning=This widget is configured to display an issue filter that doesn't exist anymore.
 widget.project_issue_filter.insufficient_privileges_warning=Widget cannot be displayed: insufficient privileges.
 widget.project_issue_filter.property.distributionAxis.option.severities.name=By Severity
@@ -1371,6 +1375,8 @@ widget.project_issue_filter.property.distributionAxis.option.resolutions.name=By
 widget.project_issue_filter.property.distributionAxis.option.languages.name=By Language
 widget.project_issue_filter.property.distributionAxis.option.reporters.name=By Reporter
 widget.project_issue_filter.property.distributionAxis.option.authors.name=By Author
+widget.project_issue_filter.property.displayMode.option.count.name=Issues
+widget.project_issue_filter.property.displayMode.option.debt.name=Technical Debt
 
 widget.issue_tag_cloud.name=Project Issue Tag Cloud
 widget.issue_tag_cloud.title=Issue Tag Cloud