diff options
author | Stas Vilchik <vilchiks@gmail.com> | 2015-04-17 15:00:50 +0200 |
---|---|---|
committer | Stas Vilchik <vilchiks@gmail.com> | 2015-04-17 15:20:42 +0200 |
commit | d8d2705e16a3e78fe07dd6bcfe65ec74731517b1 (patch) | |
tree | cfeee135ad7472006a8e9db42213078a74eae8de | |
parent | 267cefcc6a8510b04173c213af10b1f58e6d14c3 (diff) | |
download | sonarqube-d8d2705e16a3e78fe07dd6bcfe65ec74731517b1.tar.gz sonarqube-d8d2705e16a3e78fe07dd6bcfe65ec74731517b1.zip |
SONAR-5851 filter list of profiles by language
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 |