aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2015-06-26 16:09:24 +0200
committerStas Vilchik <vilchiks@gmail.com>2015-06-29 11:44:56 +0200
commit0bff1d5589852dae48dc65f68722290e3ceb5215 (patch)
treef44625486ed8a0c2c67755de36b5a395ca3ce29a
parent9849b523a2bcc018b84f5b11e0fb3e2bd5d3d13a (diff)
downloadsonarqube-0bff1d5589852dae48dc65f68722290e3ceb5215.tar.gz
sonarqube-0bff1d5589852dae48dc65f68722290e3ceb5215.zip
SONAR-6078 show debt on issues page
-rw-r--r--server/sonar-web/src/main/js/apps/issues/app-context.js3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/app-new.js3
-rw-r--r--server/sonar-web/src/main/js/apps/issues/facets-view.js8
-rw-r--r--server/sonar-web/src/main/js/apps/issues/facets/base-facet.js6
-rw-r--r--server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js5
-rw-r--r--server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js23
-rw-r--r--server/sonar-web/src/main/js/apps/issues/helpers/format-facet-value.js8
-rw-r--r--server/sonar-web/src/main/js/apps/issues/models/state.js12
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs8
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs12
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs5
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs14
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs8
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs4
-rw-r--r--server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs88
-rw-r--r--server/sonar-web/src/main/js/libs/application.js84
-rw-r--r--server/sonar-web/src/main/js/libs/graphics/barchart.js4
-rw-r--r--server/sonar-web/src/main/less/init/forms.less4
-rw-r--r--server/sonar-web/src/main/less/pages/issues.less5
-rw-r--r--server/sonar-web/src/test/js/application-spec.js20
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties1
24 files changed, 270 insertions, 67 deletions
diff --git a/server/sonar-web/src/main/js/apps/issues/app-context.js b/server/sonar-web/src/main/js/apps/issues/app-context.js
index ba15e720664..3d7db3aa2ef 100644
--- a/server/sonar-web/src/main/js/apps/issues/app-context.js
+++ b/server/sonar-web/src/main/js/apps/issues/app-context.js
@@ -8,7 +8,8 @@ define([
'./router',
'./workspace-list-view',
'./workspace-header-view',
- './facets-view'
+ './facets-view',
+ './helpers/format-facet-value'
], function (State, Layout, Issues, Facets, Filters, Controller, Router, WorkspaceListView, WorkspaceHeaderView,
FacetsView) {
diff --git a/server/sonar-web/src/main/js/apps/issues/app-new.js b/server/sonar-web/src/main/js/apps/issues/app-new.js
index 061903ae01f..12e5671c5c3 100644
--- a/server/sonar-web/src/main/js/apps/issues/app-new.js
+++ b/server/sonar-web/src/main/js/apps/issues/app-new.js
@@ -9,7 +9,8 @@ define([
'./workspace-list-view',
'./workspace-header-view',
'./facets-view',
- './filters-view'
+ './filters-view',
+ './helpers/format-facet-value'
], function (State, Layout, Issues, Facets, Filters, Controller, Router, WorkspaceListView, WorkspaceHeaderView,
FacetsView, FiltersView) {
diff --git a/server/sonar-web/src/main/js/apps/issues/facets-view.js b/server/sonar-web/src/main/js/apps/issues/facets-view.js
index 26477d4788c..fa715f902f7 100644
--- a/server/sonar-web/src/main/js/apps/issues/facets-view.js
+++ b/server/sonar-web/src/main/js/apps/issues/facets-view.js
@@ -16,10 +16,11 @@ define([
'./facets/language-facet',
'./facets/author-facet',
'./facets/issue-key-facet',
- './facets/context-facet'
+ './facets/context-facet',
+ './facets/mode-facet'
], function (FacetsView, BaseFacet, SeverityFacet, StatusFacet, ProjectFacet, ModuleFacet, AssigneeFacet, RuleFacet,
TagFacet, ResolutionFacet, CreationDateFacet, ActionPlanFacet, FileFacet, ReporterFacet, LanguageFacet,
- AuthorFacet, IssueKeyFacet, ContextFacet) {
+ AuthorFacet, IssueKeyFacet, ContextFacet, ModeFacet) {
var viewsMapping = {
severities: SeverityFacet,
@@ -37,7 +38,8 @@ define([
languages: LanguageFacet,
authors: AuthorFacet,
issues: IssueKeyFacet,
- context: ContextFacet
+ context: ContextFacet,
+ facetMode: ModeFacet
};
return FacetsView.extend({
diff --git a/server/sonar-web/src/main/js/apps/issues/facets/base-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/base-facet.js
index 4f7d9d8ea55..923e1d4e6d1 100644
--- a/server/sonar-web/src/main/js/apps/issues/facets/base-facet.js
+++ b/server/sonar-web/src/main/js/apps/issues/facets/base-facet.js
@@ -13,6 +13,12 @@ define([
onDestroy: function () {
return this.$('[data-toggle="tooltip"]').tooltip('destroy');
+ },
+
+ serializeData: function () {
+ return _.extend(this._super(), {
+ state: this.options.app.state.toJSON()
+ });
}
});
diff --git a/server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js
index 831cead6424..fbf81e94fbb 100644
--- a/server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js
+++ b/server/sonar-web/src/main/js/apps/issues/facets/creation-date-facet.js
@@ -47,6 +47,11 @@ define([
});
values.reverse();
}
+ values = values.map(function (v) {
+ var format = that.options.app.state.getFacetMode() === 'count' ? 'SHORT_INT' : 'SHORT_WORK_DUR';
+ var text = window.formatMeasure(v.count, format);
+ return _.extend(v, { text: text });
+ });
return this.$('.js-barchart').barchart(values);
},
diff --git a/server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js b/server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js
new file mode 100644
index 00000000000..454b4e96803
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/issues/facets/mode-facet.js
@@ -0,0 +1,23 @@
+define([
+ './base-facet',
+ '../templates'
+], function (BaseFacet) {
+
+ return BaseFacet.extend({
+ template: Templates['issues-mode-facet'],
+
+ events: {
+ 'change [name="issues-page-mode"]': 'onModeChange'
+ },
+
+ onModeChange: function () {
+ var mode = this.$('[name="issues-page-mode"]:checked').val();
+ this.options.app.state.updateFilter({ facetMode: mode });
+ },
+
+ serializeData: function () {
+ return _.extend(this._super(), { mode: this.options.app.state.getFacetMode() });
+ }
+ });
+
+});
diff --git a/server/sonar-web/src/main/js/apps/issues/helpers/format-facet-value.js b/server/sonar-web/src/main/js/apps/issues/helpers/format-facet-value.js
new file mode 100644
index 00000000000..b89d39ccef2
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/issues/helpers/format-facet-value.js
@@ -0,0 +1,8 @@
+define(function () {
+
+ Handlebars.registerHelper('formatFacetValue', function (value, facetMode) {
+ var formatter = facetMode === 'debt' ? 'SHORT_WORK_DUR' : 'SHORT_INT';
+ return window.formatMeasure(value, formatter);
+ });
+
+});
diff --git a/server/sonar-web/src/main/js/apps/issues/models/state.js b/server/sonar-web/src/main/js/apps/issues/models/state.js
index 38814d71111..246d27c24ca 100644
--- a/server/sonar-web/src/main/js/apps/issues/models/state.js
+++ b/server/sonar-web/src/main/js/apps/issues/models/state.js
@@ -7,9 +7,10 @@ define([
page: 1,
maxResultsReached: false,
query: {},
- facets: ['severities', 'resolutions'],
+ facets: ['facetMode', 'severities', 'resolutions'],
isContext: false,
allFacets: [
+ 'facetMode',
'issues',
'severities',
'resolutions',
@@ -52,6 +53,15 @@ define([
'createdAfter': 'createdAt',
'createdInLast': 'createdAt'
}
+ },
+
+ getFacetMode: function () {
+ var query = this.get('query');
+ return query.facetMode || 'count';
+ },
+
+ toJSON: function () {
+ return _.extend({ facetMode: this.getFacetMode() }, this.attributes);
}
});
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs
index fa6295586c8..25dace0c91f 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-action-plan-facet.hbs
@@ -6,12 +6,16 @@
{{! unplanned }}
<a class="facet search-navigator-facet js-facet" data-unplanned title="{{t "issue.unplanned"}}">
<span class="facet-name">{{t "issue.unplanned"}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{formatFacetValue count ../../state.facetMode}}
+ </span>
</a>
{{else}}
<a class="facet search-navigator-facet js-facet" data-value="{{val}}" title="{{label}}">
<span class="facet-name">{{label}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{formatFacetValue count ../../state.facetMode}}
+ </span>
</a>
{{/eq}}
{{/each}}
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs
index f3dcb4584d0..4121c2eee5c 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-assignee-facet.hbs
@@ -4,7 +4,9 @@
{{#notNull myIssues}}
<a class="facet search-navigator-facet js-facet" data-value="__me__" title="{{t "me"}}">
<span class="facet-name">{{t "me"}}</span>
- <span class="facet-stat">{{myIssues}}</span>
+ <span class="facet-stat">
+ {{formatFacetValue myIssues state.facetMode}}
+ </span>
</a>
<hr>
{{/notNull}}
@@ -14,12 +16,16 @@
{{! unassigned }}
<a class="facet search-navigator-facet js-facet" data-unassigned title="{{t "unassigned"}}">
<span class="facet-name">{{t "unassigned"}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{formatFacetValue count ../../state.facetMode}}
+ </span>
</a>
{{else}}
<a class="facet search-navigator-facet js-facet" data-value="{{val}}" title="{{label}}">
<span class="facet-name">{{label}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{formatFacetValue count ../../state.facetMode}}
+ </span>
</a>
{{/eq}}
{{/each}}
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs
index 61781221ddc..83442f81b37 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-base-facet.hbs
@@ -1,10 +1,11 @@
{{> "_issues-facet-header"}}
-
<div class="search-navigator-facet-list">
{{#each values}}
<a class="facet search-navigator-facet js-facet" data-value="{{val}}" title="{{default label val}}">
<span class="facet-name">{{default label val}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{formatFacetValue count ../state.facetMode}}
+ </span>
</a>
{{/each}}
</div>
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs
index 9f7f60d7fed..0674f5b87bb 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-custom-values-facet.hbs
@@ -4,7 +4,9 @@
{{#each values}}
<a class="facet search-navigator-facet js-facet" data-value="{{val}}" title="{{#if extra}}({{extra}}) {{/if}}{{default label val}}">
<span class="facet-name">{{default label val}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{#eq ../state.facetMode 'count'}}{{numberShort count}}{{else}}{{formatMeasure count 'SHORT_WORK_DUR'}}{{/eq}}
+ </span>
</a>
{{/each}}
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs
index 32cd2fe2c27..3569040b69c 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-file-facet.hbs
@@ -4,7 +4,9 @@
{{#each values}}
<a class="facet search-navigator-facet js-facet" data-value="{{val}}" title="{{default label val}}">
<span class="facet-name">{{default label val}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{#eq ../state.facetMode 'count'}}{{numberShort count}}{{else}}{{formatMeasure count 'SHORT_WORK_DUR'}}{{/eq}}
+ </span>
</a>
{{/each}}
</div>
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs
new file mode 100644
index 00000000000..ea2f7433c8b
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-mode-facet.hbs
@@ -0,0 +1,14 @@
+<div class="issues-facet-mode">
+ <ul class="radio-toggle">
+ <li>
+ <input type="radio" name="issues-page-mode" value="count" id="issues-page-mode-count"
+ {{#eq mode 'count'}}checked{{/eq}}>
+ <label for="issues-page-mode-count">Issues</label>
+ </li>
+ <li>
+ <input type="radio" name="issues-page-mode" value="debt" id="issues-page-mode-debt"
+ {{#eq mode 'debt'}}checked{{/eq}}>
+ <label for="issues-page-mode-debt">Debt</label>
+ </li>
+ </ul>
+</div>
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs
index 166b052f75f..19e47071f8b 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-resolution-facet.hbs
@@ -7,13 +7,17 @@
<a class="facet search-navigator-facet search-navigator-facet-half js-facet" data-unresolved
title="{{t "issue.unresolved.description"}}" data-toggle="tooltip" data-placement="right">
<span class="facet-name">{{t "unresolved"}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{#eq ../../state.facetMode 'count'}}{{numberShort count}}{{else}}{{formatMeasure count 'SHORT_WORK_DUR'}}{{/eq}}
+ </span>
</a>
{{else}}
<a class="facet search-navigator-facet search-navigator-facet-half js-facet" data-value="{{val}}"
title="{{t "issue.resolution" val "description"}}" data-toggle="tooltip" data-placement="right">
<span class="facet-name">{{t "issue.resolution" val}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{#eq ../../state.facetMode 'count'}}{{numberShort count}}{{else}}{{formatMeasure count 'SHORT_WORK_DUR'}}{{/eq}}
+ </span>
</a>
{{/eq}}
{{/each}}
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs
index 0d60fda358f..88b9bd0585b 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-severity-facet.hbs
@@ -5,7 +5,9 @@
<a class="facet search-navigator-facet search-navigator-facet-half js-facet"
data-value="{{val}}" title="{{t "severity" val "description"}}" data-toggle="tooltip" data-placement="right">
<span class="facet-name">{{severityIcon val}} {{t "severity" val}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{#eq ../state.facetMode 'count'}}{{numberShort count}}{{else}}{{formatMeasure count 'SHORT_WORK_DUR'}}{{/eq}}
+ </span>
</a>
{{/each}}
</div>
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs
index 8b74908d3cb..cc7f1fcefdb 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/facets/issues-status-facet.hbs
@@ -5,7 +5,9 @@
<a class="facet search-navigator-facet search-navigator-facet-half js-facet"
data-value="{{val}}" title="{{t "issue.status" val "description"}}" data-toggle="tooltip" data-placement="right">
<span class="facet-name">{{statusIcon val}} {{t "issue.status" val}}</span>
- <span class="facet-stat">{{numberShort count}}</span>
+ <span class="facet-stat">
+ {{#eq ../state.facetMode 'count'}}{{numberShort count}}{{else}}{{formatMeasure count 'SHORT_WORK_DUR'}}{{/eq}}
+ </span>
</a>
{{/each}}
</div>
diff --git a/server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs b/server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs
index 3feab6a89a5..c3ffd012a3a 100644
--- a/server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs
+++ b/server/sonar-web/src/main/js/apps/issues/templates/issues-filters.hbs
@@ -1,55 +1,57 @@
-<h1 class="page-title dropdown">
- {{#if state.canManageFilters}}
- <a class="search-navigator-filters-show-list dropdown-toggle" data-toggle="dropdown">
- <i class="icon-list"></i><span class="issues-filters-name">{{> "_issues-filter-name"}}</span>
- </a>
- <ul class="dropdown-menu">
- {{#each items}}
+{{#unless state.isContext}}
+ <h1 class="page-title dropdown">
+ {{#if state.canManageFilters}}
+ <a class="search-navigator-filters-show-list dropdown-toggle" data-toggle="dropdown">
+ <i class="icon-list"></i><span class="issues-filters-name">{{> "_issues-filter-name"}}</span>
+ </a>
+ <ul class="dropdown-menu">
+ {{#each items}}
+ <li>
+ <a class="search-navigator-filters-button search-navigator-filters-filter js-filter" data-id="{{id}}">
+ {{name}}
+ </a>
+ </li>
+ {{/each}}
+ {{#notEmpty items}}
+ <li class="divider"></li>
+ {{/notEmpty}}
<li>
- <a class="search-navigator-filters-button search-navigator-filters-filter js-filter" data-id="{{id}}">
- {{name}}
- </a>
+ <a class="search-navigator-filters-manage" href="{{link "/issues/manage"}}">{{t "manage"}}</a>
</li>
- {{/each}}
- {{#notEmpty items}}
- <li class="divider"></li>
- {{/notEmpty}}
- <li>
- <a class="search-navigator-filters-manage" href="{{link "/issues/manage"}}">{{t "manage"}}</a>
- </li>
- </ul>
- {{#if filter.description}}
- <div class="search-navigator-filters-description">{{filter.description}}</div>
+ </ul>
+ {{#if filter.description}}
+ <div class="search-navigator-filters-description">{{filter.description}}</div>
+ {{/if}}
+ {{else}}
+ <span class="search-navigator-filters-name">{{t "issues"}}</span>
{{/if}}
- {{else}}
- <span class="search-navigator-filters-name">{{t "issues"}}</span>
- {{/if}}
-</h1>
+ </h1>
-<div class="page-actions">
- <div class="button-group">
- {{#if state.canManageFilters}}
- {{#if filter.canModify}}
- {{#if state.changed}}
- <button class="js-filter-save" id="issues-filter-save">{{t "save"}}</button>
+ <div class="page-actions">
+ <div class="button-group">
+ {{#if state.canManageFilters}}
+ {{#if filter.canModify}}
+ {{#if state.changed}}
+ <button class="js-filter-save" id="issues-filter-save">{{t "save"}}</button>
+ {{/if}}
{{/if}}
- {{/if}}
-
- {{#unless filter.id}}
- <button class="js-filter-save-as" id="issues-filter-save-as">{{t "save_as"}}</button>
- {{/unless}}
- {{#if filter.id}}
- {{#unless state.changed}}
- <button class="js-filter-copy" id="issues-filter-copy">{{t "copy"}}</button>
+ {{#unless filter.id}}
+ <button class="js-filter-save-as" id="issues-filter-save-as">{{t "save_as"}}</button>
{{/unless}}
- {{/if}}
- {{#if filter.canModify}}
{{#if filter.id}}
- <button class="js-filter-edit" id="issues-filter-edit">{{t "edit"}}</button>
+ {{#unless state.changed}}
+ <button class="js-filter-copy" id="issues-filter-copy">{{t "copy"}}</button>
+ {{/unless}}
+ {{/if}}
+
+ {{#if filter.canModify}}
+ {{#if filter.id}}
+ <button class="js-filter-edit" id="issues-filter-edit">{{t "edit"}}</button>
+ {{/if}}
{{/if}}
{{/if}}
- {{/if}}
+ </div>
</div>
-</div>
+{{/unless}}
diff --git a/server/sonar-web/src/main/js/libs/application.js b/server/sonar-web/src/main/js/libs/application.js
index 6b7fc913488..fa006f7bacc 100644
--- a/server/sonar-web/src/main/js/libs/application.js
+++ b/server/sonar-web/src/main/js/libs/application.js
@@ -333,6 +333,16 @@ function closeModalWindow () {
}
/**
+ * Check if hours should be displayed for a work duration
+ * @param {number} days
+ * @param {number} hours
+ * @returns {boolean}
+ */
+ function shouldDisplayHoursInShortFormat (days, hours) {
+ return hours > 0 && days === 0;
+ }
+
+ /**
* Check if minutes should be displayed for a work duration
* @param {number} days
* @param {number} hours
@@ -344,6 +354,17 @@ function closeModalWindow () {
}
/**
+ * Check if minutes should be displayed for a work duration
+ * @param {number} days
+ * @param {number} hours
+ * @param {number} minutes
+ * @returns {boolean}
+ */
+ function shouldDisplayMinutesInShortFormat (days, hours, minutes) {
+ return minutes > 0 && hours === 0 && days === 0;
+ }
+
+ /**
* Add a space between units if needed
* @param {string} value
* @returns {string}
@@ -353,6 +374,21 @@ function closeModalWindow () {
}
/**
+ * Check if about sign be displayed for a work duration
+ * @param {number} days
+ * @param {number} hours
+ * @param {number} minutes
+ * @returns {boolean}
+ */
+ function shouldDisplayAbout (days, hours, minutes) {
+ var hasDays = days > 0,
+ fewDays = days < 1000,
+ hasHours = hours > 0,
+ hasMinutes = minutes > 0;
+ return (hasDays && fewDays && hasHours) || (!hasDays && hasHours && hasMinutes);
+ }
+
+ /**
* Format a work duration based on parameters
* @param {bool} isNegative
* @param {number} days
@@ -377,6 +413,34 @@ function closeModalWindow () {
}
/**
+ * Format a work duration based on parameters
+ * @param {bool} isNegative
+ * @param {number} days
+ * @param {number} hours
+ * @param {number} minutes
+ * @returns {string}
+ */
+ function formatDurationShort (isNegative, days, hours, minutes) {
+ var formatted = '';
+ if (shouldDisplayDays(days)) {
+ var formattedDays = window.formatMeasure(isNegative ? -1 * days : days, 'SHORT_INT');
+ formatted += tp('work_duration.x_days', formattedDays);
+ }
+ if (shouldDisplayHoursInShortFormat(days, hours)) {
+ formatted = addSpaceIfNeeded(formatted);
+ formatted += tp('work_duration.x_hours', isNegative && formatted.length === 0 ? -1 * hours : hours);
+ }
+ if (shouldDisplayMinutesInShortFormat(days, hours, minutes)) {
+ formatted = addSpaceIfNeeded(formatted);
+ formatted += tp('work_duration.x_minutes', isNegative && formatted.length === 0 ? -1 * minutes : minutes);
+ }
+ if (shouldDisplayAbout(days, hours, minutes)) {
+ formatted = tp('work_duration.about', formatted);
+ }
+ return formatted;
+ }
+
+ /**
* Format a work duration measure
* @param {number} value
* @returns {string}
@@ -396,6 +460,25 @@ function closeModalWindow () {
};
/**
+ * Format a work duration measure
+ * @param {number} value
+ * @returns {string}
+ */
+ var shortDurationFormatter = function (value) {
+ if (value === 0) {
+ return '0';
+ }
+ var hoursInDay = window.SS.hoursInDay || 8,
+ isNegative = value < 0,
+ absValue = Math.abs(value);
+ var days = Math.floor(absValue / hoursInDay / 60);
+ var remainingValue = absValue - days * hoursInDay * 60;
+ var hours = Math.floor(remainingValue / 60);
+ remainingValue -= hours * 60;
+ return formatDurationShort(isNegative, days, hours, remainingValue);
+ };
+
+ /**
* Format a work duration variation
* @param {number} value
*/
@@ -435,6 +518,7 @@ function closeModalWindow () {
return numeral(+value / 100).format('0,0.0%');
},
'WORK_DUR': durationFormatter,
+ 'SHORT_WORK_DUR': shortDurationFormatter,
'RATING': ratingFormatter
};
if (measure != null && type != null) {
diff --git a/server/sonar-web/src/main/js/libs/graphics/barchart.js b/server/sonar-web/src/main/js/libs/graphics/barchart.js
index c107a68661b..40f68eeb251 100644
--- a/server/sonar-web/src/main/js/libs/graphics/barchart.js
+++ b/server/sonar-web/src/main/js/libs/graphics/barchart.js
@@ -114,7 +114,7 @@
var beginning = moment(d.val),
ending = i < data.length - 1 ? moment(data[i + 1].val).subtract(1, 'days') : options.endDate,
isSameDay = ending.diff(beginning, 'days') <= 1;
- return d.count + '<br>' + beginning.format('LL') + (isSameDay ? '' : (' – ' + ending.format('LL')));
+ return d.text + '<br>' + beginning.format('LL') + (isSameDay ? '' : (' – ' + ending.format('LL')));
})
.attr('data-placement', 'bottom')
.attr('data-toggle', 'tooltip');
@@ -129,7 +129,7 @@
.attr('transform', trans(barWidth / 2, -4))
.style('text-anchor', 'middle')
.text(function (d) {
- var text = !isValueShown && d.count === maxValue ? d.count : '';
+ var text = !isValueShown && d.count === maxValue ? d.text : '';
isValueShown = d.count === maxValue;
return text;
});
diff --git a/server/sonar-web/src/main/less/init/forms.less b/server/sonar-web/src/main/less/init/forms.less
index 69dff8f62db..c08d01fea35 100644
--- a/server/sonar-web/src/main/less/init/forms.less
+++ b/server/sonar-web/src/main/less/init/forms.less
@@ -261,8 +261,8 @@ label[for] {
}
input[type="radio"]:checked + label {
- border-color: @blue;
- background-color: @blue;
+ border-color: @darkBlue;
+ background-color: @darkBlue;
color: #fff;
font-weight: 500;
}
diff --git a/server/sonar-web/src/main/less/pages/issues.less b/server/sonar-web/src/main/less/pages/issues.less
index bd32a0e3d8e..0f512c1ba6c 100644
--- a/server/sonar-web/src/main/less/pages/issues.less
+++ b/server/sonar-web/src/main/less/pages/issues.less
@@ -172,3 +172,8 @@
.box-sizing(border-box);
overflow: hidden;
}
+
+.issues-facet-mode {
+ padding: 8px 0;
+ text-align: center;
+}
diff --git a/server/sonar-web/src/test/js/application-spec.js b/server/sonar-web/src/test/js/application-spec.js
index 5b205cb4903..8cb1508f92b 100644
--- a/server/sonar-web/src/test/js/application-spec.js
+++ b/server/sonar-web/src/test/js/application-spec.js
@@ -100,7 +100,8 @@ casper.test.begin(testName('Format Measures'), function (test) {
window.messages = {
'work_duration.x_days': '{0}d',
'work_duration.x_hours': '{0}h',
- 'work_duration.x_minutes': '{0}min'
+ 'work_duration.x_minutes': '{0}min',
+ 'work_duration.about': '~ {0}'
};
window.hoursInDay = hoursInDay;
}, HOURS_IN_DAY);
@@ -154,6 +155,23 @@ casper.test.begin(testName('Format Measures'), function (test) {
test.assertEqual(formatMeasure(-2 * ONE_HOUR, 'WORK_DUR'), '-2h');
test.assertEqual(formatMeasure(-1 * ONE_MINUTE, 'WORK_DUR'), '-1min');
+ test.assertEqual(formatMeasure(0, 'SHORT_WORK_DUR'), '0');
+ test.assertEqual(formatMeasure(5 * ONE_DAY, 'SHORT_WORK_DUR'), '5d');
+ test.assertEqual(formatMeasure(2 * ONE_HOUR, 'SHORT_WORK_DUR'), '2h');
+ test.assertEqual(formatMeasure(ONE_MINUTE, 'SHORT_WORK_DUR'), '1min');
+ test.assertEqual(formatMeasure(5 * ONE_DAY + 2 * ONE_HOUR, 'SHORT_WORK_DUR'), '~ 5d');
+ test.assertEqual(formatMeasure(2 * ONE_HOUR + ONE_MINUTE, 'SHORT_WORK_DUR'), '~ 2h');
+ test.assertEqual(formatMeasure(5 * ONE_DAY + 2 * ONE_HOUR + ONE_MINUTE, 'SHORT_WORK_DUR'), '~ 5d');
+ test.assertEqual(formatMeasure(15 * ONE_DAY + 2 * ONE_HOUR + ONE_MINUTE, 'SHORT_WORK_DUR'), '~ 15d');
+ test.assertEqual(formatMeasure(7 * ONE_MINUTE, 'SHORT_WORK_DUR'), '7min');
+ test.assertEqual(formatMeasure(-5 * ONE_DAY, 'SHORT_WORK_DUR'), '-5d');
+ test.assertEqual(formatMeasure(-2 * ONE_HOUR, 'SHORT_WORK_DUR'), '-2h');
+ test.assertEqual(formatMeasure(-1 * ONE_MINUTE, 'SHORT_WORK_DUR'), '-1min');
+
+ test.assertEqual(formatMeasure(1529 * ONE_DAY, 'SHORT_WORK_DUR'), '1.5kd');
+ test.assertEqual(formatMeasure(1234567 * ONE_DAY, 'SHORT_WORK_DUR'), '1md');
+ test.assertEqual(formatMeasure(1234567 * ONE_DAY + 2 * ONE_HOUR, 'SHORT_WORK_DUR'), '1md');
+
test.assertEqual(formatMeasure(1, 'RATING'), 'A');
test.assertEqual(formatMeasure(2, 'RATING'), 'B');
test.assertEqual(formatMeasure(3, 'RATING'), 'C');
diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
index 5b5e55c9121..0e762b376cc 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -271,6 +271,7 @@ time_changes=Time changes
work_duration.x_days={0}d
work_duration.x_hours={0}h
work_duration.x_minutes={0}min
+work_duration.about=~ {0}
#------------------------------------------------------------------------------