UNPKG

sparnatural

Version:

Visual client-side SPARQL query builder and knowledge graph exploration tool

250 lines (216 loc) 8.44 kB
import { WidgetFactory } from "../../sparnatural/components/builder-section/groupwrapper/criteriagroup/edit-components/WidgetFactory"; import { SparnaturalFormI18n } from "../settings/SparnaturalFormI18n"; import UnselectBtn from "../../sparnatural/components/buttons/UnselectBtn"; import { Branch, CriteriaLine, ISparJson, } from "../../sparnatural/generators/json/ISparJson"; import ISparnaturalSpecification from "../../sparnatural/spec-providers/ISparnaturalSpecification"; import OptionalCriteriaManager from "./optionalCriteria/OptionalCriteriaManager"; import { AbstractWidget } from "../../sparnatural/components/widgets/AbstractWidget"; import { Binding } from "../FormStructure"; class FormField { private binding: Binding; private formContainer: HTMLElement; private specProvider: ISparnaturalSpecification; private query: ISparJson; private widgetFactory: WidgetFactory; private optionalCriteriaManager!: OptionalCriteriaManager; // Optional Criteria Manager instance constructor( binding: Binding, formContainer: HTMLElement, specProvider: ISparnaturalSpecification, query: ISparJson, widgetFactory: WidgetFactory ) { this.binding = binding; this.formContainer = formContainer; this.specProvider = specProvider; this.query = query; this.widgetFactory = widgetFactory; } generateField(): void { const variable = this.binding.variable; // Create a container for the field const formFieldDiv = document.createElement("div"); formFieldDiv.classList.add("formField"); this.formContainer.appendChild(formFieldDiv); // Create a label for the widget const label = this.createLabel(variable); formFieldDiv.appendChild(label); // Find the line in the query corresponding to the variable const queryLine = this.findInBranches(this.query.branches, variable); if (queryLine) { const widget = this.createWidget(queryLine); formFieldDiv.appendChild(widget.html[0]); // Initialize OptionalCriteriaManager this.optionalCriteriaManager = new OptionalCriteriaManager( this.query, variable, queryLine, widget, formFieldDiv ); // Add options like "An'y value" and "Not Exist" this.addValuesAndOptions(formFieldDiv, queryLine, widget, variable); } } //method to create a label for the widget in the form private createLabel(variable: string): HTMLLabelElement { const label = document.createElement("label"); label.setAttribute("for", variable); label.innerHTML = `<strong>${SparnaturalFormI18n.getLabel( variable )}</strong>`; label.style.fontSize = "18px"; return label; } //method to find the line in the query corresponding to the variable private findInBranches( branches: Branch[], variable: string ): CriteriaLine | null { for (const branch of branches) { if (branch.line.o === variable) return branch.line; if (branch.children && branch.children.length > 0) { const result = this.findInBranches(branch.children, variable); if (result) return result; } } return null; } //method to create a widget in the form private createWidget1(queryLine: CriteriaLine): AbstractWidget { const subject = queryLine.sType; const predicate = queryLine.p; const object = queryLine.oType; const specEntity = this.specProvider.getEntity(subject); const connectingProperty = this.specProvider.getProperty(predicate); const propertyType = connectingProperty.getPropertyType(object); const widget = this.widgetFactory.buildWidget( propertyType, { variable: queryLine.s, type: specEntity.getId() }, { variable: "predicate", type: connectingProperty.getId() }, { variable: queryLine.o, type: object } ); widget.render(); //console.log("widget", widget); return widget; } private createWidget(queryLine: CriteriaLine): AbstractWidget { const subject = queryLine.sType; const predicate = queryLine.p; const object = queryLine.oType; const specEntity = this.specProvider.getEntity(subject); const connectingProperty = this.specProvider.getProperty(predicate); const propertyType = connectingProperty.getPropertyType(object); const widget = this.widgetFactory.buildWidget( propertyType, { variable: queryLine.s, type: specEntity.getId() }, { variable: "predicate", type: connectingProperty.getId() }, { variable: queryLine.o, type: object } ); widget.render(); // console.log("widget", widget); return widget; } //methode to add values and options to the widget in the form private addValuesAndOptions( formFieldDiv: HTMLElement, queryLine: CriteriaLine, widget: AbstractWidget, variable: string ): void { const valueDisplay = document.createElement("div"); valueDisplay.setAttribute("id", `selected-value-${variable}`); valueDisplay.classList.add("value-display-container"); valueDisplay.style.marginTop = "5px"; formFieldDiv.appendChild(valueDisplay); // Add a set to store selected values and a method to update the display const selectedValues = new Set<any>(); const updateValueDisplay = () => { valueDisplay.innerHTML = ""; selectedValues.forEach((val) => { const valueContainer = document.createElement("div"); valueContainer.classList.add("selected-value-container"); const valueLabel = document.createElement("span"); valueLabel.innerText = `${val.label}`; valueLabel.classList.add("selected-value-label"); valueContainer.appendChild(valueLabel); const removeBtn = new UnselectBtn(widget, () => { selectedValues.delete(val); console.log(selectedValues); updateValueDisplay(); queryLine.values = Array.from(selectedValues); console.log(true); console.log("QUERYLINE ", queryLine); formFieldDiv.dispatchEvent( new CustomEvent("valueRemoved", { bubbles: true, detail: { value: val, variable: variable }, }) ); // Update options visibility if (this.optionalCriteriaManager) { this.optionalCriteriaManager.updateOptionVisibility(); } }).render(); valueContainer.appendChild(removeBtn.html[0]); valueDisplay.appendChild(valueContainer); }); }; // Add existing values to the widget // Add an event listener to add values to the widget widget.html[0].addEventListener("renderWidgetVal", (e: CustomEvent) => { //console.log("widget", widget); console.log("e.detail", e.detail); let valueToInject: any[]; // Handle different cases for e.detail if (Array.isArray(e.detail)) { // Case: e.detail is an array valueToInject = e.detail.map((item: any) => item.value); console.log("here"); typeof valueToInject[0] === "string"; } else if (e.detail.value) { // Case: e.detail contains a single value or a wrapped object valueToInject = Array.isArray(e.detail.value) ? e.detail.value : [e.detail.value]; } else { console.warn("Unexpected e.detail format:", e.detail); return; // Exit early if the format is not recognized } console.log("valueToInject", valueToInject); valueToInject.forEach((val: any) => { const existingValue = Array.from(selectedValues).find( (existingVal: any) => existingVal.label === val.label ); if (!existingValue) { selectedValues.add(val); updateValueDisplay(); queryLine.values = Array.from(selectedValues); formFieldDiv.dispatchEvent( new CustomEvent("valueAdded", { bubbles: true, detail: { value: val, variable: variable }, }) ); // Update options visibility if (this.optionalCriteriaManager) { this.optionalCriteriaManager.updateOptionVisibility(); } } }); }); // Add An'yValue and NotExist options this.optionalCriteriaManager = new OptionalCriteriaManager( this.query, variable, queryLine, widget, formFieldDiv ); } } export default FormField;