diff --git a/docs/OWL-based-configuration-datasources.md b/docs/OWL-based-configuration-datasources.md index 9ea80957..e7a41fac 100644 --- a/docs/OWL-based-configuration-datasources.md +++ b/docs/OWL-based-configuration-datasources.md @@ -1,10 +1,10 @@ -_[Home](index.html) > OWL-based configuration Datasources_ +_[Home](index.html) > Datasources_ # Datasources ## Datasources basics -As indicated in the [[OWL-based configuration]] reference, lists and autocomplete properties in Sparnatural require a [`ds:datasource`](http://data.sparna.fr/ontologies/sparnatural-config-datasources#datasource) annotation to populate respectively the list of values or the values proposed by autocompletion. In its simplest and most common form a datasource is basically a SPARQL query that returns the expected columns to be used to populate the list/autocomplete values. +Lists and autocomplete properties in Sparnatural can be associated to a [`ds:datasource`](http://data.sparna.fr/ontologies/sparnatural-config-datasources#datasource) annotation to populate respectively the list of values or the values proposed by autocompletion. In its simplest and most common form a datasource is a SPARQL query that returns the expected columns to be used to populate the list/autocomplete values. The datasource annotation configuration can be either: @@ -120,7 +120,9 @@ To use the range as a criteria in the query and filter the list based on the typ You can provide your own SPARQL queries to populate lists or autocomplete suggestions. To do so, attach a `queryString` data property assertion on your datasource object, holding the SPARQL query that should be used to populate the list/autocomplete. -**The SPARQL query MUST return 2 variables : `?uri` and `?label`, populated anyway you like.** Additionnally, since version 8.6.0, the query can return, optionnally, an extra `?group` variable, which will be used to generate `optgroup` sections in lists widgets, and will be used as hover tooltips in autocompletion lists. This is used to indicate the source endpoint of the result in cases of multiple endpoints. +**The SPARQL query MUST return 2 variables : `?uri` and `?label`, populated anyway you like.** Additionnally, the query can return, optionnally: +- an extra `?group` variable, which will be used to generate `optgroup` sections in lists widgets, and will be used as hover tooltips in autocompletion lists. This is used to indicate the source endpoint of the result in cases of multiple endpoints. +- an extra `?itemLabel` variable, which will be used, if present, as the label of the selected value; for exemple, `?label` can hold a count, like _"Italy (307)"_, while `?itemLabel` can be just _"Italy"_. In this SPARQL query, the following replacements will happen: - **`$domain`**, if present, will be replaced by the URI of the domain class; @@ -136,7 +138,7 @@ Take a look at the preconfigured SPARQL queries in the [Sparnatural datasources Here is an example of such a query: (note the use of the placeholder variables that will be replaced with the corresponding values): ```sparql -SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) +SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT DISTINCT ?uri (COUNT(?domain) AS ?count) diff --git a/ontologies/sparnatural-config-datasources.owl b/ontologies/sparnatural-config-datasources.owl index 3cbede1c..47ee348d 100644 --- a/ontologies/sparnatural-config-datasources.owl +++ b/ontologies/sparnatural-config-datasources.owl @@ -571,7 +571,7 @@ LIMIT 500 - SELECT ?uri ?count (CONCAT(STR(?uri), ' (', STR(?count), ')') AS ?label) + SELECT ?uri ?count (CONCAT(STR(?uri), ' (', STR(?count), ')') AS ?label) (STR(?uri) AS ?itemLabel) WHERE { { SELECT DISTINCT ?uri (COUNT(?domain) AS ?count) @@ -637,7 +637,7 @@ LIMIT 500 - SELECT DISTINCT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " <sup>(",LANG(?value),")</sup>"),STR(?value)), ' (', STR(?count), ')') AS ?label) + SELECT DISTINCT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " <sup>(",LANG(?value),")</sup>"),STR(?value)), ' (', STR(?count), ')') AS ?label) (STR(?value) AS ?itemLabel) WHERE { { SELECT DISTINCT ?value (COUNT(DISTINCT ?domain) AS ?count) @@ -685,7 +685,7 @@ LIMIT 500 - SELECT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " <sup>(",LANG(?value),")</sup>"),STR(?value)), ' (', STR(?count), ')') AS ?label) + SELECT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " <sup>(",LANG(?value),")</sup>"),STR(?value)), ' (', STR(?count), ')') AS ?label) (STR(?value) AS ?itemLabel) WHERE { { SELECT DISTINCT ?value (COUNT(DISTINCT ?domain) AS ?count) @@ -753,7 +753,7 @@ LIMIT 500 - SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) + SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -783,7 +783,7 @@ ORDER BY UCASE(?label) - SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) + SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -833,7 +833,7 @@ LIMIT 500 - SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) + SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -865,7 +865,7 @@ ORDER BY UCASE(?label) - SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) + SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -911,7 +911,7 @@ LIMIT 500 - SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) + SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT DISTINCT ?count ?theLabel @@ -939,7 +939,7 @@ ORDER BY UCASE(?label) - SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) + SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT DISTINCT ?count ?theLabel @@ -1105,7 +1105,7 @@ ORDER BY UCASE(?label) - SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count + SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT DISTINCT ?uri ?theLabel ?hasChildren (COUNT(?x) AS ?count) @@ -1166,7 +1166,7 @@ ORDER BY UCASE(?label) - SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count + SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?theLabel ?hasChildren (COUNT(?x) AS ?count) diff --git a/src/sparnatural/components/widgets/ListWidget.ts b/src/sparnatural/components/widgets/ListWidget.ts index 319c424b..0b79a7e5 100644 --- a/src/sparnatural/components/widgets/ListWidget.ts +++ b/src/sparnatural/components/widgets/ListWidget.ts @@ -6,7 +6,7 @@ import "select2"; import "select2/dist/css/select2.css"; import SparqlFactory from "../../generators/sparql/SparqlFactory"; import EndClassGroup from "../builder-section/groupwrapper/criteriagroup/startendclassgroup/EndClassGroup"; -import { ListDataProviderIfc, NoOpListDataProvider } from "./data/DataProviders"; +import { ListDataProviderIfc, RdfTermDatasourceItem, NoOpListDataProvider } from "./data/DataProviders"; import { I18n } from "../../settings/I18n"; import { Term } from "@rdfjs/types/data-model"; import HTMLComponent from "../HtmlComponent"; @@ -69,7 +69,7 @@ export class ListWidget extends AbstractWidget { ${I18n.labels.ListWidgetNoItem} `); - let callback = (items:{term:RDFTerm;label:string;group?:string}[]) => { + let callback = (items:RdfTermDatasourceItem[]) => { if (items.length > 0) { @@ -79,8 +79,10 @@ export class ListWidget extends AbstractWidget { if(groups.length == 1 && groups[0] == undefined) { // no groups were defined at all items.forEach(item => { + // select item label : either displayed label, or itemLabel if provided + let itemLabel = item.itemLabel?item.itemLabel:item.label; this.selectHtml.append( - $("") + $("") ); }); } else { @@ -88,7 +90,10 @@ export class ListWidget extends AbstractWidget { groups.forEach(group => { let html = ""; items.filter(item => (item.group == group)).forEach(item => { - html += ""; + // select item label : either displayed label, or itemLabel if provided + let itemLabel = item.itemLabel?item.itemLabel:item.label; + + html += ""; }); html += "" this.selectHtml.append($(html)); @@ -111,7 +116,8 @@ export class ListWidget extends AbstractWidget { if (option.length > 1) throw Error("List widget should allow only for one el to be selected!"); - let listWidgetValue: WidgetValue = this.buildValue(option[0].value, option[0].label); + let itemLabel = option[0].getAttribute("data-itemLabel"); + let listWidgetValue: WidgetValue = this.buildValue(option[0].value, itemLabel); this.renderWidgetVal(listWidgetValue); }); diff --git a/src/sparnatural/components/widgets/data/DataProviders.ts b/src/sparnatural/components/widgets/data/DataProviders.ts index e2071a54..db7d12ae 100644 --- a/src/sparnatural/components/widgets/data/DataProviders.ts +++ b/src/sparnatural/components/widgets/data/DataProviders.ts @@ -2,6 +2,23 @@ import { RDFTerm } from "../AbstractWidget"; import { AutocompleteSparqlQueryBuilderIfc, ListSparqlQueryBuilderIfc, TreeSparqlQueryBuilderIfc } from "./SparqlBuilders"; import { SparqlFetcherFactory, SparqlFetcherIfc } from "./UrlFetcher"; +/** + * An item returned by a list widget datasource + */ +export interface RdfTermDatasourceItem { + term:RDFTerm; + label:string; + group?:string; + itemLabel?:string; +} + +/** + * Datasource item for a tree. The "group" variable is not used in that case. + */ +export interface RdfTermTreeDatasourceItem extends RdfTermDatasourceItem { + hasChildren:boolean; + disabled:boolean; +} /** * Interface for objects that can provide data to a ListWidget : @@ -19,7 +36,7 @@ export interface ListDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;group?:string}[]) => void, + callback:(items:RdfTermDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void } @@ -41,7 +58,7 @@ export class NoOpListDataProvider implements ListDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;group?:string}[]) => void, + callback:(items:RdfTermDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { // does nothing ! @@ -83,7 +100,7 @@ export class SparqlListDataProvider implements ListDataProviderIfc { domainType: string, predicate: string, rangeType: string, - callback:(items:{term:RDFTerm;label:string;group?:string}[]) => void, + callback:(items:RdfTermDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { // 1. create the SPARQL @@ -99,22 +116,22 @@ export class SparqlListDataProvider implements ListDataProviderIfc { // 2. execute it this.sparqlFetcher.executeSparql(sparql,(data:{results:{bindings:any}}) => { // 3. parse the results - let result = new Array<{term:RDFTerm, label:string, group?:string}>; + let result = new Array; for (let index = 0; index < data.results.bindings.length; index++) { const solution = data.results.bindings[index]; if(solution.uri) { // if we find a "uri" column... // read uri key & label key - result[result.length] = {term:solution.uri, label:solution.label.value, group:solution.group?.value}; + result[result.length] = {term:solution.uri, label:solution.label.value, group:solution.group?.value, itemLabel:solution.itemLabel?.value}; } else if(solution.value) { // if we find a "value" column... // read value key & label key - result[result.length] = {term:solution.value, label:solution.label.value, group:solution.group?.value}; + result[result.length] = {term:solution.value, label:solution.label.value, group:solution.group?.value, itemLabel:solution.itemLabel?.value}; } else { // try to determine the payload column by taking the column other than label let columnName = this.getRdfTermColumn(solution); if(columnName) { - result[result.length] ={term:solution[columnName], label:solution.label.value, group:solution.group?.value}; + result[result.length] ={term:solution[columnName], label:solution.label.value, group:solution.group?.value, itemLabel:solution.itemLabel?.value}; } else { throw Error("Could not determine which column to read from the result set") } @@ -174,14 +191,14 @@ export class SortListDataProvider implements ListDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;group?:string}[]) => void, + callback:(items:RdfTermDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { this.delegate.getListContent( domain, predicate, range, - (items:{term:RDFTerm;label:string;group?:string}[]) => { + (items:RdfTermDatasourceItem[]) => { // sort according to lang var collator = new Intl.Collator(this.lang); @@ -220,7 +237,7 @@ export interface AutocompleteDataProviderIfc { predicate:string, range:string, key:string, - callback:(items:{term:RDFTerm;label:string;group?:string}[]) => void, + callback:(items:RdfTermDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void } @@ -243,7 +260,7 @@ export class NoOpAutocompleteProvider implements AutocompleteDataProviderIfc { predicate:string, range:string, key:string, - callback:(items:{term:RDFTerm;label:string;group?:string}[]) => void, + callback:(items:RdfTermDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { // does nothing ! @@ -287,7 +304,7 @@ export class SparqlAutocompleDataProvider implements AutocompleteDataProviderIfc predicate: string, range: string, key: string, - callback:(items:{term:RDFTerm;label:string;group?:string}[]) => void, + callback:(items:RdfTermDatasourceItem[]) => void, errorCallback?:(payload:any) => void ): void { @@ -305,7 +322,7 @@ export class SparqlAutocompleDataProvider implements AutocompleteDataProviderIfc // 2. execute it this.sparqlFetcher.executeSparql(sparql,(data:{results:{bindings:any}}) => { // 3. parse the results - let result = new Array<{term:RDFTerm, label:string;group?:string}>; + let result = new Array; for (let index = 0; index < data.results.bindings.length; index++) { const solution = data.results.bindings[index]; if(solution.uri) { @@ -364,7 +381,7 @@ export interface TreeDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void @@ -373,7 +390,7 @@ export interface TreeDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void @@ -394,7 +411,7 @@ export class NoOpTreeDataProvider implements TreeDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { // does nothing ! @@ -406,7 +423,7 @@ export class NoOpTreeDataProvider implements TreeDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { // does nothing ! @@ -446,7 +463,7 @@ export class SparqlTreeDataProvider implements TreeDataProviderIfc { domainType: string, predicate: string, rangeType: string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { @@ -474,7 +491,7 @@ export class SparqlTreeDataProvider implements TreeDataProviderIfc { domainType: string, predicate: string, rangeType: string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { @@ -499,17 +516,18 @@ export class SparqlTreeDataProvider implements TreeDataProviderIfc { } #getParser( - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void + callback:(items:RdfTermTreeDatasourceItem[]) => void ):(data: any) => void { return (data) => { // 3. parse the results - let result = new Array<{term:RDFTerm, label:string,hasChildren:boolean,disabled:boolean}>; + let result = new Array; for (let index = 0; index < data.results.bindings.length; index++) { const solution = data.results.bindings[index]; result[result.length] = { term:solution.uri, label:solution.label.value, + itemLabel:solution.itemLabel?.value, // make sure to parse the value as a boolean so that it is not a string // we also test on "1" because Virtuoso returns this as a result instead of a true boolean hasChildren:solution.hasChildren?((solution.hasChildren.value === "true" || solution.hasChildren.value == 1)?true:false):true, @@ -551,14 +569,14 @@ export class SortTreeDataProvider implements TreeDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { this.delegate.getRoots( domain, predicate, range, - (items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => { + (items:RdfTermTreeDatasourceItem[]) => { var collator = new Intl.Collator(this.lang); items.sort(function(a:{label:string}, b:{label:string}) { return collator.compare(a.label,b.label); @@ -575,7 +593,7 @@ export class SortTreeDataProvider implements TreeDataProviderIfc { domain:string, predicate:string, range:string, - callback:(items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => void, + callback:(items:RdfTermTreeDatasourceItem[]) => void, errorCallback?:(payload:any) => void ):void { this.delegate.getChildren( @@ -583,7 +601,7 @@ export class SortTreeDataProvider implements TreeDataProviderIfc { domain, predicate, range, - (items:{term:RDFTerm;label:string;hasChildren:boolean;disabled:boolean}[]) => { + (items:RdfTermTreeDatasourceItem[]) => { callback(items); }, errorCallback diff --git a/src/sparnatural/components/widgets/treewidget/TreeWidget.ts b/src/sparnatural/components/widgets/treewidget/TreeWidget.ts index 909696e9..4101bd72 100644 --- a/src/sparnatural/components/widgets/treewidget/TreeWidget.ts +++ b/src/sparnatural/components/widgets/treewidget/TreeWidget.ts @@ -9,7 +9,7 @@ import EndClassGroup from "../../builder-section/groupwrapper/criteriagroup/star import SparqlFactory from "../../../generators/sparql/SparqlFactory"; import { DataFactory } from 'rdf-data-factory'; import { I18n } from "../../../settings/I18n"; -import { NoOpTreeDataProvider, TreeDataProviderIfc } from "../data/DataProviders"; +import { NoOpTreeDataProvider, RdfTermTreeDatasourceItem, TreeDataProviderIfc } from "../data/DataProviders"; import HTMLComponent from "../../HtmlComponent"; const factory = new DataFactory(); @@ -118,15 +118,8 @@ export class TreeWidget extends AbstractWidget { } ) { - interface TreeItem { - term:RDFTerm; - label:string; - hasChildren:boolean; - disabled:boolean - } - - let nodeCallback:(items:TreeItem[]) => void = function( - items:TreeItem[] + let nodeCallback:(items:RdfTermTreeDatasourceItem[]) => void = function( + items:RdfTermTreeDatasourceItem[] ) { var result = []; @@ -332,6 +325,7 @@ export class TreeWidget extends AbstractWidget { var values = []; for (var node in checked) { const val = new RdfTermValue({ + // TODO : find a wat to retrieve the itemLabel label: checked[node].original.text, rdfTerm: { type: "uri", diff --git a/src/sparnatural/ontologies/SparnaturalConfigDatasources.js b/src/sparnatural/ontologies/SparnaturalConfigDatasources.js index c9745a9f..5808dd05 100644 --- a/src/sparnatural/ontologies/SparnaturalConfigDatasources.js +++ b/src/sparnatural/ontologies/SparnaturalConfigDatasources.js @@ -19,7 +19,7 @@ LIMIT 500 QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_literal_list_count", ` -SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) +SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) as ?itemLabel) WHERE { { SELECT DISTINCT ?count ?theLabel @@ -45,7 +45,7 @@ ORDER BY DESC(?count) UCASE(?label) QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_literal_list_alpha_with_count", ` -SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) +SELECT ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) as ?itemLabel) WHERE { { SELECT DISTINCT ?count ?theLabel @@ -85,7 +85,7 @@ LIMIT 500 QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_list_URI_count", ` -SELECT ?uri ?count (CONCAT(STR(?uri), ' (', STR(?count), ')') AS ?label) +SELECT ?uri ?count (CONCAT(STR(?uri), ' (', STR(?count), ')') AS ?label) (STR(?uri) as ?itemLabel) WHERE { { SELECT DISTINCT ?uri (COUNT(?domain) AS ?count) @@ -146,7 +146,7 @@ QUERY_STRINGS_BY_QUERY_TEMPLATE.set( QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_list_URI_or_literal_alpha_with_count", ` - SELECT DISTINCT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " (",LANG(?value),")"),STR(?value)), ' (', STR(?count), ')') AS ?label) + SELECT DISTINCT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " (",LANG(?value),")"),STR(?value)), ' (', STR(?count), ')') AS ?label) (STR(?value) as ?itemLabel) WHERE { { SELECT DISTINCT ?value (COUNT(DISTINCT ?domain) AS ?count) @@ -192,7 +192,7 @@ QUERY_STRINGS_BY_QUERY_TEMPLATE.set( QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_list_URI_or_literal_count", ` - SELECT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " (",LANG(?value),")"),STR(?value)), ' (', STR(?count), ')') AS ?label) + SELECT ?value ?count (CONCAT(IF(isLiteral(?value) && LANG(?value) != '' && LANG(?value) != $lang,CONCAT(STR(?value), " (",LANG(?value),")"),STR(?value)), ' (', STR(?count), ')') AS ?label) (STR(?value) as ?itemLabel) WHERE { { SELECT DISTINCT ?value (COUNT(DISTINCT ?domain) AS ?count) @@ -254,7 +254,7 @@ LIMIT 500 QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_list_label_count", ` -SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) +SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -282,7 +282,7 @@ ORDER BY DESC(?count) UCASE(?label) QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_list_label_alpha_with_count", ` -SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) +SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -327,7 +327,7 @@ LIMIT 500 QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_list_label_with_range_count", ` -SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) +SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -357,7 +357,7 @@ QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_list_label_with_range_alpha_with_count", ` -SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) +SELECT ?uri ?count (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?count ?theLabel @@ -513,7 +513,7 @@ ORDER BY UCASE(?label) QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_tree_children_with_count", ` -SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count +SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT DISTINCT ?uri ?theLabel ?hasChildren (COUNT(?x) AS ?count) @@ -570,7 +570,7 @@ ORDER BY UCASE(?label) QUERY_STRINGS_BY_QUERY_TEMPLATE.set( SPARNATURAL_CONFIG_DATASOURCES + "query_tree_root_noparent_with_count", ` -SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count +SELECT ?uri (CONCAT(STR(?theLabel), ' (', STR(?count), ')') AS ?label) ?hasChildren ?count (STR(?theLabel) AS ?itemLabel) WHERE { { SELECT ?uri ?theLabel ?hasChildren (COUNT(?x) AS ?count)