diff --git a/grails-app/assets/javascripts/search.js b/grails-app/assets/javascripts/search.js index ae948662..f8b3a1dc 100644 --- a/grails-app/assets/javascripts/search.js +++ b/grails-app/assets/javascripts/search.js @@ -35,6 +35,9 @@ $(document).ready(function() { }, 50) }); // end JQuery document ready +var inFacetsLoop = false; +var loadFacetsQueue = []; + function init() { // check for i18n var i = 0; @@ -51,21 +54,8 @@ function init() { // listeners for sort & paging widgets var excludeCounts = {}; - $.get(BC_CONF.excludeCountUrl).done(function(data) { - $('.exclude-loader').hide(); - for (var key in data) { - var categoryEnabled = $('.exclude-count-label[data-category='+key+']').data('enabled') - data[key] = categoryEnabled ? (new Intl.NumberFormat()).format(parseInt(data[key])) : '0'; - $('.exclude-count-label[data-category='+key+']').text(data[key]).show(); - - if (data[key] === '0') { - $('.exclude-count-facet[data-category=' + key + ']').text('(' + data[key] + ')').show(); - } else { - $('.exclude-count-facet[data-category=' + key + ']').text('(-' + data[key] + ')').show(); - } - } - excludeCounts = data; - }); + var excludeCountsStarted = false; + $("select#sort").change(function() { var val = $("option:selected", this).val(); reloadWithParam('sort',val); @@ -366,7 +356,7 @@ function init() { replace("data_resource_name", "data_resource_uid"). replace("data_provider_name", "data_provider_uid"). replace("species_list_name", "species_list_uid"). - replace("occurrence_year", "decade"); + replace("occurrence_year", "decade"); var displayName = $(link).data("displayname"); loadMoreFacets(facetName, displayName, 'index'); @@ -909,6 +899,7 @@ function init() { $(el).addClass('fa-caret-right'); $.cookie(BC_CONF.expandKey, {expand: false}); } + getExcludedCounts(); }); // when dlg pops, load and init status, set checkall status @@ -1328,10 +1319,18 @@ function init() { e.preventDefault(); var name = $(this).data('name'); $(this).find('span').toggleClass('right-caret'); - $('#group_' + name).slideToggle(600, function() { - if ($('#group_' + name).is(":visible") ) { - $('#group_' + name).find(".nano").nanoScroller({ preventPageScrolling: true }); + var group = $('#group_' + name); + group.slideToggle(600, function() { + if (group.is(":visible") ) { amplify.store('search-facets-state-' + name, true); + + // load all facets in this group + var facets = BC_CONF.groupedFacetsRequested[name]; + if (facets) { // dq and custom will be undefined + for (facet in facets) { + loadFacet(facets[facet]); + } + } } else { amplify.store('search-facets-state-' + name, null); } @@ -1342,16 +1341,13 @@ function init() { $('.facetsGroup').each(function(i, el) { var name = $(el).attr('id').replace(/^group_/, ''); var wasShown = amplify.store('search-facets-state-' + name); - if ($.trim($(el).html()) == '') { + if ($.trim($(el).html()) == '' && !BC_CONF.groupedFacetsRequested[name]) { $('#heading_' + name).hide(); } else if (wasShown) { $(el).prev().find('a').click(); } }); - // scroll bars on facet values - $(".nano").nanoScroller({ preventPageScrolling: true}); - // store last search in local storage for a "back button" on record pages amplify.store('lastSearch', $.url().attr('relative')); @@ -1435,14 +1431,45 @@ function init() { $(el).removeClass('fa-caret-right'); $(el).addClass('fa-caret-down'); } + } + + function getExcludedCounts() { + // run only once + if (excludeCountsStarted) return; + excludeCountsStarted = true; + + $.get(BC_CONF.excludeCountUrl).done(function(data) { + $('.exclude-loader').hide(); + for (var key in data) { + var categoryEnabled = $('.exclude-count-label[data-category='+key+']').data('enabled') + data[key] = categoryEnabled ? (new Intl.NumberFormat()).format(parseInt(data[key])) : '0'; + $('.exclude-count-label[data-category='+key+']').text(data[key]).show(); + + if (data[key] === '0') { + $('.exclude-count-facet[data-category=' + key + ']').text('(' + data[key] + ')').show(); + } else { + $('.exclude-count-facet[data-category=' + key + ']').text('(-' + data[key] + ')').show(); + } + } + excludeCounts = data; + }); + } + + // get excluded counts if either of the dq sections are open + if ($('.dq-filters-collapse').attr('aria-expanded') === 'true' || !$('#group_data_quality').is(':hidden')) { + getExcludedCounts(); + } + + $('#showHideDQFilter').on('click', function() { + getExcludedCounts(); + }); } -/** - * Catch sort drop-down and build GET URL manually - */ -function reloadWithParam(paramName, paramValue) { - var paramList = []; +/** get list of encoded query params, excluding the one provided */ +function getParamList(paramName, paramValue) { + var paramList = [] + var q = $.url().param('q'); //$.query.get('q')[0]; var fqList = $.url().param('fq'); //$.query.get('fq'); var sort = $.url().param('sort'); @@ -1520,8 +1547,15 @@ function reloadWithParam(paramName, paramValue) { paramList.push('disableAllQualityFilters=' + disableAllQualityFilters); } - //alert("params = "+paramList.join("&")); - //alert("url = "+window.location.pathname); + return paramList; +} + +/** + * Catch sort drop-down and build GET URL manually + */ +function reloadWithParam(paramName, paramValue) { + var paramList = getParamList(paramName, paramValue); + window.location.href = window.location.pathname + '?' + paramList.join('&'); } @@ -1529,31 +1563,7 @@ function reloadWithParam(paramName, paramValue) { * Load the default charts */ function loadDefaultCharts() { - if (dynamicFacets && dynamicFacets.length > 0) { - var chartsConfigUri = BC_CONF.biocacheServiceUrl + "/upload/charts/" + BC_CONF.selectedDataResource + ".json"; - $.getJSON(chartsConfigUri, function (chartsConfig) { - - var conf = {} - - $.each(chartsConfig, function (index, config) { - if (config.visible) { - var type = 'bar' - if (config.format == 'pie') type = 'doughnut' - conf[config.field] = { - chartType: type, - emptyValueMsg: '', - hideEmptyValues: true, - title: config.field - } - } - }); - chartConfig.charts = conf; - - var charts = ALA.BiocacheCharts('charts', chartConfig); - }); - } else { - var charts = ALA.BiocacheCharts('charts', chartConfig); - } + var charts = ALA.BiocacheCharts('charts', chartConfig); } /** @@ -1568,8 +1578,8 @@ function loadUserCharts() { url: BC_CONF.serverName + "/user/chart", success: function(data) { if ($.map(data, function (n, i) { - return i; - }).length > 3) { + return i; + }).length > 3) { //do not display user charts by default $.map(data.charts, function (value, key) { value.hideOnce = true; @@ -1630,68 +1640,68 @@ function loadImagesInTab() { function loadImages(start) { - start = (start) ? start : 0; - var imagesJsonUri = BC_CONF.biocacheServiceUrl + "/occurrences/search" + BC_CONF.searchString + - "&fq=multimedia:Image&facet=false&pageSize=20&start=" + start + "&sort=identification_qualifier_s&dir=asc"; - $.getJSON(imagesJsonUri, function (data) { - if (data.occurrences && data.occurrences.length > 0) { - //var htmlUl = ""; - if (start == 0) { - $("#imagesGrid").html(""); - } - var count = 0; - $.each(data.occurrences, function (i, el) { - count++; - var sciNameRawOrMatched = (el.raw_scientificName === undefined? el.scientificName : el.raw_scientificName); //e.g. if data submitted using species ID's instead of scientific names - // clone template div & populate with metadata - var $ImgConTmpl = $('.imgConTmpl').clone(); - $ImgConTmpl.removeClass('imgConTmpl').removeClass('hide'); - var link = $ImgConTmpl.find('a.cbLink'); - //link.attr('id','thumb_' + category + i); - link.addClass('thumbImage tooltips'); - link.attr('href', BC_CONF.contextPath + "/occurrences/" + el.uuid); - link.attr('title', 'click to enlarge'); - link.attr('data-occurrenceuid', el.uuid); - link.attr('data-image-id', el.image); - link.attr('data-scientific-name', sciNameRawOrMatched); - - $ImgConTmpl.find('img').attr('src', el.smallImageUrl); - // brief metadata - var briefHtml = sciNameRawOrMatched; - var br = "
"; - if (el.typeStatus) briefHtml += br + el.typeStatus; - if (el.institutionName) briefHtml += ((el.typeStatus) ? ' | ' : br) + el.institutionName; - $ImgConTmpl.find('.brief').html(briefHtml); - // detail metadata - var detailHtml = sciNameRawOrMatched; - if (el.typeStatus) detailHtml += br + 'Type: ' + el.typeStatus; - if (el.collector) detailHtml += br + 'By: ' + el.collector; - if (el.eventDate) detailHtml += br + 'Date: ' + moment(el.eventDate).format('YYYY-MM-DD'); - if (el.institutionName) { - detailHtml += br + el.institutionName; - } else { - detailHtml += br + el.dataResourceName; - } - $ImgConTmpl.find('.detail').html(detailHtml); - - // write to DOM - $("#imagesGrid").append($ImgConTmpl.html()); - }); - - if (count + start < data.totalRecords) { - $('#imagesGrid').data('count', count + start); - $("#loadMoreImages").show(); - $("#loadMoreImages .btn").removeClass('disabled'); + start = (start) ? start : 0; + var imagesJsonUri = BC_CONF.biocacheServiceUrl + "/occurrences/search" + BC_CONF.searchString + + "&fq=multimedia:Image&facet=false&pageSize=20&start=" + start + "&sort=identification_qualifier_s&dir=asc"; + $.getJSON(imagesJsonUri, function (data) { + if (data.occurrences && data.occurrences.length > 0) { + //var htmlUl = ""; + if (start == 0) { + $("#imagesGrid").html(""); + } + var count = 0; + $.each(data.occurrences, function (i, el) { + count++; + var sciNameRawOrMatched = (el.raw_scientificName === undefined? el.scientificName : el.raw_scientificName); //e.g. if data submitted using species ID's instead of scientific names + // clone template div & populate with metadata + var $ImgConTmpl = $('.imgConTmpl').clone(); + $ImgConTmpl.removeClass('imgConTmpl').removeClass('hide'); + var link = $ImgConTmpl.find('a.cbLink'); + //link.attr('id','thumb_' + category + i); + link.addClass('thumbImage tooltips'); + link.attr('href', BC_CONF.contextPath + "/occurrences/" + el.uuid); + link.attr('title', 'click to enlarge'); + link.attr('data-occurrenceuid', el.uuid); + link.attr('data-image-id', el.image); + link.attr('data-scientific-name', sciNameRawOrMatched); + + $ImgConTmpl.find('img').attr('src', el.smallImageUrl); + // brief metadata + var briefHtml = sciNameRawOrMatched; + var br = "
"; + if (el.typeStatus) briefHtml += br + el.typeStatus; + if (el.institutionName) briefHtml += ((el.typeStatus) ? ' | ' : br) + el.institutionName; + $ImgConTmpl.find('.brief').html(briefHtml); + // detail metadata + var detailHtml = sciNameRawOrMatched; + if (el.typeStatus) detailHtml += br + 'Type: ' + el.typeStatus; + if (el.collector) detailHtml += br + 'By: ' + el.collector; + if (el.eventDate) detailHtml += br + 'Date: ' + moment(el.eventDate).format('YYYY-MM-DD'); + if (el.institutionName) { + detailHtml += br + el.institutionName; } else { - $("#loadMoreImages").hide(); + detailHtml += br + el.dataResourceName; } + $ImgConTmpl.find('.detail').html(detailHtml); + // write to DOM + $("#imagesGrid").append($ImgConTmpl.html()); + }); + + if (count + start < data.totalRecords) { + $('#imagesGrid').data('count', count + start); + $("#loadMoreImages").show(); + $("#loadMoreImages .btn").removeClass('disabled'); } else { - $('#imagesGrid').html('

' + jQuery.i18n.prop('list.noimages.available') + '

'); + $("#loadMoreImages").hide(); } - }).always(function () { - $("#loadMoreImages img").hide(); - }); + + } else { + $('#imagesGrid').html('

' + jQuery.i18n.prop('list.noimages.available') + '

'); + } + }).always(function () { + $("#loadMoreImages img").hide(); + }); } /** @@ -1751,7 +1761,7 @@ function loadSpeciesInTab(start, sortField, group) { } var speciesJsonUrl = BC_CONF.contextPath + "/proxy/exploreGroupWithGallery" + BC_CONF.searchString + // TODO fix proxy - "&group=" + group + "&pageSize=" + pageSize + "&start=" + start + sortExtras; + "&group=" + group + "&pageSize=" + pageSize + "&start=" + start + sortExtras; $.getJSON(speciesJsonUrl, function(data) { if (data.length > 0) { @@ -1790,10 +1800,10 @@ function loadSpeciesInTab(start, sortField, group) { } }).error(function (request, status, error) { - alert(request.responseText); + alert(request.responseText); }).complete(function() { - $("#loadingSpecies").remove(); - $("#loadMoreSpecies img").hide(); + $("#loadingSpecies").remove(); + $("#loadMoreSpecies img").hide(); }); } @@ -1979,29 +1989,9 @@ function addFacetItems(facetName, fsort, facetLimit, foffset, replaceFacets, res var fqEsc = ((el.label.indexOf(" ") != -1 || el.label.indexOf(",") != -1 || el.label.indexOf("lsid") != -1) && el.label.indexOf("[") != 0) ? "\"" + el.label + "\"" : el.label; // .replace(/:/g,"\\:") - var label = (el.displayLabel) ? el.displayLabel : el.label ; + var label = formatFieldValue(facetName, el); var encodeFq = true; - if (label.indexOf("@") != -1) { - label = label.substring(0,label.indexOf("@")); - } else if (jQuery.i18n.prop(el.i18nCode).indexOf("[") == -1) { - // i18n substitution - label = jQuery.i18n.prop(el.i18nCode); - } else if (facetName.indexOf("outlier_layer") != -1 || /^el\d+/.test(label)) { - label = jQuery.i18n.prop("layer." + label); - } else if (facetName.indexOf("user_assertions") != -1 || /^el\d+/.test(label)) { - label = jQuery.i18n.prop("user_assertions." + label); - } else if (facetName.indexOf("duplicate_type") != -1 || /^el\d+/.test(label)) { - label = jQuery.i18n.prop("duplication." + label); - } else if (facetName.indexOf("taxonomic_issue") != -1 || /^el\d+/.test(label)) { - label = jQuery.i18n.prop(label); - } else if (!label && el.i18nCode.indexOf("novalue") != -1) { - label = "[no value]"; - } else { - var code = facetName + "." + label; - var i18nLabel = jQuery.i18n.prop(code); - var newLabel = (i18nLabel.indexOf("[") == -1) ? i18nLabel : (jQuery.i18n.prop(label)); - label = (newLabel.indexOf("[") == -1) ? newLabel : label; - } + facetName = facetName.replace(/_RNG$/,""); // remove range version if present var fqParam = (el.fq) ? encodeURIComponent(el.fq) : facetName + ":" + ((encodeFq) ? encodeURIComponent(fqEsc) : fqEsc) ; @@ -2050,3 +2040,161 @@ function sortFacetList(fsort) { }) } } + +function processLoadFacetQueue() { + if (loadFacetsQueue.length > 0 && !inFacetsLoop) { + inFacetsLoop = true; + var proc = loadFacetsQueue.shift(); + proc(); + } +} + +// load facets, one at a time +function loadFacet(facet) { + loadFacetsQueue.push(function () { + console.log("loadFacet", facet) + var parentNode = $('#facet_' + facet); + + // skip if already loaded or not visible + if (parentNode.length === 0 || parentNode.is(':hidden') || parentNode.find('ul').length > 0) { + inFacetsLoop = false; + processLoadFacetQueue(); + return; + } + + var spinnerNode = $('#spinner_' + facet); + var moreNode = $('#more_' + facet); + var queryString = getParamList().join('&'); + + var url = BC_CONF.biocacheServiceUrl + '/occurrences/search?' + queryString + '&facets=' + facet; + + $.ajax({ + url: url, + success: function (data) { + if (data.facetResults.length === 0 || data.facetResults[0].fieldResult.length === 0) { + // remove if there are no results + parentNode.prev().remove(); + parentNode.remove(); + } else { + var fieldDisplayName = formatFieldName(facet); + var list = createFacetLinkList(data.facetResults[0], queryString, fieldDisplayName); + + spinnerNode.remove(); + + if (data.facetResults[0].fieldResult.length > 1) { + moreNode.show(); + } + + parentNode.append(list); + } + + inFacetsLoop = false; + processLoadFacetQueue(); + }, + error: function () { + // remove the facet label if there is an error + parentNode.prev().remove(); + parentNode.remove(); + + inFacetsLoop = false; + processLoadFacetQueue(); + } + }); + }); + + processLoadFacetQueue(); +} + +function createFacetLinkList(facetResult, queryString, fieldDisplayName) { + const ul = document.createElement('ul'); + ul.classList.add('facets'); + + // Define the link title + const linkTitle = jQuery.i18n.prop('alatag.filter.results.by') + ` ${fieldDisplayName ? fieldDisplayName.toLowerCase() : facetResult.fieldName}`; + + // Function to add counts to the facet item + function addCounts(count) { + const span = document.createElement('span'); + span.classList.add('facetCount'); + span.innerHTML = ` (${count.toLocaleString()})`; + return span; + } + + // Move the "before" element to the front if it exists + const lastEl = facetResult.fieldResult[facetResult.fieldResult.length - 1]; + if (lastEl.label === 'before') { + facetResult.fieldResult.pop(); + facetResult.fieldResult.unshift(lastEl); + } + + // Iterate over the field results and create list items + facetResult.fieldResult.forEach(fieldResult => { + if (fieldResult.count > 0) { + const li = document.createElement('li'); + const a = document.createElement('a'); + a.href = `?${queryString}&fq=${encodeURIComponent(fieldResult.fq || `${facetResult.fieldName}:"${fieldResult.label}"`)}`; + a.classList.add('tooltips'); + a.title = linkTitle; + + const spanIcon = document.createElement('span'); + spanIcon.classList.add('fa', 'fa-square-o'); + spanIcon.innerHTML = ' '; + a.appendChild(spanIcon); + + const spanItem = document.createElement('span'); + spanItem.classList.add('facet-item'); + spanItem.textContent = formatFieldValue(facetResult.fieldName, fieldResult); + spanItem.appendChild(addCounts(fieldResult.count)); + a.appendChild(spanItem); + + li.appendChild(a); + ul.appendChild(li); + } + }); + + return ul; +} + +function formatFieldName(fieldName){ + var output + if (fieldName.endsWith('_s') || fieldName.endsWith('_i') || fieldName.endsWith('_d')) { + var temp = fieldName.slice(0, -2).replaceAll("_", " "); + output = jQuery.i18n.prop('facet.' + fieldName); + if (output.indexOf("[") == 0) { + output = temp; + } + } else if (fieldName.endsWith('_RNG')) { + output = fieldName.slice(0, -4).replaceAll("_", " ") + " (range)"; + } else { + var label = jQuery.i18n.prop('facet.' + fieldName); + if (!label){ + // try without "facet." + label = jQuery.i18n.prop(fieldName); + } + + label = label || fieldName; + output = label; + } + return output; +} + +function formatFieldValue(facetName, item) { + // surround with quotes: fq value if contains spaces but not for range queries + var label = (item.displayLabel) ? item.displayLabel : item.label ; + if (label.indexOf("@") != -1) { + label = label.substring(0,label.indexOf("@")); + } else if (jQuery.i18n.prop(item.i18nCode).indexOf("[") == -1) { + // i18n substitution + label = jQuery.i18n.prop(item.i18nCode); + } else if (!label && el.i18nCode.indexOf("novalue") != -1) { + label = "[no value]"; + } else { + var code = facetName + "." + label; + var i18nLabel = jQuery.i18n.prop(code); + + var newLabel = (i18nLabel.indexOf("[") == -1) ? i18nLabel : (jQuery.i18n.prop(label)); + label = (newLabel.indexOf("[") == -1) ? newLabel : label; + } + + return label; +} diff --git a/grails-app/assets/stylesheets/search.css b/grails-app/assets/stylesheets/search.css index 56b2bb28..6f68f49b 100644 --- a/grails-app/assets/stylesheets/search.css +++ b/grails-app/assets/stylesheets/search.css @@ -1,4 +1,4 @@ -/* +/* Document : search Created on : Feb 10, 2011, 4:23:15 PM Author : "Nick dos Remedios " @@ -9,7 +9,7 @@ *= require_self */ -/* +/* TODO customize this sample style Syntax recommendation http://www.w3.org/TR/REC-CSS2/ */ @@ -356,7 +356,7 @@ span.activeFq, span.facet-item { vertical-align: top; display: inline-block; width: 90%; - margin-left: -4px; + /*margin-left: -4px;*/ text-indent: 0px; /*font-weight: bold;*/ } @@ -845,6 +845,8 @@ ul.facets { padding-left:0; margin-left:0; list-style:none; + overflow-y: scroll; + max-height: 91px; } ul.facets li { diff --git a/grails-app/conf/ehcache.xml b/grails-app/conf/ehcache.xml index acee4f77..a3fc2dab 100644 --- a/grails-app/conf/ehcache.xml +++ b/grails-app/conf/ehcache.xml @@ -28,4 +28,13 @@ 100000 + + + + 1 + + + 10000 + + diff --git a/grails-app/conf/plugin.groovy b/grails-app/conf/plugin.groovy index 5900a96a..bc4eacad 100644 --- a/grails-app/conf/plugin.groovy +++ b/grails-app/conf/plugin.groovy @@ -104,7 +104,6 @@ exploreYourArea.lng = "149.0" exploreYourArea.location = "Canberra, ACT" exploreYourArea.zoomLevels = [ 1: 14, 5: 12, 10: 11, 50: 9 ] -facets.includeDynamicFacets = false // sandbox facets.limit = "100" facets.max = "40" facets.customOrder = "" diff --git a/grails-app/controllers/au/org/ala/biocache/hubs/OccurrenceController.groovy b/grails-app/controllers/au/org/ala/biocache/hubs/OccurrenceController.groovy index 72d92bd1..25413958 100644 --- a/grails-app/controllers/au/org/ala/biocache/hubs/OccurrenceController.groovy +++ b/grails-app/controllers/au/org/ala/biocache/hubs/OccurrenceController.groovy @@ -101,19 +101,10 @@ class OccurrenceController { } } -// List dynamicFacets = [] - String[] requestedFacets = userFacets ?: filteredFacets -// if (grailsApplication.config.getProperty('facets.includeDynamicFacets', Boolean, false)) { -// // Sandbox only... -// time("sandbox only facets") { -// dynamicFacets = webServicesService.getDynamicFacets(requestParams.q) -// requestedFacets = postProcessingService.mergeRequestedFacets(requestedFacets as List, dynamicFacets) -// } -// } - - requestParams.facets = requestedFacets + // Disable the biocache-service request for facets. They are new retrieved dynamically by the client + requestParams.facets = null def wsStart = System.currentTimeMillis() JSONObject searchResults = time("full text search") { webServicesService.fullTextSearch(requestParams) } @@ -125,10 +116,13 @@ class OccurrenceController { } //create a facet lookup map - Map groupedFacetsMap = postProcessingService.getMapOfFacetResults(searchResults.facetResults) + Map groupedFacetsMap = postProcessingService.getMapOfFacetResults(requestedFacets) //grouped facets - Map groupedFacets = postProcessingService.getAllGroupedFacets(configuredGroupedFacets, searchResults.facetResults, []) + Map groupedFacets = postProcessingService.getAllGroupedFacets(configuredGroupedFacets, groupedFacetsMap) + + //grouped facets, but only those requested and not in the activeFacetMap + Map groupedFacetsRequested = postProcessingService.getRequestedGroupedFacets(configuredGroupedFacets, groupedFacetsMap, requestedFacets, searchResults?.activeFacetMap) //remove qc from active facet map if (params?.qc) { @@ -183,8 +177,8 @@ class OccurrenceController { searchRequestParams : requestParams, defaultFacets : defaultFacets, groupedFacets : groupedFacets, + groupedFacetsRequested: groupedFacetsRequested, groupedFacetsMap : groupedFacetsMap, - dynamicFacets : [], selectedDataResource: getSelectedResource(requestParams.q), hasImages : hasImages, showSpeciesImages : false, diff --git a/grails-app/i18n/messages_ca.properties b/grails-app/i18n/messages_ca.properties index 55bc76f9..ab048fc8 100644 --- a/grails-app/i18n/messages_ca.properties +++ b/grails-app/i18n/messages_ca.properties @@ -423,7 +423,6 @@ map.downloadmap.button01.label=Descarregar mapa map.downloadmap.button02.label=Tanca facets.currentfilter.link=Esborrar totes -facets.groupdynamicfacets.link=seleccioneu m\u00e9s facets.facetfromgroup.link=seleccioneu m\u00e9s facets.multiplefacets.title=Filtrar la cerca facets.multiplefacets.tableth01=Comptatge diff --git a/grails-app/i18n/messages_de.properties b/grails-app/i18n/messages_de.properties index e1738419..556c5a70 100644 --- a/grails-app/i18n/messages_de.properties +++ b/grails-app/i18n/messages_de.properties @@ -422,7 +422,6 @@ map.downloadmap.button01.label=Karte herunterladen map.downloadmap.button02.label=Schlie\u00dfen facets.currentfilter.link=Alles l\u00f6schen -facets.groupdynamicfacets.link=weitere ausw\u00e4hlen facets.facetfromgroup.link=weitere ausw\u00e4hlen facets.multiplefacets.title=Suche einschr\u00e4nken facets.multiplefacets.tableth01=Anzahl diff --git a/grails-app/i18n/messages_de_AT.properties b/grails-app/i18n/messages_de_AT.properties index 1f967e65..543895b7 100644 --- a/grails-app/i18n/messages_de_AT.properties +++ b/grails-app/i18n/messages_de_AT.properties @@ -422,7 +422,6 @@ map.downloadmap.button01.label=Karte herunterladen map.downloadmap.button02.label=Schlie\u00dfen facets.currentfilter.link=Alles l\u00f6schen -facets.groupdynamicfacets.link=weitere ausw\u00e4hlen facets.facetfromgroup.link=weitere ausw\u00e4hlen facets.multiplefacets.title=Suche einschr\u00e4nken facets.multiplefacets.tableth01=Anzahl diff --git a/grails-app/i18n/messages_de_LU.properties b/grails-app/i18n/messages_de_LU.properties index ddd57496..dbcc9286 100644 --- a/grails-app/i18n/messages_de_LU.properties +++ b/grails-app/i18n/messages_de_LU.properties @@ -422,7 +422,6 @@ map.downloadmap.button01.label=Karte herunterladen map.downloadmap.button02.label=Schlie\u00dfen facets.currentfilter.link=Alles l\u00f6schen -facets.groupdynamicfacets.link=weitere ausw\u00e4hlen facets.facetfromgroup.link=weitere ausw\u00e4hlen facets.multiplefacets.title=Suche einschr\u00e4nken facets.multiplefacets.tableth01=Anzahl diff --git a/grails-app/i18n/messages_en.properties b/grails-app/i18n/messages_en.properties index 6bf05867..fcea5a77 100644 --- a/grails-app/i18n/messages_en.properties +++ b/grails-app/i18n/messages_en.properties @@ -499,7 +499,7 @@ map.downloadmap.button01.label = Download map map.downloadmap.button02.label = Close facets.currentfilter.link = Clear all -facets.groupdynamicfacets.link = choose more + facets.facetfromgroup.link = choose more facets.multiplefacets.title = Refine your search facets.multiplefacets.tableth01 = Count diff --git a/grails-app/i18n/messages_es.properties b/grails-app/i18n/messages_es.properties index 4a183a41..0979b37a 100644 --- a/grails-app/i18n/messages_es.properties +++ b/grails-app/i18n/messages_es.properties @@ -423,7 +423,6 @@ map.downloadmap.button01.label=Descargar mapa map.downloadmap.button02.label=Cerrar facets.currentfilter.link=Borrar todo -facets.groupdynamicfacets.link=elegir m\u00e1s facets.facetfromgroup.link=elegir m\u00e1s facets.multiplefacets.title=Filtrar la b\u00fasqueda facets.multiplefacets.tableth01=Recuento diff --git a/grails-app/i18n/messages_eu.properties b/grails-app/i18n/messages_eu.properties index 4851175f..8a9368dc 100644 --- a/grails-app/i18n/messages_eu.properties +++ b/grails-app/i18n/messages_eu.properties @@ -374,7 +374,6 @@ map.downloadmap.button01.label=Jeitsi mapa map.downloadmap.button02.label=Itxi facets.currentfilter.link=Ezabatu dena -facets.groupdynamicfacets.link=Aukeratu gehiago facets.facetfromgroup.link=Aukeratu gehiago facets.multiplefacets.title=Zehaztu zure bilaketa facets.multiplefacets.tableth01=Kopurua diff --git a/grails-app/i18n/messages_fr.properties b/grails-app/i18n/messages_fr.properties index ff370aee..32565c14 100644 --- a/grails-app/i18n/messages_fr.properties +++ b/grails-app/i18n/messages_fr.properties @@ -424,7 +424,6 @@ map.downloadmap.button02.label=Fermer map.legend.click.to.expand = Afficher la l\u00e9gende facets.currentfilter.link=Tout effacer -facets.groupdynamicfacets.link=choisir plus de facets.facetfromgroup.link=choisir plus de facets.multiplefacets.title=Affiner votre recherche facets.multiplefacets.tableth01=Total diff --git a/grails-app/i18n/messages_pt_BR.properties b/grails-app/i18n/messages_pt_BR.properties index 755be829..2bac515e 100644 --- a/grails-app/i18n/messages_pt_BR.properties +++ b/grails-app/i18n/messages_pt_BR.properties @@ -421,7 +421,6 @@ map.downloadmap.button01.label=Baixar mapa map.downloadmap.button02.label=Fechar facets.currentfilter.link=Limpar tudo -facets.groupdynamicfacets.link=escolha mais facets.facetfromgroup.link=escolha mais facets.multiplefacets.title=Refine a sua pesquisa facets.multiplefacets.tableth01=Contagem diff --git a/grails-app/i18n/messages_pt_PT.properties b/grails-app/i18n/messages_pt_PT.properties index 8834f3b5..baec1f32 100644 --- a/grails-app/i18n/messages_pt_PT.properties +++ b/grails-app/i18n/messages_pt_PT.properties @@ -388,7 +388,6 @@ map.downloadmap.button01.label=Transferir mapa map.downloadmap.button02.label=Fechar facets.currentfilter.link=Limpar tudo -facets.groupdynamicfacets.link=escolha mais facets.facetfromgroup.link=escolha mais facets.multiplefacets.title=Refine a sua pesquisa facets.multiplefacets.tableth01=Contagem diff --git a/grails-app/i18n/messages_zh.properties b/grails-app/i18n/messages_zh.properties index f7f5045c..fc27b753 100644 --- a/grails-app/i18n/messages_zh.properties +++ b/grails-app/i18n/messages_zh.properties @@ -384,7 +384,6 @@ map.downloadmap.button01.label=\u4e0b\u8f7d\u5730\u56fe map.downloadmap.button02.label=\u5173\u95ed facets.currentfilter.link=\u6e05\u9664\u6240\u6709 -facets.groupdynamicfacets.link=\u9009\u62e9\u66f4\u591a facets.facetfromgroup.link=\u9009\u62e9\u66f4\u591a facets.multiplefacets.title=\u4f18\u5316\u4f60\u7684\u67e5\u8be2 facets.multiplefacets.tableth01=\u8ba1\u6570 diff --git a/grails-app/services/au/org/ala/biocache/hubs/PostProcessingService.groovy b/grails-app/services/au/org/ala/biocache/hubs/PostProcessingService.groovy index d77b1399..1008344d 100644 --- a/grails-app/services/au/org/ala/biocache/hubs/PostProcessingService.groovy +++ b/grails-app/services/au/org/ala/biocache/hubs/PostProcessingService.groovy @@ -178,7 +178,7 @@ class PostProcessingService { * @param finalFacetsMap * @return */ - def String[] getFilteredFacets(LinkedHashMap finalFacetsMap) { + String[] getFilteredFacets(LinkedHashMap finalFacetsMap) { List finalFacets = [] for (String key : finalFacetsMap.keySet()) { @@ -188,7 +188,6 @@ class PostProcessingService { } } - //log.debug("FinalFacets = " + StringUtils.join(finalFacets, "|")); String[] filteredFacets = finalFacets.toArray(new String[finalFacets.size()]); return filteredFacets @@ -326,17 +325,17 @@ class PostProcessingService { * @param facetResults * @return */ - def Map getMapOfFacetResults(JSONArray facetResults) { + Map getMapOfFacetResults(String[] requestedFacets) { Map facetMap = [:] - facetResults.each { fr -> - def facet = fr.fieldName + requestedFacets.each { fn -> + def facet = fn if (facet == "occurrence_year") { facet = "decade" } - facetMap.put(facet, fr) + facetMap.put(facet, [fieldName: fn]) // data for this key will be populated by the client } facetMap @@ -350,21 +349,49 @@ class PostProcessingService { * @param ungroupedFacetsList * @return */ - def Map getAllGroupedFacets(Map groupedFacets, def facetResults, dynamicFacets) { - List ungroupedFacetsList = getUngroupedFacetsList(groupedFacets, getMapOfFacetResults(facetResults)) + Map getAllGroupedFacets(Map groupedFacets, Map groupedFacetsMap) { + List ungroupedFacetsList = getUngroupedFacetsList(groupedFacets, groupedFacetsMap) def finalGroupedFacets = groupedFacets.clone() - def dynamicFacetNames = dynamicFacets.collect { it.name } finalGroupedFacets.put("Ungrouped", []) ungroupedFacetsList.each { facet -> - if (dynamicFacetNames.contains(facet)) { - finalGroupedFacets.get("Custom").add(facet) - } else { - finalGroupedFacets.get("Ungrouped").add(facet) - } + finalGroupedFacets.get("Ungrouped").add(facet) } finalGroupedFacets } + /** + * Add only the requested ungrouped facets from search results to the groupedFacetsMap + * used to construct the facets column in search results. + * + * @param groupedFacets + * @param ungroupedFacetsList + * @return + */ + Map getRequestedGroupedFacets(Map groupedFacets, Map groupedFacetsMap, String[] requestedFacets, Map activeFacetMap) { + List ungroupedFacetsList = getUngroupedFacetsList(groupedFacets, groupedFacetsMap) + def finalGroupedFacets = groupedFacets.clone() + finalGroupedFacets.put("Ungrouped", []) + ungroupedFacetsList.each { facet -> + finalGroupedFacets.get("Ungrouped").add(facet) + } + + def requestedFacetsSet = requestedFacets.sort() as Set + def requestedGroupedFacets = [:] + finalGroupedFacets.each { key, list -> + def requestedList = [] + for (String item : list) { + if (requestedFacetsSet.contains(item) && !activeFacetMap.containsKey(item)) { + requestedList.add(item) + } + } + if (requestedList.size() > 0) { + requestedGroupedFacets.put(key, requestedList) + } + } + + requestedGroupedFacets + } + /** * Get a list of facet fields (from search results) that are * NOT in the grouped facets Map. diff --git a/grails-app/services/au/org/ala/biocache/hubs/QualityService.groovy b/grails-app/services/au/org/ala/biocache/hubs/QualityService.groovy index ce1810d2..cfc578de 100644 --- a/grails-app/services/au/org/ala/biocache/hubs/QualityService.groovy +++ b/grails-app/services/au/org/ala/biocache/hubs/QualityService.groovy @@ -87,6 +87,7 @@ class QualityService { } + @Cacheable(value = 'qualityShortTermCache', key = { profileName }) List findAllEnabledCategories(String profileName) { if (dataQualityEnabled) { return responseOrThrow(api.findAllEnabledCategories(profileName)) @@ -95,6 +96,7 @@ class QualityService { } } + @Cacheable(value = 'qualityShortTermCache', key = { profileName }) QualityProfile activeProfile(String profileName) { if (dataQualityEnabled) { return responseOrThrow(api.activeProfile(profileName)) @@ -119,6 +121,7 @@ class QualityService { } } + @Cacheable(value = 'qualityShortTermCache', key = { profile.name }) Map getAllInverseCategoryFiltersForProfile(QualityProfile profile) { if (dataQualityEnabled) { return responseOrThrow(api.getAllInverseCategoryFiltersForProfile(profile.id?.toInteger())) @@ -127,6 +130,7 @@ class QualityService { } } + @Cacheable(value = 'qualityShortTermCache', key = { enabled }) List findAllEnabledProfiles(boolean enabled) { if (dataQualityEnabled) { return responseOrThrow(dataProfilesApi.dataProfiles(null, null, null, null, enabled, null, null)) @@ -162,7 +166,7 @@ class QualityService { private Long countRecordsExcludedByLabel(List otherLabels, SpatialSearchRequestParams requestParams) { def srp = requestParams.clone().with { - it.pageSize = 0 + it.pageSize = 1 // when it is 0 it will return 20 records it.start = 0 it.flimit = 0 it.facet = false @@ -178,7 +182,7 @@ class QualityService { Long countTotalRecords(SpatialSearchRequestParams requestParams) { if (dataQualityEnabled) { def srp = requestParams.clone().with { - it.pageSize = 0 + it.pageSize = 1 // when it is 0 it will return 20 records it.start = 0 it.flimit = 0 it.facet = false @@ -205,7 +209,7 @@ class QualityService { def otherLabels = (labels - it.label) as List [(it.label): totalRecords - countRecordsExcludedByLabel(otherLabels, requestParams)] } - log.error("Quality Category facet counts took {}", sw) + log.debug("Quality Category facet counts took {}", sw) return response } else { return [:] diff --git a/grails-app/services/au/org/ala/biocache/hubs/WebServicesService.groovy b/grails-app/services/au/org/ala/biocache/hubs/WebServicesService.groovy index 52fa986d..ea25597f 100644 --- a/grails-app/services/au/org/ala/biocache/hubs/WebServicesService.groovy +++ b/grails-app/services/au/org/ala/biocache/hubs/WebServicesService.groovy @@ -428,24 +428,6 @@ class WebServicesService { imageSizes } - /** - * Get list of dynamic facets for a given query (Sandbox) - * - * @param query - * @return - */ -// List getDynamicFacets(String query) { -// def url = "${grailsApplication.config.getProperty('biocache.baseUrl')}/upload/dynamicFacets?q=${query}" -// JSONArray facets = getJsonElements(url) -// def dfs = [] -// facets.each { -// if (it.name && it.displayName) { -// dfs.add([name: it.name, displayName: it.displayName]) -// } // reduce to List of Maps -// } -// dfs -// } - /** * Use HTTP HEAD to determine the file size of a URL (image) * diff --git a/grails-app/views/occurrence/_facets.gsp b/grails-app/views/occurrence/_facets.gsp index 2dbbdc8c..88374929 100644 --- a/grails-app/views/occurrence/_facets.gsp +++ b/grails-app/views/occurrence/_facets.gsp @@ -37,13 +37,13 @@
- +