@@ -30,6 +30,7 @@ import org.sonar.api.issue.IssueQuery; | |||
import org.sonar.core.persistence.MyBatis; | |||
import javax.annotation.CheckForNull; | |||
import java.util.Collection; | |||
import java.util.Collections; | |||
import java.util.List; | |||
@@ -97,21 +98,22 @@ public class IssueDao implements BatchComponent, ServerComponent { | |||
return mapper.selectIssueAndComponentIds(query); | |||
} | |||
Collection<IssueDto> selectByIds(Collection<Long> ids) { | |||
@VisibleForTesting | |||
Collection<IssueDto> selectByIds(Collection<Long> ids, IssueQuery.Sort sort, boolean asc) { | |||
SqlSession session = mybatis.openSession(); | |||
try { | |||
return selectByIds(ids, session); | |||
return selectByIds(ids, sort, asc, session); | |||
} finally { | |||
MyBatis.closeQuietly(session); | |||
} | |||
} | |||
public Collection<IssueDto> selectByIds(Collection<Long> ids, SqlSession session) { | |||
public Collection<IssueDto> selectByIds(Collection<Long> ids, IssueQuery.Sort sort, boolean asc, SqlSession session) { | |||
if (ids.isEmpty()) { | |||
return Collections.emptyList(); | |||
} | |||
List<List<Long>> idsPartition = Lists.partition(newArrayList(ids), 1000); | |||
Map<String, List<List<Long>>> params = ImmutableMap.of("ids", idsPartition); | |||
Object idsPartition = Lists.partition(newArrayList(ids), 1000); | |||
Map<String, Object> params = ImmutableMap.of("ids", idsPartition, "sort", sort, "asc", asc); | |||
return session.selectList("org.sonar.core.issue.db.IssueMapper.selectByIds", params); | |||
} | |||
} |
@@ -32,6 +32,40 @@ | |||
p.kee as componentKey | |||
</sql> | |||
<sql id="sortFilter"> | |||
<if test="sort != null"> | |||
order by | |||
<choose> | |||
<when test="'SEVERITY'.equals(sort.name())"> | |||
i.severity | |||
</when> | |||
<when test="'STATUS'.equals(sort.name())"> | |||
i.status | |||
</when> | |||
<when test="'ASSIGNEE'.equals(sort.name())"> | |||
i.assignee | |||
</when> | |||
<when test="'CREATION_DATE'.equals(sort.name())"> | |||
i.issue_creation_date | |||
</when> | |||
<when test="'UPDATE_DATE'.equals(sort.name())"> | |||
i.issue_update_date | |||
</when> | |||
<when test="'CLOSE_DATE'.equals(sort.name())"> | |||
i.issue_close_date | |||
</when> | |||
</choose> | |||
<choose> | |||
<when test="true.equals(asc)"> | |||
asc | |||
</when> | |||
<otherwise> | |||
desc | |||
</otherwise> | |||
</choose> | |||
</if> | |||
</sql> | |||
<insert id="insert" parameterType="Issue" useGeneratedKeys="false" keyProperty="id"> | |||
INSERT INTO issues (kee, resource_id, rule_id, action_plan_key, severity, manual_severity, | |||
message, line, effort_to_fix, status, | |||
@@ -115,6 +149,7 @@ | |||
and i.rule_id=r.id | |||
and p.id=i.resource_id | |||
</where> | |||
<include refid="sortFilter"/> | |||
</select> | |||
<select id="selectIssueAndComponentIds" parameterType="map" resultType="Issue"> | |||
@@ -244,31 +279,7 @@ | |||
<if test="sort == null"> | |||
order by i.id | |||
</if> | |||
<if test="sort != null"> | |||
order by | |||
<choose> | |||
<when test="'CREATION_DATE'.equals(sort.name())"> | |||
i.issue_creation_date | |||
</when> | |||
<when test="'UPDATE_DATE'.equals(sort.name())"> | |||
i.issue_update_date | |||
</when> | |||
<when test="'CLOSE_DATE'.equals(sort.name())"> | |||
i.issue_close_date | |||
</when> | |||
<when test="'ASSIGNEE'.equals(sort.name())"> | |||
i.assignee | |||
</when> | |||
</choose> | |||
<choose> | |||
<when test="true.equals(asc)"> | |||
asc | |||
</when> | |||
<otherwise> | |||
desc | |||
</otherwise> | |||
</choose> | |||
</if> | |||
<include refid="sortFilter"/> | |||
</sql> | |||
</mapper> |
@@ -27,7 +27,6 @@ import org.sonar.api.rule.RuleKey; | |||
import org.sonar.api.utils.DateUtils; | |||
import org.sonar.core.persistence.AbstractDaoTestCase; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import static com.google.common.collect.Lists.newArrayList; | |||
@@ -221,9 +220,33 @@ public class IssueDaoTest extends AbstractDaoTestCase { | |||
assertThat(dao.select(query)).hasSize(3); | |||
} | |||
@Test | |||
public void should_select_sort_by_severity() { | |||
setupData("shared", "should_select_returned_sorted_result_by_severity"); | |||
IssueQuery query = IssueQuery.builder().sort(IssueQuery.Sort.SEVERITY).asc(true).build(); | |||
List<IssueDto> results = newArrayList(dao.select(query)); | |||
assertThat(results).hasSize(3); | |||
assertThat(results.get(0).getSeverity()).isEqualTo("BLOCKER"); | |||
assertThat(results.get(1).getSeverity()).isEqualTo("MAJOR"); | |||
assertThat(results.get(2).getSeverity()).isEqualTo("MINOR"); | |||
} | |||
@Test | |||
public void should_select_sort_by_status() { | |||
setupData("shared", "should_select_returned_sorted_result_by_status"); | |||
IssueQuery query = IssueQuery.builder().sort(IssueQuery.Sort.STATUS).asc(true).build(); | |||
List<IssueDto> results = newArrayList(dao.select(query)); | |||
assertThat(results).hasSize(3); | |||
assertThat(results.get(0).getStatus()).isEqualTo("CLOSED"); | |||
assertThat(results.get(1).getStatus()).isEqualTo("OPEN"); | |||
assertThat(results.get(2).getStatus()).isEqualTo("REOPEN"); | |||
} | |||
@Test | |||
public void should_select_sort_by_assignee() { | |||
setupData("shared", "should_select_returned_sorted_result"); | |||
setupData("shared", "should_select_returned_sorted_result_by_assignee"); | |||
IssueQuery query = IssueQuery.builder().sort(IssueQuery.Sort.ASSIGNEE).asc(true).build(); | |||
List<IssueDto> results = newArrayList(dao.select(query)); | |||
@@ -233,6 +256,42 @@ public class IssueDaoTest extends AbstractDaoTestCase { | |||
assertThat(results.get(2).getAssignee()).isEqualTo("perceval"); | |||
} | |||
@Test | |||
public void should_select_sort_by_creation_date() { | |||
setupData("shared", "should_select_returned_sorted_result_by_creation_date"); | |||
IssueQuery query = IssueQuery.builder().sort(IssueQuery.Sort.CREATION_DATE).asc(false).build(); | |||
List<IssueDto> results = newArrayList(dao.select(query)); | |||
assertThat(results).hasSize(3); | |||
assertThat(results.get(0).getId()).isEqualTo(102); | |||
assertThat(results.get(1).getId()).isEqualTo(100); | |||
assertThat(results.get(2).getId()).isEqualTo(101); | |||
} | |||
@Test | |||
public void should_select_sort_by_update_date() { | |||
setupData("shared", "should_select_returned_sorted_result_by_update_date"); | |||
IssueQuery query = IssueQuery.builder().sort(IssueQuery.Sort.UPDATE_DATE).asc(false).build(); | |||
List<IssueDto> results = newArrayList(dao.select(query)); | |||
assertThat(results).hasSize(3); | |||
assertThat(results.get(0).getId()).isEqualTo(102); | |||
assertThat(results.get(1).getId()).isEqualTo(100); | |||
assertThat(results.get(2).getId()).isEqualTo(101); | |||
} | |||
@Test | |||
public void should_select_sort_by_close_date() { | |||
setupData("shared", "should_select_returned_sorted_result_by_close_date"); | |||
IssueQuery query = IssueQuery.builder().sort(IssueQuery.Sort.CLOSE_DATE).asc(false).build(); | |||
List<IssueDto> results = newArrayList(dao.select(query)); | |||
assertThat(results).hasSize(3); | |||
assertThat(results.get(0).getId()).isEqualTo(102); | |||
assertThat(results.get(1).getId()).isEqualTo(100); | |||
assertThat(results.get(2).getId()).isEqualTo(101); | |||
} | |||
@Test | |||
public void should_select_issue_and_component_ids() { | |||
setupData("shared", "should_select_issue_and_component_ids"); | |||
@@ -259,7 +318,10 @@ public class IssueDaoTest extends AbstractDaoTestCase { | |||
public void should_select_by_ids() { | |||
setupData("shared", "should_select_by_ids"); | |||
Collection<IssueDto> results = dao.selectByIds(newArrayList(100l, 101l, 102l)); | |||
List<IssueDto> results = newArrayList(dao.selectByIds(newArrayList(100l, 101l, 102l), IssueQuery.Sort.CREATION_DATE, false)); | |||
assertThat(results).hasSize(3); | |||
assertThat(results.get(0).getId()).isEqualTo(102); | |||
assertThat(results.get(1).getId()).isEqualTo(100); | |||
assertThat(results.get(2).getId()).isEqualTo(101); | |||
} | |||
} |
@@ -18,11 +18,11 @@ | |||
assignee="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" | |||
issue_creation_date="2013-04-17" | |||
issue_update_date="2013-04-17" | |||
issue_close_date="2013-04-17" | |||
created_at="2013-04-17" | |||
updated_at="2013-04-17" | |||
/> | |||
<issues | |||
@@ -68,10 +68,10 @@ | |||
assignee="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" | |||
issue_creation_date="2013-04-18" | |||
issue_update_date="2013-04-18" | |||
issue_close_date="2013-04-18" | |||
created_at="2013-04-18" | |||
updated_at="2013-04-18" | |||
/> | |||
</dataset> |
@@ -0,0 +1,77 @@ | |||
<dataset> | |||
<!-- rule 500 --> | |||
<issues | |||
id="100" | |||
kee="ABCDE-1" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="arthur" | |||
author_login="[null]" | |||
attributes="JIRA=FOO-1234" | |||
issue_creation_date="2013-04-16" | |||
issue_update_date="2013-04-17" | |||
issue_close_date="2013-04-17" | |||
created_at="2013-04-16" | |||
updated_at="2013-04-17" | |||
/> | |||
<issues | |||
id="101" | |||
kee="ABCDE-2" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="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" | |||
/> | |||
<!-- rule 501 --> | |||
<issues | |||
id="102" | |||
kee="ABCDE-3" | |||
resource_id="401" | |||
rule_id="501" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="henry" | |||
author_login="[null]" | |||
attributes="JIRA=FOO-1234" | |||
issue_creation_date="2013-04-16" | |||
issue_update_date="2013-04-18" | |||
issue_close_date="2013-04-18" | |||
created_at="2013-04-16" | |||
updated_at="2013-04-18" | |||
/> | |||
</dataset> |
@@ -0,0 +1,74 @@ | |||
<dataset> | |||
<issues | |||
id="100" | |||
kee="ABCDE-1" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="arthur" | |||
author_login="[null]" | |||
attributes="JIRA=FOO-1234" | |||
issue_creation_date="2013-04-15" | |||
issue_update_date="2013-04-16" | |||
issue_close_date="2013-04-16" | |||
created_at="2013-04-15" | |||
updated_at="2013-04-16" | |||
/> | |||
<issues | |||
id="101" | |||
kee="ABCDE-2" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="perceval" | |||
author_login="[null]" | |||
attributes="JIRA=FOO-1234" | |||
issue_creation_date="2013-04-14" | |||
issue_update_date="2013-04-16" | |||
issue_close_date="2013-04-16" | |||
created_at="2013-04-14" | |||
updated_at="2013-04-16" | |||
/> | |||
<issues | |||
id="102" | |||
kee="ABCDE-3" | |||
resource_id="401" | |||
rule_id="501" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="henry" | |||
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> |
@@ -0,0 +1,74 @@ | |||
<dataset> | |||
<issues | |||
id="100" | |||
kee="ABCDE-1" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="MINOR" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="arthur" | |||
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="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="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="401" | |||
rule_id="501" | |||
severity="MAJOR" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="henry" | |||
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> |
@@ -0,0 +1,77 @@ | |||
<dataset> | |||
<!-- rule 500 --> | |||
<issues | |||
id="100" | |||
kee="ABCDE-1" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="arthur" | |||
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="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="CLOSED" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="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" | |||
/> | |||
<!-- rule 501 --> | |||
<issues | |||
id="102" | |||
kee="ABCDE-3" | |||
resource_id="401" | |||
rule_id="501" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="REOPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="henry" | |||
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> |
@@ -0,0 +1,74 @@ | |||
<dataset> | |||
<issues | |||
id="100" | |||
kee="ABCDE-1" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="arthur" | |||
author_login="[null]" | |||
attributes="JIRA=FOO-1234" | |||
issue_creation_date="2013-04-16" | |||
issue_update_date="2013-04-17" | |||
issue_close_date="2013-04-17" | |||
created_at="2013-04-16" | |||
updated_at="2013-04-17" | |||
/> | |||
<issues | |||
id="101" | |||
kee="ABCDE-2" | |||
resource_id="401" | |||
rule_id="500" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="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="401" | |||
rule_id="501" | |||
severity="BLOCKER" | |||
manual_severity="[false]" | |||
message="[null]" | |||
line="200" | |||
effort_to_fix="4.2" | |||
status="OPEN" | |||
resolution="FIXED" | |||
checksum="XXX" | |||
reporter="arthur" | |||
assignee="henry" | |||
author_login="[null]" | |||
attributes="JIRA=FOO-1234" | |||
issue_creation_date="2013-04-16" | |||
issue_update_date="2013-04-18" | |||
issue_close_date="2013-04-18" | |||
created_at="2013-04-16" | |||
updated_at="2013-04-18" | |||
/> | |||
</dataset> |
@@ -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; | |||
@@ -39,7 +40,7 @@ public class IssueQuery { | |||
public static final int MAX_ISSUE_KEYS = 500; | |||
public static enum Sort { | |||
CREATION_DATE, UPDATE_DATE, CLOSE_DATE, ASSIGNEE, SEVERITY | |||
CREATION_DATE, UPDATE_DATE, CLOSE_DATE, ASSIGNEE, SEVERITY, STATUS | |||
} | |||
private final Collection<String> issueKeys; | |||
@@ -58,7 +59,7 @@ public class IssueQuery { | |||
private final Date createdAfter; | |||
private final Date createdBefore; | |||
private final Sort sort; | |||
private final boolean asc; | |||
private final Boolean asc; | |||
private final String requiredRole; | |||
// max results per page | |||
@@ -154,7 +155,7 @@ public class IssueQuery { | |||
return sort; | |||
} | |||
public boolean asc() { | |||
public Boolean asc() { | |||
return asc; | |||
} | |||
@@ -197,7 +198,7 @@ public class IssueQuery { | |||
private Date createdAfter; | |||
private Date createdBefore; | |||
private Sort sort; | |||
private boolean asc = false; | |||
private Boolean asc = false; | |||
private Integer pageSize; | |||
private Integer pageIndex; | |||
private String requiredRole; | |||
@@ -297,7 +298,7 @@ public class IssueQuery { | |||
return this; | |||
} | |||
public Builder asc(boolean asc) { | |||
public Builder asc(Boolean asc) { | |||
this.asc = asc; | |||
return this; | |||
} |
@@ -46,6 +46,7 @@ import org.sonar.core.user.AuthorizationDao; | |||
import org.sonar.server.platform.UserSession; | |||
import javax.annotation.CheckForNull; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Map; | |||
@@ -117,7 +118,7 @@ public class DefaultIssueFinder implements IssueFinder { | |||
Set<Long> pagedIssueIds = pagedIssueIds(authorizedIssues, paging); | |||
// 4. Load issues and their related data (rules, components, comments, action plans, ...) | |||
Collection<IssueDto> pagedIssues = issueDao.selectByIds(pagedIssueIds, sqlSession); | |||
Collection<IssueDto> pagedIssues = issueDao.selectByIds(pagedIssueIds, query.sort(), query.asc(), sqlSession); | |||
Map<String, DefaultIssue> issuesByKey = newHashMap(); | |||
List<Issue> issues = newArrayList(); | |||
Set<Integer> ruleIds = Sets.newHashSet(); |
@@ -32,6 +32,7 @@ import org.sonar.api.web.UserRole; | |||
import org.sonar.server.util.RubyUtils; | |||
import javax.annotation.Nullable; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.List; | |||
@@ -84,7 +85,8 @@ public class PublicRubyIssueService implements RubyIssueService { | |||
builder.pageIndex(RubyUtils.toInteger(props.get("pageIndex"))); | |||
String sort = (String) props.get("sort"); | |||
if (sort != null) { | |||
builder.sort(IssueQuery.Sort.valueOf(sort)); | |||
builder.sort(IssueQuery.Sort.valueOf(sort.toUpperCase())); | |||
builder.asc(RubyUtils.toBoolean(props.get("asc"))); | |||
} | |||
return builder.build(); | |||
} |
@@ -32,7 +32,6 @@ class IssuesController < ApplicationController | |||
@filter.criteria=criteria_params | |||
@filter.execute | |||
# TODO replace by project from issues result API | |||
@project = Project.by_key(@filter.criteria('componentRoots')).root_project if @filter.criteria('componentRoots') | |||
end | |||
@@ -912,5 +912,4 @@ module ApplicationHelper | |||
html | |||
end | |||
end |
@@ -0,0 +1,32 @@ | |||
# | |||
# Sonar, entreprise quality control tool. | |||
# Copyright (C) 2008-2013 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. | |||
# | |||
module IssuesHelper | |||
def column_html(filter, column_label, column_tooltip, sort) | |||
filter_sort = filter.criteria[:sort] | |||
filter_asc = filter.criteria[:asc] == 'true' ? true : false | |||
html = link_to_function(h(column_label), "refreshList('#{escape_javascript sort}',#{!filter_asc}, #{filter.criteria[:page]||1})", :title => h(column_tooltip)) | |||
if sort == filter_sort | |||
html << (filter_asc ? image_tag("asc12.png") : image_tag("desc12.png")) | |||
end | |||
html | |||
end | |||
end |
@@ -20,9 +20,6 @@ | |||
require 'set' | |||
class IssueFilter | |||
CRITERIA_SEPARATOR = '|' | |||
CRITERIA_KEY_VALUE_SEPARATOR = ',' | |||
attr_reader :paging, :issues, :issues_result | |||
def criteria(key=nil) | |||
@@ -75,7 +72,9 @@ class IssueFilter | |||
@issues_result = nil | |||
@paging = nil | |||
@issues = nil | |||
criteria['pageSize'] = 25 | |||
criteria['pageSize'] = 100 | |||
criteria['sort'] ||= 'CREATION_DATE' | |||
criteria['asc'] ||= 'false' | |||
self | |||
end | |||
@@ -1,3 +1,22 @@ | |||
<% content_for :script do %> | |||
<script> | |||
var filterCriteria = <%= @filter.criteria.to_json -%>; | |||
function refreshList(sort, asc, page) { | |||
$j('#issue-filter-foot_pages').hide(); | |||
$j('#issue-filter-foot_loading').show(); | |||
filterCriteria['sort']=sort; | |||
filterCriteria['asc']=asc; | |||
filterCriteria['pageIndex']=page; | |||
var url=baseUrl + '/issues/search?' + $j.param(filterCriteria); | |||
window.location = url; | |||
return false; | |||
} | |||
</script> | |||
<% end %> | |||
<% | |||
if @filter.issues && !@filter.issues.empty? | |||
colspan = 8 | |||
@@ -7,10 +26,10 @@ | |||
<thead> | |||
<tr> | |||
<th width="1%" nowrap> | |||
<%= message('severity_abbreviated') -%> | |||
<%= column_html(@filter, message('severity_abbreviated'), message('severity'), 'SEVERITY') %> | |||
</th> | |||
<th width="1%" nowrap> | |||
<%= message('status_abbreviated') -%> | |||
<%= column_html(@filter, message('status_abbreviated'), message('status'), 'STATUS') %> | |||
</th> | |||
<th> | |||
<%= message('description') -%> | |||
@@ -19,16 +38,16 @@ | |||
<%= message('component') -%> | |||
</th> | |||
<th> | |||
<%= message('issue_filter.header.assignee') -%> | |||
<%= column_html(@filter, message('issue_filter.header.assignee'), message('issue_filter.header.assignee'), 'ASSIGNEE') %> | |||
</th> | |||
<th> | |||
<%= message('issue_filter.header.action_plan') -%> | |||
</th> | |||
<th> | |||
<%= message('issue_filter.header.creation_date') -%> | |||
<%= column_html(@filter, message('issue_filter.header.creation_date'), message('issue_filter.header.creation_date'), 'CREATION_DATE') %> | |||
</th> | |||
<th> | |||
<%= message('issue_filter.header.update_date') -%> | |||
<%= column_html(@filter, message('issue_filter.header.update_date'), message('issue_filter.header.update_date'), 'UPDATE_DATE') %> | |||
</th> | |||
</tr> | |||
</thead> | |||
@@ -44,7 +63,7 @@ | |||
<img src="<%= ApplicationController.root_context -%>/images/status/<%= issue.status -%>.png" title="<%= message(issue.status.downcase).capitalize -%>"/> | |||
</td> | |||
<td> | |||
<%= link_to h(issue.message), :controller => 'issue', :action => 'view', :id => issue.key -%> | |||
<%= link_to h(truncate(issue.message, :length => 100)), :controller => 'issue', :action => 'view', :id => issue.key -%> | |||
</td> | |||
<td> | |||
<%= h @filter.issues_result.component(issue).name -%> | |||
@@ -72,7 +91,7 @@ | |||
<% end %> | |||
</tbody> | |||
<%= paginate_java(@filter.paging, :colspan => colspan, :include_loading_icon => true) { |label, page_id| | |||
<%= paginate_java(@filter.paging, :colspan => colspan, :id => 'issue-filter-foot', :include_loading_icon => true) { |label, page_id| | |||
link_to(label, @filter.criteria.merge({:pageIndex => page_id})) | |||
} -%> | |||
@@ -1,10 +1,13 @@ | |||
<ul class="sidebar gray-sidebar"> | |||
<form method="GET" action="<%= ApplicationController.root_context -%>/issues/search" > | |||
<input type="hidden" name="sort" value="<%= @filter.criteria('sort')-%>"/> | |||
<input type="hidden" name="asc" value="<%= @filter.criteria('asc') -%>"/> | |||
<li class="sidebar-title"> | |||
<%= message('issue_filter.new_search') -%> | |||
</li> | |||
<li id="criteria-project" class="marginbottom5"> | |||
<!-- TODO replace by project from issues result API--> | |||
<% selected_project = @project if @filter.criteria('componentRoots') %> | |||
<%= message 'issue_filter.criteria.project' -%>: | |||
<%= resource_select_tag 'componentRoots', :resource_type_property => 'supportsGlobalDashboards', :width => '100%', |
@@ -3,9 +3,14 @@ | |||
<%= render :partial => 'issues/sidebar' -%> | |||
</div> | |||
<div class="page-split-right"> | |||
<div id="content"> | |||
<div class="marginbottom10"> | |||
<% if @filter.issues_result && @filter.issues_result.securityExclusions() %> | |||
<p class="notes"><%= message('results_not_display_due_to_security') -%></p> | |||
<% end %> | |||
<%= render :partial => 'list' -%> | |||
</div> | |||
</div> |
@@ -53,6 +53,7 @@ import static org.mockito.Matchers.anyInt; | |||
import static org.mockito.Matchers.anySet; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Matchers.eq; | |||
import static org.mockito.Mockito.anyBoolean; | |||
import static org.mockito.Mockito.*; | |||
public class DefaultIssueFinderTest { | |||
@@ -82,7 +83,7 @@ public class DefaultIssueFinderTest { | |||
.setStatus("OPEN").setResolution("OPEN"); | |||
List<IssueDto> dtoList = newArrayList(issue1, issue2); | |||
when(issueDao.selectIssueAndComponentIds(eq(query), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(dtoList); | |||
IssueQueryResult results = finder.find(query); | |||
assertThat(results.issues()).hasSize(2); | |||
@@ -107,11 +108,11 @@ public class DefaultIssueFinderTest { | |||
List<IssueDto> dtoList = newArrayList(issue1, issue2); | |||
when(issueDao.selectIssueAndComponentIds(eq(query), any(SqlSession.class))).thenReturn(dtoList); | |||
when(authorizationDao.keepAuthorizedComponentIds(anySet(), anyInt(), anyString(), any(SqlSession.class))).thenReturn(newHashSet(123)); | |||
when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(newArrayList(issue1)); | |||
when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(newArrayList(issue1)); | |||
IssueQueryResult results = finder.find(query); | |||
verify(issueDao).selectByIds(eq(newHashSet(1L)), any(SqlSession.class)); | |||
verify(issueDao).selectByIds(eq(newHashSet(1L)), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class)); | |||
assertThat(results.securityExclusions()).isTrue(); | |||
} | |||
@@ -131,7 +132,7 @@ public class DefaultIssueFinderTest { | |||
.setStatus("OPEN").setResolution("OPEN"); | |||
List<IssueDto> dtoList = newArrayList(issue1, issue2); | |||
when(issueDao.selectIssueAndComponentIds(eq(query), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(dtoList); | |||
IssueQueryResult results = finder.find(query); | |||
assertThat(results.paging().offset()).isEqualTo(0); | |||
@@ -139,7 +140,7 @@ public class DefaultIssueFinderTest { | |||
assertThat(results.paging().pages()).isEqualTo(2); | |||
// Only one result is expected because the limit is 1 | |||
verify(issueDao).selectByIds(eq(newHashSet(1L)), any(SqlSession.class)); | |||
verify(issueDao).selectByIds(eq(newHashSet(1L)), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class)); | |||
} | |||
@Test | |||
@@ -174,7 +175,7 @@ public class DefaultIssueFinderTest { | |||
.setStatus("OPEN").setResolution("OPEN"); | |||
List<IssueDto> dtoList = newArrayList(issue1, issue2); | |||
when(issueDao.selectIssueAndComponentIds(eq(query), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(dtoList); | |||
IssueQueryResult results = finder.find(query); | |||
assertThat(results.issues()).hasSize(2); | |||
@@ -202,7 +203,7 @@ public class DefaultIssueFinderTest { | |||
.setStatus("OPEN").setResolution("OPEN"); | |||
List<IssueDto> dtoList = newArrayList(issue1, issue2); | |||
when(issueDao.selectIssueAndComponentIds(eq(query), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(dtoList); | |||
IssueQueryResult results = finder.find(query); | |||
assertThat(results.issues()).hasSize(2); | |||
@@ -230,7 +231,7 @@ public class DefaultIssueFinderTest { | |||
.setStatus("OPEN").setResolution("OPEN"); | |||
List<IssueDto> dtoList = newArrayList(issue1, issue2); | |||
when(issueDao.selectIssueAndComponentIds(eq(query), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); | |||
when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(dtoList); | |||
when(actionPlanService.findByKeys(anyCollection())).thenReturn(newArrayList(actionPlan1, actionPlan2)); | |||
IssueQueryResult results = finder.find(query); | |||
@@ -245,7 +246,7 @@ public class DefaultIssueFinderTest { | |||
grantAccessRights(); | |||
IssueQuery query = IssueQuery.builder().build(); | |||
when(issueDao.selectIssueAndComponentIds(eq(query), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList()); | |||
when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList()); | |||
when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList()); | |||
IssueQueryResult results = finder.find(query); |
@@ -74,6 +74,8 @@ public class PublicRubyIssueServiceTest { | |||
map.put("rules", "squid:AvoidCycle,findbugs:NullReference"); | |||
map.put("pageSize", 10l); | |||
map.put("pageIndex", 50); | |||
map.put("sort", "creation_date"); | |||
map.put("asc", true); | |||
IssueQuery query = new PublicRubyIssueService(finder).toQuery(map); | |||
assertThat(query.issueKeys()).containsOnly("ABCDE1234"); | |||
@@ -92,6 +94,8 @@ public class PublicRubyIssueServiceTest { | |||
assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDateTime("2013-04-17T09:08:24+0200")); | |||
assertThat(query.pageSize()).isEqualTo(10); | |||
assertThat(query.pageIndex()).isEqualTo(50); | |||
assertThat(query.sort()).isEqualTo(IssueQuery.Sort.CREATION_DATE); | |||
assertThat(query.asc()).isTrue(); | |||
} | |||
@Test |