diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/ItemsApiController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/ItemsApiController.java index b9cd34be3..e83a3f4ac 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/ItemsApiController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/api/v1/user/ItemsApiController.java @@ -65,7 +65,7 @@ public ResponseEntity getCollectionsByGroupId(@RequestHeader HttpHeaders @PathVariable("zoteroGroupId") String groupId, @PathVariable(value = "collectionId", required = false) String collectionId, @RequestParam(defaultValue = "1", required = false, value = "page") String page, - @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, + @RequestParam(defaultValue = "title", required = false, value = "sortBy") String sort, @RequestParam(required = false, value = "columns") String[] columns, Principal principal) throws GroupDoesNotExistException { Integer pageInt = 1; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index e2aff4cb4..b612938fa 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -2,6 +2,8 @@ import java.time.OffsetDateTime; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -15,8 +17,6 @@ import javax.transaction.Transactional; import org.bson.types.ObjectId; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; @@ -47,6 +47,7 @@ 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.model.bib.IPerson; import edu.asu.diging.citesphere.model.bib.IReference; import edu.asu.diging.citesphere.model.bib.ItemType; import edu.asu.diging.citesphere.model.bib.impl.BibField; @@ -93,11 +94,68 @@ public class CitationManager implements ICitationManager { @PostConstruct public void init() { sortFunctions = new HashMap<>(); - sortFunctions.put("title", ((o1, o2) -> { - String o1Title = o1 != null && o1.getTitle() != null ? o1.getTitle() : ""; - String o2Title = o2 != null && o2.getTitle() != null ? o2.getTitle() : ""; - return o1Title.toLowerCase().compareTo(o2Title.toLowerCase()); - })); + // Title + sortFunctions.put("title", (o1, o2) -> { + String t1 = Optional.ofNullable(o1).map(ICitation::getTitle).orElse("").toLowerCase(); + String t2 = Optional.ofNullable(o2).map(ICitation::getTitle).orElse("").toLowerCase(); + return t1.compareTo(t2); + }); + // Type + sortFunctions.put("type", (o1, o2) -> { + String s1 = Optional.ofNullable(o1) + .map(ICitation::getItemType) + .map(Enum::name) + .orElse(""); + String s2 = Optional.ofNullable(o2) + .map(ICitation::getItemType) + .map(Enum::name) + .orElse(""); + return s1.compareToIgnoreCase(s2); + }); + // Author + sortFunctions.put("author", (o1, o2) -> { + List authors1 = o1 != null && o1.getAuthors() != null + ? new ArrayList<>(o1.getAuthors()) + : Collections.emptyList(); + List authors2 = o2 != null && o2.getAuthors() != null + ? new ArrayList<>(o2.getAuthors()) + : Collections.emptyList(); + + int minSize = Math.min(authors1.size(), authors2.size()); + + for (int i = 0; i < minSize; i++) { + IPerson p1 = authors1.get(i); + IPerson p2 = authors2.get(i); + if(p1!=null && p2!=null) { + String ln1 = p1.getLastName() != null ? p1.getLastName().replaceAll("\\s+", " ").trim() : ""; + String ln2 = p2.getLastName() != null ? p2.getLastName().replaceAll("\\s+", " ").trim() : ""; + + int cmp = ln1.compareToIgnoreCase(ln2); + if (cmp != 0) return cmp; + + String fn1 = p1.getFirstName() != null ? p1.getFirstName().replaceAll("\\s+", " ").trim() : ""; + String fn2 = p2.getFirstName() != null ? p2.getFirstName().replaceAll("\\s+", " ").trim() : ""; + + cmp = fn1.compareToIgnoreCase(fn2); + if (cmp != 0) return cmp; + } + } + return Integer.compare(authors1.size(), authors2.size()); + }); + + // Date (dateFreetext) + sortFunctions.put("date", (o1, o2) -> { + String d1 = Optional.ofNullable(o1).map(ICitation::getDateFreetext).orElse(""); + String d2 = Optional.ofNullable(o2).map(ICitation::getDateFreetext).orElse(""); + return d1.compareToIgnoreCase(d2); + }); + + // URL + sortFunctions.put("url", (o1, o2) -> { + String u1 = Optional.ofNullable(o1).map(ICitation::getUrl).orElse("").toLowerCase(); + String u2 = Optional.ofNullable(o2).map(ICitation::getUrl).orElse("").toLowerCase(); + return u1.compareToIgnoreCase(u2); + }); } @Override @@ -443,6 +501,11 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti total = citations.size(); } } + BiFunction sorter = sortFunctions.get(sortBy); + if (sorter != null) { + Comparator comparator = sorter::apply; + citations.sort(comparator); + } results.setCitations(citations != null ? citations : new ArrayList<>()); results.setTotalResults(total); return results; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/CollectionItemsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/CollectionItemsController.java index 0bd328a3a..2d03e9448 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/CollectionItemsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/CollectionItemsController.java @@ -33,7 +33,7 @@ public class CollectionItemsController { public String show(Authentication authentication, Model model, @PathVariable("zoteroGroupId") String groupId, @RequestParam(defaultValue = "1", required = false, value = "page") String page, - @RequestParam(defaultValue = "title", required = false, value = "sort") String sort) + @RequestParam(defaultValue = "title", required = false, value = "sortBy") String sort) throws GroupDoesNotExistException, ZoteroHttpStatusException { Integer pageInt = 1; try { @@ -49,7 +49,7 @@ public String show(Authentication authentication, Model model, @PathVariable("zo model.addAttribute("totalPages", Math.ceil(new Float(results.getTotalResults()) / new Float(zoteroPageSize))); model.addAttribute("currentPage", pageInt); model.addAttribute("zoteroGroupId", groupId); - model.addAttribute("citationCollections", collectionManager.getCitationCollections(user, groupId, null, pageInt, "title").getCitationCollections()); + model.addAttribute("citationCollections", collectionManager.getCitationCollections(user, groupId, null, pageInt, sort).getCitationCollections()); return "auth/group/items"; } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/FetchItemsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/FetchItemsController.java index 3eca9681d..1d2a2b34d 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/FetchItemsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/FetchItemsController.java @@ -58,7 +58,7 @@ public class FetchItemsController { public @ResponseBody String show(Authentication authentication, @PathVariable("zoteroGroupId") String groupId, @PathVariable(value = "collectionId", required = false) String collectionId, @RequestParam(defaultValue = "1", required = false, value = "page") String page, - @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, + @RequestParam(defaultValue = "title", required = false, value = "sortBy") String sort, @RequestParam(required = false, value = "columns") String[] columns) { Integer pageInt = 1; try { @@ -93,7 +93,7 @@ public class FetchItemsController { try { itemsData.setCitationCollections( - collectionManager.getAllCollections(user, groupId, collectionId, "title", 200)); + collectionManager.getAllCollections(user, groupId, collectionId, sort, 200)); } catch (GroupDoesNotExistException e) { logger.error("Group does not exist exception occured while fecting items data", e); return "error/404"; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/GroupItemsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/GroupItemsController.java index b4c7de9ef..f40ad51c7 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/GroupItemsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/GroupItemsController.java @@ -58,7 +58,7 @@ public class GroupItemsController { public String show(Authentication authentication, Model model, @PathVariable("zoteroGroupId") String groupId, @PathVariable(value="collectionId", required=false) String collectionId, @RequestParam(defaultValue = "1", required = false, value = "page") String page, - @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, + @RequestParam(defaultValue = "title", required = false, value = "sortBy") String sortBy, @RequestParam(required = false, value = "columns") String[] columns, @RequestParam(required = false, defaultValue = "", value = "conceptIds") String[] conceptIds) { Integer pageInt = 1; @@ -70,7 +70,7 @@ public String show(Authentication authentication, Model model, @PathVariable("zo IUser user = (IUser) authentication.getPrincipal(); CitationResults results; try { - results = citationManager.getGroupItems(user, groupId, collectionId, pageInt, sort, Arrays.asList(conceptIds)); + results = citationManager.getGroupItems(user, groupId, collectionId, pageInt, sortBy, Arrays.asList(conceptIds)); } catch(ZoteroHttpStatusException e) { logger.error("Exception occured", e); return "error/500"; @@ -86,11 +86,11 @@ public String show(Authentication authentication, Model model, @PathVariable("zo model.addAttribute("zoteroGroupId", groupId); model.addAttribute("group", groupManager.getGroup(user, groupId)); model.addAttribute("collectionId", collectionId); - model.addAttribute("sort", sort); + model.addAttribute("sortBy", sortBy); model.addAttribute("results", results); // more than 200 really don't make sense here, this needs to be changed try { - model.addAttribute("citationCollections", collectionManager.getAllCollections(user, groupId, collectionId, "title", 200)); + model.addAttribute("citationCollections", collectionManager.getAllCollections(user, groupId, collectionId, sortBy, 200)); } catch(GroupDoesNotExistException e) { logger.error("Exception occured", e); return "error/404"; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/MoveItemsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/MoveItemsController.java index 0858c497f..7b91ecf45 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/MoveItemsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/MoveItemsController.java @@ -98,10 +98,11 @@ public class MoveItemsController { }) public @ResponseBody Sync startSync(Authentication authentication, @PathVariable("zoteroGroupId") String zoteroGroupId, @PathVariable("targetCollectionId") String collectionId, - @RequestParam(defaultValue = "1", required = false, value = "page") String page) { + @RequestParam(defaultValue = "1", required = false, value = "page") String page, + @RequestParam(defaultValue = "title", required = false, value = "sortBy") String sortBy) { try { citationManager.getGroupItems((IUser) authentication.getPrincipal(), zoteroGroupId, collectionId, - new Integer(page), null, null); + new Integer(page), sortBy, null); Sync sync = new Sync(); sync.setStatus("sync-started"); return sync; 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..2da6c707a 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 @@ -54,7 +54,7 @@ public class SearchController { public @ResponseBody String search(@PathVariable String zoteroGroupId, @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(defaultValue = "title", required = false, value = "sortBy") String sort, @RequestParam(required = false, value = "columns") String[] columns, Authentication authentication) { IUser user = (IUser) authentication.getPrincipal(); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SyncGroupItemsController.java b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SyncGroupItemsController.java index 13ef33427..1d520ceef 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SyncGroupItemsController.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/web/user/SyncGroupItemsController.java @@ -22,7 +22,7 @@ public String getCitationsList(Authentication authentication, Model model, @PathVariable("zoteroGroupId") String zoteroGroupId, @PathVariable(value="collectionId", required=false) String collectionId, @RequestParam(required = false, value = "page") String page, - @RequestParam(defaultValue = "title", required = false, value = "sort") String sort, + @RequestParam(defaultValue = "title", required = false, value = "sortBy") String sort, @RequestParam(required = false, value = "columns") String columns) throws GroupDoesNotExistException { if (page == null || page.trim().isEmpty()) { page = "1"; diff --git a/citesphere/src/main/webapp/WEB-INF/views/auth/group/item.html b/citesphere/src/main/webapp/WEB-INF/views/auth/group/item.html index e55bf9880..9eec776ed 100644 --- a/citesphere/src/main/webapp/WEB-INF/views/auth/group/item.html +++ b/citesphere/src/main/webapp/WEB-INF/views/auth/group/item.html @@ -291,7 +291,7 @@
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..dbcb4f817 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 @@ -101,9 +101,12 @@ } let pageNumber = $(".page-item.active").text(); + var queryParams = window.location.search; + var params = new URLSearchParams(queryParams); + let sortBy = params.get("sortBy"); $.ajax({ type: "GET", - url: "items/data?page="+pageNumber+"&columns=" + shownColumns, + url: "items/data?page="+pageNumber+"&columns=" + shownColumns+"&sortBy=" + sortBy, dataType: "json", success: function (data){ rewriteCitationsTable(data); @@ -204,6 +207,24 @@ $(document).ready(function() { var queryParams = window.location.search; + + const sortLabelMap = { + title: "Title", + type: "Type", + author: "Author", + date: "Date", + url: "URL" + }; + + if (queryParams) { + var params = new URLSearchParams(queryParams); + sortBy = params.get("sortBy"); + } else { + sortBy = title; + } + const label = sortLabelMap[sortBy] || sortLabelMap[title]; + document.getElementById("sortLabel").textContent = "Sort by: " + label; + if (queryParams) { var params = new URLSearchParams(queryParams); params.delete('page'); @@ -318,9 +339,9 @@
  • Home
  • - [[${crumb.label}]] - [[${crumb.label}]] - [[${crumb.label}]] + [[${crumb.label}]] + [[${crumb.label}]] + [[${crumb.label}]]
  • @@ -390,9 +411,13 @@

    function getCurrentItemsData(parameter){ let pageNumber = $(".page-item.active").text(); +var queryParams = window.location.search; +var params = new URLSearchParams(queryParams); +let sortBy = params.get("sortBy"); + $.ajax({ type: "GET", - url: "items/data?page="+pageNumber+"&columns=" + shownColumns, + url: "items/data?page="+pageNumber+"&columns=" + shownColumns+"&sortBy=" + sortBy, dataType: "json", success: function (data){ if(parameter === "onFirstLoad" || (!data['notModified'] && parameter === "notFirstLoad") || parameter === "requestingNewPage"){ @@ -453,9 +478,9 @@

    let href; if(collectionId){ - href = '"items/'+citation.key+'?index='+i+'&collectionId='+collectionId+'&page='+data['currentPage']+'&sortBy='+data['sort']+'"' + href = '"items/'+citation.key+'?index='+i+'&collectionId='+collectionId+'&page='+data['currentPage']+'&sortBy='+data['sortBy']+'"' } else{ - href = '"items/'+citation.key+'?index='+i+'&page='+data['currentPage']+'&sortBy='+data['sort']+'"' + href = '"items/'+citation.key+'?index='+i+'&page='+data['currentPage']+'&sortBy='+data['sortBy']+'"' } let authors = $(''+''); @@ -515,9 +540,12 @@

    for(const collection of data['citationCollections']){ let list = $('
  • '+'
  • '); list.append($(''+'').text(collection.numberOfItems)); - let collectionURL = window.location.href +"/../collection/"+collection.key+"/items"; + const currentUrl = new URL(window.location.href); + const basePath = currentUrl.pathname; + const queryString = currentUrl.search; + let collectionURL = basePath +"/../collection/"+collection.key+"/items" + queryString; if((window.location.href).match(/collection/)){ - collectionURL = window.location.href +"/../../"+collection.key+"/items"; + collectionURL = window.location.href +"/../../"+collection.key+"/items" + queryString; } list.append($(''+'').append($('').text(collection.name))); unOrderedList.append(list); @@ -550,6 +578,28 @@

    $("#addionalColumns").replaceWith(columnsList); } +function onSortChange(sortBy) { + const sortLabelMap = { + title: "Title", + type: "Type", + author: "Author", + date: "Date", + url: "URL" + }; + + const label = sortLabelMap[sortBy] || sortBy; + document.getElementById("sortLabel").textContent = "Sort by: " + label; + + var queryParams = window.location.search; + if (queryParams) { + var params = new URLSearchParams(queryParams); + params.set("sortBy", sortBy); + queryParams = params.toString(); + } + window.location.search = queryParams.toString(); + +} +

    @@ -602,11 +652,11 @@

    -
    -
    @@ -639,7 +689,7 @@

  • - +
  • @@ -648,7 +698,7 @@

    -