From 31bad6e14d7bd97a53c1cb04853025ccf8c92d62 Mon Sep 17 00:00:00 2001 From: diya17 Date: Wed, 6 Mar 2024 16:00:23 -0700 Subject: [PATCH 01/10] [CITE-212] Adding endpoint --- .../core/search/service/SearchEngine.java | 13 +++++++ .../search/service/impl/SearchEngineImpl.java | 24 ++++++++++++ .../citesphere/web/user/SearchController.java | 39 +++++++++++++++++-- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java index 72d98b824..902f7b712 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java @@ -16,6 +16,19 @@ public interface SearchEngine { */ ResultPage search(String searchTerm, String groupId, int page, int pageSize); + /** + * Search for a given term in a group. + * + * @param searchTerm Term to search for. + * @param groupId Group id of the group that should be searched. + * @param collectionId id of the collection that should be searched. + * @param page Current page. + * @param pageSize page size of results. + * @return Page of results + */ + ResultPage search(String searchTerm, String groupId, String collectionId, int page, int pageSize); + + /** * Fetches the next and previous citation keys for the given search term in group and the current index and page number. * diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java index 90bb6c1e3..fb33c0a87 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java @@ -56,6 +56,30 @@ public ResultPage search(String searchTerm, String groupId, int page, int pageSi .should(QueryBuilders.queryStringQuery(searchTerm).field("title").field("creators.name")); BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)); + + NativeSearchQueryBuilder b = new NativeSearchQueryBuilder().withQuery(boolBuilder).withPageable(PageRequest.of(page, pageSize)); + + AggregatedPage results = template.queryForPage(b.build(), Reference.class); + List foundCitations = new ArrayList(); + results.get().forEach(r -> { + foundCitations.add(mapReference(r)); + }); + return new ResultPage(foundCitations, results.getTotalElements(), results.getTotalPages()); + } + + /** + * {@inheritDoc} + * + * This method searches in the title and creators name field for references that are + * not deleted in a collection in a group. + * + */ + @Override + public ResultPage search(String searchTerm, String groupId, String collectionId, int page, int pageSize) { + BoolQueryBuilder orFieldsBuilder = QueryBuilders.boolQuery() + .should(QueryBuilders.queryStringQuery(searchTerm).field("title").field("creators.name")); + BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); + boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)).must(QueryBuilders.termsQuery("collections", collectionId)); NativeSearchQueryBuilder b = new NativeSearchQueryBuilder().withQuery(boolBuilder).withPageable(PageRequest.of(page, pageSize)); AggregatedPage results = template.queryForPage(b.build(), Reference.class); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java index a8b498d68..6cc61688b 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java @@ -19,8 +19,10 @@ import edu.asu.diging.citesphere.core.search.service.SearchEngine; import edu.asu.diging.citesphere.core.search.service.impl.ResultPage; +import edu.asu.diging.citesphere.core.service.ICitationCollectionManager; import edu.asu.diging.citesphere.core.service.IGroupManager; import edu.asu.diging.citesphere.model.bib.ICitation; +import edu.asu.diging.citesphere.model.bib.ICitationCollection; import edu.asu.diging.citesphere.model.bib.ICitationGroup; import edu.asu.diging.citesphere.user.IUser; import edu.asu.diging.citesphere.web.BreadCrumb; @@ -37,6 +39,9 @@ public class SearchController { @Autowired private IGroupManager groupManager; + + @Autowired + private ICitationCollectionManager collectionManager; @Value("${_zotero_page_size}") private Integer zoteroPageSize; @@ -44,8 +49,9 @@ public class SearchController { @Value("${_available_item_columns}") private String availableColumns; - @RequestMapping(value = { "/auth/group/{zoteroGroupId}/search" }) + @RequestMapping(value = { "/auth/group/{zoteroGroupId}/search", "/auth/group/{zoteroGroupId}/collection/{collectionId}/search" }) public String search(@PathVariable String zoteroGroupId, + @PathVariable(value="collectionId", required=false) String collectionId, @RequestParam(value = "searchTerm", required = false) String searchTerm, Model model, @RequestParam(defaultValue = "0", required = false, value = "page") String page, @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, @@ -60,7 +66,10 @@ public String search(@PathVariable String zoteroGroupId, } if (searchTerm == null || searchTerm.trim().isEmpty()) { - return "redirect:/auth/group/" + zoteroGroupId + "/items"; + if (collectionId == null) { + return "redirect:/auth/group/" + zoteroGroupId + "/items"; + } + return "redirect:/auth/group/" + zoteroGroupId + "/collection/" + collectionId + "/items"; } Integer pageInt = 1; @@ -71,8 +80,16 @@ public String search(@PathVariable String zoteroGroupId, } pageInt = pageInt > 0 ? pageInt : 1; + + ResultPage citations; + + if (collectionId == null) { + citations = engine.search(searchTerm, zoteroGroupId, pageInt-1, 50); + } else { + citations = engine.search(searchTerm, zoteroGroupId, collectionId, pageInt-1, 50); + } - ResultPage citations = engine.search(searchTerm, zoteroGroupId, pageInt-1, 50); + model.addAttribute("searchTerm", searchTerm); model.addAttribute("items", citations.getResults()); @@ -80,6 +97,7 @@ public String search(@PathVariable String zoteroGroupId, model.addAttribute("total", citations.getTotalResults()); model.addAttribute("currentPage", pageInt); model.addAttribute("zoteroGroupId", zoteroGroupId); + model.addAttribute("collectionId", collectionId); model.addAttribute("group", groupManager.getGroup(user, zoteroGroupId)); model.addAttribute("sort", sort); @@ -96,6 +114,21 @@ public String search(@PathVariable String zoteroGroupId, model.addAttribute("availableColumns", allowedColumns); List breadCrumbs = new ArrayList<>(); + ICitationCollection collection = null; + if (collectionId != null) { + collection = collectionManager.getCollection(user, zoteroGroupId, collectionId); + if(collection != null) { + model.addAttribute("collectionName", collection.getName()); + } + } + while(collection != null) { + breadCrumbs.add(new BreadCrumb(collection.getName(), BreadCrumbType.COLLECTION, collection.getKey(), collection)); + if (collection.getParentCollectionKey() != null) { + collection = collectionManager.getCollection(user, zoteroGroupId, collection.getParentCollectionKey()); + } else { + collection = null; + } + } breadCrumbs.add(new BreadCrumb(group.getName(), BreadCrumbType.GROUP, group.getGroupId() + "", group)); Collections.reverse(breadCrumbs); model.addAttribute("breadCrumbs", breadCrumbs); From 0f070c37978d6c9cf8dbf782225988e75952c92f Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 12 Mar 2024 15:01:37 -0700 Subject: [PATCH 02/10] [CITE-212] : Debugging query --- .../core/search/service/impl/SearchEngineImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java index fb33c0a87..ee66be3b6 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java @@ -81,10 +81,14 @@ public ResultPage search(String searchTerm, String groupId, String collectionId, BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)).must(QueryBuilders.termsQuery("collections", collectionId)); NativeSearchQueryBuilder b = new NativeSearchQueryBuilder().withQuery(boolBuilder).withPageable(PageRequest.of(page, pageSize)); - + System.out.println("Diya Biju"); + System.out.println(collectionId + groupId); + System.out.println(boolBuilder.toString()); + System.out.println(b.toString()); AggregatedPage results = template.queryForPage(b.build(), Reference.class); List foundCitations = new ArrayList(); results.get().forEach(r -> { + foundCitations.add(mapReference(r)); }); return new ResultPage(foundCitations, results.getTotalElements(), results.getTotalPages()); @@ -128,6 +132,7 @@ public CitationPage getPrevAndNextCitation(String searchTerm, String groupId, in } private ICitation mapReference(Reference ref) { + System.out.println(ref.getTitle()); ICitation citation = new Citation(); citation.setAbstractNote(ref.getAbstractNote()); citation.setAccessDate(ref.getAccessDate()); From 1055f4d33c45a3dd71dcd75cd8b83827ae2d12fd Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 12 Mar 2024 16:00:18 -0700 Subject: [PATCH 03/10] [CITE-212] Changing query to match from terms --- .../citesphere/core/search/service/SearchEngine.java | 2 +- .../core/search/service/impl/SearchEngineImpl.java | 9 ++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java index 902f7b712..eee29f7f3 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/SearchEngine.java @@ -17,7 +17,7 @@ public interface SearchEngine { ResultPage search(String searchTerm, String groupId, int page, int pageSize); /** - * Search for a given term in a group. + * Search for a given term in a collection within the group. * * @param searchTerm Term to search for. * @param groupId Group id of the group that should be searched. diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java index ee66be3b6..dae108a22 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java @@ -71,7 +71,7 @@ public ResultPage search(String searchTerm, String groupId, int page, int pageSi * {@inheritDoc} * * This method searches in the title and creators name field for references that are - * not deleted in a collection in a group. + * not deleted in a collection within a group. * */ @Override @@ -79,12 +79,8 @@ public ResultPage search(String searchTerm, String groupId, String collectionId, BoolQueryBuilder orFieldsBuilder = QueryBuilders.boolQuery() .should(QueryBuilders.queryStringQuery(searchTerm).field("title").field("creators.name")); BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); - boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)).must(QueryBuilders.termsQuery("collections", collectionId)); + boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)).must(QueryBuilders.matchQuery("collections", collectionId)); NativeSearchQueryBuilder b = new NativeSearchQueryBuilder().withQuery(boolBuilder).withPageable(PageRequest.of(page, pageSize)); - System.out.println("Diya Biju"); - System.out.println(collectionId + groupId); - System.out.println(boolBuilder.toString()); - System.out.println(b.toString()); AggregatedPage results = template.queryForPage(b.build(), Reference.class); List foundCitations = new ArrayList(); results.get().forEach(r -> { @@ -132,7 +128,6 @@ public CitationPage getPrevAndNextCitation(String searchTerm, String groupId, in } private ICitation mapReference(Reference ref) { - System.out.println(ref.getTitle()); ICitation citation = new Citation(); citation.setAbstractNote(ref.getAbstractNote()); citation.setAccessDate(ref.getAccessDate()); From cd7e94afe987274271de2f5c0a43d5d74b3d9231 Mon Sep 17 00:00:00 2001 From: diya17 Date: Wed, 13 Mar 2024 10:43:06 -0700 Subject: [PATCH 04/10] [CITE-212] Update search controller --- .../citesphere/web/user/SearchController.java | 72 +++++++++++++++---- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java index 6cc61688b..c879dfc54 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java @@ -49,9 +49,8 @@ public class SearchController { @Value("${_available_item_columns}") private String availableColumns; - @RequestMapping(value = { "/auth/group/{zoteroGroupId}/search", "/auth/group/{zoteroGroupId}/collection/{collectionId}/search" }) + @RequestMapping(value = { "/auth/group/{zoteroGroupId}/search" }) public String search(@PathVariable String zoteroGroupId, - @PathVariable(value="collectionId", required=false) String collectionId, @RequestParam(value = "searchTerm", required = false) String searchTerm, Model model, @RequestParam(defaultValue = "0", required = false, value = "page") String page, @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, @@ -66,9 +65,64 @@ public String search(@PathVariable String zoteroGroupId, } if (searchTerm == null || searchTerm.trim().isEmpty()) { - if (collectionId == null) { - return "redirect:/auth/group/" + zoteroGroupId + "/items"; + return "redirect:/auth/group/" + zoteroGroupId + "/items"; + } + + Integer pageInt = 1; + try { + pageInt = new Integer(page); + } catch (NumberFormatException ex) { + logger.warn("Trying to access invalid page number: " + page); + } + + pageInt = pageInt > 0 ? pageInt : 1; + + ResultPage citations = engine.search(searchTerm, zoteroGroupId, pageInt-1, 50); + + model.addAttribute("searchTerm", searchTerm); + model.addAttribute("items", citations.getResults()); + model.addAttribute("totalPages", Math.max(1, citations.getTotalPages())); + model.addAttribute("total", citations.getTotalResults()); + model.addAttribute("currentPage", pageInt); + model.addAttribute("zoteroGroupId", zoteroGroupId); + model.addAttribute("group", groupManager.getGroup(user, zoteroGroupId)); + model.addAttribute("sort", sort); + + List allowedColumns = Arrays.asList(availableColumns.split(",")); + List shownColumns = new ArrayList<>(); + if (columns != null && columns.length > 0) { + for (String column : columns) { + if (allowedColumns.contains(column)) { + shownColumns.add(column); + } } + } + model.addAttribute("columns", shownColumns); + model.addAttribute("availableColumns", allowedColumns); + + List breadCrumbs = new ArrayList<>(); + breadCrumbs.add(new BreadCrumb(group.getName(), BreadCrumbType.GROUP, group.getGroupId() + "", group)); + Collections.reverse(breadCrumbs); + model.addAttribute("breadCrumbs", breadCrumbs); + return "auth/group/items"; + } + + @RequestMapping(value = {"/auth/group/{zoteroGroupId}/collection/{collectionId}/search"}) + public String searchCollection(@PathVariable String zoteroGroupId, + @PathVariable(value="collectionId", required=false) String collectionId, + @RequestParam(value = "searchTerm", required = false) String searchTerm, Model model, + @RequestParam(defaultValue = "0", required = false, value = "page") String page, + @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, + @RequestParam(required = false, value = "columns") String[] columns, Authentication authentication) { + IUser user = (IUser) authentication.getPrincipal(); + ICitationGroup group = groupManager.getGroup(user, zoteroGroupId); + + if (group == null) { + logger.error("User " + user.getUsername() + " does not have access to group " + zoteroGroupId); + return "error/404"; + } + + if (searchTerm == null || searchTerm.trim().isEmpty()) { return "redirect:/auth/group/" + zoteroGroupId + "/collection/" + collectionId + "/items"; } @@ -81,16 +135,8 @@ public String search(@PathVariable String zoteroGroupId, pageInt = pageInt > 0 ? pageInt : 1; - ResultPage citations; + ResultPage citations = engine.search(searchTerm, zoteroGroupId, collectionId, pageInt-1, 50); - if (collectionId == null) { - citations = engine.search(searchTerm, zoteroGroupId, pageInt-1, 50); - } else { - citations = engine.search(searchTerm, zoteroGroupId, collectionId, pageInt-1, 50); - } - - - model.addAttribute("searchTerm", searchTerm); model.addAttribute("items", citations.getResults()); model.addAttribute("totalPages", Math.max(1, citations.getTotalPages())); From 8debefb2dc1aa64452c48ed8e42fb7209922e5eb Mon Sep 17 00:00:00 2001 From: diya17 Date: Tue, 16 Apr 2024 15:01:43 -0700 Subject: [PATCH 05/10] [CITE-212] Adressing review comments --- .../citesphere/web/user/SearchController.java | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java index c879dfc54..16c006fdf 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java @@ -61,7 +61,7 @@ public String search(@PathVariable String zoteroGroupId, if (group == null) { logger.error("User " + user.getUsername() + " does not have access to group " + zoteroGroupId); - return "error/404"; + return "error/403"; } if (searchTerm == null || searchTerm.trim().isEmpty()) { @@ -99,11 +99,7 @@ public String search(@PathVariable String zoteroGroupId, } model.addAttribute("columns", shownColumns); model.addAttribute("availableColumns", allowedColumns); - - List breadCrumbs = new ArrayList<>(); - breadCrumbs.add(new BreadCrumb(group.getName(), BreadCrumbType.GROUP, group.getGroupId() + "", group)); - Collections.reverse(breadCrumbs); - model.addAttribute("breadCrumbs", breadCrumbs); + model.addAttribute("breadCrumbs", getBreadCrumbs(null, group, user, zoteroGroupId)); return "auth/group/items"; } @@ -119,7 +115,7 @@ public String searchCollection(@PathVariable String zoteroGroupId, if (group == null) { logger.error("User " + user.getUsername() + " does not have access to group " + zoteroGroupId); - return "error/404"; + return "error/403"; } if (searchTerm == null || searchTerm.trim().isEmpty()) { @@ -158,8 +154,6 @@ public String searchCollection(@PathVariable String zoteroGroupId, } model.addAttribute("columns", shownColumns); model.addAttribute("availableColumns", allowedColumns); - - List breadCrumbs = new ArrayList<>(); ICitationCollection collection = null; if (collectionId != null) { collection = collectionManager.getCollection(user, zoteroGroupId, collectionId); @@ -167,6 +161,12 @@ public String searchCollection(@PathVariable String zoteroGroupId, model.addAttribute("collectionName", collection.getName()); } } + model.addAttribute("breadCrumbs", getBreadCrumbs(collection, group, user, zoteroGroupId)); + return "auth/group/items"; + } + + private List getBreadCrumbs(ICitationCollection collection, ICitationGroup group, IUser user, String zoteroGroupId) { + List breadCrumbs = new ArrayList<>(); while(collection != null) { breadCrumbs.add(new BreadCrumb(collection.getName(), BreadCrumbType.COLLECTION, collection.getKey(), collection)); if (collection.getParentCollectionKey() != null) { @@ -177,7 +177,6 @@ public String searchCollection(@PathVariable String zoteroGroupId, } breadCrumbs.add(new BreadCrumb(group.getName(), BreadCrumbType.GROUP, group.getGroupId() + "", group)); Collections.reverse(breadCrumbs); - model.addAttribute("breadCrumbs", breadCrumbs); - return "auth/group/items"; + return breadCrumbs; } } From 469c01449e17a559b3c6191031435392fab62124 Mon Sep 17 00:00:00 2001 From: Rajvi Patel Date: Wed, 25 Jun 2025 12:00:43 -0700 Subject: [PATCH 06/10] [CITE-212] Add collectionId field and its getter/setter methods to the SearchItemsDataDto class --- .../diging/citesphere/web/user/SearchItemsDataDto.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchItemsDataDto.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchItemsDataDto.java index e4442151c..50dc6b801 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchItemsDataDto.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchItemsDataDto.java @@ -15,6 +15,7 @@ public class SearchItemsDataDto { private long totalResults; private int currentPage; private String zoteroGroupId; + private String collectionId; private ICitationGroup group; private String sort; private List citationsData; @@ -69,6 +70,14 @@ public void setZoteroGroupId(String zoteroGroupId) { this.zoteroGroupId = zoteroGroupId; } + public String getCollectionId() { + return collectionId; + } + + public void setCollectionId(String collectionId) { + this.collectionId = collectionId; + } + public ICitationGroup getGroup() { return group; } From 857052f0e05d56ad5ca3138d22631f8cea8049ab Mon Sep 17 00:00:00 2001 From: Rajvi Patel Date: Thu, 26 Jun 2025 16:18:15 -0700 Subject: [PATCH 07/10] [CITE-212] Changed the collection search endpoint from returning a view name to returning JSON data --- .../citesphere/web/user/SearchController.java | 47 +++++++++---------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java index 0513c5d37..019434a2f 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java @@ -120,7 +120,7 @@ public class SearchController { } @RequestMapping(value = {"/auth/group/{zoteroGroupId}/collection/{collectionId}/search"}) - public String searchCollection(@PathVariable String zoteroGroupId, + public @ResponseBody String searchCollection(@PathVariable String zoteroGroupId, @PathVariable(value="collectionId", required=false) String collectionId, @RequestParam(value = "searchTerm", required = false) String searchTerm, Model model, @RequestParam(defaultValue = "0", required = false, value = "page") String page, @@ -149,36 +149,35 @@ public String searchCollection(@PathVariable String zoteroGroupId, ResultPage citations = engine.search(searchTerm, zoteroGroupId, collectionId, pageInt-1, 50); - model.addAttribute("searchTerm", searchTerm); - model.addAttribute("items", citations.getResults()); - model.addAttribute("totalPages", Math.max(1, citations.getTotalPages())); - model.addAttribute("total", citations.getTotalResults()); - model.addAttribute("currentPage", pageInt); - model.addAttribute("zoteroGroupId", zoteroGroupId); - model.addAttribute("collectionId", collectionId); - model.addAttribute("group", groupManager.getGroup(user, zoteroGroupId)); - model.addAttribute("sort", sort); - - List allowedColumns = Arrays.asList(availableColumns.split(",")); + SearchItemsDataDto searchItemsData = new SearchItemsDataDto(); + searchItemsData.setSearchTerm(searchTerm); + searchItemsData.setCurrentPage(pageInt); + searchItemsData.setCitationsData(citations.getResults().stream().map(c -> new CitationsDto(c, + env.getProperty(c.getItemType() + "_label"), env.getProperty(c.getItemType() + "_icon"))) + .collect(Collectors.toList())); + searchItemsData.setTotalPages(Math.max(1, citations.getTotalPages())); + searchItemsData.setZoteroGroupId(zoteroGroupId); + searchItemsData.setCollectionId(collectionId); + searchItemsData.setSort(sort); + searchItemsData.setTotalResults(citations.getTotalResults()); + searchItemsData.setGroup(group); + + List availableColumnsList = Arrays.asList(availableColumns.split(",")); List shownColumns = new ArrayList<>(); if (columns != null && columns.length > 0) { for (String column : columns) { - if (allowedColumns.contains(column)) { + if (availableColumnsList.contains(column)) { shownColumns.add(column); } } } - model.addAttribute("columns", shownColumns); - model.addAttribute("availableColumns", allowedColumns); - ICitationCollection collection = null; - if (collectionId != null) { - collection = collectionManager.getCollection(user, zoteroGroupId, collectionId); - if(collection != null) { - model.addAttribute("collectionName", collection.getName()); - } - } - model.addAttribute("breadCrumbs", getBreadCrumbs(collection, group, user, zoteroGroupId)); - return "auth/group/items"; + searchItemsData.setShownColumns(shownColumns); + searchItemsData.setAvailableColumnsData(availableColumnsList.stream() + .map(c -> new AvailableColumnsDataDto(c, env.getProperty("_item_attribute_label_" + c))) + .collect(Collectors.toList())); + + Gson gson = new Gson(); + return gson.toJson(searchItemsData, SearchItemsDataDto.class); } private List getBreadCrumbs(ICitationCollection collection, ICitationGroup group, IUser user, String zoteroGroupId) { From 83d0b271ffcd92119bdd38221bfa03c58b456ae7 Mon Sep 17 00:00:00 2001 From: Rajvi Patel Date: Fri, 27 Jun 2025 08:45:40 -0700 Subject: [PATCH 08/10] [CITE-212] Code cleanup --- .../search/service/impl/SearchEngineImpl.java | 1 - .../citesphere/web/user/SearchController.java | 15 --------------- .../webapp/WEB-INF/views/auth/group/items.html | 14 ++++++++++++-- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java index dae108a22..bdcc287de 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java @@ -56,7 +56,6 @@ public ResultPage search(String searchTerm, String groupId, int page, int pageSi .should(QueryBuilders.queryStringQuery(searchTerm).field("title").field("creators.name")); BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)); - NativeSearchQueryBuilder b = new NativeSearchQueryBuilder().withQuery(boolBuilder).withPageable(PageRequest.of(page, pageSize)); AggregatedPage results = template.queryForPage(b.build(), Reference.class); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java index 019434a2f..ae8ed1699 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java @@ -179,19 +179,4 @@ public class SearchController { Gson gson = new Gson(); return gson.toJson(searchItemsData, SearchItemsDataDto.class); } - - private List getBreadCrumbs(ICitationCollection collection, ICitationGroup group, IUser user, String zoteroGroupId) { - List breadCrumbs = new ArrayList<>(); - while(collection != null) { - breadCrumbs.add(new BreadCrumb(collection.getName(), BreadCrumbType.COLLECTION, collection.getKey(), collection)); - if (collection.getParentCollectionKey() != null) { - collection = collectionManager.getCollection(user, zoteroGroupId, collection.getParentCollectionKey()); - } else { - collection = null; - } - } - breadCrumbs.add(new BreadCrumb(group.getName(), BreadCrumbType.GROUP, group.getGroupId() + "", group)); - Collections.reverse(breadCrumbs); - return breadCrumbs; - } } diff --git a/citesphere/src/main/webapp/WEB-INF/views/auth/group/items.html b/citesphere/src/main/webapp/WEB-INF/views/auth/group/items.html index 3965aeff8..b392be241 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/auth/group/items.html +++ b/citesphere/src/main/webapp/WEB-INF/views/auth/group/items.html @@ -118,7 +118,12 @@ $("#findByItemKeyBtn").click(function() { var key = $("#findItemKey").val(); if (key != undefined && key != '') { - window.location.href="items/" + key; + var itemUrl = "items/" + key; + var currentURL = window.location.href; + if(currentURL.match(/collection/)){ + itemUrl = "../../items/" + key; + } + window.location.href = itemUrl; } }); @@ -126,7 +131,12 @@ if(e.which == 13) { var key = $("#findItemKey").val(); if (key != undefined && key != '') { - window.location.href="items/" + key; + var itemUrl = "items/" + key; + var currentURL = window.location.href; + if(currentURL.match(/collection/)){ + itemUrl = "../../items/" + key; + } + window.location.href = itemUrl; } } }); From 18855caf33564d7afe51a427fc0ce04d5dec52d3 Mon Sep 17 00:00:00 2001 From: Rajvi Patel Date: Fri, 5 Sep 2025 16:35:58 -0700 Subject: [PATCH 09/10] [CITE-212] Added private helper method performSearch --- .../search/service/impl/SearchEngineImpl.java | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java index bdcc287de..ff027a0c4 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/search/service/impl/SearchEngineImpl.java @@ -52,18 +52,7 @@ public class SearchEngineImpl implements SearchEngine { */ @Override public ResultPage search(String searchTerm, String groupId, int page, int pageSize) { - BoolQueryBuilder orFieldsBuilder = QueryBuilders.boolQuery() - .should(QueryBuilders.queryStringQuery(searchTerm).field("title").field("creators.name")); - BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); - boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)); - NativeSearchQueryBuilder b = new NativeSearchQueryBuilder().withQuery(boolBuilder).withPageable(PageRequest.of(page, pageSize)); - - AggregatedPage results = template.queryForPage(b.build(), Reference.class); - List foundCitations = new ArrayList(); - results.get().forEach(r -> { - foundCitations.add(mapReference(r)); - }); - return new ResultPage(foundCitations, results.getTotalElements(), results.getTotalPages()); + return performSearch(searchTerm, groupId, null, page, pageSize); } /** @@ -75,15 +64,38 @@ public ResultPage search(String searchTerm, String groupId, int page, int pageSi */ @Override public ResultPage search(String searchTerm, String groupId, String collectionId, int page, int pageSize) { + return performSearch(searchTerm, groupId, collectionId, page, pageSize); + } + + /** + * Common search implementation that handles both collection-specific and general searches. + * + * @param searchTerm the term to search for in title and creators.name fields + * @param groupId the group ID to filter by + * @param collectionId the collection ID to filter by (optional, can be null) + * @param page the page number for pagination + * @param pageSize the number of results per page + * @return ResultPage containing the search results + */ + private ResultPage performSearch(String searchTerm, String groupId, String collectionId, int page, int pageSize) { BoolQueryBuilder orFieldsBuilder = QueryBuilders.boolQuery() .should(QueryBuilders.queryStringQuery(searchTerm).field("title").field("creators.name")); BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); - boolBuilder.must(orFieldsBuilder).must(QueryBuilders.matchQuery("deleted", false)).must(QueryBuilders.matchQuery("group", groupId)).must(QueryBuilders.matchQuery("collections", collectionId)); - NativeSearchQueryBuilder b = new NativeSearchQueryBuilder().withQuery(boolBuilder).withPageable(PageRequest.of(page, pageSize)); + boolBuilder.must(orFieldsBuilder) + .must(QueryBuilders.matchQuery("deleted", false)) + .must(QueryBuilders.matchQuery("group", groupId)); + + if (collectionId != null) { + boolBuilder.must(QueryBuilders.matchQuery("collections", collectionId)); + } + + NativeSearchQueryBuilder b = new NativeSearchQueryBuilder() + .withQuery(boolBuilder) + .withPageable(PageRequest.of(page, pageSize)); + AggregatedPage results = template.queryForPage(b.build(), Reference.class); List foundCitations = new ArrayList(); results.get().forEach(r -> { - foundCitations.add(mapReference(r)); }); return new ResultPage(foundCitations, results.getTotalElements(), results.getTotalPages()); From c0681fb1672e9c09e6085184126807c73a2bbecb Mon Sep 17 00:00:00 2001 From: Rajvi Patel Date: Wed, 10 Sep 2025 12:05:16 -0700 Subject: [PATCH 10/10] [CITE-212] Update requestMapping logic to eliminate duplication --- .../citesphere/web/user/SearchController.java | 82 ++++--------------- 1 file changed, 17 insertions(+), 65 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java index ae8ed1699..82e970b86 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SearchController.java @@ -58,8 +58,9 @@ public class SearchController { @Autowired private Environment env; - @RequestMapping(value = { "/auth/group/{zoteroGroupId}/search" }) + @RequestMapping(value = { "/auth/group/{zoteroGroupId}/search", "/auth/group/{zoteroGroupId}/collection/{collectionId}/search" }) public @ResponseBody String search(@PathVariable String zoteroGroupId, + @PathVariable(value = "collectionId", required = false) String collectionId, @RequestParam(value = "searchTerm", required = false) String searchTerm, Model model, @RequestParam(defaultValue = "0", required = false, value = "page") String page, @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, @@ -74,81 +75,30 @@ public class SearchController { } if (searchTerm == null || searchTerm.trim().isEmpty()) { - return "redirect:/auth/group/" + zoteroGroupId + "/items"; + String redirectUrl = "/auth/group/" + zoteroGroupId; + if (collectionId != null) { + redirectUrl += "/collection/" + collectionId; + } + redirectUrl += "/items"; + return "redirect:" + redirectUrl; } Integer pageInt = 1; try { - pageInt = new Integer(page); + pageInt = Integer.valueOf(page); } catch (NumberFormatException ex) { logger.warn("Trying to access invalid page number: " + page); } pageInt = pageInt > 0 ? pageInt : 1; - ResultPage citations = engine.search(searchTerm, zoteroGroupId, pageInt - 1, 50); - - SearchItemsDataDto searchItemsData = new SearchItemsDataDto(); - searchItemsData.setSearchTerm(searchTerm); - searchItemsData.setCurrentPage(pageInt); - searchItemsData.setCitationsData(citations.getResults().stream().map(c -> new CitationsDto(c, - env.getProperty(c.getItemType() + "_label"), env.getProperty(c.getItemType() + "_icon"))) - .collect(Collectors.toList())); - searchItemsData.setTotalPages(Math.max(1, citations.getTotalPages())); - searchItemsData.setZoteroGroupId(zoteroGroupId); - searchItemsData.setSort(sort); - searchItemsData.setTotalResults(citations.getTotalResults()); - searchItemsData.setGroup(group); - - List availableColumnsList = Arrays.asList(availableColumns.split(",")); - List shownColumns = new ArrayList<>(); - if (columns != null && columns.length > 0) { - for (String column : columns) { - if (availableColumnsList.contains(column)) { - shownColumns.add(column); - } - } - } - searchItemsData.setShownColumns(shownColumns); - searchItemsData.setAvailableColumnsData(availableColumnsList.stream() - .map(c -> new AvailableColumnsDataDto(c, env.getProperty("_item_attribute_label_" + c))) - .collect(Collectors.toList())); - - Gson gson = new Gson(); - - return gson.toJson(searchItemsData, SearchItemsDataDto.class); - } - - @RequestMapping(value = {"/auth/group/{zoteroGroupId}/collection/{collectionId}/search"}) - public @ResponseBody String searchCollection(@PathVariable String zoteroGroupId, - @PathVariable(value="collectionId", required=false) String collectionId, - @RequestParam(value = "searchTerm", required = false) String searchTerm, Model model, - @RequestParam(defaultValue = "0", required = false, value = "page") String page, - @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, - @RequestParam(required = false, value = "columns") String[] columns, Authentication authentication) { - IUser user = (IUser) authentication.getPrincipal(); - ICitationGroup group = groupManager.getGroup(user, zoteroGroupId); - - if (group == null) { - logger.error("User " + user.getUsername() + " does not have access to group " + zoteroGroupId); - return "error/403"; + ResultPage citations; + if (collectionId != null) { + citations = engine.search(searchTerm, zoteroGroupId, collectionId, pageInt - 1, 50); + } else { + citations = engine.search(searchTerm, zoteroGroupId, pageInt - 1, 50); } - if (searchTerm == null || searchTerm.trim().isEmpty()) { - return "redirect:/auth/group/" + zoteroGroupId + "/collection/" + collectionId + "/items"; - } - - Integer pageInt = 1; - try { - pageInt = new Integer(page); - } catch (NumberFormatException ex) { - logger.warn("Trying to access invalid page number: " + page); - } - - pageInt = pageInt > 0 ? pageInt : 1; - - ResultPage citations = engine.search(searchTerm, zoteroGroupId, collectionId, pageInt-1, 50); - SearchItemsDataDto searchItemsData = new SearchItemsDataDto(); searchItemsData.setSearchTerm(searchTerm); searchItemsData.setCurrentPage(pageInt); @@ -157,7 +107,9 @@ public class SearchController { .collect(Collectors.toList())); searchItemsData.setTotalPages(Math.max(1, citations.getTotalPages())); searchItemsData.setZoteroGroupId(zoteroGroupId); - searchItemsData.setCollectionId(collectionId); + if (collectionId != null) { + searchItemsData.setCollectionId(collectionId); + } searchItemsData.setSort(sort); searchItemsData.setTotalResults(citations.getTotalResults()); searchItemsData.setGroup(group);