From: Stas Vilchik Date: Fri, 17 Apr 2015 15:21:04 +0000 (+0200) Subject: SONAR-6210 add a rule description in the workspace X-Git-Tag: 5.2-RC1~2215 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=20499b26a45114913f94387be92e9c473c5c7170;p=sonarqube.git SONAR-6210 add a rule description in the workspace --- 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/issue/issue-rule.hbs b/server/sonar-web/src/main/hbs/issue/issue-rule.hbs deleted file mode 100644 index 2e11a623e9d..00000000000 --- a/server/sonar-web/src/main/hbs/issue/issue-rule.hbs +++ /dev/null @@ -1,32 +0,0 @@ - - - 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}} diff --git a/server/sonar-web/src/main/hbs/workspace/workspace-rule.hbs b/server/sonar-web/src/main/hbs/workspace/workspace-rule.hbs new file mode 100644 index 00000000000..acdf14906c2 --- /dev/null +++ b/server/sonar-web/src/main/hbs/workspace/workspace-rule.hbs @@ -0,0 +1,25 @@ +
+ +
+ + + +
{{{htmlDesc}}}
+ + {{#if htmlNote}} +
+
{{{htmlNote}}}
+
+ {{/if}} +
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 @@ -
{{qualifierIcon q}} {{name}}
+
{{#if q}}{{qualifierIcon q}} {{/if}}{{name}}
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": "

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.

", + "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": "

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.

", + "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" + } + ] + } +}