aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@gmail.com>2013-05-14 12:03:56 +0200
committerJulien Lancelot <julien.lancelot@gmail.com>2013-05-14 12:03:56 +0200
commit5e0fa9fce76a4fbc7bee9151643fb1c891ae92db (patch)
tree476b861672bc13edab361b9f795bf0bd790f053a
parent203a2b8addf29efe6b611bdafb50835e15ce164c (diff)
downloadsonarqube-5e0fa9fce76a4fbc7bee9151643fb1c891ae92db.tar.gz
sonarqube-5e0fa9fce76a4fbc7bee9151643fb1c891ae92db.zip
SONAR-3755 Add resolved parameter to IssueFinder and improve issues search page
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/ActionPlanStats.java9
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/DefaultActionPlan.java9
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml11
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java17
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_by_resolved.xml77
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java17
-rw-r--r--sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java5
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb13
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/helpers/application_helper.rb12
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/views/issues/_list.html.erb11
-rw-r--r--sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java2
-rw-r--r--sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java5
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java4
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"));