diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java index 925d76364f..629cd06883 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java @@ -137,6 +137,7 @@ public class DisplayVocabulary { /* URI of property for Fixed HTML Generator */ public static final String FIXED_HTML_VALUE = DISPLAY_NS + "htmlValue"; + public static final String SEARCH_FILTER_VALUE = DISPLAY_NS + "searchFilter"; /* URI of property for Search Query Generator */ diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java index 9f259afa10..818defefc2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/ManagePageGenerator.java @@ -526,6 +526,8 @@ private void addRequiredPageData(VitroRequest vreq, Map data) { MenuManagementDataUtils.includeRequiredSystemData(vreq.getSession().getServletContext(), data); data.put("classGroup", new ArrayList()); data.put("classGroups", DataGetterUtils.getClassGroups(vreq)); + data.put("searchFilter", new ArrayList()); + data.put("searchFilters", DataGetterUtils.getSearchFilters(vreq)); //for search individuals data get getter data.put("classes", this.getAllVClasses(vreq)); data.put("availablePermissions", this.getAvailablePermissions(vreq)); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java index b307eb0d8d..a919b27747 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Map.java @@ -7,29 +7,37 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchFilterValuesDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchIndividualsDataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter; + /* * This class determines what n3 should be returned for a particular data getter and can be overwritten or extended in VIVO. */ public class ProcessDataGetterN3Map { private static final Log log = LogFactory.getLog(ProcessDataGetterN3Map.class); - private static HashMap dataGetterMap; + private static HashMap dataGetterMap; static { - dataGetterMap = new HashMap(); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessSparqlDataGetterN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessClassGroupDataGetterN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessIndividualsForClassesDataGetterN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessFixedHTMLN3"); - dataGetterMap.put("edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchIndividualsDataGetter", "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils.ProcessSearchIndividualsDataGetterN3"); + dataGetterMap = new HashMap(); + dataGetterMap.put(SparqlQueryDataGetter.class.getCanonicalName(), ProcessSparqlDataGetterN3.class); + dataGetterMap.put(ClassGroupPageData.class.getCanonicalName(), ProcessClassGroupDataGetterN3.class); + dataGetterMap.put(SearchFilterValuesDataGetter.class.getCanonicalName(), ProcessSearchFilterValuesDataGetterN3.class); + dataGetterMap.put(IndividualsForClassesDataGetter.class.getCanonicalName(), ProcessIndividualsForClassesDataGetterN3.class); + dataGetterMap.put(FixedHTMLDataGetter.class.getCanonicalName(), ProcessFixedHTMLN3.class); + dataGetterMap.put(SearchIndividualsDataGetter.class.getCanonicalName(), ProcessSearchIndividualsDataGetterN3.class); } - public static HashMap getDataGetterTypeToProcessorMap() { + public static HashMap getDataGetterTypeToProcessorMap() { return dataGetterMap; } - public static void replaceDataGetterMap(HashMap newMap) { - dataGetterMap = new HashMap(); + public static void replaceDataGetterMap(HashMap newMap) { + dataGetterMap = new HashMap(); dataGetterMap.putAll(newMap); } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java index 0a40c447c3..aa436778ce 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessDataGetterN3Utils.java @@ -17,26 +17,28 @@ public class ProcessDataGetterN3Utils { private static final Log log = LogFactory.getLog(ProcessDataGetterN3Utils.class); public static ProcessDataGetterN3 getDataGetterProcessorN3(String dataGetterClass, ObjectNode jsonObject) { - HashMap map = ProcessDataGetterN3Map.getDataGetterTypeToProcessorMap(); + HashMap map = ProcessDataGetterN3Map.getDataGetterTypeToProcessorMap(); // if(map.containsKey(dataGetterClass)) { - String processorClass = map.get(dataGetterClass); + Class processorClass = map.get(dataGetterClass); try { ProcessDataGetterN3 pn = instantiateClass(processorClass, jsonObject); return pn; } catch(Exception ex) { log.error("Exception occurred in trying to get processor class for n3 for " + dataGetterClass, ex); return null; - } + } + } else { + log.error(ProcessDataGetterN3Map.class.getSimpleName() + " doesn't contain processor class for n3 for " + dataGetterClass); + return null; } - return null; + } - private static ProcessDataGetterN3 instantiateClass(String processorClass, ObjectNode jsonObject) { + private static ProcessDataGetterN3 instantiateClass(Class processorClass, ObjectNode jsonObject) { ProcessDataGetterN3 pn = null; try { - Class clz = Class.forName(processorClass); - Constructor[] ctList = clz.getConstructors(); + Constructor[] ctList = processorClass.getConstructors(); for (Constructor ct: ctList) { Class[] parameterTypes =ct.getParameterTypes(); if(parameterTypes.length > 0 && parameterTypes[0].isAssignableFrom(jsonObject.getClass())) { @@ -47,7 +49,7 @@ private static ProcessDataGetterN3 instantiateClass(String processorClass, Objec } } catch(Exception ex) { - log.error("Error occurred instantiating " + processorClass, ex); + log.error("Error occurred instantiating " + processorClass.getCanonicalName(), ex); } return pn; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSearchFilterValuesDataGetterN3.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSearchFilterValuesDataGetterN3.java new file mode 100644 index 0000000000..93bc1b9b6d --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/preprocessors/utils/ProcessSearchFilterValuesDataGetterN3.java @@ -0,0 +1,157 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.preprocessors.utils; + +import static edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary.SEARCH_FILTER_VALUE; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.servlet.ServletContext; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchFilterValuesDataGetter; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jena.ontology.OntModel; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Resource; + +//Returns the appropriate n3 based on data getter +public class ProcessSearchFilterValuesDataGetterN3 extends ProcessDataGetterAbstract { + private static String classType = "java:" + SearchFilterValuesDataGetter.class.getCanonicalName(); + public static String searchFilterVarBase = "filterUri"; + private Log log = LogFactory.getLog(ProcessSearchFilterValuesDataGetterN3.class); + + public ProcessSearchFilterValuesDataGetterN3() { + } + + public List retrieveN3Required(int counter) { + return retrieveN3ForTypeAndFilter(counter); + } + + public List retrieveN3Optional(int counter) { + return null; + } + + public List retrieveN3ForTypeAndFilter(int counter) { + String n3ForType = getN3ForTypePartial(counter); + String n3 = n3ForType + "; \n" + "<" + DisplayVocabulary.SEARCH_FILTER_VALUE + "> " + + getN3VarName(searchFilterVarBase, counter) + " ."; + List n3List = new ArrayList(); + n3List.add(getPrefixes() + n3); + return n3List; + } + + public String getN3ForTypePartial(int counter) { + String dataGetterVar = getDataGetterVar(counter); + String classTypeVar = getN3VarName(classTypeVarBase, counter); + String n3 = dataGetterVar + " a " + classTypeVar; + return n3; + } + + public List retrieveLiteralsOnForm(int counter) { + // no literals, just the class group URI + List literalsOnForm = new ArrayList(); + return literalsOnForm; + } + + public List retrieveUrisOnForm(int counter) { + List urisOnForm = new ArrayList(); + urisOnForm.add(getVarName("filterUri", counter)); + urisOnForm.add(getVarName(classTypeVarBase, counter)); + return urisOnForm; + } + + public List retrieveFields(int counter) { + List fields = new ArrayList(); + fields.add(new FieldVTwo().setName(getVarName("filterUri", counter))); + fields.add(new FieldVTwo().setName(getVarName(classTypeVarBase, counter))); + return fields; + } + + public List getLiteralVarNamesBase() { + return Arrays.asList(); + } + + public List getUriVarNamesBase() { + return Arrays.asList("filterUri", classTypeVarBase); + } + + public String getClassType() { + return classType; + } + + public void populateExistingValues(String dataGetterURI, int counter, OntModel queryModel) { + // First, put dataGetterURI within scope as well + this.populateExistingDataGetterURI(dataGetterURI, counter); + // Put in type + this.populateExistingClassType(this.getClassType(), counter); + // Sparql queries for values to be executed + // And then placed in the correct place/literal or uri + String querystr = getExistingValuesClassGroup(dataGetterURI); + QueryExecution qe = null; + try { + Query query = QueryFactory.create(querystr); + qe = QueryExecutionFactory.create(query, queryModel); + ResultSet results = qe.execSelect(); + while (results.hasNext()) { + QuerySolution qs = results.nextSolution(); + Resource classGroupResource = qs.getResource("filterUri"); + // Put both literals in existing literals + existingUriValues.put(this.getVarName(searchFilterVarBase, counter), + new ArrayList(Arrays.asList(classGroupResource.getURI()))); + } + } catch (Exception ex) { + log.error("Exception occurred in retrieving existing values with query " + querystr, ex); + } + } + + protected String getExistingValuesClassGroup(String dataGetterURI) { + String query = getSparqlPrefix() + "\n" + + "SELECT ?filterUri ?filterName WHERE {" + + "<" + dataGetterURI + "> <" + SEARCH_FILTER_VALUE + "> ?filterUri .\n" + + "?filterUri <" + VitroVocabulary.LABEL + "> ?filterName .\n" + + "}"; + return query; + } + + public ObjectNode getExistingValuesJSON(String dataGetterURI, OntModel queryModel, ServletContext context) { + ObjectNode jObject = new ObjectMapper().createObjectNode(); + jObject.put("dataGetterClass", classType); + jObject.put(classTypeVarBase, classType); + getExistingSearchFilters(dataGetterURI, jObject, queryModel); + return jObject; + } + + private void getExistingSearchFilters(String dataGetterURI, ObjectNode jObject, OntModel queryModel) { + String querystr = getExistingValuesClassGroup(dataGetterURI); + QueryExecution qe = null; + try { + Query query = QueryFactory.create(querystr); + qe = QueryExecutionFactory.create(query, queryModel); + ResultSet results = qe.execSelect(); + while (results.hasNext()) { + QuerySolution qs = results.nextSolution(); + Resource filterUri = qs.getResource("filterUri"); + Literal name = qs.getLiteral("filterName"); + jObject.put("searchFilterUri", filterUri.getURI()); + jObject.put("searchFilterName", name.getLexicalForm()); + } + } catch (Exception ex) { + log.error("Exception occurred in retrieving existing values with query " + querystr, ex); + } + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java index 9596ed4838..20e08dd934 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/PagedSearchController.java @@ -76,7 +76,7 @@ public class PagedSearchController extends FreemarkerHttpServlet { public static final String PARAM_QUERY_TEXT = "querytext"; public static final String PARAM_QUERY_SORT_BY = "sort"; - protected static final Map> templateTable; + protected static final Map> templateTable = setupTemplateTable(); protected enum Format { HTML, @@ -90,10 +90,6 @@ protected enum Result { BAD_QUERY } - static { - templateTable = setupTemplateTable(); - } - /** * Overriding doGet from FreemarkerHttpController to do a page template (as opposed to body template) style output * for XML requests. @@ -134,7 +130,11 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) thro @Override protected ResponseValues processRequest(VitroRequest vreq) { + Map> requestFilters = SearchFiltering.getRequestFilters(vreq); + return process(vreq, requestFilters); + } + public static ResponseValues process(VitroRequest vreq, Map> requestFilters) { // There may be other non-html formats in the future Format format = getFormat(vreq); boolean wasXmlRequested = Format.XML == format; @@ -176,18 +176,12 @@ protected ResponseValues processRequest(VitroRequest vreq) { if (log.isDebugEnabled()) { log.debug(getSpentTime(startTime) + "ms spent before get sort configurations."); } - for (SearchFilter filter: filterConfigurationsByField.values()) { - filter.setInputText(SearchFiltering.getFilterInputText(vreq, filter.getId())); - filter.setRangeValues(SearchFiltering.getFilterRangeText(vreq, filter.getId())); - } - Map> requestFilters = SearchFiltering.getRequestFilters(vreq); - if (log.isDebugEnabled()) { - log.debug(getSpentTime(startTime) + "ms spent after getRequestFilters."); - } + SearchFiltering.setSelectedFilters(filterConfigurationsByField, requestFilters); if (log.isDebugEnabled()) { log.debug(getSpentTime(startTime) + "ms spent after setSelectedFilters."); } + Map sortConfigurations = SearchFiltering.getSortConfigurations(vreq); if (log.isDebugEnabled()) { log.debug(getSpentTime(startTime) + "ms spent before get query configurations."); @@ -272,7 +266,7 @@ protected ResponseValues processRequest(VitroRequest vreq) { SearchFiltering.getFiltersForTemplate(filterConfigurationsByField); body.put("filters", filtersForTemplateById); body.put("filterGroups", SearchFiltering.readFilterGroupsConfigurations(vreq, filtersForTemplateById)); - body.put("sorting", sortConfigurations.values()); + body.put("sortOptions", sortConfigurations); body.put("emptySearch", isEmptySearchFilters(filterConfigurationsByField)); } @@ -315,11 +309,11 @@ protected ResponseValues processRequest(VitroRequest vreq) { } } - private long getSpentTime(long startTime) { + private static long getSpentTime(long startTime) { return (System.nanoTime() - startTime) / 1000000; } - private Object isEmptySearchFilters(Map filterConfigurationsByField) { + private static Object isEmptySearchFilters(Map filterConfigurationsByField) { for (SearchFilter filter : filterConfigurationsByField.values()) { if (filter.isSelected()) { return false; @@ -328,7 +322,7 @@ private Object isEmptySearchFilters(Map filterConfiguratio return true; } - private void addFacetCountersFromRequest(SearchResponse response, Map filtersByField, + private static void addFacetCountersFromRequest(SearchResponse response, Map filtersByField, VitroRequest vreq) { long startTime = System.nanoTime(); List resultfacetFields = response.getFacetFields(); @@ -389,7 +383,7 @@ public static String getQueryText(VitroRequest vreq) { return query; } - private int getHitsPerPage(VitroRequest vreq) { + private static int getHitsPerPage(VitroRequest vreq) { int hitsPerPage = DEFAULT_HITS_PER_PAGE; try { int hits = Integer.parseInt(vreq.getParameter(PARAM_HITS_PER_PAGE)); @@ -403,7 +397,7 @@ private int getHitsPerPage(VitroRequest vreq) { return hitsPerPage; } - private int getDocumentsNumber(VitroRequest vreq) { + private static int getDocumentsNumber(VitroRequest vreq) { int documentsNumber = DEFAULT_DOCUMENTS_NUMBER; try { documentsNumber = Integer.parseInt(vreq.getParameter(PARAM_DOCUMENTS_NUMBER)); @@ -417,7 +411,7 @@ private int getDocumentsNumber(VitroRequest vreq) { return documentsNumber; } - private int getStartIndex(VitroRequest vreq) { + private static int getStartIndex(VitroRequest vreq) { int startIndex = 0; try { startIndex = Integer.parseInt(vreq.getParameter(PARAM_START_INDEX)); @@ -428,7 +422,7 @@ private int getStartIndex(VitroRequest vreq) { return startIndex; } - private String getSnippet(SearchResultDocument doc, SearchResponse response) { + private static String getSnippet(SearchResultDocument doc, SearchResponse response) { String docId = doc.getStringValue(VitroSearchTermNames.DOCID); StringBuilder text = new StringBuilder(); Map>> highlights = response.getHighlighting(); @@ -441,8 +435,8 @@ private String getSnippet(SearchResultDocument doc, SearchResponse response) { return text.toString(); } - private SearchQuery getQuery(String queryText, int hitsPerPage, int startIndex, VitroRequest vreq, - Map filtersByField, Map sortOptions) { + private static SearchQuery getQuery(String queryText, int hitsPerPage, int startIndex, VitroRequest vreq, + Map filters, Map sortOptions) { // Lowercase the search term to support wildcard searches: The search engine // applies no text // processing to a wildcard search term. @@ -457,24 +451,22 @@ private SearchQuery getQuery(String queryText, int hitsPerPage, int startIndex, addDefaultVitroFacets(vreq, query); - SearchFiltering.addFacetFieldsToQuery(filtersByField, query); - - Map filtersById = SearchFiltering.getFiltersById(filtersByField); + SearchFiltering.addFacetFieldsToQuery(filters, query); - SearchFiltering.addFiltersToQuery(vreq, query, filtersById); + SearchFiltering.addFiltersToQuery(query, filters); log.debug("Query = " + query.toString()); return query; } - private void addDefaultVitroFacets(VitroRequest vreq, SearchQuery query) { + private static void addDefaultVitroFacets(VitroRequest vreq, SearchQuery query) { String[] facets = vreq.getParameterValues(FACETS); if (facets != null && facets.length > 0) { query.addFacetFields(facets); } } - private void addSortRules(VitroRequest vreq, SearchQuery query, Map sortOptions) { + private static void addSortRules(VitroRequest vreq, SearchQuery query, Map sortOptions) { String sortType = getSortType(vreq); if (sortOptions.isEmpty()) { return; @@ -495,7 +487,7 @@ private void addSortRules(VitroRequest vreq, SearchQuery query, Map sortOptions, Set appliedSortOptions) { if (conf == null || appliedSortOptions.contains(conf.getId())) { return; @@ -512,7 +504,7 @@ private void addSortField(VitroRequest vreq, SearchQuery query, SortConfiguratio } } - private String getSortType(VitroRequest vreq) { + private static String getSortType(VitroRequest vreq) { return vreq.getParameter(PARAM_QUERY_SORT_BY); } @@ -550,12 +542,12 @@ protected static List getPagingLinks(int startIndex, int hitsPerPage return pagingLinks; } - private String getPreviousPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { + private static String getPreviousPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { params.put(PARAM_START_INDEX, String.valueOf(startIndex - hitsPerPage)); return UrlBuilder.getUrl(baseUrl, params); } - private String getNextPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { + private static String getNextPageLink(int startIndex, int hitsPerPage, String baseUrl, ParamMap params) { params.put(PARAM_START_INDEX, String.valueOf(startIndex + hitsPerPage)); return UrlBuilder.getUrl(baseUrl, params); } @@ -577,13 +569,13 @@ protected static class PagingLink extends LinkTemplateModel { } } - private ExceptionResponseValues doSearchError(Throwable e, Format f) { + private static ExceptionResponseValues doSearchError(Throwable e, Format f) { Map body = new HashMap(); body.put("message", "Search failed: " + e.getMessage()); return new ExceptionResponseValues(getTemplate(f, Result.ERROR), body, e); } - private TemplateResponseValues doFailedSearch(String message, String querytext, Format f, VitroRequest vreq) { + private static TemplateResponseValues doFailedSearch(String message, String querytext, Format f, VitroRequest vreq) { Map body = new HashMap(); body.put("title", I18n.text(vreq, "search_for", querytext)); if (StringUtils.isEmpty(message)) { @@ -596,7 +588,7 @@ private TemplateResponseValues doFailedSearch(String message, String querytext, /** * Makes a message to display to user for a bad search term. */ - private String makeBadSearchMessage(String querytext, String exceptionMsg, VitroRequest vreq) { + private static String makeBadSearchMessage(String querytext, String exceptionMsg, VitroRequest vreq) { String rv = ""; try { // try to get the column in the search term that is causing the problems @@ -658,7 +650,7 @@ protected boolean isRequestedFormatCSV(VitroRequest req) { } } - protected Format getFormat(VitroRequest req) { + protected static Format getFormat(VitroRequest req) { if (req != null && req.getParameter("xml") != null && "1".equals(req.getParameter("xml"))) { return Format.XML; } else if (req != null && req.getParameter("csv") != null && "1".equals(req.getParameter("csv"))) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java index 8066c6424e..4f9a8cae5d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFilter.java @@ -8,8 +8,10 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -40,15 +42,15 @@ public class SearchFilter { private boolean selected = false; private boolean input = false; private Map values = new LinkedHashMap<>(); - private boolean inputRegex = false; - private boolean facetsRequired; - + private boolean reverseFacetOrder; private String type = FILTER; private String rangeText = ""; private String rangeInput = ""; private boolean hidden = false; + private Optional locale; + private boolean multilingual; public String getRangeInput() { return rangeInput; @@ -62,8 +64,9 @@ public String getRangeText() { return rangeText; } - public SearchFilter(String id) { + public SearchFilter(String id, Optional locale) { this.id = id; + this.locale = locale; } public String getName() { @@ -87,6 +90,13 @@ public Integer getOrder() { } public String getField() { + if (multilingual) { + if (locale.isPresent()) { + return locale.get().toLanguageTag() + field; + } else { + return Locale.getDefault().toLanguageTag() + field; + } + } return field; } @@ -272,8 +282,8 @@ public void setToYear(String toYear) { public void sortValues() { List> list = new LinkedList<>(values.entrySet()); list.sort(new FilterValueComparator()); - values = list.stream() - .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, LinkedHashMap::new)); + values = list.stream().collect(Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> b, + LinkedHashMap::new)); } public boolean isPublic() { @@ -286,15 +296,22 @@ public void setPublic(boolean isPublic) { private class FilterValueComparator implements Comparator> { public int compare(Entry obj1, Entry obj2) { - FilterValue filter1 = obj1.getValue(); - FilterValue filter2 = obj2.getValue(); - int result = filter1.getOrder().compareTo(filter2.getOrder()); + FilterValue first = obj1.getValue(); + FilterValue second = obj2.getValue(); + // sort by order first + int result = first.getOrder().compareTo(second.getOrder()); if (result == 0) { // order are equal, sort by name - return filter1.getName().toLowerCase().compareTo(filter2.getName().toLowerCase()); - } else { - return result; + result = first.getName().toLowerCase().compareTo(second.getName().toLowerCase()); + if (result == 0) { + // names are equal, sort by id + result = first.getId().toLowerCase().compareTo(second.getId().toLowerCase()); + } + if (reverseFacetOrder) { + result = -result; + } } + return result; } } @@ -331,4 +348,12 @@ public int getMoreLimit() { public void setMoreLimit(int moreLimit) { this.moreLimit = moreLimit; } + + public void setMulitlingual(boolean multilingual) { + this.multilingual = multilingual; + } + + public void setReverseFacetOrder(boolean reverseFacetOrder) { + this.reverseFacetOrder = reverseFacetOrder; + } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java index a32e963a83..9972081c3d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/search/controller/SearchFiltering.java @@ -3,7 +3,6 @@ import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.ROLE_PUBLIC_URI; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; @@ -12,8 +11,10 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import java.util.Optional; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -47,6 +48,7 @@ public class SearchFiltering { private static final String FILTER_RANGE = "filter_range_"; private static final String FILTER_INPUT_PREFIX = "filter_input_"; private static final String FILTERS = "filters"; + public static final String ANY_VALUE = "[* TO *]"; private static final String FILTER_QUERY = "" + "PREFIX search: \n" @@ -54,7 +56,7 @@ public class SearchFiltering { + "PREFIX rdfs: \n" + "SELECT ?filter_id ?filter_type ?filter_label ?value_label ?value_id ?field_name ?public ?filter_order " + "?value_order (STR(?isUriReq) as ?isUri ) ?multivalued ?input ?regex ?facet ?min ?max ?role " - + "?value_public ?more_limit \n" + + "?value_public ?more_limit ?multilingual ?reverseFacetOrder\n" + "WHERE {\n" + " ?filter rdf:type search:Filter .\n" + " ?filter rdfs:label ?filter_label .\n" @@ -77,11 +79,16 @@ public class SearchFiltering { + " ?value search:public ?value_public .\n" + " }\n" + " }\n" + + " OPTIONAL {\n" + + " ?field search:isLanguageSpecific ?f_multilingual .\n" + + " BIND(?f_multilingual as ?bind_multilingual) .\n" + + " }\n" + " OPTIONAL {?field search:multivalued ?multivalued}\n" + " OPTIONAL {?filter search:isUriValues ?isUriReq }\n" + " OPTIONAL {?filter search:userInput ?input }\n" + " OPTIONAL {?filter search:userInputRegex ?regex }\n" + " OPTIONAL {?filter search:facetResults ?facet }\n" + + " OPTIONAL {?filter search:reverseFacetOrder ?reverseFacetOrder }\n" + " OPTIONAL {?filter search:from ?min }\n" + " OPTIONAL {?filter search:public ?public }\n" + " OPTIONAL {?filter search:to ?max }\n" @@ -92,6 +99,7 @@ public class SearchFiltering { + " }\n" + " BIND(coalesce(?filter_order_found, 0) as ?filter_order)\n" + " BIND(coalesce(?value_order_found, 0) as ?value_order)\n" + + " BIND(COALESCE(?bind_multilingual, false) as ?multilingual)\n" + "} ORDER BY ?filter_id ?filter_order ?value_order"; private static final String FILTER_GROUPS_QUERY = "" @@ -157,43 +165,20 @@ public class SearchFiltering { + " BIND(COALESCE(?bind_multilingual, false) as ?multilingual)\n" + "} ORDER BY ?sort_order ?label "; - protected static void addFiltersToQuery(VitroRequest vreq, SearchQuery query, - Map filterById) { - Enumeration paramNames = vreq.getParameterNames(); - while (paramNames.hasMoreElements()) { - String paramFilterName = paramNames.nextElement(); - if (!StringUtils.isBlank(paramFilterName) && paramFilterName.startsWith(SearchFiltering.FILTERS)) { - String[] filters = vreq.getParameterValues(paramFilterName); - if (filters != null && filters.length > 0) { - for (String filter : filters) { - String[] pair = filter.split(":", 2); - if (pair.length == 2) { - String name = pair[0].replace("\"", ""); - String value = pair[1].replace("\"", ""); - SearchFilter searchFilter = filterById.get(name); - if (searchFilter != null && searchFilter.getField() != null) { - query.addFilterQuery(searchFilter.getField() + ":\"" + value + "\""); - } - - } - } - } - - } - } - addPreconfiguredFiltersToQuery(query, filterById.values()); - } - - public static void addPreconfiguredFiltersToQuery(SearchQuery query, Collection collection) { - for (SearchFilter searchFilter : collection) { + protected static void addFiltersToQuery(SearchQuery query, Map filters) { + for (SearchFilter searchFilter : filters.values()) { if (searchFilter.isInput()) { SearchFiltering.addInputFilter(query, searchFilter); } else if (searchFilter.isRange()) { SearchFiltering.addRangeFilter(query, searchFilter); } for (FilterValue fv : searchFilter.getValues().values()) { - if (fv.isDefault()) { - query.addFilterQuery(searchFilter.getField() + ":\"" + fv.getId() + "\""); + if (fv.isDefault() || fv.getSelected()) { + if (ANY_VALUE.equals(fv.getId())) { + query.addFilterQuery(searchFilter.getField() + ":" + ANY_VALUE ); + } else { + query.addFilterQuery(searchFilter.getField() + ":\"" + fv.getId() + "\""); + } } } } @@ -204,32 +189,44 @@ public static Map> getRequestFilters(VitroRequest vreq) { Enumeration paramNames = vreq.getParameterNames(); while (paramNames.hasMoreElements()) { String paramFilterName = paramNames.nextElement(); - if (!StringUtils.isBlank(paramFilterName) && paramFilterName.startsWith(SearchFiltering.FILTERS)) { - String[] filters = vreq.getParameterValues(paramFilterName); - if (filters != null && filters.length > 0) { - for (String filter : filters) { + if (paramFilterName.startsWith(SearchFiltering.FILTERS)) { + String[] filterValues = vreq.getParameterValues(paramFilterName); + if (filterValues != null && filterValues.length > 0) { + for (String filter : filterValues) { String[] pair = filter.split(":", 2); if (pair.length == 2) { - String name = pair[0].replace("\"", ""); + String filterId = pair[0].replace("\"", ""); String value = pair[1].replace("\"", ""); - if (requestFilters.containsKey(name)) { - List list = requestFilters.get(name); + if (requestFilters.containsKey(filterId)) { + List list = requestFilters.get(filterId); list.add(value); } else { - requestFilters.put(name, new LinkedList(Arrays.asList(value))); + requestFilters.put(filterId, new LinkedList(Arrays.asList(value))); } } } } } + if (paramFilterName.startsWith(SearchFiltering.FILTER_RANGE)) { + String[] values = vreq.getParameterValues(paramFilterName); + if (values != null && values.length > 0) { + String filterId = paramFilterName.replace(SearchFiltering.FILTER_RANGE, ""); + requestFilters.put(filterId, new LinkedList(Arrays.asList(values[0]))); + } + } + if (paramFilterName.startsWith(SearchFiltering.FILTER_INPUT_PREFIX)) { + String[] values = vreq.getParameterValues(paramFilterName); + if (values != null && values.length > 0) { + String filterId = paramFilterName.replace(SearchFiltering.FILTER_INPUT_PREFIX, ""); + requestFilters.put(filterId, new LinkedList(Arrays.asList(values[0]))); + } + } } - return requestFilters; } public static Map readFilterConfigurations(Set currentRoles, VitroRequest vreq) { long startTime = System.nanoTime(); - Map filtersByField = new LinkedHashMap<>(); Model model; if (vreq != null) { @@ -258,8 +255,11 @@ public static Map readFilterConfigurations(Set cur if (filtersByField.containsKey(resultFieldName)) { filter = filtersByField.get(resultFieldName); } else { - filter = createSearchFilter(filtersByField, solution, resultFilterId, resultFieldName); + Optional locale = vreq != null ? Optional.of(vreq.getLocale()) : Optional.empty(); + filter = createSearchFilter(filtersByField, solution, resultFilterId, resultFieldName, locale); } + filter.setType(solution.get("filter_type")); + filter.setMulitlingual(solution.get("multilingual").asLiteral().getBoolean()); if (solution.get("value_id") == null) { continue; } @@ -292,7 +292,18 @@ public static Map readFilterConfigurations(Set cur public static void addDefaultFilters(SearchQuery query, Set currentRoles) { Map filtersByField = SearchFiltering.readFilterConfigurations(currentRoles, null); - SearchFiltering.addPreconfiguredFiltersToQuery( query, filtersByField.values()); + for (SearchFilter searchFilter : filtersByField.values()) { + if (searchFilter.isInput()) { + SearchFiltering.addInputFilter(query, searchFilter); + } else if (searchFilter.isRange()) { + SearchFiltering.addRangeFilter(query, searchFilter); + } + for (FilterValue fv : searchFilter.getValues().values()) { + if (fv.isDefault() || fv.getSelected()) { + query.addFilterQuery(searchFilter.getField() + ":\"" + fv.getId() + "\""); + } + } + } } public static Map sortFilters(Map filters) { @@ -408,9 +419,9 @@ public static Map getSortConfigurations(VitroRequest } private static SearchFilter createSearchFilter(Map filtersByField, - QuerySolution solution, String resultFilterId, String resultFieldName) { + QuerySolution solution, String resultFilterId, String resultFieldName, Optional locale) { SearchFilter filter; - filter = new SearchFilter(resultFilterId); + filter = new SearchFilter(resultFilterId, locale); filtersByField.put(resultFieldName, filter); filter.setName(solution.get("filter_label")); filter.setOrder(solution.get("filter_order")); @@ -450,6 +461,11 @@ private static SearchFilter createSearchFilter(Map filters filter.setFacetsRequired(facet.asLiteral().getBoolean()); } + RDFNode reverseFacetOrder = solution.get("reverseFacetOrder"); + if (reverseFacetOrder != null) { + filter.setReverseFacetOrder(reverseFacetOrder.asLiteral().getBoolean()); + } + RDFNode moreLimit = solution.get("more_limit"); if (moreLimit != null && moreLimit.isLiteral()) { filter.setMoreLimit(moreLimit.asLiteral().getInt()); @@ -472,8 +488,7 @@ private static void addInputFilter(SearchQuery query, SearchFilter searchFilter) } String searchText = searchFilter.getInputText(); if (searchFilter.isInputRegex()) { - searchText = searchText.replaceAll("([ )(:])", "\\\\$1") + "*"; - query.addFilterQuery(searchFilter.getField() + ":" + searchText); + query.addFilterQuery(searchFilter.getField() + ":/" + searchText + "/"); } else { query.addFilterQuery(searchFilter.getField() + ":\"" + searchText + "\""); } @@ -498,17 +513,26 @@ static String getFilterRangeText(VitroRequest vreq, String name) { return ""; } - public static void setSelectedFilters(Map filtersByField, - Map> requestFilters) { - for (SearchFilter filter : filtersByField.values()) { + public static void setSelectedFilters(Map filters, Map> requestFilters) { + for (SearchFilter filter : filters.values()) { if (requestFilters.containsKey(filter.getId())) { List requestValues = requestFilters.get(filter.getId()); if (!SearchFiltering.isEmptyValues(requestValues)) { filter.setSelected(true); - for (String requestValue : requestValues) { - if (filter.getValues().containsKey(requestValue)) { - FilterValue value = filter.getValue(requestValue); - value.setSelected(true); + if (filter.isRange()) { + filter.setRangeValues(requestValues.iterator().next()); + } else if (filter.isInput()) { + filter.setInputText(requestValues.iterator().next()); + } else { + for (String requestValue : requestValues) { + if (filter.getValues().containsKey(requestValue)) { + FilterValue value = filter.getValue(requestValue); + value.setSelected(true); + } else { + FilterValue value = new FilterValue(requestValue); + value.setSelected(true); + filter.addValue(value); + } } } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java index 2fc1a35ee1..1839cacfce 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java @@ -16,7 +16,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - +import org.apache.jena.ontology.OntModel; import org.apache.jena.query.Query; import org.apache.jena.query.QueryExecution; import org.apache.jena.query.QueryExecutionFactory; @@ -447,8 +447,38 @@ public static void getClassGroupForDataGetter(HttpServletRequest req, Map \n" + + "SELECT ?filterUri ?filterName WHERE {\n" + + " ?filterUri a search:Filter .\n" + + " ?filterUri search:facetResults true .\n" + + " ?filterUri <" + VitroVocabulary.LABEL + "> ?filterName .\n" + + "}"; + + public static Object getSearchFilters(VitroRequest vreq) { + OntModel model = vreq.getDisplayModel(); + List> filters = new ArrayList>(); + Query q = QueryFactory.create(searchFiltersQuery); + QuerySolutionMap bindings = new QuerySolutionMap(); + model.enterCriticalSection(Lock.READ); + try (QueryExecution qexec = QueryExecutionFactory.create(q, model, bindings);) { + ResultSet res = qexec.execSelect(); + while (res.hasNext()) { + QuerySolution sol = res.next(); + Resource uri = sol.getResource("filterUri"); + Literal name = sol.getLiteral("filterName"); + HashMap filter = new HashMap(); + filter.put("URI", uri.toString()); + filter.put("publicName", name.getLexicalForm()); + filters.add(filter); + } + } catch (Exception e) { + log.error(e, e); + } finally { + model.leaveCriticalSection(); + } + return filters; + } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchFilterValuesDataGetter.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchFilterValuesDataGetter.java new file mode 100644 index 0000000000..290873984b --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/SearchFilterValuesDataGetter.java @@ -0,0 +1,130 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ +package edu.cornell.mannlib.vitro.webapp.utils.dataGetter; + +import static edu.cornell.mannlib.vitro.webapp.search.controller.SearchFiltering.ANY_VALUE; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.search.controller.PagedSearchController; +import edu.cornell.mannlib.vitro.webapp.search.controller.SearchFiltering; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.QuerySolutionMap; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.shared.Lock; +import org.apache.tika.utils.StringUtils; + +public class SearchFilterValuesDataGetter extends DataGetterBase implements DataGetter { + private static final String defaultTemplate = "browseSearchFilterValues.ftl"; + private static final String searchFilterUri = "<" + DisplayVocabulary.SEARCH_FILTER_VALUE + ">"; + private static final Log log = LogFactory.getLog(SearchFilterValuesDataGetter.class); + + private String dataGetterURI; + private String searchFilter; + private VitroRequest vreq; + + /** + * Constructor with display model and data getter URI that will be called by reflection. + */ + public SearchFilterValuesDataGetter(VitroRequest vreq, Model displayModel, String dataGetterURI) { + this.configure(vreq, displayModel, dataGetterURI); + } + + @Override + public Map getData(Map pageData) { + Map responseMap = new HashMap<>(); + responseMap.putAll(vreq.getParameterMap()); + Map> requestFilters = new HashMap<>(); + requestFilters.put(searchFilter, new ArrayList(Arrays.asList(ANY_VALUE))); + Map defaultSearchResults = PagedSearchController.process(vreq, requestFilters).getMap(); + responseMap.put("filterGenericInfo", defaultSearchResults); + requestFilters = SearchFiltering.getRequestFilters(vreq); + if (!isValidFilterValueProvided(requestFilters)) { + requestFilters.put(searchFilter, new ArrayList(Arrays.asList(ANY_VALUE))); + } + responseMap.putAll(PagedSearchController.process(vreq, requestFilters).getMap()); + responseMap.put("searchFilter", this.searchFilter); + responseMap.put("bodyTemplate", defaultTemplate); + responseMap.put("languageAware", isLanguageAwarenessEnabled()); + return responseMap; + } + + private Boolean isLanguageAwarenessEnabled() { + ConfigurationProperties cp = ConfigurationProperties.getInstance(); + return Boolean.valueOf(cp.getProperty("RDFService.languageFilter", "false")); + } + + private boolean isValidFilterValueProvided(Map> requestFilters) { + if (!requestFilters.containsKey(searchFilter)) { + return false; + } + List values = requestFilters.get(searchFilter); + for (String value : values) { + if (!StringUtils.isBlank(value)) { + return true; + } + } + return true; + } + + /** + * Configure this instance based on the URI and display model. + */ + protected void configure(VitroRequest vreq, Model displayModel, String dataGetterURI) { + if (vreq == null) { + throw new IllegalArgumentException("VitroRequest may not be null."); + } + if (displayModel == null) { + throw new IllegalArgumentException("Display Model may not be null."); + } + if (dataGetterURI == null) { + throw new IllegalArgumentException("PageUri may not be null."); + } + + this.vreq = vreq; + this.dataGetterURI = dataGetterURI; + + QuerySolutionMap initBindings = new QuerySolutionMap(); + initBindings.add("dataGetterURI", ResourceFactory.createResource(this.dataGetterURI)); + + Query configurationQuery = QueryFactory.create(dataGetterQuery); + displayModel.enterCriticalSection(Lock.READ); + try (QueryExecution qexec = QueryExecutionFactory.create(configurationQuery, displayModel, initBindings)) { + ResultSet res = qexec.execSelect(); + while (res.hasNext()) { + QuerySolution soln = res.next(); + this.searchFilter = soln.getLiteral("id").toString(); + } + } finally { + displayModel.leaveCriticalSection(); + } + } + + public static final String defaultVarNameForResults = "results"; + + /** + * Query to get search filter id for a given URI. + */ + private static final String dataGetterQuery = + "PREFIX display: <" + DisplayVocabulary.DISPLAY_NS + "> \n" + + "PREFIX search: \n" + + "SELECT ?id WHERE { \n" + + "?dataGetterURI " + searchFilterUri + " ?searchFilter .\n" + + "?searchFilter search:id ?id .\n" + + "}"; + +} diff --git a/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 b/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 index a53effd4fe..763f9773e9 100644 --- a/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 +++ b/home/src/main/resources/rdf/display/everytime/dataGetterLabels.n3 @@ -6,6 +6,7 @@ @prefix rdfs: . rdfs:label "Class Group Page" . + rdfs:label "Search filter values" . rdfs:label "Browse Page" . rdfs:label "Class Group Page - Selected Classes" . rdfs:label "Sparql Query Results" . diff --git a/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 b/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 index 444c16e128..8c8767dc3c 100644 --- a/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 +++ b/home/src/main/resources/rdf/display/firsttime/search_individuals_vitro.n3 @@ -4,7 +4,7 @@ @prefix rdfs: . :filter_group_search_filters a vitro-search:FilterGroup ; - vitro-search:contains :filter_category , :filter_type , :filter_querytext ; + vitro-search:contains :filter_category , :filter_type , :filter_querytext; vitro-search:id "main" ; vitro-search:order 1 ; vitro-search:public true . @@ -25,6 +25,27 @@ vitro-search:isUriValues true ; vitro-search:public true . +:filter_raw_label_regex + a vitro-search:Filter ; + rdfs:label "Label regular expression"@en-US ; + vitro-search:facetResults false ; + vitro-search:filterField :field_name_raw ; + vitro-search:id "raw_label_regex" ; + vitro-search:public true ; + vitro-search:userInput true ; + vitro-search:userInputRegex true . + +:filter_label_regex + a vitro-search:Filter ; + rdfs:label "Label regular expression"@en-US ; + vitro-search:facetResults false ; + vitro-search:filterField :field_label_display ; + vitro-search:id "label_regex" ; + vitro-search:public true ; + vitro-search:userInput true ; + vitro-search:userInputRegex true . + + :filter_querytext a vitro-search:Filter ; vitro-search:order 1 ; @@ -75,6 +96,11 @@ vitro-search:isLanguageSpecific true ; vitro-search:indexField "_label_sort" . +:field_label_display + a vitro-search:SearchField ; + vitro-search:isLanguageSpecific true ; + vitro-search:indexField "_label_display" . + :field_name_raw a vitro-search:SearchField ; vitro-search:indexField "nameRaw" . @@ -85,7 +111,6 @@ :field_type a vitro-search:SearchField ; vitro-search:indexField "type" ; - vitro-search:isLanguageSpecific true ; vitro-search:multivalued true . :field_querytext diff --git a/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 b/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 index e2764a5bc3..8b0d940d27 100644 --- a/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 +++ b/home/src/main/resources/rdf/displayTbox/everytime/displayTBOX.n3 @@ -28,6 +28,8 @@ display:HomePage a owl:Class . display:ClassGroupPage a owl:Class . +display:SearchFilterValuesDataGetter a owl:Class . + display:IndividualsForClassesPage a owl:Class . display:InternalClassesPage a owl:Class . @@ -57,6 +59,10 @@ display:RequiredAction a owl:Class ; a owl:Class ; rdfs:comment "A data getter for a VClassGroup page" . + + a owl:Class ; + rdfs:comment "A data getter for a search filter values page" . + a owl:Class ; rdfs:comment "A data getter for a Fixed piece of HTML stored in RDF" . diff --git a/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl index e831d2b0e3..51619edbfa 100644 --- a/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@de-DE ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Ergebnisse der Suchfilterung durchsuchen"@de-DE ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Suchfilter auswählen"@de-DE ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl index 0c1d748f46..35ee25d903 100644 --- a/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:suppress_operation_for_unrelated_individuals_of_this_class.Vitro uil:hasApp "Vitro" ; uil:hasKey "suppress_operation_for_unrelated_individuals_of_this_class" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@en-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Browse search filter results"@en-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Select search filter"@en-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl index aedb481253..b94cb67717 100644 --- a/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,27 @@ uil-data:suppress_operation_for_unrelated_individuals_of_this_class.Vitro uil:hasApp "Vitro" ; uil:hasKey "suppress_operation_for_unrelated_individuals_of_this_class" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@en-US ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Browse search filter results"@en-US ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Select search filter"@en-US ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . diff --git a/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl index c9cb7f4aed..303592473d 100644 --- a/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,ñ,o,p,q,r,s,t,u,v,w,x,y,z"@es ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Explorar resultados de búsqueda filtrada"@es ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Seleccionar filtro de búsqueda"@es ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl index b763cd47ee..131843119e 100644 --- a/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@fr-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Parcourir les résultats de filtrage de recherche"@fr-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Sélectionner un filtre de recherche"@fr-CA ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl index 08d1635612..54e805d4df 100644 --- a/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,28 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z"@pt-BR ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Navegar pelos resultados de filtragem de pesquisa"@pt-BR ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Selecionar filtro de pesquisa"@pt-BR ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + diff --git a/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl index f0c3143a74..7c34cf98ec 100644 --- a/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,29 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "а,б,в,г,д,е,ё,ж,з,и,ӣ,к,л,м,н,о,п,р,с,т,у,ф,х,ц,ч,ш,щ,э,ю,я"@ru-RU ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Отображение результатов поискового фильтра"@ru-RU ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Выберите фильтр"@ru-RU ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . + + diff --git a/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl index 9ebf657aa1..4c3ac1edff 100644 --- a/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -6445,3 +6445,27 @@ uil-data:password_reset_admin_notification_email_html.Vitro uil:hasApp "Vitro" ; uil:hasKey "password_reset_admin_notification_email_html" ; uil:hasPackage "Vitro-languages" . + +uil-data:browse_results_alphabetical_index.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "a,b,c,č,ć,d,dž,đ,e,f,g,h,i,j,k,l,lj,m,n,nj,o,p,r,s,š,t,u,v,z,ž"@sr-Latn-RS ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_results_alphabetical_index" ; + uil:hasPackage "Vitro-languages" . + +uil-data:browse_search_filter_facets.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Pregledajte rezultate filtriranja pretrage"@sr-Latn-RS ; + uil:hasApp "Vitro" ; + uil:hasKey "browse_search_filter_facets" ; + uil:hasPackage "Vitro-languages" . + +uil-data:select_search_filter_to_browse.Vitro + rdf:type owl:NamedIndividual ; + rdf:type uil:UILabel ; + rdfs:label "Izaberite filter za pretragu"@sr-Latn-RS ; + uil:hasApp "Vitro" ; + uil:hasKey "select_search_filter_to_browse" ; + uil:hasPackage "Vitro-languages" . diff --git a/webapp/src/main/webapp/css/search-results.css b/webapp/src/main/webapp/css/search-results.css index 235955e29a..8768b5ec71 100644 --- a/webapp/src/main/webapp/css/search-results.css +++ b/webapp/src/main/webapp/css/search-results.css @@ -41,10 +41,44 @@ display: block; } -.tab-pane > label { +.tab > label { display: inline-block; } +.tab > a { + padding: 10px 15px; + position: relative; + display: block; + float: left; + text-decoration: none; + color: #555; +} + +.tab { + display: block; +} + +.tabs { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1px; +} + +#filter-groups > .tab { + border: 1px solid #ddd; + border-bottom: 0; + border-radius: 4px 4px 0 0; +} +#filter-groups { + border-bottom: 1px solid #ddd; +} + +#filter-groups > .tab.active { + margin-bottom: -1px; + background-color: #fff; +} + input[type=radio]:checked + label { background-color: #0F6568; padding: 2px 5px 2px 5px; @@ -101,10 +135,18 @@ input[type=checkbox]:not(:checked) + label { padding: 0.3em; } +.filter-area >.tab.active { + width: 100%; +} + .range-filter { padding: 15px; } +.search-filter-group-container { + border-bottom: solid 1px #ddd; + width: 100%; +} #search-filter-container > ul > li > a { padding: 7px 7px; diff --git a/webapp/src/main/webapp/css/search/custom_filters.css b/webapp/src/main/webapp/css/search/custom_filters.css new file mode 100644 index 0000000000..025c383868 --- /dev/null +++ b/webapp/src/main/webapp/css/search/custom_filters.css @@ -0,0 +1,42 @@ +.li-selected>label { + background: url(../../images/arrowIcon.gif) 0px 5px no-repeat; + color: #2ea0cf; + padding-left: 16px; +} + +.checked-search-input-label { + padding: 2px 5px 2px 5px; + border: 0px; + background-color: inherit; +} + +.range-slider { + margin-bottom: 15px; +} + +.range-slider-end { + display: inline-block; +} + +.range-slider-start { + display: inline-block; +} + +#filter-form-sort { + margin: 0px; + border-bottom: 0px; + border-top: 0px; + border-left: 0px; +} + +#filter-form-hits-per-page { + margin: 0px; + border-bottom: 0px; + border-top: 0px; + border-left: 0px; +} + +#browsing-options { + border-bottom: 1px solid #dde4e3; + border-top: 1px solid #dde4e3; +} \ No newline at end of file diff --git a/webapp/src/main/webapp/js/menupage/pageManagementUtils.js b/webapp/src/main/webapp/js/menupage/pageManagementUtils.js index 99ed88d00d..66e04c2b9f 100644 --- a/webapp/src/main/webapp/js/menupage/pageManagementUtils.js +++ b/webapp/src/main/webapp/js/menupage/pageManagementUtils.js @@ -102,6 +102,7 @@ var pageManagementUtils = { //list of options this.contentTypeSelectOptions = $('select#typeSelect option'); this.classGroupSection = $("section#browseClassGroup"); + this.searchFilterSection = $("section#searchFilterValues"); this.sparqlQuerySection = $("section#sparqlQuery"); this.fixedHTMLSection = $("section#fixedHtml"); this.searchIndividualsSection = $("section#searchIndividuals"); @@ -145,6 +146,7 @@ var pageManagementUtils = { // $("section#pageDetails").hide(); this.headerBar.hide(); this.classGroupSection.hide(); + this.searchFilterSection.hide(); this.sparqlQuerySection.hide(); this.fixedHTMLSection.hide(); this.searchIndividualsSection.hide(); @@ -241,6 +243,7 @@ var pageManagementUtils = { pageManagementUtils.clearSourceTemplateValues(); pageManagementUtils.headerBar.hide(); pageManagementUtils.classGroupSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.contentTypeSelectOptions.eq(0).prop('selected', 'selected'); @@ -283,6 +286,7 @@ var pageManagementUtils = { //Hide all sections pageManagementUtils.classGroupSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); @@ -355,6 +359,7 @@ var pageManagementUtils = { pageManagementUtils.clearSourceTemplateValues(); if ( _this.contentTypeSelect.val() == "browseClassGroup" ) { pageManagementUtils.classGroupSection.show(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); @@ -362,7 +367,7 @@ var pageManagementUtils = { pageManagementUtils.headerBar.show(); $('div#selfContainedDiv').hide(); } - if ( _this.contentTypeSelect.val() == "fixedHtml" || _this.contentTypeSelect.val() == "sparqlQuery" || _this.contentTypeSelect.val() == "searchIndividuals") { + if ( _this.contentTypeSelect.val() == "fixedHtml" || _this.contentTypeSelect.val() == "sparqlQuery" || _this.contentTypeSelect.val() == "searchIndividuals" || _this.contentTypeSelect.val() == "searchFilterValues") { pageManagementUtils.classGroupSection.hide(); //if fixed html show that, otherwise show sparql results if ( _this.contentTypeSelect.val() == "fixedHtml" ) { @@ -370,17 +375,26 @@ var pageManagementUtils = { pageManagementUtils.fixedHTMLSection.show(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); + pageManagementUtils.searchFilterSection.hide(); } else if (_this.contentTypeSelect.val() == "sparqlQuery"){ pageManagementUtils.headerBar.text(pageManagementUtils.sparqlResults + " - "); pageManagementUtils.sparqlQuerySection.show(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.searchIndividualsSection.hide(); + pageManagementUtils.searchFilterSection.hide(); + } else if (_this.contentTypeSelect.val() == "searchFilterValues"){ + pageManagementUtils.headerBar.text(pageManagementUtils.browseSearchFilter + " - "); + pageManagementUtils.searchFilterSection.show(); + pageManagementUtils.sparqlQuerySection.hide(); + pageManagementUtils.fixedHTMLSection.hide(); + pageManagementUtils.searchIndividualsSection.hide(); } else { //search individuals pageManagementUtils.headerBar.text(pageManagementUtils.searchIndividuals + " - "); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.fixedHTMLSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.searchIndividualsSection.show(); } @@ -390,6 +404,7 @@ var pageManagementUtils = { } if ( _this.contentTypeSelect.val() == "" ) { pageManagementUtils.classGroupSection.hide(); + pageManagementUtils.searchFilterSection.hide(); pageManagementUtils.fixedHTMLSection.hide(); pageManagementUtils.sparqlQuerySection.hide(); pageManagementUtils.searchIndividualsSection.hide(); diff --git a/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js b/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js index 6639480417..454698f715 100644 --- a/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js +++ b/webapp/src/main/webapp/js/menupage/processDataGetterUtils.js @@ -7,6 +7,7 @@ //This will need to be overridden or extended, what have you.. in VIVO var processDataGetterUtils = { dataGetterProcessorMap:{"browseClassGroup": processClassGroupDataGetterContent, + "searchFilterValues": processSearchFilterValuesDataGetterContent, "sparqlQuery": processSparqlDataGetterContent, "fixedHtml":processFixedHTMLDataGetterContent, "individualsForClasses":processIndividualsForClassesDataGetterContent, diff --git a/webapp/src/main/webapp/js/menupage/processSearchFilterValuesDataGetterContent.js b/webapp/src/main/webapp/js/menupage/processSearchFilterValuesDataGetterContent.js new file mode 100644 index 0000000000..55e1855249 --- /dev/null +++ b/webapp/src/main/webapp/js/menupage/processSearchFilterValuesDataGetterContent.js @@ -0,0 +1,44 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +$.extend(this, i18nStringsBrowseSearchFilters); +//Process sparql data getter and provide a json object with the necessary information +//Depending on what is included here, a different type of data getter might be used +var processSearchFilterValuesDataGetterContent = { + dataGetterClass:null, + //can use this if expect to initialize from elsewhere + initProcessor:function(dataGetterClassInput) { + this.dataGetterClass = dataGetterClassInput; + }, + + processPageContentSection:function(pageContentSection) { + var searchFilter = pageContentSection.find("select[name='selectSearchFilter']").val(); + //query model should also be an input, ensure class group URI is saved as URI and not string + var returnObject = {filterUri:searchFilter, dataGetterClass:this.dataGetterClass}; + return returnObject; + }, + //For an existing set of content where form is already set, fill in the values + populatePageContentSection:function(existingContentObject, pageContentSection) { + let searchFilterValue = existingContentObject["searchFilterUri"]; + pageContentSection.find("select[name='selectSearchFilter']").val(searchFilterValue); + }, + + retrieveContentLabel:function() { + return i18nStringsBrowseSearchFilters.browseSearchFilter; + }, + retrieveAdditionalLabelText:function(existingContentObject) { + var label = ""; + var filterName = existingContentObject["searchFilterName"]; + if(filterName != null) { + label = filterName; + } + return label; + }, + //Validation on form submit: Check to see that filter has been selected + validateFormSubmission: function(pageContentSection, pageContentSectionLabel) { + var validationError = ""; + if (pageContentSection.find('select[name="selectSearchFilter"]').val() =='-1') { + validationError += pageContentSectionLabel + ": " + i18nStringsBrowseSearchFilters.supplySearchFilterValues + "
"; + } + return validationError; + } +} diff --git a/webapp/src/main/webapp/js/search/search_results.js b/webapp/src/main/webapp/js/search/search_results.js new file mode 100644 index 0000000000..bd63a0e9b1 --- /dev/null +++ b/webapp/src/main/webapp/js/search/search_results.js @@ -0,0 +1,122 @@ +$("input:radio").on("click",function (e) { + var input=$(this); + if (input.is(".selected-input")) { + input.prop("checked",false); + } else { + input.prop("checked",true); + } + $('#' + searchFormId).submit(); +}); + +$("input:checkbox").on("click",function (e) { + var input=$(this); + input.checked = !input.checked; + $('#' + searchFormId).submit(); +}); + +function clearInput(elementId) { + let inputEl = document.getElementById(elementId); + inputEl.value = ""; + let srcButton = document.getElementById("button_" + elementId); + srcButton.classList.add("unchecked-selected-search-input-label"); + $('#' + searchFormId).submit(); +} + +function createSliders(){ + sliders = document.getElementsByClassName('range-slider-container'); + for (let sliderElement of sliders) { + createSlider(sliderElement); + } + $(".noUi-handle").on("mousedown", function (e) { + $(this)[0].setPointerCapture(e.pointerId); + }); + $(".noUi-handle").on("mouseup", function (e) { + $('#' + searchFormId).submit(); + }); + $(".noUi-handle").on("pointerup", function (e) { + $('#' + searchFormId).submit(); + }); +}; + +function createSlider(sliderContainer){ + rangeSlider = sliderContainer.querySelector('.range-slider'); + + noUiSlider.create(rangeSlider, { + range: { + min: Number(sliderContainer.getAttribute('min')), + max: Number(sliderContainer.getAttribute('max')) + }, + + step: 1, + start: [Number(sliderContainer.querySelector('.range-slider-start').textContent), + Number(sliderContainer.querySelector('.range-slider-end').textContent)], + + format: wNumb({ + decimals: 0 + }) + }); + + var dateValues = [ + sliderContainer.querySelector('.range-slider-start'), + sliderContainer.querySelector('.range-slider-end') + ]; + + var input = sliderContainer.querySelector('.range-slider-input'); + var first = true; + + rangeSlider.noUiSlider.on('update', function (values, handle) { + dateValues[handle].innerHTML = values[handle]; + var active = input.getAttribute('active'); + if (active === null){ + input.setAttribute('active', "false"); + } else if (active !== "true"){ + input.setAttribute('active', "true"); + } else { + var startDate = new Date(+values[0],0,1); + var endDate = new Date(+values[1],0,1); + input.value = startDate.toISOString() + " " + endDate.toISOString(); + } + }); +} + +window.onload = (event) => { + createSliders(); +}; + +$('#' + searchFormId).submit(function () { +$('#' + searchFormId) + .find('input') + .filter(function () { + return !this.value; + }) + .prop('name', ''); +}); + +function expandSearchOptions(){ + $(event.target).parent().children('.additional-search-options').removeClass("hidden-search-option"); + $(event.target).parent().children('.less-facets-link').show(); + $(event.target).hide(); +} + +function collapseSearchOptions(){ + $(event.target).parent().children('.additional-search-options').addClass("hidden-search-option"); + $(event.target).parent().children('.more-facets-link').show(); + $(event.target).hide(); +} + +function openTab(event, tabName) { + let currentTab = document.getElementById(tabName); + let tabs = currentTab.parentElement.querySelectorAll(':scope > .tab'); + for (let i = 0; i < tabs.length; i++) { + let tab = tabs[i]; + tab.classList.add('fade'); + } + let tabElement = event.srcElement.parentElement; + let srcTabs = tabElement.parentElement.querySelectorAll(':scope > .tab'); + for (let i = 0; i < srcTabs.length; i++) { + let tab = srcTabs[i]; + tab.classList.remove('active'); + } + tabElement.classList.add('active'); + currentTab.classList.remove('fade'); +} \ No newline at end of file diff --git a/webapp/src/main/webapp/templates/freemarker/body/menupage/browseSearchFilterValues.ftl b/webapp/src/main/webapp/templates/freemarker/body/menupage/browseSearchFilterValues.ftl new file mode 100644 index 0000000000..4e8468d72c --- /dev/null +++ b/webapp/src/main/webapp/templates/freemarker/body/menupage/browseSearchFilterValues.ftl @@ -0,0 +1,236 @@ +<#-- $This file is distributed under the terms of the license in LICENSE$ --> +<#import "search-lib.ftl" as sl> + + +<#-- <#assign additionalFilters = ["type"]> --> +<#if filterGenericInfo.filters[searchFilter]??> + + ${stylesheets.add('')} +
+
+
+ +
+ <@printPagingLinks /> +
+ <@showSortOptions /> + <@sl.showHits "filter-form" /> +
+ <@filteredResults /> + <@printPagingLinks /> +
+
+
+
+ + + + + +<#macro filteredResults> +
    + <#if individuals??> + <#list individuals as individual> +
  • + <@shortView uri=individual.uri viewContext="index" /> +
  • + + +
+ + +<#macro filterFacets f> + <#assign selectedValue = "" > + <#assign valueNumber = 1> + <#list f.values?values as value> + <#if user.loggedIn || value.publiclyAvailable> + <#if value.selected> + <#assign selectedValue = value.id > + + <#assign valueLabel = value.name > + <#if !(valueLabel?has_content)> + <#assign valueLabel = value.id > + + <#if value.selected> +
  • + + <@sl.getInput f value sl.getValueID(f.id, valueNumber) valueNumber 'filter-form' /> + <@sl.getSelectedLabel sl.getValueID(f.id, valueNumber)?html value f getCurrentCount(f value) /> + +
  • + <#else> +
  • + + <@sl.getInput f value sl.getValueID(f.id, valueNumber) valueNumber 'filter-form' /> + <@sl.getLabel sl.getValueID(f.id, valueNumber) value f getCurrentCount(f value) /> + +
  • + + <#assign valueNumber = valueNumber + 1> + + + + +<#function getCurrentCount f v> + <#if filters[f.id]??> + <#assign filter = filters[f.id]> + <#if filter.values[v.id]??> + <#return filter.values[v.id].count > + <#else> + <#return 0 /> + + <#else> + <#return 0 /> + + + +<#macro alphabeticalIndexLinks> + <#if languageAware > + <#assign indexFilterName = "label_regex"> + <#else> + <#assign indexFilterName = "raw_label_regex"> + + <#if filterGenericInfo.filters[indexFilterName]??> + <#assign indexFilter = filterGenericInfo.filters[indexFilterName]> + + + + +<#macro printPagingLinks> + <#if (pagingLinks?? && pagingLinks?size > 0)> + + + + +<#macro getAlphabetLabel valueId label> + + +<#-- create radio input fields for alphabetical indexes --> +<#macro getAlphabetInput filter filterValue valueID form="filter-form"> + <#assign checked = ""> + <#if filter.inputText == filterValue> + <#assign checked = " checked=\"checked\" " > + <#assign class = "selected-input" > + + <#assign type = "radio" > + <#assign filterName = filter.id > + + + + +<#macro showSortOptions> + <#if sortOptions?has_content && sortOptionIds?? && sortOptionIds?is_sequence> + + + + +${scripts.add('')} +${stylesheets.add('')} +${stylesheets.add('')} +${headScripts.add('')} +${headScripts.add('')} + + + diff --git a/webapp/src/main/webapp/templates/freemarker/body/search/search-lib.ftl b/webapp/src/main/webapp/templates/freemarker/body/search/search-lib.ftl new file mode 100644 index 0000000000..f51525b3b8 --- /dev/null +++ b/webapp/src/main/webapp/templates/freemarker/body/search/search-lib.ftl @@ -0,0 +1,303 @@ + +<#macro printPagingLinks> + +<#-- Paging controls --> + <#if (pagingLinks?size > 0)> +
    + ${i18n().pages}: + <#if prevPage??> + <#list pagingLinks as link> + <#if link.url??> + ${link.text?html} + <#else> + ${link.text?html} <#-- no link if current page --> + + + <#if nextPage??> +
    + + + +<#macro printResultNumbers> +

    + <#escape x as x?html> + ${i18n().results_found(hitCount)} + + ${i18n().download_results} +

    + + +<#macro searchForm> +
    + <@printSelectedFilterValueLabels filters /> +
    +
    + <#assign active = true> + <#list filterGroups as group> + <#if ( user.loggedIn || group.public ) && !group.hidden > + <@searchFormGroupTab group active/> + <#assign active = false> + + +
    +
    + <#assign active = true> + <#list filterGroups as group> + <#if ( user.loggedIn || group.public ) && !group.hidden > + <@groupFilters group active/> + <#assign active = false> + + +
    + + + + +<#macro groupFilters group active> + +
    +
    +
    + <#assign assignedActive = false> + <#list group.filters as filterId> + <#if filters[filterId]??> + <#assign f = filters[filterId]> + <#if ( user.loggedIn || f.public ) && !f.hidden > + <@searchFormFilterTab f assignedActive/> + <#if !assignedActive && (f.selected || emptySearch )> + <#assign assignedActive = true> + + + + +
    +
    +
    + <#assign assignedActive = false> + <#list group.filters as filterId> + <#if filters[filterId]??> + <#assign f = filters[filterId]> + <#if ( user.loggedIn || f.public ) && !f.hidden > + <@printFilterValues f assignedActive emptySearch/> + <#if !assignedActive && ( f.selected || emptySearch )> + <#assign assignedActive = true> + + + + +
    +
    + + +<#macro printSelectedFilterValueLabels filters> + <#list filters?values as filter> + <#assign valueNumber = 1> + <#list filter.values?values as v> + <#if v.selected> + <@getInput filter v getValueID(filter.id, valueNumber) valueNumber /> + <#if user.loggedIn || filter.public> + <@getSelectedLabel getValueID(filter.id, valueNumber)?html v filter v.count /> + + + <#assign valueNumber = valueNumber + 1> + + <@userSelectedInput filter "search-form" /> + + + +<#macro printSorting> + <#if sortOptions?has_content> +
    + +
    + + + +<#macro showHits form="search-form"> + + + +<#macro searchFormGroupTab group active > + + + +<#macro searchFormFilterTab filter assignedActive> + <#if filter.id == "querytext"> + <#return> + + + + +<#macro printFilterValues filter assignedActive isEmptySearch> +
    + <#if filter.id == "querytext"> + <#-- skip query text filter --> + <#elseif filter.type == "RangeFilter"> + <@rangeFilter filter "search-form" /> + <#else> + <#if filter.input> +
    + <@createUserInput filter /> +
    + + <#assign valueNumber = 1> + <#assign additionalLabels = false> + <#list filter.values?values as v> + <#if !v.selected> + <#if filter.moreLimit = valueNumber - 1 > + <#assign additionalLabels = true> + ${i18n().paging_link_more} + + <#if user.loggedIn || v.publiclyAvailable> + <@getInput filter v getValueID(filter.id, valueNumber) valueNumber /> + <@getLabel getValueID(filter.id, valueNumber)?html v filter v.count additionalLabels /> + + + <#assign valueNumber = valueNumber + 1> + + <#if additionalLabels > + ${i18n().display_less} + + +
    + + +<#macro rangeFilter filter form> + <#assign min = filter.min > + <#assign max = filter.max > + <#assign from = filter.fromYear > + <#assign to = filter.toYear > + +
    +
    +
    + ${i18n().from} + <#if from?has_content> +
    ${from?html}
    + <#else> +
    ${min?html}
    + + ${i18n().to} + <#if to?has_content> +
    ${to?html}
    + <#else> +
    ${max?html}
    + + +
    +
    + + + +<#macro getSelectedLabel valueId value filter count > + <#assign label = filter.name + " : " + value.name > + <#if !filter.localizationRequired> + <#assign label = filter.name + " : " + value.id > + + + + +<#macro getLabel valueId value filter count additional=false > + <#assign label = value.name > + <#assign additionalClass = "" > + <#if !filter.localizationRequired> + <#assign label = value.id > + + <#if additional=true> + <#assign additionalClass = "additional-search-options hidden-search-option" > + + + + +<#macro userSelectedInput filter form> + <#if filter.inputText?has_content> + + + <#assign from = filter.fromYear > + <#assign to = filter.toYear > + <#if from?has_content && to?has_content > + <#assign range = i18n().from + " " + from + " " + i18n().to + " " + to > + + + + +<#macro createUserInput filter> + + + +<#macro getInput filter filterValue valueID valueNumber form="search-form"> + <#assign checked = "" > + <#assign class = "" > + <#if filterValue.selected> + <#assign checked = " checked=\"checked\" " > + <#assign class = "selected-input" > + + <#assign type = "checkbox" > + <#if !filter.multivalued> + <#assign type = "radio" > + + <#assign filterName = filter.id > + <#if filter.multivalued> + <#assign filterName = filterName + "_" + valueNumber > + + + + + +<#function getValueID id number> + <#return id + "__" + number /> + + +<#function getValueLabel label count > + <#assign result = label > + <#if count!=0> + <#assign result = result + " (" + count + ")" > + + <#return result /> + diff --git a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl index f187802970..e94d0ac8bd 100644 --- a/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl +++ b/webapp/src/main/webapp/templates/freemarker/body/search/search-pagedResults.ftl @@ -2,11 +2,20 @@ ${stylesheets.add('')} ${stylesheets.add('')} -${stylesheets.add('')} -${stylesheets.add('')} ${headScripts.add('')} ${headScripts.add('')} -${headScripts.add('')} + +<#include "search-lib.ftl"> + + <@searchForm /> @@ -17,7 +26,7 @@ ${headScripts.add(' - ${i18n().download_results} - <#-- --> - - - -<#macro searchForm> -
    -
    - <@printSelectedFilterValueLabels filters /> -
    -
    - - <#assign active = true> - <#list filterGroups as group> - <#if ( user.loggedIn || group.public ) && !group.hidden > - <@groupFilters group active/> - <#assign active = false> - - -
    - -
    - - -<#macro groupFilters group active> - <#if active > -
    - <#else> -
    - -
    - -
    -
    - <#assign assignedActive = false> - <#list group.filters as filterId> - <#if filters[filterId]??> - <#assign f = filters[filterId]> - <#if ( user.loggedIn || f.public ) && !f.hidden > - <@printFilterValues f assignedActive emptySearch/> - <#if !assignedActive && ( f.selected || emptySearch )> - <#assign assignedActive = true> - - - - -
    -
    - - -<#macro printSelectedFilterValueLabels filters> - <#list filters?values as filter> - <#assign valueNumber = 1> - <#list filter.values?values as v> - <#if v.selected> - ${getInput(filter, v, getValueID(filter.id, valueNumber), valueNumber)} - <#if user.loggedIn || filter.public> - ${getSelectedLabel(valueNumber, v, filter)} - - - <#assign valueNumber = valueNumber + 1> - - <@userSelectedInput filter /> - - - -<#macro printSorting> - <#if sorting?has_content> -
    - -
    - - - -<#macro printHits> -
    - -
    - - -<#macro searchFormGroupTab group active > - <#if active> -
  • - <#else> -
  • - - ${group.label?html} -
  • - - -<#macro searchFormFilterTab filter assignedActive isEmptySearch> - <#if filter.id == "querytext"> - <#-- skip query text filter --> - <#return> - -
  • - ${filter.name?html} -
  • - - -<#macro printFilterValues filter assignedActive isEmptySearch> -
    - <#if filter.id == "querytext"> - <#-- skip query text filter --> - <#elseif filter.type == "RangeFilter"> - <@rangeFilter filter/> - <#else> - <#if filter.input> -
    - <@createUserInput filter /> -
    - - - <#assign valueNumber = 1> - <#assign additionalLabels = false> - <#list filter.values?values as v> - <#if !v.selected> - <#if filter.moreLimit = valueNumber - 1 > - <#assign additionalLabels = true> - ${i18n().paging_link_more} - - <#if user.loggedIn || v.publiclyAvailable> - ${getInput(filter, v, getValueID(filter.id, valueNumber), valueNumber)} - ${getLabel(valueNumber, v, filter, additionalLabels)} - - - <#assign valueNumber = valueNumber + 1> - - - <#if additionalLabels > - ${i18n().display_less} - - -
    - - -<#macro rangeFilter filter> - <#assign min = filter.min > - <#assign max = filter.max > - <#assign from = filter.fromYear > - <#assign to = filter.toYear > - -
    -
    -
    - ${i18n().from} - <#if from?has_content> -
    ${from?html}
    - <#else> -
    ${min?html}
    - - ${i18n().to} - <#if to?has_content> -
    ${to?html}
    - <#else> -
    ${max?html}
    - - -
    -
    - - - -<#function getSelectedLabel valueID value filter > - <#assign label = filter.name + " : " + value.name > - <#if !filter.localizationRequired> - <#assign label = filter.name + " : " + value.id > - - <#return "" /> - - -<#function getLabel valueID value filter additional=false > - <#assign label = value.name > - <#assign additionalClass = "" > - <#if !filter.localizationRequired> - <#assign label = value.id > - - <#if additional=true> - <#assign additionalClass = "additional-search-options hidden-search-option" > - - <#return "" /> - - - -<#macro userSelectedInput filter> - <#if filter.inputText?has_content> - - - <#assign from = filter.fromYear > - <#assign to = filter.toYear > - <#if from?has_content && to?has_content > - <#assign range = i18n().from + " " + from + " " + i18n().to + " " + to > - - - - -<#macro createUserInput filter> - - - -<#function getInput filter filterValue valueID valueNumber> - <#assign checked = "" > - <#assign class = "" > - <#if filterValue.selected> - <#assign checked = " checked=\"checked\" " > - <#assign class = "selected-input" > - - <#assign type = "checkbox" > - <#if !filter.multivalued> - <#assign type = "radio" > - - <#assign filterName = filter.id > - <#if filter.multivalued> - <#assign filterName = filterName + "_" + valueNumber > - - - <#return "" /> - - -<#function getValueID id number> - <#return id + "__" + number /> - - -<#function getValueLabel label count > - <#assign result = label > - ${label} - <#if count!=0> - <#assign result = result + " (" + count + ")" > - - <#return result /> - - - -${stylesheets.add('', - '', +${stylesheets.add('', + '', '')} -${headScripts.add('', - '', +${headScripts.add('', + '', '' )} ${scripts.add('')} +${scripts.add('')} + diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--browseSearchFilterValues.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--browseSearchFilterValues.ftl new file mode 100644 index 0000000000..bdf3065d89 --- /dev/null +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--browseSearchFilterValues.ftl @@ -0,0 +1,41 @@ +<#-- $This file is distributed under the terms of the license in LICENSE$ --> +<#--Browse Search Filter Values Section--> +<#-----------Variable assignment--------------> +<#--Requires Menu action be defined in parent template--> + +<#assign searchFilter = pageData.searchFilter /> +<#assign searchFilters = pageData.searchFilters /> +<#-- some additional processing here which shows or hides the class group selection and classes based on initial action--> +<#assign selectFilterStyle = 'class="hidden"' /> +<#-- Reveal the class group and hide the class selects if adding a new menu item or editing an existing menu item with an empty class group (no classes)--> +<#-- Menu action needs to be sent from main template--> +<#if menuAction == "Add" || !searchFilter?has_content> + <#assign selectFilterStyle = " " /> + + +<#--HTML Portion--> +
    +
    + + + +
    + + <#if menuAction == "Add"> + ${i18n().or} ${i18n().cancel_link} + +
    + + <#--Include JavaScript specific to the types of data getters related to this content--> +${scripts.add('')} diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl index 891497e462..e2e8bed774 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--contentTemplates.ftl @@ -4,3 +4,4 @@ <#include "pageManagement--sparqlQuery.ftl"> <#include "pageManagement--fixedHtml.ftl"> <#include "pageManagement--searchIndividuals.ftl"> +<#include "pageManagement--browseSearchFilterValues.ftl"> diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl index ec6fed2251..cac9daf7a2 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement--customDataScript.ftl @@ -10,6 +10,7 @@ scripts list.--> dataGetterLabelToURI:{ //maps labels to URIs "browseClassGroup": "java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ClassGroupPageData", + "searchFilterValues": "java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SearchFilterValuesDataGetter", "individualsForClasses": "java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.IndividualsForClassesDataGetter", "sparqlQuery":"java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter", "fixedHtml":"java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.FixedHTMLDataGetter", diff --git a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl index 550ae8b398..81172b6a32 100644 --- a/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl +++ b/webapp/src/main/webapp/templates/freemarker/edit/forms/pageManagement.ftl @@ -79,6 +79,7 @@