sparnatural
Version:
Visual client-side SPARQL query builder and knowledge graph exploration tool
113 lines • 5.82 kB
JavaScript
import { AbstractWidget, ValueRepetition } from "./AbstractWidget";
import { DataFactory } from 'rdf-data-factory';
import "select2";
import "select2/dist/css/select2.css";
import { I18n } from "../../settings/I18n";
import { NoOpListDataProvider } from "../datasources/NoOpDataProviders";
import { mergeDatasourceResults } from "../datasources/SparqlDataProviders";
const factory = new DataFactory();
export class ListWidget extends AbstractWidget {
constructor(parentComponent, config, startClassVal, objectPropVal, endClassVal) {
super("list-widget", parentComponent, null, startClassVal, objectPropVal, endClassVal, ValueRepetition.MULTIPLE);
this.configuration = config;
this.startClassVal = startClassVal;
this.objectPropVal = objectPropVal;
this.endClassVal = endClassVal;
}
render() {
super.render();
this.selectHtml = $(`<select style="width:100%; min-width:200px;"></select>`);
this.html.append(this.selectHtml);
let noItemsHtml = $(`<div class="no-items" style="display: none; font-style:italic;">
${I18n.labels.ListWidgetNoItem}
</div>`);
let errorHtml = $(`<div class="no-items" style="display: none; font-style:italic;">
${I18n.labels.ListWidgetNoItem}
</div>`);
let callback = (items) => {
if (items.length > 0) {
this.selectHtml.append($("<option value=''>" + I18n.labels.ListWidgetSelectValue + "</option>"));
// find distinct values of the 'group' binding
const groups = [...new Set(items.map(item => item.group))];
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($("<option value='" + JSON.stringify(item.term) + "' data-itemLabel='" + itemLabel + "'>" + item.label + "</option>"));
});
}
else {
// 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 + "\">";
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;
html += "<option value='" + JSON.stringify(item.term) + "' data-itemLabel='" + itemLabel + "'>" + item.label + "</option>";
});
html += "</optgroup>";
this.selectHtml.append($(html));
});
}
this.selectHtml = this.selectHtml.select2({
// use the minimumResultsForSearch parameter to avoid using a search box when only a few items are present
minimumResultsForSearch: 20,
// pass a JQUery object so that HTML markup is preserved
// TODO : this does not work ATM
// templateResult: function formatLabel(label:any) {return $(label)},
width: "style"
});
// set a listener for when a value is selected
this.selectHtml.on("select2:close", (e) => {
let option = e.currentTarget.selectedOptions;
if (option.length > 1)
throw Error("List widget should allow only for one el to be selected!");
// this is the placeholder
if (option[0].value == "")
return;
let itemLabel = option[0].getAttribute("data-itemLabel");
let listWidgetValue = this.buildValue(option[0].value, itemLabel);
this.triggerRenderWidgetVal(listWidgetValue);
});
}
else {
this.html.append(noItemsHtml);
}
// switch off spinner
this.toggleSpinner('');
};
// TODO : this is not working for now
let errorCallback = (payload) => {
this.html.append(errorHtml);
};
// toggle spinner before loading
this.toggleSpinner(I18n.labels.AutocompleteSpinner_Searching);
// if there are some provided values like in sh:in...
if (this.configuration.values?.length > 0) {
this.configuration.dataProvider.getListContent(this.configuration.values, callback, errorCallback);
}
else {
this.configuration.dataProvider.getListContent(this.startClassVal.type, this.objectPropVal.type, this.endClassVal.type, callback, errorCallback);
}
return this;
}
// separate the creation of the value from the widget code itself
// so that it can be overriden by LiteralListWidget
buildValue(termString, label) {
let term = JSON.parse(termString);
return {
label: label,
criteria: { rdfTerm: term }
};
}
parseInput(input) { return input; }
}
// The default implementation of ListConfiguration
ListWidget.defaultConfiguration = {
dataProvider: new NoOpListDataProvider(),
values: undefined
};
//# sourceMappingURL=ListWidget.js.map