Commit 8125c880 authored by Matija Obreza's avatar Matija Obreza
Browse files

Removed obsolete methods for picking and filtering in ExplorerController

Removed the use of filter "pick" list, selected filters are obtained
from the keyset of filterJson
filterJson may contain empty filters {"crop":[]}
Only filters in filterJson are rendered in JSP, other filters are AJAX'd
using /additional-filter  (+1 squashed commit)
Squashed commits:
[be9e34f] Removed unused filtering and filter pick functionality
parent c2cd8802
......@@ -16,11 +16,9 @@
package org.genesys2.server.service;
import java.util.Collection;
import java.util.List;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.service.impl.GenesysFilterServiceImpl.LabelValue;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
......@@ -50,9 +48,7 @@ public interface GenesysFilterService {
}
}
List<GenesysFilter> selectFilters(Crop crop, String[] selectedFilters);
Collection<GenesysFilter> generateFilters(Collection<Long> methodIds);
List<GenesysFilter> selectFilters(String[] selectedFilters);
List<LabelValue<String>> autocomplete(String filter, String ac);
......
......@@ -73,26 +73,31 @@ public class DirectMysqlQuery {
}
protected DirectMysqlQuery join(ObjectNode jsonTree) {
if (jsonTree.has("crop") || jsonTree.has("genus") || jsonTree.has("taxon")) {
if (hasFilter(jsonTree, "crop") || hasFilter(jsonTree, "genus") || hasFilter(jsonTree, "taxon")) {
innerJoin("taxonomy2", "t", "t.id=a.taxonomyId2");
if (jsonTree.has("crop")) {
if (hasFilter(jsonTree, "crop")) {
innerJoin("croptaxonomy", "ct", "ct.taxonomyId=t.id");
innerJoin("crop", null, "crop.id=ct.cropId");
}
}
if (jsonTree.has("organization")) {
if (hasFilter(jsonTree, "organization")) {
innerJoin("faoinstitute", "fao", "fao.id=a.instituteId");
innerJoin("organizationinstitute", "oi", "oi.instituteId=fao.id");
innerJoin("organization", "org", "org.id=oi.organizationId");
}
if (jsonTree.has("latitude") || jsonTree.has("longitude") || jsonTree.has("elevation")) {
if (hasFilter(jsonTree, "latitude") || hasFilter(jsonTree, "longitude") || hasFilter(jsonTree, "elevation")) {
innerJoin("accessiongeo", "geo", "geo.accessionId=a.id");
}
return this;
}
static boolean hasFilter(ObjectNode jsonTree, String filterName) {
JsonNode f = jsonTree.get(filterName);
return f != null && f.isArray() && f.size() > 0;
}
protected DirectMysqlQuery filter(ObjectNode jsonTree, MethodResolver methodResolver) {
createQuery(whereBuffer, "a.id", jsonTree.get("id"), params);
createQuery(whereBuffer, "a.taxGenus", jsonTree.get("genusId"), params);
......@@ -174,10 +179,13 @@ public class DirectMysqlQuery {
if (LOG.isDebugEnabled()) {
LOG.debug("Handling " + dbName);
}
if (fieldQuery != null) {
if (fieldQuery != null && fieldQuery.isArray() && fieldQuery.size() > 0) {
// Always an array of filters
if (LOG.isDebugEnabled()) {
LOG.debug("Adding " + fieldQuery + " sz=" + fieldQuery.size() + " t=" + fieldQuery.getNodeType());
}
if (sb.length() == 0)
sb.append(" where ");
else
......@@ -186,31 +194,27 @@ public class DirectMysqlQuery {
// Opening
sb.append(" ( ");
// Always an array of filters
if (fieldQuery.getNodeType() == JsonNodeType.ARRAY) {
// A filter value can be (a) explicit value or (b) an operation
// (a) explicit values are handled by =? or by IN (?,?,..)
int handledCount = handleExplicitValues(sb, dbName, fieldQuery.elements(), params);
// A filter value can be (a) explicit value or (b) an operation
// do we have more?
if (handledCount > 0 && fieldQuery.size() > handledCount) {
sb.append(" OR ");
}
// (a) explicit values are handled by =? or by IN (?,?,..)
int handledCount = handleExplicitValues(sb, dbName, fieldQuery.elements(), params);
handledCount += handleNullValues(sb, dbName, fieldQuery.elements(), params);
// do we have more?
if (handledCount > 0 && fieldQuery.size() > handledCount) {
sb.append(" OR ");
}
// do we have more?
if (handledCount > 0 && fieldQuery.size() > handledCount) {
sb.append(" OR ");
}
handledCount += handleNullValues(sb, dbName, fieldQuery.elements(), params);
// (b) operations are expressed as {"min":12} or {"max":33} or
// {"range":[3,10]} or {"like":"test"}
handleOperations(sb, dbName, fieldQuery.elements(), params);
// do we have more?
if (handledCount > 0 && fieldQuery.size() > handledCount) {
sb.append(" OR ");
}
// (b) operations are expressed as {"min":12} or {"max":33} or
// {"range":[3,10]} or {"like":"test"}
handleOperations(sb, dbName, fieldQuery.elements(), params);
// closing
sb.append(" ) ");
}
......
......@@ -20,27 +20,24 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.sql.DataSource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.list.UnmodifiableList;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.TraitCode;
import org.genesys2.server.model.impl.Country;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.persistence.domain.AccessionRepository;
import org.genesys2.server.persistence.domain.MethodRepository;
......@@ -135,18 +132,16 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
}
@Override
public List<GenesysFilter> selectFilters(Crop crop, String[] selectedFilters) {
public List<GenesysFilter> selectFilters(String[] selectedFilters) {
LOG.debug("Loading filter definitions sel=" + ArrayUtils.toString(selectedFilters));
List<GenesysFilter> filters = new ArrayList<GenesysFilter>();
Set<Long> methodIds = new HashSet<Long>();
for (final String selectedFilter : selectedFilters) {
if (crop != null && selectedFilter.equals("crop")) {
// Skip filter
continue;
}
if (selectedFilter.startsWith("gm:")) {
try {
methodIds.add(Long.parseLong(selectedFilter.substring(3)));
GenesysFilter methodFilter = getMethodFilter(Long.parseLong(selectedFilter.substring(3)));
if (methodFilter != null)
filters.add(methodFilter);
} catch (NumberFormatException | NullPointerException e) {
LOG.warn(e);
}
......@@ -163,22 +158,12 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
}
}
filters.addAll(generateFilters(methodIds));
return filters;
}
@Override
public Collection<GenesysFilter> generateFilters(Collection<Long> methodIds) {
List<GenesysFilter> filters = new ArrayList<GenesysFilter>();
for (long methodId : methodIds) {
Method method = methodRepository.findOne(methodId);
if (method == null) {
continue;
}
filters.add(toFilter(method));
}
return filters;
GenesysFilter getMethodFilter(long methodId) {
Method method = methodRepository.findOne(methodId);
return method == null ? null : toFilter(method);
}
private GenesysFilter toFilter(Method method) {
......
......@@ -12,7 +12,7 @@
<c:set var="normalizedKey" value="${fn:replace(filter.key,':', '_')}"/>
<c:set var="filterKey" value="${filter.key}"/>
<div class="clearfix filter-block" style="display:${pick[filterKey] eq filterKey ? '' : 'none'}"
<div class="clearfix filter-block"
id="${normalizedKey}_filter" key="${normalizedKey}">
<div class="col-lg-3">
......@@ -24,7 +24,7 @@
<spring:message code="filter.${filter.name}" />
</c:if>
</div>
<div class="col-lg-5 filter-new" style="display:none">
<div class="col-lg-5 filter-new">
<c:choose>
<c:when test="${filter.filterType=='LIST'}">
......@@ -32,7 +32,7 @@
<c:forEach items="${filter.options}" var="option">
<div>
<label>
<input class="filter-list" id="${option.value}_input" ${fn:contains(filters[filter.key], option.value)?'checked':''} norm-key="${normalizedKey}" i-key="${normalizedKey}${option.value}" type="checkbox" value="${option.value}" />
<input class="filter-list" id="${option.value}_input" norm-key="${normalizedKey}" i-key="${normalizedKey}${option.value}" type="checkbox" value="${option.value}" />
<spring:message code="${option.name}"/>
</label>
</div>
......@@ -47,7 +47,7 @@
<c:forEach items="${filter.options}" var="option">
<div>
<label>
<input class="filter-list" id="${option.value}_input" ${fn:contains(filters[filter.key], option.value)?'checked':''} norm-key="${normalizedKey}" i-key="${normalizedKey}${option.value}" type="checkbox" value="${option.value}" />
<input class="filter-list" id="${option.value}_input" norm-key="${normalizedKey}" i-key="${normalizedKey}${option.value}" type="checkbox" value="${option.value}" />
<spring:message code="${option.name}"/>
</label>
</div>
......@@ -86,9 +86,9 @@
</c:when>
<c:when test="${filter.dataType=='BOOLEAN'}">
<div class="">
<div><label><input type="checkbox" ${fn:contains(filters[filter.key], 'true')?'checked':''} class="filter-bool" i-key="${normalizedKey}true" id="${normalizedKey}" value="true"/><spring:message code="boolean.true"/></label></div>
<div><label><input type="checkbox" ${fn:contains(filters[filter.key], 'false')?'checked':''} class="filter-bool" i-key="${normalizedKey}false" id="${normalizedKey}" value="false"/><spring:message code="boolean.false"/></label></div>
<div><label><input type="checkbox" ${fn:contains(filters[filter.key], 'null')?'checked':''} class="filter-bool" i-key="${normalizedKey}null" id="${normalizedKey}" value="null"/><spring:message code="boolean.null"/></label></div>
<div><label><input type="checkbox" class="filter-bool" i-key="${normalizedKey}true" id="${normalizedKey}" value="true"/><spring:message code="boolean.true"/></label></div>
<div><label><input type="checkbox" class="filter-bool" i-key="${normalizedKey}false" id="${normalizedKey}" value="false"/><spring:message code="boolean.false"/></label></div>
<div><label><input type="checkbox" class="filter-bool" i-key="${normalizedKey}null" id="${normalizedKey}" value="null"/><spring:message code="boolean.null"/></label></div>
</div>
<div style="margin-top: 3px">
<button class="btn btn-primary apply"><spring:message code="filter.apply"/></button>
......@@ -114,26 +114,7 @@
<a href="#" style="float: right" class="edit-fil glyphicon glyphicon-pencil"></a>
</div>
<div class="col-lg-4 filter-values" id="${normalizedKey}_value">
<c:forEach items="${filters[filter.key]}" var="value">
<c:set var="string" value="${value}"/>
<c:if test="${fn:contains(value, 'range')}">
<c:set var="string" value="${fn:replace(value,'{range=[','Between ')}"/>
<c:set var="string" value="${fn:replace(string,',',' and ')}"/>
<c:set var="string" value="${fn:replace(string,']}','')}"/>
</c:if>
<c:if test="${fn:contains(value, 'min')}">
<c:set var="string" value="${fn:replace(value,'{min=','More than ')}"/>
<c:set var="string" value="${fn:replace(string,'}','')}"/>
</c:if>
<c:if test="${fn:contains(value, 'max')}">
<c:set var="string" value="${fn:replace(value,'{max=','Less than ')}"/>
<c:set var="string" value="${fn:replace(string,'}','')}"/>
</c:if>
<div class="filtval complex" x-key="${normalizedKey}${value}" id="${normalizedKey}">${string}</div>
</c:forEach>
</div>
</div>
</c:forEach>
......@@ -33,8 +33,8 @@
</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: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>
<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+2}" /><spring:param name="filter" value="${jsonFilter}" /></spring:url>"><spring:message code="pagination.next-page" /></a>
</div>
</div>
</div>
......@@ -63,7 +63,7 @@
</li>
<li class="dropdown form-horizontal" id="menu2" style="display:${fn:contains(jsonPick,'crop')?'':'none'}">
<li class="dropdown form-horizontal" id="menu2" style="display: none">
<a class="" data-toggle="modal" data-target="#myModal">
<spring:message code="filter.additional"/>
<b class="glyphicon-plus"></b>
......@@ -71,14 +71,14 @@
</li>
</ul>
<c:forEach items="${availableFilters}" var="filter">
<%-- Only render currently present filters --%>
<c:forEach items="${currentFilters}" var="filter">
<c:set var="normalizedKey" value="${fn:replace(filter.key,':', '_')}"/>
<c:set var="filterKey" value="${filter.key}"/>
<div class="clearfix filter-block" style="display:${pick[filterKey] eq filterKey ? '' : 'none'}"
id="${normalizedKey}_filter" key="${normalizedKey}">
<div class="clearfix filter-block" id="${normalizedKey}_filter" key="${normalizedKey}">
<div class="col-lg-3">
<c:if test="${not filter.core}">
......@@ -223,36 +223,7 @@
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<%--<div class="modal-header">--%>
<%--<h4 class="modal-title" id="myModalLabel"><spring:message code="filter.additional"/></h4>--%>
<%--</div>--%>
<%--<div class="modal-body" style="overflow: auto;height: 200px">--%>
<%--<c:forEach items="${categories}" var="category">--%>
<%--<c:if test="${descriptors[category].size() gt 0}">--%>
<%--<h2><c:out value="${crop.getName(pageContext.request.locale)}:" /> <c:out value="${category.getName(pageContext.request.locale)}" /></h2>--%>
<%--<c:forEach items="${descriptors[category]}" var="descriptor">--%>
<%--<c:if test="${methods[descriptor.id].size() gt 0}">--%>
<%--<div class="row filter-block">--%>
<%--<div class="col-lg-3">--%>
<%--<div dir="ltr"><c:out value="${descriptor.title}" /></div>--%>
<%--</div>--%>
<%--<div class="col-lg-9">--%>
<%--<c:forEach items="${methods[descriptor.id]}" var="method">--%>
<%--<c:set value="gm:${method.id}" var="gm_value"/>--%>
<%--<div><label><input class="additional" ${fn:contains(jsonPick, gm_value)?'checked':''} id="gm_${method.id}_id" type="checkbox" style="margin-right: 1em;" value="gm:${method.id}" /><span dir="ltr"><c:out value="${method.method}" /></span></label></div>--%>
<%--</c:forEach>--%>
<%--</div>--%>
<%--</div>--%>
<%--</c:if>--%>
<%--</c:forEach>--%>
<%--</c:if>--%>
<%--</c:forEach>--%>
<%--</div>--%>
<%--<div class="modal-footer">--%>
<%--<button type="button" class="btn btn-primary" data-dismiss="modal"><spring:message code="filter.apply"/></button>--%>
<%--</div>--%>
</div>
<div class="modal-content"></div>
</div>
</div>
<!--End modal-->
......@@ -292,9 +263,7 @@
<content tag="javascript">
<script type="text/javascript">
var jsonData = ${fn:replace(jsonFilter,'_',':')};
var filterPick = ${jsonPick};
var jsonData = ${jsonFilter};
var page=${pagedData.number};
......@@ -304,16 +273,8 @@
}
function submitJson() {
for (var key in jsonData) {
if(!filterPick.indexOf(key)>-1){
filterPick.push(key);
}
}
var filter = JSON.stringify(jsonData);
var pick = JSON.stringify(filterPick);
var url='/explore?filter=' + filter + "&pick=" + pick;
var filter = JSON.stringify(jsonData);
var url='/explore?filter=' + filter;
window.location.href = encodeURI(url);
}
......@@ -333,25 +294,7 @@
function enableFilter(key) {
var editId = "#" + key + "_filter";
var inputId = "#" + key + "_id";
var parent = $(editId).find(".filter-new");
parent.show();
var isAdditionalFilter = key.indexOf("gm") > -1;
var checked = $(inputId).is(":checked");
if (isAdditionalFilter) {
if (checked) {
$(editId).show();
} else {
$(editId).hide();
}
} else {
$(editId).show();
}
appendFilter(key, editId);
}
function appendHtml(key, value,element) {
......@@ -391,11 +334,6 @@
if (jsonArray == value) {
array.splice(val, 1);
}
if (array.length == 0) {
filterPick.splice(filterPick.indexOf(key),1);
delete jsonData[key];
}
}
}
......@@ -504,27 +442,44 @@
$("#menu2").hide();
}
}
function appendFilter(filter, filterId) {
if ($(filterId).length != 0) {
console.log("Filter already loaded");
return;
}
$.ajax("/additional-filter", {
type: 'GET',
data: "filter=" + filter,
success: function (data) {
jsonData[filter]=[];
$("#allfilters").append(data);
},
error: function (error) {
console.log(error);
}
});
}
$( document ).ready(function() {
$.ajax("/additional-filter", {
type: 'GET',
data: "filter=" + JSON.stringify(jsonData) + "&shortName=" + jsonData.crop+"&pick="+JSON.stringify(filterPick),
success: function (data) {
$("#allfilters").append(data);
},
error: function (error) {
console.log(error);
}
});
if (jsonData.crop != null) {
$("#menu2").show();
}
$("#menu2").on("click", function (event) {
$.ajax("/modal", {
type: 'GET',
data: "shortName=" + jsonData.crop + "&pick=" + JSON.stringify(filterPick),
data: "shortName=" + jsonData.crop,
success: function (data) {
$(".modal-content").empty();
$(".modal-content").append(data);
for (var x in jsonData) {
console.log(".modal-body input[value='"+x+"']");
$(".modal-body .filter-block label > input[value='"+x+"']").prop("checked", true);
}
},
error: function (error) {
console.log(error);
......@@ -537,33 +492,10 @@
var id = $(this).attr("id");
var filterId = "#" + id.replace("_id", "_filter");
var filter = id.replace("gm_", "gm:").replace("_id", "");
var pick=[];
if ($(this).is(":checked")&&!filterPick.indexOf(filter)>-1) {
jsonData[filter] = "";
pick.push(filter);
if(!filterPick.indexOf(filter)>-1) {
filterPick.push(filter);
}
$.ajax("/additional-filter", {
type: 'GET',
data: "filter=" + JSON.stringify(jsonData) + "&shortName=" + jsonData.crop + "&pick=" + JSON.stringify(pick),
success: function (data) {
delete jsonData[filter];
filterPick.splice(filterPick.indexOf(filter),1);
$("#allfilters").append(data);
$(filterId).find(".filter-new").show();
},
error: function (error) {
console.log(error);
}
});
if ($(this).is(":checked")) {
appendFilter(filter, filterId);
}else{
delete jsonData[filter];
filterPick.splice(filterPick.indexOf(filter),1);
pick.splice(pick.indexOf(filter),1);
$(filterId).remove();
}
});
......@@ -620,7 +552,6 @@
var parent = $(this).parent().parent();
var key = parent.attr("key");
delete jsonData[key.replace("_",":")];
filterPick.splice(filterPick.indexOf(key.replace("_",":")));
submitJson();
parent.hide();
});
......
......@@ -13,7 +13,9 @@
<div class="modal-body" style="overflow: auto;height: 200px">
<c:forEach items="${categories}" var="category">
<c:if test="${descriptors[category].size() gt 0}">
<h2><c:out value="${crop.getName(pageContext.request.locale)}:" /> <c:out value="${category.getName(pageContext.request.locale)}" /></h2>
<div class="row">
<h2><c:out value="${crop.getName(pageContext.request.locale)}:" /> <c:out value="${category.getName(pageContext.request.locale)}" /></h2>
</div>
<c:forEach items="${descriptors[category]}" var="descriptor">
<c:if test="${methods[descriptor.id].size() gt 0}">
<div class="row filter-block">
......
<!DOCTYPE html>
<%@include file="/WEB-INF/jsp/init.jsp"%>
<html>
<head>
<title><spring:message code="filters.page.title" /></title>
</head>
<body>
<h1><spring:message code="filters.view" /></h1>
<div id="allfilters">
<c:if test="${crop ne null}">
<div class="filter-block row">
<div class="col-lg-3">
<spring:message code="filter.crop" />
</div>
<div class="col-lg-9">
<c:out value="${crop.getName(pageContext.response.locale)}" />
</div>
</div>
</c:if>
<c:forEach items="${selectedFilters}" var="filter">
<div class="clearfix filter-block" x-filtername="${filter.key}">
<div class="col-lg-3">
<c:if test="${not filter.core}">
<a href="<c:url value="/descriptors/${filter.key}" />"><c:out value="${filter.title}" /></a>
</c:if>
<c:if test="${filter.core}">
<spring:message code="filter.${filter.name}" />
</c:if>
</div>
<div class="col-lg-5 filter-new">
<c:choose>
<c:when test="${filter.filterType=='LIST'}">
<div class="">
<c:forEach items="${filter.options}" var="option">
<div><label><input type="checkbox" value="${option.value}" /> <c:out value="