Skip to content

Commit

Permalink
Fix #681
Browse files Browse the repository at this point in the history
  • Loading branch information
tfrancart committed Nov 28, 2024
1 parent e25f820 commit c0a3163
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 13 deletions.
32 changes: 25 additions & 7 deletions src/sparnatural/components/widgets/AutoCompleteWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { SelectedVal } from "../SelectedVal";
import SparqlFactory from "../../generators/sparql/SparqlFactory";
import { AbstractWidget, RDFTerm, RdfTermValue, ValueRepetition, WidgetValue } from "./AbstractWidget";
import EndClassGroup from "../builder-section/groupwrapper/criteriagroup/startendclassgroup/EndClassGroup";
import { AutocompleteDataProviderIfc, NoOpAutocompleteProvider, RdfTermDatasourceItem } from "./data/DataProviders";
import { AutocompleteDataProviderIfc, mergeDatasourceResults, NoOpAutocompleteProvider, RdfTermDatasourceItem } from "./data/DataProviders";
import Awesomplete from 'awesomplete';
import { I18n } from '../../settings/I18n';
import HTMLComponent from '../HtmlComponent';
Expand Down Expand Up @@ -76,14 +76,31 @@ export class AutoCompleteWidget extends AbstractWidget {
// the callback called when proposals have been fetched, to populate the suggestion list
let callback = (items:RdfTermDatasourceItem[]) => {

// find distinct values of the 'group' binding
const groups = [...new Set(items.map(item => item.group))];

let list = new Array<{label:String, value:String}>();
$.each(items, (key, item) => {
// Awesomplete list will contain the label as 'label', and the RDFTerm JSON serialization as 'value'
list.push({
label: (item.group)?"<span title='"+item.group+"'>"+item.label+"</span>":item.label,
value: JSON.stringify(item.term)
if(groups.length == 1 && groups[0] == undefined) {
// no groups defined at all

items.forEach(item => {
// Awesomplete list will contain the label as 'label', and the RDFTerm JSON serialization as 'value'
list.push({
label: item.label,
value: JSON.stringify(item.term)
});
});
});
} else {
// we have some groups, merge
let mergedResult = mergeDatasourceResults(items);

mergedResult.forEach(item => {
list.push({
label: (item.group)?"<span title='"+item.group+"'>"+item.label+"</span>":item.label,
value: JSON.stringify(item.term)
});
});
}

// toggle spinner
if(list.length == 0) {
Expand Down Expand Up @@ -152,3 +169,4 @@ export class AutoCompleteWidget extends AbstractWidget {
parseInput(input: RdfTermValue["value"]): RdfTermValue {return new RdfTermValue(input)}

}

14 changes: 9 additions & 5 deletions src/sparnatural/components/widgets/ListWidget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, RdfTermDatasourceItem, NoOpListDataProvider } from "./data/DataProviders";
import { ListDataProviderIfc, RdfTermDatasourceItem, NoOpListDataProvider, mergeDatasourceResults } from "./data/DataProviders";
import { I18n } from "../../settings/I18n";
import { Term } from "@rdfjs/types/data-model";
import HTMLComponent from "../HtmlComponent";
Expand Down Expand Up @@ -72,7 +72,7 @@ export class ListWidget extends AbstractWidget {
let callback = (items:RdfTermDatasourceItem[]) => {

if (items.length > 0) {

this.selectHtml.append(
$("<option value=''>" + I18n.labels.ListWidgetSelectValue + "</option>")
);
Expand All @@ -90,10 +90,14 @@ export class ListWidget extends AbstractWidget {
);
});
} else {
// we found some group, organise the list content with optgroup
groups.forEach(group => {
// we found some groups, organise the list content with optgroup

let mergedResult = mergeDatasourceResults(items);
const groupsAfterMerge = [...new Set(mergedResult.map(item => item.group))];

groupsAfterMerge.forEach(group => {
let html = "<optgroup label=\""+group+"\">";
items.filter(item => (item.group == group)).forEach(item => {
mergedResult.filter(item => (item.group == group)).forEach(item => {
// select item label : either displayed label, or itemLabel if provided
let itemLabel = item.itemLabel?item.itemLabel:item.label;

Expand Down
53 changes: 52 additions & 1 deletion src/sparnatural/components/widgets/data/DataProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class SparqlListDataProvider implements ListDataProviderIfc {
const solution = data.results.bindings[index];
// this is to avoid corner-cases with GraphDB queries returning only count=0 in aggregation queries.
// we need at least 2 bindings anyway
if(solution.length > 1) {
if(Object.keys(solution).length > 1) {
if(solution.uri) {
// if we find a "uri" column...
// read uri key & label key
Expand Down Expand Up @@ -626,3 +626,54 @@ export class SortTreeDataProvider implements TreeDataProviderIfc {
}

}

/**
* @param items Merges the datasource items based on their equality, in the case that multiple groups
* (= multiple datasets) return the same RDF term (= the same URI or literal value). In that case a single result is kept,
* with a group that is the concatenation of the groups of the merged items.
* @returns a new list of datasource items in which the items have been merge based on their rdfTerm equality.
*/
export function mergeDatasourceResults(items:RdfTermDatasourceItem[]):RdfTermDatasourceItem[] {
let result:RdfTermDatasourceItem[] = new Array<RdfTermDatasourceItem>();

// iterate on each item
items.forEach(item => {
// if it wasn't already added...
if(!result.some(itemInResult => sameTerm(itemInResult.term, item.term))) {
// find all items with the same URI
let sameTerms = items.filter(i => sameTerm(item.term, i.term));
// add the first identical item of this in our result table, with a merged group
let newTerm:RdfTermDatasourceItem = {
term: sameTerms[0].term,
label : sameTerms[0].label,
itemLabel: sameTerms[0].itemLabel,
group: sameTerms.map(i => i.group).join(" + ")
}
result.push(newTerm);
}

});

return result;
}

/**
* @param t1
* @param t2
* @returns true if both RDF term are equal (same type, same value, same datatype, same language)
*/
export function sameTerm(t1:RDFTerm, t2:RDFTerm):boolean {
return(
t1 != null
&&
t2 != null
&&
t1.type == t2.type
&&
t1.value == t2.value
&&
t1.datatype == t2.datatype
&&
t1["xml:lang"] == t2["xml:lang"]
);
}

0 comments on commit c0a3163

Please sign in to comment.