aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2015-04-17 17:21:04 +0200
committerStas Vilchik <vilchiks@gmail.com>2015-04-17 17:21:23 +0200
commit20499b26a45114913f94387be92e9c473c5c7170 (patch)
treeaed0861c463bedaf9c7337d1c447d77c89a354d6
parentbf39b235e5d55f07a43707949129aee6a85dd4a3 (diff)
downloadsonarqube-20499b26a45114913f94387be92e9c473c5c7170.tar.gz
sonarqube-20499b26a45114913f94387be92e9c473c5c7170.zip
SONAR-6210 add a rule description in the workspace
-rw-r--r--server/sonar-web/src/main/coffee/issue/issue-view.coffee14
-rw-r--r--server/sonar-web/src/main/coffee/issue/views/rule-overlay.coffee35
-rw-r--r--server/sonar-web/src/main/hbs/workspace/workspace-item.hbs2
-rw-r--r--server/sonar-web/src/main/hbs/workspace/workspace-rule.hbs (renamed from server/sonar-web/src/main/hbs/issue/issue-rule.hbs)17
-rw-r--r--server/sonar-web/src/main/hbs/workspace/workspace-viewer-header.hbs2
-rw-r--r--server/sonar-web/src/main/js/common/handlebars-extensions.js6
-rw-r--r--server/sonar-web/src/main/js/workspace/main.js39
-rw-r--r--server/sonar-web/src/main/js/workspace/views/base-viewer-view.js57
-rw-r--r--server/sonar-web/src/main/js/workspace/views/rule-view.js40
-rw-r--r--server/sonar-web/src/main/js/workspace/views/viewer-view.js34
-rw-r--r--server/sonar-web/src/test/js/issues-page-spec.js42
-rw-r--r--server/sonar-web/src/test/js/workspace.js43
-rw-r--r--server/sonar-web/src/test/json/issues-spec/rule.json36
-rw-r--r--server/sonar-web/src/test/json/workspace/rule.json36
14 files changed, 305 insertions, 98 deletions
diff --git a/server/sonar-web/src/main/coffee/issue/issue-view.coffee b/server/sonar-web/src/main/coffee/issue/issue-view.coffee
index 457f0cffd59..bb2ea79d86b 100644
--- a/server/sonar-web/src/main/coffee/issue/issue-view.coffee
+++ b/server/sonar-web/src/main/coffee/issue/issue-view.coffee
@@ -32,9 +32,10 @@ define [
'issue/views/plan-form-view'
'issue/views/set-severity-form-view'
'issue/views/more-actions-view'
- 'issue/views/rule-overlay'
'issue/views/tags-form-view'
+ 'workspace/main'
+
'templates/issue'
], (
@@ -51,9 +52,10 @@ define [
PlanFormView
SetSeverityFormView
MoreActionsView
- RuleOverlay
TagsFormView
+ Workspace
+
) ->
$ = jQuery
@@ -261,12 +263,10 @@ define [
showRule: ->
+ unless Workspace?
+ Workspace = require 'workspace/main'
ruleKey = @model.get 'rule'
- $.get "#{baseUrl}/api/rules/show", key: ruleKey, (r) =>
- ruleOverlay = new RuleOverlay
- model: new Backbone.Model r.rule
- large: true
- ruleOverlay.render()
+ Workspace.openRule key: ruleKey
editTags: (e)->
diff --git a/server/sonar-web/src/main/coffee/issue/views/rule-overlay.coffee b/server/sonar-web/src/main/coffee/issue/views/rule-overlay.coffee
deleted file mode 100644
index c4dbc5a2fb3..00000000000
--- a/server/sonar-web/src/main/coffee/issue/views/rule-overlay.coffee
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# SonarQube, open source software quality management tool.
-# Copyright (C) 2008-2014 SonarSource
-# mailto:contact AT sonarsource DOT com
-#
-# SonarQube is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 3 of the License, or (at your option) any later version.
-#
-# SonarQube is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-
-define [
- 'common/modals'
- 'templates/issue'
-], (
- ModalView
-) ->
-
- class extends ModalView
- template: Templates['issue-rule']
-
-
- serializeData: ->
- _.extend super,
- permalink: "#{baseUrl}/coding_rules#rule_key=#{encodeURIComponent @model.get('key')}"
- allTags: _.union @model.get('sysTags'), @model.get('tags')
diff --git a/server/sonar-web/src/main/hbs/workspace/workspace-item.hbs b/server/sonar-web/src/main/hbs/workspace/workspace-item.hbs
index 24cf2862541..a4fb7a98661 100644
--- a/server/sonar-web/src/main/hbs/workspace/workspace-item.hbs
+++ b/server/sonar-web/src/main/hbs/workspace/workspace-item.hbs
@@ -2,6 +2,6 @@
{{qualifierIcon q}}
{{/if}}
-{{default name uuid}}
+{{limitString name}}
<button class="js-close button-clean" style="color: #fff;">&times;</button>
diff --git a/server/sonar-web/src/main/hbs/issue/issue-rule.hbs b/server/sonar-web/src/main/hbs/workspace/workspace-rule.hbs
index 2e11a623e9d..acdf14906c2 100644
--- a/server/sonar-web/src/main/hbs/issue/issue-rule.hbs
+++ b/server/sonar-web/src/main/hbs/workspace/workspace-rule.hbs
@@ -1,12 +1,6 @@
-<div class="modal-container">
- <h3 class="coding-rules-detail-header">
- {{name}}
- <a class="coding-rules-detail-permalink" target="_blank" href="{{permalink}}">
- <i class="icon-link"></i> {{t 'coding_rules.permalink'}}
- </a>
- </h3>
+<div class="workspace-viewer-header"></div>
- <span class="note">{{key}}</span>
+<div class="workspace-viewer-container">
<ul class="coding-rules-detail-properties">
<li class="coding-rules-detail-property coding-rules-detail-tag-list">
@@ -16,6 +10,9 @@
{{#if debtCharName}}
<li class="coding-rules-detail-property">{{debtCharName}}{{#if debtSubCharName}} > {{debtSubCharName}}{{/if}}</li>
{{/if}}
+ <li class="pull-right">
+ <a class="icon-link" target="_blank" href="{{rulePermalink key}}"></a>
+ </li>
</ul>
<div class="coding-rules-detail-description rule-desc markdown">{{{htmlDesc}}}</div>
@@ -26,7 +23,3 @@
</div>
{{/if}}
</div>
-
-<div class="modal-foot">
- <a class="js-modal-close" href="#">{{t 'close'}}</a>
-</div>
diff --git a/server/sonar-web/src/main/hbs/workspace/workspace-viewer-header.hbs b/server/sonar-web/src/main/hbs/workspace/workspace-viewer-header.hbs
index c6546fa7fd6..ef4971f6077 100644
--- a/server/sonar-web/src/main/hbs/workspace/workspace-viewer-header.hbs
+++ b/server/sonar-web/src/main/hbs/workspace/workspace-viewer-header.hbs
@@ -1,4 +1,4 @@
-<h6 class="workspace-viewer-name">{{qualifierIcon q}}&nbsp;{{name}}</h6>
+<h6 class="workspace-viewer-name">{{#if q}}{{qualifierIcon q}}&nbsp;{{/if}}{{name}}</h6>
<div class="workspace-viewer-resize js-resize"></div>
diff --git a/server/sonar-web/src/main/js/common/handlebars-extensions.js b/server/sonar-web/src/main/js/common/handlebars-extensions.js
index 158cf1ac898..83826c5de35 100644
--- a/server/sonar-web/src/main/js/common/handlebars-extensions.js
+++ b/server/sonar-web/src/main/js/common/handlebars-extensions.js
@@ -517,8 +517,10 @@
});
Handlebars.registerHelper('limitString', function (str) {
- var LIMIT = 30;
- return str.length > LIMIT ? str.substr(0, LIMIT) + '...' : str;
+ if (typeof str === 'string') {
+ var LIMIT = 30;
+ return str.length > LIMIT ? str.substr(0, LIMIT) + '...' : str;
+ }
});
Handlebars.registerHelper('withSign', function (number) {
diff --git a/server/sonar-web/src/main/js/workspace/main.js b/server/sonar-web/src/main/js/workspace/main.js
index a68efff25ba..594f8e783c2 100644
--- a/server/sonar-web/src/main/js/workspace/main.js
+++ b/server/sonar-web/src/main/js/workspace/main.js
@@ -21,8 +21,9 @@ define([
'workspace/models/item',
'workspace/models/items',
'workspace/views/items-view',
- 'workspace/views/viewer-view'
-], function (Item, Items, ItemsView, ViewerView) {
+ 'workspace/views/viewer-view',
+ 'workspace/views/rule-view'
+], function (Item, Items, ItemsView, ViewerView, RuleView) {
var $ = jQuery,
@@ -56,10 +57,6 @@ define([
this.items.save();
},
- load: function () {
- this.items.load();
- },
-
addComponent: function (model) {
if (!this.items.has(model)) {
this.items.add(model);
@@ -76,21 +73,26 @@ define([
if (model.isComponent()) {
this.showComponentViewer(model);
}
+ if (model.isRule()) {
+ this.showRule(model);
+ }
},
openComponent: function (options) {
return this.open(_.extend(options, { type: 'component' }));
},
- showComponentViewer: function (model) {
+ openRule: function (options) {
+ return this.open(_.extend(options, { type: 'rule' }));
+ },
+
+ showViewer: function (Viewer, model) {
var that = this;
if (this.viewerView != null) {
this.viewerView.close();
}
$('.source-viewer').addClass('with-workspace');
- this.viewerView = new ViewerView({
- model: model
- });
+ this.viewerView = new Viewer({ model: model });
this.viewerView
.on('viewerMinimize', function () {
that.closeComponentViewer();
@@ -102,11 +104,28 @@ define([
this.viewerView.render().$el.appendTo(document.body);
},
+ showComponentViewer: function (model) {
+ this.showViewer(ViewerView, model);
+ },
+
closeComponentViewer: function () {
if (this.viewerView != null) {
this.viewerView.close();
$('.with-workspace').removeClass('with-workspace');
}
+ },
+
+ showRule: function (model) {
+ this.showViewer(RuleView, model);
+ this.fetchRule(model);
+ },
+
+ fetchRule: function (model) {
+ var url = baseUrl + '/api/rules/show',
+ options = { key: model.get('key') };
+ return $.get(url, options).done(function (r) {
+ model.set(r.rule);
+ });
}
};
diff --git a/server/sonar-web/src/main/js/workspace/views/base-viewer-view.js b/server/sonar-web/src/main/js/workspace/views/base-viewer-view.js
new file mode 100644
index 00000000000..20396a7cb51
--- /dev/null
+++ b/server/sonar-web/src/main/js/workspace/views/base-viewer-view.js
@@ -0,0 +1,57 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+define([
+ 'workspace/views/viewer-header-view'
+], function (HeaderView) {
+
+ return Marionette.Layout.extend({
+ className: 'workspace-viewer',
+
+ modelEvents: {
+ 'destroy': 'close'
+ },
+
+ regions: {
+ headerRegion: '.workspace-viewer-header',
+ viewerRegion: '.workspace-viewer-container'
+ },
+
+ onRender: function () {
+ this.showHeader();
+ this.$('.workspace-viewer-container').isolatedScroll();
+ },
+
+ onViewerMinimize: function () {
+ this.trigger('viewerMinimize');
+ },
+
+ onViewerClose: function () {
+ this.trigger('viewerClose', this.model);
+ },
+
+ showHeader: function () {
+ var headerView = new HeaderView({ model: this.model });
+ this.listenTo(headerView, 'viewerMinimize', this.onViewerMinimize);
+ this.listenTo(headerView, 'viewerClose', this.onViewerClose);
+ this.headerRegion.show(headerView);
+ }
+ });
+
+});
diff --git a/server/sonar-web/src/main/js/workspace/views/rule-view.js b/server/sonar-web/src/main/js/workspace/views/rule-view.js
new file mode 100644
index 00000000000..f3626009209
--- /dev/null
+++ b/server/sonar-web/src/main/js/workspace/views/rule-view.js
@@ -0,0 +1,40 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+define([
+ 'workspace/views/base-viewer-view',
+ 'templates/workspace'
+], function (BaseView) {
+
+ return BaseView.extend({
+ template: Templates['workspace-rule'],
+
+ modelEvents: {
+ 'destroy': 'close',
+ 'change': 'render'
+ },
+
+ serializeData: function () {
+ return _.extend(Marionette.Layout.prototype.serializeData.apply(this, arguments), {
+ allTags: _.union(this.model.get('sysTags'), this.model.get('tags'))
+ });
+ }
+ });
+
+});
diff --git a/server/sonar-web/src/main/js/workspace/views/viewer-view.js b/server/sonar-web/src/main/js/workspace/views/viewer-view.js
index d294a56a83c..171186f6179 100644
--- a/server/sonar-web/src/main/js/workspace/views/viewer-view.js
+++ b/server/sonar-web/src/main/js/workspace/views/viewer-view.js
@@ -18,43 +18,17 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
define([
- 'workspace/views/viewer-header-view',
+ 'workspace/views/base-viewer-view',
'source-viewer/viewer',
'templates/workspace'
-], function (HeaderView, SourceViewer) {
+], function (BaseView, SourceViewer) {
- return Marionette.Layout.extend({
- className: 'workspace-viewer',
+ return BaseView.extend({
template: Templates['workspace-viewer'],
- modelEvents: {
- 'destroy': 'close'
- },
-
- regions: {
- headerRegion: '.workspace-viewer-header',
- viewerRegion: '.workspace-viewer-container'
- },
-
onRender: function () {
- this.showHeader();
+ BaseView.prototype.onRender.apply(this, arguments);
this.showViewer();
- this.$('.workspace-viewer-container').isolatedScroll();
- },
-
- onViewerMinimize: function () {
- this.trigger('viewerMinimize');
- },
-
- onViewerClose: function () {
- this.trigger('viewerClose', this.model);
- },
-
- showHeader: function () {
- var headerView = new HeaderView({ model: this.model });
- this.listenTo(headerView, 'viewerMinimize', this.onViewerMinimize);
- this.listenTo(headerView, 'viewerClose', this.onViewerClose);
- this.headerRegion.show(headerView);
},
showViewer: function () {
diff --git a/server/sonar-web/src/test/js/issues-page-spec.js b/server/sonar-web/src/test/js/issues-page-spec.js
index aadd4db0ae1..89286655883 100644
--- a/server/sonar-web/src/test/js/issues-page-spec.js
+++ b/server/sonar-web/src/test/js/issues-page-spec.js
@@ -234,6 +234,48 @@ casper.test.begin(testName('Issue Box', 'Transitions'), function (test) {
});
+casper.test.begin(testName('Issue Box', 'Rule'), function (test) {
+ casper
+ .start(lib.buildUrl('issues'), function () {
+ lib.setDefaultViewport();
+
+
+ lib.mockRequestFromFile('/api/issue_filters/app', 'app.json');
+ lib.mockRequestFromFile('/api/issues/search', 'search.json');
+ lib.mockRequestFromFile('/api/rules/show', 'rule.json');
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/issues/app-new.js']);
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('.issue.selected');
+ })
+
+ .then(function () {
+ casper.click('.issue.selected .js-issue-rule');
+ casper.waitForSelector('.workspace-viewer-container .coding-rules-detail-properties');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('.workspace-viewer-name', 'Insufficient branch coverage by unit tests');
+ test.assertSelectorContains('.workspace-viewer-container', 'Reliability > Unit tests coverage');
+ test.assertSelectorContains('.workspace-viewer-container', 'An issue is created on a file as soon as the');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
casper.test.begin(testName('File-Level Issues'), function (test) {
var issueKey = '200d4a8b-9666-4e70-9953-7bab57933f97',
issueSelector = '.issue[data-key="' + issueKey + '"]';
diff --git a/server/sonar-web/src/test/js/workspace.js b/server/sonar-web/src/test/js/workspace.js
index 35a9ef58026..47ce6bd3839 100644
--- a/server/sonar-web/src/test/js/workspace.js
+++ b/server/sonar-web/src/test/js/workspace.js
@@ -286,3 +286,46 @@ casper.test.begin(testName('Full Screen'), 6, function (test) {
test.done();
});
});
+
+
+casper.test.begin(testName('Rule'), 3, function (test) {
+ casper
+ .start(lib.buildUrl('nav'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequestFromFile('/api/rules/show', 'rule.json');
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ window.localStorage.setItem('sonarqube-workspace',
+ '[{"key":"common-java:InsufficientBranchCoverage","type":"rule"}]');
+ window.SS.isUserAdmin = false;
+ window.navbarOptions = new Backbone.Model();
+ require(['/js/nav/app.js']);
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('.workspace-nav-item');
+ })
+
+ .then(function () {
+ casper.click('.workspace-nav-item');
+ casper.waitForSelector('.workspace-viewer .coding-rules-detail-properties');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('.workspace-viewer-name', 'Insufficient branch coverage by unit tests');
+ test.assertSelectorContains('.workspace-viewer-container', 'Reliability > Unit tests coverage');
+ test.assertSelectorContains('.workspace-viewer-container', 'An issue is created on a file as soon as the');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
diff --git a/server/sonar-web/src/test/json/issues-spec/rule.json b/server/sonar-web/src/test/json/issues-spec/rule.json
new file mode 100644
index 00000000000..f4abb0ce469
--- /dev/null
+++ b/server/sonar-web/src/test/json/issues-spec/rule.json
@@ -0,0 +1,36 @@
+{
+ "rule": {
+ "key": "common-java:InsufficientBranchCoverage",
+ "repo": "common-java",
+ "name": "Insufficient branch coverage by unit tests",
+ "createdAt": "2015-04-13T13:44:07+0200",
+ "severity": "MAJOR",
+ "status": "READY",
+ "internalKey": "InsufficientBranchCoverage",
+ "isTemplate": false,
+ "tags": [],
+ "sysTags": [],
+ "lang": "java",
+ "langName": "Java",
+ "htmlDesc": "<p>An issue is created on a file as soon as the branch coverage on this file is less than the required threshold.It gives the number of branches to be covered in order to reach the required threshold.</p>",
+ "defaultDebtChar": "RELIABILITY",
+ "defaultDebtSubChar": "UNIT_TESTS",
+ "debtChar": "RELIABILITY",
+ "debtSubChar": "UNIT_TESTS",
+ "debtCharName": "Reliability",
+ "debtSubCharName": "Unit tests coverage",
+ "defaultDebtRemFnType": "LINEAR",
+ "defaultDebtRemFnCoeff": "10min",
+ "debtOverloaded": false,
+ "debtRemFnType": "LINEAR",
+ "debtRemFnCoeff": "10min",
+ "params": [
+ {
+ "key": "minimumBranchCoverageRatio",
+ "htmlDesc": "The minimum required branch coverage ratio.",
+ "type": "STRING",
+ "defaultValue": "65.0"
+ }
+ ]
+ }
+}
diff --git a/server/sonar-web/src/test/json/workspace/rule.json b/server/sonar-web/src/test/json/workspace/rule.json
new file mode 100644
index 00000000000..f4abb0ce469
--- /dev/null
+++ b/server/sonar-web/src/test/json/workspace/rule.json
@@ -0,0 +1,36 @@
+{
+ "rule": {
+ "key": "common-java:InsufficientBranchCoverage",
+ "repo": "common-java",
+ "name": "Insufficient branch coverage by unit tests",
+ "createdAt": "2015-04-13T13:44:07+0200",
+ "severity": "MAJOR",
+ "status": "READY",
+ "internalKey": "InsufficientBranchCoverage",
+ "isTemplate": false,
+ "tags": [],
+ "sysTags": [],
+ "lang": "java",
+ "langName": "Java",
+ "htmlDesc": "<p>An issue is created on a file as soon as the branch coverage on this file is less than the required threshold.It gives the number of branches to be covered in order to reach the required threshold.</p>",
+ "defaultDebtChar": "RELIABILITY",
+ "defaultDebtSubChar": "UNIT_TESTS",
+ "debtChar": "RELIABILITY",
+ "debtSubChar": "UNIT_TESTS",
+ "debtCharName": "Reliability",
+ "debtSubCharName": "Unit tests coverage",
+ "defaultDebtRemFnType": "LINEAR",
+ "defaultDebtRemFnCoeff": "10min",
+ "debtOverloaded": false,
+ "debtRemFnType": "LINEAR",
+ "debtRemFnCoeff": "10min",
+ "params": [
+ {
+ "key": "minimumBranchCoverageRatio",
+ "htmlDesc": "The minimum required branch coverage ratio.",
+ "type": "STRING",
+ "defaultValue": "65.0"
+ }
+ ]
+ }
+}