aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStas Vilchik <vilchiks@gmail.com>2015-04-17 15:00:50 +0200
committerStas Vilchik <vilchiks@gmail.com>2015-04-17 15:20:42 +0200
commitd8d2705e16a3e78fe07dd6bcfe65ec74731517b1 (patch)
treecfeee135ad7472006a8e9db42213078a74eae8de
parent267cefcc6a8510b04173c213af10b1f58e6d14c3 (diff)
downloadsonarqube-d8d2705e16a3e78fe07dd6bcfe65ec74731517b1.tar.gz
sonarqube-d8d2705e16a3e78fe07dd6bcfe65ec74731517b1.zip
SONAR-5851 filter list of profiles by language
-rw-r--r--server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-actions.hbs62
-rw-r--r--server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-profiles-language.hbs2
-rw-r--r--server/sonar-web/src/main/js/quality-profiles/actions-view.js33
-rw-r--r--server/sonar-web/src/main/js/quality-profiles/app.js4
-rw-r--r--server/sonar-web/src/main/js/quality-profiles/profile-view.js1
-rw-r--r--server/sonar-web/src/main/js/quality-profiles/profiles-view.js15
-rw-r--r--server/sonar-web/src/test/js/quality-profiles.js79
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties2
8 files changed, 164 insertions, 34 deletions
diff --git a/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-actions.hbs b/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-actions.hbs
index b173c8ee77f..24fa188c899 100644
--- a/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-actions.hbs
+++ b/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-actions.hbs
@@ -1,26 +1,46 @@
-<h1 class="page-title">{{t 'quality_profiles.page'}}</h1>
+<header class="page-header">
+ <h1 class="page-title">{{t 'quality_profiles.page'}}</h1>
+ <div class="page-actions">
+ {{#if canWrite}}
+ <div class="button-group dropdown">
+ <button id="quality-profiles-create">{{t 'create'}}</button>
+ <a class="button dropdown-toggle" href="#" data-toggle="dropdown"><i class="icon-dropdown"></i></a>
+ <ul class="dropdown-menu dropdown-menu-right">
+ <li>
+ <a id="quality-profiles-compare" href="#">{{t 'quality_profiles.compare_profiles'}}</a>
+ </li>
+ <li>
+ <a id="quality-profiles-restore" href="#">{{t 'quality_profiles.restore_profile'}}</a>
+ </li>
+ <li>
+ <a id="quality-profiles-restore-built-in" href="#">{{t 'quality_profiles.restore_built_in_profiles'}}</a>
+ </li>
+ </ul>
+ </div>
+ {{else}}
+ <div class="button-group">
+ <button id="quality-profiles-compare">{{t 'quality_profiles.compare_profiles'}}</button>
+ </div>
+ {{/if}}
+ </div>
+</header>
-<div class="page-actions">
- {{#if canWrite}}
- <div class="button-group dropdown">
- <button id="quality-profiles-create">{{t 'create'}}</button>
- <a class="button dropdown-toggle" href="#" data-toggle="dropdown"><i class="icon-dropdown"></i></a>
- <ul class="dropdown-menu dropdown-menu-right">
- <li>
- <a id="quality-profiles-compare" href="#">{{t 'quality_profiles.compare_profiles'}}</a>
- </li>
- <li>
- <a id="quality-profiles-restore" href="#">{{t 'quality_profiles.restore_profile'}}</a>
- </li>
- <li>
- <a id="quality-profiles-restore-built-in" href="#">{{t 'quality_profiles.restore_built_in_profiles'}}</a>
- </li>
- </ul>
- </div>
+<div class="dropdown" id="quality-profiles-filter-by-language">
+ <span>Show:</span>
+ {{#if selectedLanguage}}
+ <a class="dropdown-toggle link-no-underline" href="#" data-toggle="dropdown">
+ {{tp 'quality_profiles.x_profiles' selectedLanguage.name}} <i class="icon-dropdown"></i>
+ </a>
{{else}}
- <div class="button-group">
- <button id="quality-profiles-compare">{{t 'quality_profiles.compare_profiles'}}</button>
- </div>
+ <a class="dropdown-toggle link-no-underline" href="#" data-toggle="dropdown">
+ {{t 'quality_profiles.all_profiles'}} <i class="icon-dropdown"></i>
+ </a>
{{/if}}
+ <ul class="dropdown-menu">
+ <li><a class="js-filter-by-language" href="#">{{t 'quality_profiles.all_profiles'}}</a></li>
+ {{#each languages}}
+ <li><a class="js-filter-by-language" href="#" data-language="{{key}}">{{tp 'quality_profiles.x_profiles' name}}</a></li>
+ {{/each}}
+ </ul>
</div>
diff --git a/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-profiles-language.hbs b/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-profiles-language.hbs
index e7288e85f87..f3ec16f0a9c 100644
--- a/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-profiles-language.hbs
+++ b/server/sonar-web/src/main/hbs/quality-profiles/quality-profiles-profiles-language.hbs
@@ -1 +1 @@
-<h6 class="spacer-top js-list-language">{{languageName}}</h6>
+<h6 class="spacer-top js-list-language" data-language="{{language}}">{{languageName}}</h6>
diff --git a/server/sonar-web/src/main/js/quality-profiles/actions-view.js b/server/sonar-web/src/main/js/quality-profiles/actions-view.js
index 9cb0e2d3f98..3581f909c1b 100644
--- a/server/sonar-web/src/main/js/quality-profiles/actions-view.js
+++ b/server/sonar-web/src/main/js/quality-profiles/actions-view.js
@@ -32,7 +32,9 @@ define([
events: {
'click #quality-profiles-create': 'onCreateClick',
'click #quality-profiles-restore': 'onRestoreClick',
- 'click #quality-profiles-restore-built-in': 'onRestoreBuiltInClick'
+ 'click #quality-profiles-restore-built-in': 'onRestoreBuiltInClick',
+
+ 'click .js-filter-by-language': 'onLanguageClick'
},
onCreateClick: function (e) {
@@ -50,9 +52,15 @@ define([
this.restoreBuiltIn();
},
+ onLanguageClick: function (e) {
+ e.preventDefault();
+ var language = $(e.currentTarget).data('language');
+ this.filterByLanguage(language);
+ },
+
create: function () {
var that = this;
- $.when(this.requestLanguages(), this.requestImporters()).done(function () {
+ this.requestImporters().done(function () {
new CreateProfileView({
collection: that.collection,
languages: that.languages,
@@ -68,13 +76,10 @@ define([
},
restoreBuiltIn: function () {
- var that = this;
- this.requestLanguages().done(function (r) {
- new RestoreBuiltInProfilesView({
- collection: that.collection,
- languages: r.languages
- }).render();
- });
+ new RestoreBuiltInProfilesView({
+ collection: this.collection,
+ languages: this.languages
+ }).render();
},
requestLanguages: function () {
@@ -93,9 +98,17 @@ define([
});
},
+ filterByLanguage: function (language) {
+ this.selectedLanguage = _.findWhere(this.languages, { key: language });
+ this.render();
+ this.collection.trigger('filter', language);
+ },
+
serializeData: function () {
return _.extend(Marionette.ItemView.prototype.serializeData.apply(this, arguments), {
- canWrite: this.options.canWrite
+ canWrite: this.options.canWrite,
+ languages: this.languages,
+ selectedLanguage: this.selectedLanguage
});
}
});
diff --git a/server/sonar-web/src/main/js/quality-profiles/app.js b/server/sonar-web/src/main/js/quality-profiles/app.js
index d139f2b17b5..e2650a470ff 100644
--- a/server/sonar-web/src/main/js/quality-profiles/app.js
+++ b/server/sonar-web/src/main/js/quality-profiles/app.js
@@ -46,7 +46,9 @@ require([
collection: this.profiles,
canWrite: this.canWrite
});
- this.layout.actionsRegion.show(this.actionsView);
+ this.actionsView.requestLanguages().done(function () {
+ App.layout.actionsRegion.show(App.actionsView);
+ });
// Profiles View
this.profilesView = new ProfilesView({
diff --git a/server/sonar-web/src/main/js/quality-profiles/profile-view.js b/server/sonar-web/src/main/js/quality-profiles/profile-view.js
index 680cc25d613..d2d42aee324 100644
--- a/server/sonar-web/src/main/js/quality-profiles/profile-view.js
+++ b/server/sonar-web/src/main/js/quality-profiles/profile-view.js
@@ -37,6 +37,7 @@ define([
onRender: function () {
this.$el.toggleClass('active', this.options.highlighted);
this.$el.attr('data-key', this.model.id);
+ this.$el.attr('data-language', this.model.get('language'));
this.$('[data-toggle="tooltip"]').tooltip({ container: 'body' });
},
diff --git a/server/sonar-web/src/main/js/quality-profiles/profiles-view.js b/server/sonar-web/src/main/js/quality-profiles/profiles-view.js
index fe2e1a97dd8..7909647c32c 100644
--- a/server/sonar-web/src/main/js/quality-profiles/profiles-view.js
+++ b/server/sonar-web/src/main/js/quality-profiles/profiles-view.js
@@ -29,6 +29,10 @@ define([
itemView: ProfileView,
itemViewContainer: '.js-list',
+ collectionEvents: {
+ 'filter': 'filterByLanguage'
+ },
+
itemViewOptions: function (model) {
return {
collectionView: this,
@@ -64,7 +68,16 @@ define([
closeChildren: function () {
Marionette.CompositeView.prototype.closeChildren.apply(this, arguments);
this.$('.js-list-language').remove();
- }
+ },
+
+ filterByLanguage: function (language) {
+ if (language) {
+ this.$('[data-language]').addClass('hidden');
+ this.$('[data-language="' + language + '"]').removeClass('hidden');
+ } else {
+ this.$('[data-language]').removeClass('hidden');
+ }
+ },
});
});
diff --git a/server/sonar-web/src/test/js/quality-profiles.js b/server/sonar-web/src/test/js/quality-profiles.js
index 04e2632639c..796a395997a 100644
--- a/server/sonar-web/src/test/js/quality-profiles.js
+++ b/server/sonar-web/src/test/js/quality-profiles.js
@@ -34,6 +34,7 @@ casper.test.begin(testName('Should Show List'), 9, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
})
.then(function () {
@@ -70,6 +71,69 @@ casper.test.begin(testName('Should Show List'), 9, function (test) {
});
+casper.test.begin(testName('Should Filter List By Language'), 15, function (test) {
+ casper
+ .start(lib.buildUrl('profiles'), function () {
+ lib.setDefaultViewport();
+
+ lib.mockRequestFromFile('/api/users/current', 'user.json');
+ lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/quality-profiles/app.js']);
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('.js-list .list-group-item');
+ })
+
+ .then(function () {
+ test.assertElementCount('.js-list .list-group-item', 5);
+ test.assertVisible('.js-list .list-group-item[data-key="java-sonar-way-67887"]');
+ test.assertVisible('.js-list .list-group-item[data-key="js-sonar-way-71566"]');
+
+ test.assertElementCount('.js-list-language', 4);
+ test.assertVisible('.js-list-language[data-language="java"]');
+ test.assertVisible('.js-list-language[data-language="js"]');
+ })
+
+ .then(function () {
+ test.assertExists('#quality-profiles-filter-by-language');
+ casper.click('.js-filter-by-language[data-language="js"]');
+ })
+
+ .then(function () {
+ test.assertNotVisible('.js-list .list-group-item[data-key="java-sonar-way-67887"]');
+ test.assertVisible('.js-list .list-group-item[data-key="js-sonar-way-71566"]');
+ test.assertNotVisible('.js-list-language[data-language="java"]');
+ test.assertVisible('.js-list-language[data-language="js"]');
+ })
+
+ .then(function () {
+ casper.click('.js-filter-by-language:nth-child(1)');
+ })
+
+ .then(function () {
+ test.assertVisible('.js-list .list-group-item[data-key="java-sonar-way-67887"]');
+ test.assertVisible('.js-list .list-group-item[data-key="js-sonar-way-71566"]');
+ test.assertVisible('.js-list-language[data-language="java"]');
+ test.assertVisible('.js-list-language[data-language="js"]');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
+
+
casper.test.begin(testName('Should Show Details'), 10, function (test) {
casper
.start(lib.buildUrl('profiles'), function () {
@@ -77,6 +141,7 @@ casper.test.begin(testName('Should Show Details'), 10, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json',
{ data: { qprofile: 'java-sonar-way-67887', activation: 'true' }});
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json', {
@@ -130,6 +195,7 @@ casper.test.begin(testName('Should Show Details', 'Admin'), 10, function (test)
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json',
{ data: { qprofile: 'java-sonar-way-67887', activation: 'true' }});
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json', {
@@ -183,6 +249,7 @@ casper.test.begin(testName('Should Show Inheritance Details'), 10, function (tes
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-inheritance.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance-plus.json', {
data: { profileKey: 'java-inherited-profile-85155' }
@@ -236,6 +303,7 @@ casper.test.begin(testName('Should Show Selected Projects'), 2, function (test)
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/projects?key=php-psr-2-46772', 'projects.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
@@ -282,6 +350,7 @@ casper.test.begin(testName('Copy Profile'), 5, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequestFromFile('/api/qualityprofiles/copy', 'copy.json', {
@@ -343,6 +412,7 @@ casper.test.begin(testName('Rename Profile'), 2, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequest('/api/qualityprofiles/rename', '{}', {
@@ -404,6 +474,7 @@ casper.test.begin(testName('Make Profile Default'), 4, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequest('/api/qualityprofiles/set_default', '{}', {
@@ -459,6 +530,7 @@ casper.test.begin(testName('Delete Profile'), 2, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-with-copy.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequest('/api/qualityprofiles/delete', '{}', {
@@ -573,6 +645,7 @@ casper.test.begin(testName('Restore Profile'), 2, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
})
@@ -739,6 +812,7 @@ casper.test.begin(testName('Change Parent'), 1, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
this.searchMock = lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-change-parent.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
this.inheritanceMock = lib.mockRequestFromFile('/api/qualityprofiles/inheritance',
'inheritance-change-parent.json');
@@ -802,6 +876,7 @@ casper.test.begin(testName('Permalink'), 9, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user-admin.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
})
@@ -846,6 +921,7 @@ casper.test.begin(testName('Changelog'), 21, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequestFromFile('/api/qualityprofiles/changelog', 'changelog2.json', {
@@ -922,6 +998,7 @@ casper.test.begin(testName('Changelog Permalink'), 2, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequestFromFile('/api/qualityprofiles/changelog', 'changelog2.json', {
@@ -979,6 +1056,7 @@ casper.test.begin(testName('Comparison'), 12, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-with-copy.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequestFromFile('/api/qualityprofiles/compare', 'compare.json', {
@@ -1036,6 +1114,7 @@ casper.test.begin(testName('Comparison Permalink'), 4, function (test) {
lib.mockRequestFromFile('/api/users/current', 'user.json');
lib.mockRequestFromFile('/api/qualityprofiles/search', 'search-with-copy.json');
+ lib.mockRequestFromFile('/api/languages/list', 'languages.json');
lib.mockRequestFromFile('/api/rules/search', 'rules.json');
lib.mockRequestFromFile('/api/qualityprofiles/inheritance', 'inheritance.json');
lib.mockRequestFromFile('/api/qualityprofiles/compare', 'compare.json', {
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 b1eb6e9d794..3b08fd16d2c 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -1792,6 +1792,8 @@ quality_profiles.inherits=Inherits "{0}"
quality_profile.x_active_rules={0} active rules
quality_profiles.x_overridden_rules={0} overridden rules
quality_profiles.change_parent=Change Parent
+quality_profiles.all_profiles=All Profiles
+quality_profiles.x_profiles={0} Profiles