From c93e1fea3a623d6d214c3fcb7b33cdd93c774937 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Tue, 21 May 2013 12:12:17 +0200 Subject: [PATCH] SONAR-4301 Add sort on issue search page --- .../org/sonar/core/issue/db/IssueDao.java | 12 +-- .../org/sonar/core/issue/db/IssueMapper.xml | 61 +++++++++------ .../org/sonar/core/issue/db/IssueDaoTest.java | 68 +++++++++++++++- .../db/IssueDaoTest/should_select_by_ids.xml | 20 ++--- ...ct_returned_sorted_result_by_assignee.xml} | 0 ...t_returned_sorted_result_by_close_date.xml | 77 +++++++++++++++++++ ...eturned_sorted_result_by_creation_date.xml | 74 ++++++++++++++++++ ...ect_returned_sorted_result_by_severity.xml | 74 ++++++++++++++++++ ...elect_returned_sorted_result_by_status.xml | 77 +++++++++++++++++++ ..._returned_sorted_result_by_update_date.xml | 74 ++++++++++++++++++ .../java/org/sonar/api/issue/IssueQuery.java | 11 +-- .../server/issue/DefaultIssueFinder.java | 3 +- .../server/issue/PublicRubyIssueService.java | 4 +- .../app/controllers/issues_controller.rb | 1 - .../WEB-INF/app/helpers/application_helper.rb | 1 - .../WEB-INF/app/helpers/issues_helper.rb | 32 ++++++++ .../webapp/WEB-INF/app/models/issue_filter.rb | 7 +- .../WEB-INF/app/views/issues/_list.html.erb | 33 ++++++-- .../app/views/issues/_sidebar.html.erb | 5 +- .../WEB-INF/app/views/issues/search.html.erb | 5 ++ .../server/issue/DefaultIssueFinderTest.java | 19 ++--- .../issue/PublicRubyIssueServiceTest.java | 4 + 22 files changed, 589 insertions(+), 73 deletions(-) rename sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/{should_select_returned_sorted_result.xml => should_select_returned_sorted_result_by_assignee.xml} (100%) create mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_returned_sorted_result_by_close_date.xml create mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_returned_sorted_result_by_creation_date.xml create mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_returned_sorted_result_by_severity.xml create mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_returned_sorted_result_by_status.xml create mode 100644 sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_returned_sorted_result_by_update_date.xml create mode 100644 sonar-server/src/main/webapp/WEB-INF/app/helpers/issues_helper.rb diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java index 6a67dcf6774..2fa1dba1ed1 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java @@ -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 selectByIds(Collection ids) { + @VisibleForTesting + Collection selectByIds(Collection 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 selectByIds(Collection ids, SqlSession session) { + public Collection selectByIds(Collection ids, IssueQuery.Sort sort, boolean asc, SqlSession session) { if (ids.isEmpty()) { return Collections.emptyList(); } - List> idsPartition = Lists.partition(newArrayList(ids), 1000); - Map>> params = ImmutableMap.of("ids", idsPartition); + Object idsPartition = Lists.partition(newArrayList(ids), 1000); + Map params = ImmutableMap.of("ids", idsPartition, "sort", sort, "asc", asc); return session.selectList("org.sonar.core.issue.db.IssueMapper.selectByIds", params); } } 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 40fc177e27d..9717a2417cf 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 @@ -32,6 +32,40 @@ p.kee as componentKey + + + order by + + + i.severity + + + i.status + + + i.assignee + + + i.issue_creation_date + + + i.issue_update_date + + + i.issue_close_date + + + + + asc + + + desc + + + + + 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 + + +
  • - <% selected_project = @project if @filter.criteria('componentRoots') %> <%= message 'issue_filter.criteria.project' -%>: <%= resource_select_tag 'componentRoots', :resource_type_property => 'supportsGlobalDashboards', :width => '100%', diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb index 1234b293a22..ffc32f12e80 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb +++ b/sonar-server/src/main/webapp/WEB-INF/app/views/issues/search.html.erb @@ -3,9 +3,14 @@ <%= render :partial => 'issues/sidebar' -%> +
    + <% if @filter.issues_result && @filter.issues_result.securityExclusions() %> +

    <%= message('results_not_display_due_to_security') -%>

    + <% end %> + <%= render :partial => 'list' -%>
    diff --git a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java index 0c9fdea9f40..fd4bca4597a 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueFinderTest.java @@ -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 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 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 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 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 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 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.emptyList()); - when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(Collections.emptyList()); + when(issueDao.selectByIds(anyCollection(), any(IssueQuery.Sort.class), anyBoolean(), any(SqlSession.class))).thenReturn(Collections.emptyList()); IssueQueryResult results = finder.find(query); 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 1267beb69ae..17c2a5262b2 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 @@ -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 -- 2.39.5