diff options
author | Julien Lancelot <julien.lancelot@gmail.com> | 2013-05-14 12:03:56 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@gmail.com> | 2013-05-14 12:03:56 +0200 |
commit | 5e0fa9fce76a4fbc7bee9151643fb1c891ae92db (patch) | |
tree | 476b861672bc13edab361b9f795bf0bd790f053a | |
parent | 203a2b8addf29efe6b611bdafb50835e15ce164c (diff) | |
download | sonarqube-5e0fa9fce76a4fbc7bee9151643fb1c891ae92db.tar.gz sonarqube-5e0fa9fce76a4fbc7bee9151643fb1c891ae92db.zip |
SONAR-3755 Add resolved parameter to IssueFinder and improve issues search page
13 files changed, 168 insertions, 24 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/ActionPlanStats.java b/sonar-core/src/main/java/org/sonar/core/issue/ActionPlanStats.java index 0dc6db2e6f7..e82b23d3753 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/ActionPlanStats.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/ActionPlanStats.java @@ -22,6 +22,9 @@ package org.sonar.core.issue; import org.sonar.api.issue.ActionPlan; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + import java.io.Serializable; import java.util.Date; import java.util.UUID; @@ -81,11 +84,12 @@ public class ActionPlanStats implements Serializable { return this; } + @CheckForNull public String description() { return description; } - public ActionPlanStats setDescription(String description) { + public ActionPlanStats setDescription(@Nullable String description) { this.description = description; return this; } @@ -108,11 +112,12 @@ public class ActionPlanStats implements Serializable { return this; } + @CheckForNull public Date deadLine() { return deadLine; } - public ActionPlanStats setDeadLine(Date deadLine) { + public ActionPlanStats setDeadLine(@Nullable Date deadLine) { this.deadLine = deadLine; return this; } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultActionPlan.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultActionPlan.java index 40f8797c816..a7b8d8c7b5f 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultActionPlan.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultActionPlan.java @@ -22,6 +22,9 @@ package org.sonar.core.issue; import org.sonar.api.issue.ActionPlan; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + import java.util.Date; import java.util.UUID; @@ -78,11 +81,12 @@ public class DefaultActionPlan implements ActionPlan { return this; } + @CheckForNull public String description() { return description; } - public DefaultActionPlan setDescription(String description) { + public DefaultActionPlan setDescription(@Nullable String description) { this.description = description; return this; } @@ -105,11 +109,12 @@ public class DefaultActionPlan implements ActionPlan { return this; } + @CheckForNull public Date deadLine() { return deadLine; } - public DefaultActionPlan setDeadLine(Date deadLine) { + public DefaultActionPlan setDeadLine(@Nullable Date deadLine) { this.deadLine = deadLine; return this; } diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index 137ca53966c..e3da441ad59 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -139,7 +139,8 @@ , projects project_component </if> <where> - i.resource_id=p.id and i.rule_id=r.id + and i.resource_id=p.id + and i.rule_id=r.id <if test="componentRoots != null and componentRoots.size() > 0"> and rootprojects.enabled=${_true} and rootprojects.kee in @@ -191,6 +192,14 @@ <foreach item="resolution" index="index" collection="resolutions" open="(" separator="," close=")">#{resolution} </foreach> </if> + <if test="resolved != null"> + <if test="resolved == true"> + and i.resolution is not null + </if> + <if test="resolved == false"> + and i.resolution is null + </if> + </if> <if test="userLogins != null"> and i.user_login in <foreach item="userLogin" index="index" collection="userLogins" open="(" separator="," close=")">#{userLogin} diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java index 5c75cbdf706..1c01caa8b39 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java @@ -178,6 +178,23 @@ public class IssueDaoTest extends AbstractDaoTestCase { } @Test + public void should_select_by_resolved() { + setupData("shared", "should_select_by_resolved"); + + IssueQuery query = IssueQuery.builder().resolved(true).build(); + List<IssueDto> issues = newArrayList(dao.select(query)); + assertThat(issues).hasSize(2); + + query = IssueQuery.builder().resolved(false).build(); + issues = newArrayList(dao.select(query)); + assertThat(issues).hasSize(1); + + query = IssueQuery.builder().resolved(null).build(); + issues = newArrayList(dao.select(query)); + assertThat(issues).hasSize(3); + } + + @Test public void should_select_by_action_plans() { setupData("shared", "should_select_by_action_plans"); diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_by_resolved.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_by_resolved.xml new file mode 100644 index 00000000000..f3eddd896cc --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_by_resolved.xml @@ -0,0 +1,77 @@ +<dataset> + + <issues + id="100" + kee="ABCDE-1" + resource_id="400" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + manual_issue="[false]" + description="[null]" + line="200" + effort_to_fix="4.2" + status="OPEN" + resolution="[null]" + checksum="XXX" + user_login="arthur" + assignee_login="perceval" + author_login="[null]" + attributes="JIRA=FOO-1234" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="2013-04-16" + updated_at="2013-04-16" + /> + + <issues + id="101" + kee="ABCDE-2" + resource_id="400" + rule_id="500" + severity="BLOCKER" + manual_severity="[false]" + manual_issue="[false]" + description="[null]" + line="200" + effort_to_fix="4.2" + status="RESOLVED" + resolution="FALSE-POSITIVE" + checksum="XXX" + user_login="arthur" + assignee_login="perceval" + author_login="[null]" + attributes="JIRA=FOO-1234" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="2013-04-16" + updated_at="2013-04-16" + /> + + <issues + id="102" + kee="ABCDE-3" + resource_id="400" + rule_id="501" + severity="BLOCKER" + manual_severity="[false]" + manual_issue="[false]" + description="[null]" + line="200" + effort_to_fix="4.2" + status="CLOSED" + resolution="FIXED" + checksum="XXX" + user_login="arthur" + assignee_login="[null]" + author_login="[null]" + attributes="JIRA=FOO-1234" + issue_creation_date="2013-04-16" + issue_update_date="2013-04-16" + issue_close_date="2013-04-16" + created_at="2013-04-16" + updated_at="2013-04-16" + /> +</dataset> diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java index acc46cede45..4588fffe071 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java @@ -25,6 +25,7 @@ import org.sonar.api.rule.RuleKey; import javax.annotation.CheckForNull; import javax.annotation.Nullable; + import java.util.Collection; import java.util.Date; @@ -49,6 +50,7 @@ public class IssueQuery { private final Collection<String> assignees; private final Boolean assigned; private final Boolean planned; + private final Boolean resolved; private final Date createdAfter; private final Date createdBefore; private final Sort sort; @@ -74,6 +76,7 @@ public class IssueQuery { this.assignees = builder.assignees; this.assigned = builder.assigned; this.planned = builder.planned; + this.resolved = builder.resolved; this.createdAfter = builder.createdAfter; this.createdBefore = builder.createdBefore; this.sort = builder.sort; @@ -131,6 +134,10 @@ public class IssueQuery { return planned; } + public Boolean resolved() { + return resolved; + } + public Date createdAfter() { return createdAfter; } @@ -188,6 +195,7 @@ public class IssueQuery { private Collection<String> assignees; private Boolean assigned = null; private Boolean planned = null; + private Boolean resolved = null; private Date createdAfter; private Date createdBefore; private Sort sort; @@ -267,6 +275,15 @@ public class IssueQuery { return this; } + /** + * If true, it will return all resolved issues + * If false, it will return all none resolved issues + */ + public Builder resolved(Boolean resolved) { + this.resolved = resolved; + return this; + } + public Builder createdAfter(Date createdAfter) { this.createdAfter = createdAfter; return this; diff --git a/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java b/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java index f93a9b7dd8c..6377d61fa9d 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java @@ -23,19 +23,17 @@ import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; -import com.google.common.primitives.Ints; import org.sonar.api.issue.IssueFinder; import org.sonar.api.issue.IssueQuery; import org.sonar.api.issue.IssueQueryResult; import org.sonar.api.issue.RubyIssueService; import org.sonar.api.rule.RuleKey; -import org.sonar.api.utils.DateUtils; import org.sonar.api.web.UserRole; import org.sonar.server.util.RubyUtils; import javax.annotation.Nullable; + import java.util.Collection; -import java.util.Date; import java.util.List; import java.util.Map; @@ -67,6 +65,7 @@ public class PublicRubyIssueService implements RubyIssueService { builder.severities(RubyUtils.toStrings(props.get("severities"))); builder.statuses(RubyUtils.toStrings(props.get("statuses"))); builder.resolutions(RubyUtils.toStrings(props.get("resolutions"))); + builder.resolved(RubyUtils.toBoolean(props.get("resolved"))); builder.components(RubyUtils.toStrings(props.get("components"))); builder.componentRoots(RubyUtils.toStrings(props.get("componentRoots"))); builder.rules(toRules(props.get("rules"))); diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb index 7822deee5b4..342b68f8da8 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb @@ -21,10 +21,19 @@ class IssuesController < ApplicationController def index - page_index = params[:page_index] || 1 - @issue_results = Api.issues.find({'pageSize' => 25, 'pageIndex' => page_index}) + init_params + @issue_results = Api.issues.find(params) @paging = @issue_results.paging @issues = @issue_results.issues end + + private + + def init_params + params.merge({:controller => nil, :action => nil, :search => nil, :widget_id => nil, :edit => nil}) + params['pageSize'] = 25 + params['pageIndex'] ||= 1 + end + end
\ No newline at end of file diff --git a/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb b/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb index ee37275ad4a..ac0a1819192 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb @@ -546,22 +546,22 @@ module ApplicationHelper # def paginate_java(pagination) total = pagination.total.to_i - page_index = pagination.page_index ? pagination.page_index.to_i : 1 - page_size = pagination.page_size.to_i || 20 - pages = pagination.pages.to_i + page_index = pagination.pageIndex() ? pagination.pageIndex().to_i : 1 + page_size = pagination.pageSize().to_i || 20 + pages = pagination.pages().to_i html = total.to_s + " " + message('results').downcase if total > page_size # render the pagination links html += " | " - html += link_to_if page_index>1, message('paging_previous'), {:overwrite_params => {:page_index => page_index-1}} + html += link_to_if page_index>1, message('paging_previous'), {:overwrite_params => {:pageIndex => page_index-1}} html += " " for index in 1..pages - html += link_to_unless index==page_index, index.to_s, {:overwrite_params => {:page_index => index}} + html += link_to_unless index==page_index, index.to_s, {:overwrite_params => {:pageIndex => index}} html += " " end - html += link_to_if page_index<pages, message('paging_next'), {:overwrite_params => {:page_index => 1+page_index}} + html += link_to_if page_index<pages, message('paging_next'), {:overwrite_params => {:pageIndex => 1+page_index}} end html diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb index 3319336cefa..bde6583a13a 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb @@ -13,14 +13,14 @@ <th> Message </th> - <th width="1%"> - <%= message('project') -%> + <th width="1%" nowrap> + Component name </th> <th> <%= message('assignee') -%> </th> <th> - Created at + Creation date </th> </tr> </thead> @@ -48,10 +48,7 @@ <%= link_to h(issue.description), :controller => "issue", :action => "view", :id => issue.key -%> </td> <td> - <span class="nowrap"><%= h(@issue_results.component(issue).longName) -%></span> - <br/> - <span class="note"><%= h(@issue_results.component(issue).name) -%></span></td> - + <%= h(@issue_results.component(issue).name) -%> </td> <td> <%= @issue_results.user(issue.assignee).name if issue.assignee -%> diff --git a/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java index d2c3c0cfe94..efcbfc5a70e 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java @@ -62,6 +62,7 @@ public class PublicRubyIssueServiceTest { map.put("severities", newArrayList("MAJOR", "MINOR")); map.put("statuses", newArrayList("CLOSED")); map.put("resolutions", newArrayList("FALSE-POSITIVE")); + map.put("resolved", true); map.put("components", newArrayList("org.apache")); map.put("componentRoots", newArrayList("org.sonar")); map.put("userLogins", newArrayList("marilyn")); @@ -79,6 +80,7 @@ public class PublicRubyIssueServiceTest { assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); assertThat(query.statuses()).containsOnly("CLOSED"); assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE"); + assertThat(query.resolved()).isTrue(); assertThat(query.components()).containsOnly("org.apache"); assertThat(query.componentRoots()).containsOnly("org.sonar"); assertThat(query.userLogins()).containsOnly("marilyn"); diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java index 3a1036f18cd..ff30b1dbb2e 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java @@ -94,6 +94,11 @@ public class IssueQuery { return this; } + public IssueQuery resolved(Boolean resolved) { + params.put("resolved", resolved); + return this; + } + public IssueQuery createdAfter(Date d) { params.put("createdAfter", EncodingUtils.toQueryParam(d, true)); return this; diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java index ff001a067ad..8d0e0b949b2 100644 --- a/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java @@ -41,6 +41,7 @@ public class IssueQueryTest { .components("Action.java", "Filter.java") .componentRoots("struts") .resolutions("FIXED", "FALSE-POSITIVE") + .resolved(true) .rules("squid:AvoidCycle") .actionPlans("ABC") .statuses("OPEN", "CLOSED") @@ -51,7 +52,7 @@ public class IssueQueryTest { .pageSize(5) .pageIndex(4); - assertThat(query.urlParams()).hasSize(16); + assertThat(query.urlParams()).hasSize(17); assertThat(query.urlParams()).includes(entry("issues", "ABCDE,FGHIJ")); assertThat(query.urlParams()).includes(entry("assignees", "arthur,perceval")); assertThat(query.urlParams()).includes(entry("assigned", true)); @@ -61,6 +62,7 @@ public class IssueQueryTest { assertThat(query.urlParams()).includes(entry("rules", "squid:AvoidCycle")); assertThat(query.urlParams()).includes(entry("actionPlans", "ABC")); assertThat(query.urlParams()).includes(entry("resolutions", "FIXED,FALSE-POSITIVE")); + assertThat(query.urlParams()).includes(entry("resolved", true)); assertThat(query.urlParams()).includes(entry("statuses", "OPEN,CLOSED")); assertThat(query.urlParams()).includes(entry("severities", "BLOCKER,INFO")); assertThat(query.urlParams()).includes(entry("userLogins", "login1,login2")); |