Commit 125c6455 authored by Matija Obreza's avatar Matija Obreza
Browse files

Explore: Version 1

parent 576bce8b
......@@ -19,10 +19,10 @@ package org.genesys2.server.servlet.controller;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.ParameterCategory;
......@@ -39,6 +39,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.social.ResourceNotFoundException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
......@@ -50,6 +51,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@Controller
public class ExplorerController extends BaseController {
......@@ -74,6 +77,34 @@ public class ExplorerController extends BaseController {
private ObjectMapper mapper = new ObjectMapper();
/**
* Action method to navigate to filter selection
*/
@RequestMapping(value = "/explore", method = RequestMethod.POST, params = { "doPick" })
public String exploreActionPick(ModelMap model, @RequestParam(value = "filter", required = false, defaultValue = "{}") String jsonFilter,
@RequestParam(value = "pick", required = false) String jsonPick, @RequestParam(value = "crop", required = false) String shortName) {
model.addAttribute("filter", jsonFilter);
model.addAttribute("pick", jsonPick);
if (StringUtils.isNotBlank(shortName))
model.addAttribute("crop", shortName);
return "redirect:/explore/pick";
}
/**
* Action method to view filtered data
*/
@RequestMapping(value = "/explore", method = RequestMethod.POST, params = { "doView" })
public String exploreActionView(ModelMap model, @RequestParam(value = "filter", required = false, defaultValue = "{}") String jsonFilter,
@RequestParam(value = "pick", required = false) String jsonPick, @RequestParam(value = "crop", required = false) String shortName) {
model.addAttribute("filter", jsonFilter);
model.addAttribute("pick", jsonPick);
if (StringUtils.isNotBlank(shortName))
model.addAttribute("crop", shortName);
return "redirect:/explore";
}
@RequestMapping(value = "/explore/pick", method = RequestMethod.GET)
public String pickFilters(ModelMap model, @RequestParam(value = "filter", required = false, defaultValue = "{}") String jsonFilter,
@RequestParam(value = "pick", required = false, defaultValue = "[]") String pick, @RequestParam(value = "crop", required = false) String shortName) {
......@@ -99,7 +130,7 @@ public class ExplorerController extends BaseController {
// What filters do we support?
model.addAttribute("availableFilters", filterService.listAvailableFilters());
model.addAttribute("jsonString", jsonFilter);
model.addAttribute("jsonFilter", jsonFilter);
model.addAttribute("selectedFilters", new HashSet<String>(Arrays.asList(selectedFilters)));
model.addAttribute("crops", cropService.list(getLocale()));
return "/filter/pick";
......@@ -122,7 +153,20 @@ public class ExplorerController extends BaseController {
_logger.error(e.getMessage(), e);
}
model.addAttribute("filter", jsonFilter);
// Keep only picked descriptors
try {
_logger.info("Cleaning up unused filters : " + jsonFilter);
ObjectNode jsonTree = (ObjectNode) mapper.readTree(jsonFilter);
for (String filter : IteratorUtils.toList(jsonTree.fieldNames())) {
if (!ArrayUtils.contains(pick, filter)) {
jsonTree.remove(filter);
}
}
model.addAttribute("filter", jsonTree.toString());
} catch (IOException e) {
_logger.error("Invalid JSON for pick", e);
}
return "redirect:/explore/pick";
}
......@@ -136,7 +180,6 @@ public class ExplorerController extends BaseController {
return "redirect:/explore/filter";
}
@RequestMapping(value = "/explore/filter", method = RequestMethod.GET)
public String showFilters(ModelMap model, @RequestParam(value = "filter", required = false, defaultValue = "{}") String jsonFilter,
@RequestParam(value = "pick", required = false) String pick, @RequestParam(value = "crop", required = false) String shortName) {
......@@ -154,12 +197,13 @@ public class ExplorerController extends BaseController {
try {
JsonNode jsonTree = mapper.readTree(jsonFilter);
model.addAttribute("jsonString", jsonTree.toString());
model.addAttribute("jsonFilter", jsonTree.toString());
} catch (NullPointerException | IOException e) {
_logger.warn(e.getMessage(), e);
}
try {
if (selectedFilters != null && selectedFilters.length > 0)
model.addAttribute("pick", mapper.writeValueAsString(selectedFilters));
} catch (IOException e) {
_logger.warn(e.getMessage(), e);
......@@ -175,6 +219,44 @@ public class ExplorerController extends BaseController {
return "/filter/filter";
}
/**
* Redirect to /explore/c/{shortName} if parameter 'crop' is provided
*/
@RequestMapping(value = "/explore", params = { "crop" })
private String x(ModelMap model, @RequestParam(value = "filter", required = true, defaultValue = "{}") String jsonFilter,
@RequestParam(value = "pick", required = true, defaultValue = "") String jsonPick, @RequestParam(value = "crop") String shortName) {
model.addAttribute("filter", jsonFilter);
model.addAttribute("pick", jsonPick);
if (StringUtils.isNotBlank(shortName)) {
Crop crop = cropService.getCrop(shortName);
if (crop == null) {
throw new ResourceNotFoundException("No crop " + shortName);
}
return "redirect:/explore/c/" + crop.getShortName();
}
return "redirect:/explore";
}
/**
* Explore accessions filtered within a crop
*/
@RequestMapping("/explore/c/{crop}")
public String viewFiltered(ModelMap model, @PathVariable("crop") String shortName,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "filter", required = true, defaultValue = "{}") String jsonFilter,
@RequestParam(value = "pick", required = true, defaultValue = "") String jsonPick) {
Crop crop = cropService.getCrop(shortName);
if (crop == null) {
throw new ResourceNotFoundException("No crop " + shortName);
}
model.addAttribute("crop", crop);
return viewFiltered(model, page, jsonFilter, jsonPick);
}
/**
* Browse all
......@@ -185,25 +267,40 @@ public class ExplorerController extends BaseController {
*/
@RequestMapping("/explore")
public String viewFiltered(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "filter", required = true, defaultValue = "{}") String jsonFilter) {
@RequestParam(value = "filter", required = true, defaultValue = "{}") String jsonFilter,
@RequestParam(value = "pick", required = false) String jsonPick) {
if (StringUtils.isNotBlank(jsonPick)) {
// Cleanup JSON pick
try {
JsonNode jsonTree = mapper.readTree(jsonPick);
model.addAttribute("jsonPick", jsonTree.toString());
_logger.info("Clean jsonPick: " + jsonTree);
} catch (IOException e) {
_logger.error("Invalid JSON for pick", e);
}
}
_logger.info("Filtering by: " + jsonFilter);
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonTree = null;
ObjectNode jsonTree = null;
try {
jsonTree = mapper.readTree(jsonFilter);
jsonTree = (ObjectNode) mapper.readTree(jsonFilter);
_logger.debug(jsonTree.toString());
model.addAttribute("jsonString", jsonTree.toString());
model.addAttribute("jsonFilter", jsonTree);
if (model.containsAttribute("crop")) {
jsonTree.remove("crop");
model.addAttribute("jsonFilter", jsonTree.toString());
Iterator<Entry<String, JsonNode>> fields = jsonTree.fields();
while (fields.hasNext()) {
Entry<String, JsonNode> entry = fields.next();
_logger.debug("2=" + entry.getKey() + " = " + entry.getValue());
// Replace any other crop filters...
ArrayNode oneCrop = jsonTree.arrayNode();
oneCrop.add(((Crop) model.get("crop")).getShortName());
jsonTree.put("crop", oneCrop);
} else {
model.addAttribute("jsonFilter", jsonTree.toString());
}
} catch (IOException e) {
e.printStackTrace();
_logger.error(e.getMessage(), e);
}
Page<Accession> accessions = filterService.listAccessions(jsonTree, new PageRequest(page - 1, 50, new Sort("acceNumb")));
......@@ -214,7 +311,6 @@ public class ExplorerController extends BaseController {
return "/accession/explore";
}
@RequestMapping(value = "/explore/ac/{field}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<LabelValue<String>> autocomplete(@PathVariable("field") String filter, @RequestParam(value = "term", required = false) String ac) {
......
......@@ -16,18 +16,16 @@
<div class="results"><spring:message code="accessions.number" arguments="${pagedData.totalElements}" /></div>
<div class="pagination">
<spring:message code="paged.pageOfPages" arguments="${pagedData.number+1},${pagedData.totalPages}" />
<a href="<spring:url value=""><spring:param name="page" value="${pagedData.number eq 0 ? 1 : pagedData.number}" /><spring:param name="filter" value="${jsonFilter}" /></spring:url>"><spring:message code="pagination.previous-page" /></a>
<a href="<spring:url value=""><spring:param name="page" value="${pagedData.number eq 0 ? 1 : pagedData.number}" /><spring:param name="filter" value="${jsonFilter}" /><spring:param name="pick" value="${jsonPick}" /></spring:url>"><spring:message code="pagination.previous-page" /></a>
<a href="<spring:url value=""><spring:param name="page" value="${pagedData.number+2}" /><spring:param name="filter" value="${jsonFilter}" /><spring:param name="pick" value="${jsonPick}" /></spring:url>"><spring:message code="pagination.next-page" /></a>
</div>
</div>
</div>
<c:if test="${filters eq null and jsonFilter ne null}">
<div class="applied-filters">
<spring:message code="filters.data-is-filtered" />
<a href="<spring:url value="/explore/filter"><spring:param name="filter" value="${jsonFilter}" /><spring:param name="pick" value="${jsonPick}" /></spring:url>"><spring:message code="filters.modify-filters" /></a>
<a href="<spring:url value="/explore/filter"><spring:param name="crop" value="${crop.shortName}" /><spring:param name="filter" value="${jsonFilter}" /><spring:param name="pick" value="${jsonPick}" /></spring:url>"><spring:message code="filters.modify-filters" /></a>
</div>
</c:if>
<c:if test="${filters ne null}">
<div class="applied-filters">
......
......@@ -65,16 +65,19 @@
</div>
</c:forEach>
<div class="row">
<form method="post" action="<c:url value="/explore" />">
<input type="hidden" id="filtersHref" name="filter" value='${jsonFilter}' />
<input type="hidden" name="pick" value='${pick}' />
<c:if test="${crop ne null}">
<input type="hidden" name="crop" value="${crop.shortName}" />
</c:if>
<div class="row">
<div class="col-lg-offset-3 col-lg-9">
<a id="filtersHref" href=""><button class="btn btn-green pull-left">View!</button></a>
<c:url var="pickUrl" value="/explore/pick">
<c:param name="pick">${pick}</c:param>
<c:param name="crop"><c:out value="${crop.shortName}" /></c:param>
</c:url>
<a href="${pickUrl}"><button class="btn btn-green pull-left">Change filters</button></a>
<button type="submit" name="doView" class="btn btn-green pull-left">View!</button>
<button type="submit" name="doPick" class="btn btn-green pull-left">Change filters</button>
</div>
</div>
</div>
</form>
</div>
......@@ -85,11 +88,11 @@
<script type="text/javascript" src="<c:url value="/html/js/jquery-ui.min.js" />"></script>
<script type="text/javascript">
jQuery(document).ready(function() {
// alert('${jsonString}');
// alert('${jsonFilter}');
var pick=[];
var filters={};
try {
filters=$.parseJSON('${jsonString}');
filters=$.parseJSON('${jsonFilter}');
} catch (e) {console.error(e);}
try {
pick=$.parseJSON('${pick}');
......@@ -133,7 +136,7 @@ jQuery(document).ready(function() {
refreshJson: function(newFilter) {
$("#filtersJson").html(JSON.stringify(newFilter));
$("#filtersHref").attr("href", "<c:url value="/explore" />?<c:if test="${crop ne null}">crop=${crop.shortName}&</c:if>filter="+JSON.stringify(newFilter)+"&pick="+JSON.stringify(pick));
$("#filtersHref").val(JSON.stringify(newFilter));
},
addFilterValue: function(element) {
......@@ -205,8 +208,8 @@ jQuery(document).ready(function() {
}
};
[<c:forEach items="${selectedFilters}" var="filter" varStatus="status">${status.index gt 0 ? ',' : ''} "${filter.name.replace(':','_')}"</c:forEach> ].forEach(function(name) {
FF.updateValues("#filter-" + name + ".filter-values", name, filters[name]);
[<c:forEach items="${selectedFilters}" var="filter" varStatus="status">${status.index gt 0 ? ',' : ''} "${filter.name}"</c:forEach> ].forEach(function(name) {
FF.updateValues("#filter-" + name.replace(':','_') + ".filter-values", name, filters[name]);
});
$("body").on("click", ".filtval", function(event) {
......
......@@ -11,7 +11,7 @@
<h1><spring:message code="filters.view" /></h1>
<form method="post" action="<c:url value="/explore/pick" />">
<input type="hidden" name="filter" value="<c:out value="${jsonString}" />" />
<input type="hidden" name="filter" value="<c:out value="${jsonFilter}" />" />
<div id="allfilters">
<h2><c:out value="MCPD" /></h2>
......
......@@ -34,7 +34,7 @@
<ul class="nav">
<li><a class="show" href="<c:url value="/acn/" />"><spring:message code="crop.all-crops" /></a></li>
<c:forEach items="${cropList}" var="crop" varStatus="status">
<li><a class="show" href="/c/${crop.shortName}/data"><c:out value="${crop.getName(pageContext.response.locale)}" /></a></li>
<li><a class="show" href="/explore/c/${crop.shortName}"><c:out value="${crop.getName(pageContext.response.locale)}" /></a></li>
</c:forEach>
</ul>
</div>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment