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..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 @@ -16,6 +16,19 @@ public interface SearchEngine { */ ResultPage search(String searchTerm, String groupId, int page, int pageSize); + /** + * 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. + * @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..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,12 +52,47 @@ public class SearchEngineImpl implements SearchEngine { */ @Override public ResultPage search(String searchTerm, String groupId, int page, int pageSize) { + return performSearch(searchTerm, groupId, null, page, pageSize); + } + + /** + * {@inheritDoc} + * + * This method searches in the title and creators name field for references that are + * not deleted in a collection within a group. + * + */ + @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)); - 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 -> { 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 e80c2cca3..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 @@ -2,6 +2,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -23,9 +24,13 @@ 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.ICitationCollection; import edu.asu.diging.citesphere.model.bib.ICitationGroup; import edu.asu.diging.citesphere.user.IUser; +import edu.asu.diging.citesphere.web.BreadCrumb; +import edu.asu.diging.citesphere.web.BreadCrumbType; @Controller @PropertySource("classpath:/config.properties") @@ -40,6 +45,9 @@ public class SearchController { @Autowired private IGroupManager groupManager; + + @Autowired + private ICitationCollectionManager collectionManager; @Value("${_zotero_page_size}") private Integer zoteroPageSize; @@ -50,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, @@ -62,23 +71,33 @@ public class SearchController { 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()) { - 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); + ResultPage citations; + if (collectionId != null) { + citations = engine.search(searchTerm, zoteroGroupId, collectionId, pageInt - 1, 50); + } else { + citations = engine.search(searchTerm, zoteroGroupId, pageInt - 1, 50); + } SearchItemsDataDto searchItemsData = new SearchItemsDataDto(); searchItemsData.setSearchTerm(searchTerm); @@ -88,6 +107,9 @@ public class SearchController { .collect(Collectors.toList())); searchItemsData.setTotalPages(Math.max(1, citations.getTotalPages())); searchItemsData.setZoteroGroupId(zoteroGroupId); + if (collectionId != null) { + searchItemsData.setCollectionId(collectionId); + } searchItemsData.setSort(sort); searchItemsData.setTotalResults(citations.getTotalResults()); searchItemsData.setGroup(group); @@ -107,7 +129,6 @@ public class SearchController { .collect(Collectors.toList())); Gson gson = new Gson(); - return gson.toJson(searchItemsData, SearchItemsDataDto.class); } } 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; } 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; } } });