--- /dev/null
+<h6>{{t 'coding_rules.filter_similar_rules'}}</h6>
+
+<div class="issue-action-options">
+ <a href="#" class="issue-action-option" data-property="languages" data-value="{{lang}}">
+ {{langName}}
+ </a>
+
+ {{#notEmpty tags}}
+ <hr>
+ {{#each tags}}
+ <a href="#" class="issue-action-option" data-property="tags" data-value="{{this}}">
+ <i class="icon-tags icon-half-transparent"></i> {{this}}
+ </a>
+ {{/each}}
+ {{/notEmpty}}
+</div>
+
+<div class="bubble-popup-arrow"></div>
<i class="icon-tags"></i>
<span class="note">{{join tags ', '}}</span>
{{/notEmpty}}
+ <a class="js-rule-filter link-no-underline spacer-left" href="#">
+ <i class="icon-filter icon-half-transparent"></i> <i class="icon-dropdown"></i>
+ </a>
</div>
</td>
--- /dev/null
+/*
+ * 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([
+ 'issue/views/action-options-view',
+ 'templates/coding-rules'
+], function (ActionOptionsView) {
+ var $ = jQuery;
+
+ return ActionOptionsView.extend({
+ template: Templates['coding-rules-rule-filter-form'],
+
+ selectOption: function (e) {
+ var property = $(e.currentTarget).data('property'),
+ value = $(e.currentTarget).data('value');
+ this.trigger('select', property, value);
+ return ActionOptionsView.prototype.selectOption.apply(this, arguments);
+ },
+
+ serializeData: function () {
+ return _.extend(ActionOptionsView.prototype.serializeData.apply(this, arguments), {
+ tags: _.union(this.model.get('sysTags'), this.model.get('tags'))
+ });
+ }
+
+ });
+});
define([
'components/navigator/workspace-list-item-view',
'coding-rules/rule/profile-activation-view',
+ 'coding-rules/rule-filter-view',
'templates/coding-rules'
-], function (WorkspaceListItemView, ProfileActivationView) {
+], function (WorkspaceListItemView, ProfileActivationView, RuleFilterView) {
+
+ var $ = jQuery;
return WorkspaceListItemView.extend({
className: 'coding-rule',
'click': 'selectCurrent',
'dblclick': 'openRule',
'click .js-rule': 'openRule',
+ 'click .js-rule-filter': 'onRuleFilterClick',
'click .coding-rules-detail-quality-profile-activate': 'activate',
'click .coding-rules-detail-quality-profile-change': 'change',
'click .coding-rules-detail-quality-profile-revert': 'revert',
});
},
+ onRuleFilterClick: function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ $('body').click();
+ var that = this,
+ popup = new RuleFilterView({
+ triggerEl: $(e.currentTarget),
+ bottomRight: true,
+ model: this.model
+ });
+ popup.on('select', function (property, value) {
+ var obj = {};
+ obj[property] = '' + value;
+ that.options.app.state.updateFilter(obj);
+ popup.close();
+ });
+ popup.render();
+ },
+
serializeData: function () {
return _.extend(WorkspaceListItemView.prototype.serializeData.apply(this, arguments), {
tags: _.union(this.model.get('sysTags'), this.model.get('tags')),
test.done();
});
});
+
+
+casper.test.begin(testName('Filter Similar Rules'), 3, function (test) {
+ casper
+ .start(lib.buildUrl('coding-rules'), function () {
+ lib.setDefaultViewport();
+
+
+ lib.mockRequestFromFile('/api/rules/app', 'app.json');
+ lib.mockRequestFromFile('/api/rules/search', 'search-sql-tag.json', { data: { tags: 'sql' } });
+ lib.mockRequestFromFile('/api/rules/search', 'search.json');
+ })
+
+ .then(function () {
+ casper.evaluate(function () {
+ require(['/js/coding-rules/app.js']);
+ });
+ })
+
+ .then(function () {
+ casper.waitForSelector('.coding-rule.selected .js-rule-filter');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('#coding-rules-total', '609');
+
+ casper.click('.js-rule-filter');
+ casper.waitForSelector('.bubble-popup');
+ })
+
+ .then(function () {
+ test.assertExists('.bubble-popup [data-property="languages"][data-value="java"]');
+
+ casper.click('.bubble-popup [data-property="tags"][data-value="sql"]');
+ casper.wait(1000, function () { lib.capture(); });
+ casper.waitForSelectorTextChange('#coding-rules-total');
+ })
+
+ .then(function () {
+ test.assertSelectorContains('#coding-rules-total', '2');
+ })
+
+ .then(function () {
+ lib.sendCoverage();
+ })
+
+ .run(function () {
+ test.done();
+ });
+});
--- /dev/null
+{
+ "total": 2,
+ "p": 1,
+ "ps": 200,
+ "rules": [
+ {
+ "key": "php:S2014",
+ "tags": [],
+ "status": "READY",
+ "langName": "PHP",
+ "name": "\"$this\" should not be used in a static context",
+ "lang": "php",
+ "sysTags": [
+ "sql"
+ ]
+ },
+ {
+ "key": "squid:S2204",
+ "tags": [],
+ "status": "READY",
+ "langName": "Java",
+ "name": "\".equals()\" should not be used to test the values of \"Atomic\" classes",
+ "lang": "java",
+ "sysTags": [
+ "sql"
+ ]
+ }
+ ],
+ "facets": []
+}
coding_rules.noncharacterized=Uncharacterized
coding_rules.update_custom_rule=Update Custom Rule
coding_rules.update_manual_rule=Update Manual Rule
+coding_rules.filter_similar_rules=Filter Similar Rules
coding_rules.validation.invalid_rule_key=The rule key "%s" is invalid, it should only contain: a-z, 0-9, "_"
coding_rules.validation.missing_name=The name is missing