diff --git a/elements/jsonform/src/custom-inputs/bounding-boxes.js b/elements/jsonform/src/custom-inputs/bounding-boxes.js new file mode 100644 index 000000000..e9e7c3f08 --- /dev/null +++ b/elements/jsonform/src/custom-inputs/bounding-boxes.js @@ -0,0 +1,116 @@ +import { AbstractEditor } from "@json-editor/json-editor/src/editor.js"; +// import "@eox/drawtools"; + +/** + * Set multiple attributes to an element + * + * @param {Element} element - The DOM element to set attributes on + * @param {{[key: string]: any}} attributes - The attributes to set on the element + */ +function setAttributes(element, attributes) { + Object.keys(attributes).forEach((attr) => { + element.setAttribute(attr, attributes[attr]); + }); +} + +// Define a custom editor class extending AbstractEditor +export class BoundingBoxesEditor extends AbstractEditor { + register() { + super.register(); + } + + unregister() { + super.unregister(); + } + + // Build the editor UI + build() { + // const properties = this.schema.properties; + const options = this.options; + const description = this.schema.description; + const theme = this.theme; + // const startVals = this.defaults.startVals[this.key]; + + // Create label and description elements if not in compact mode + if (!options.compact) + this.header = this.label = theme.getFormInputLabel( + this.getTitle(), + this.isRequired() + ); + if (description) + this.description = theme.getFormInputDescription( + this.translateProperty(description) + ); + if (options.infoText) + this.infoButton = theme.getInfoButton( + this.translateProperty(options.infoText) + ); + + const drawtoolsEl = document.createElement("eox-drawtools"); + + const attributes = { + type: "Box", + }; + if (this.schema.format === "bounding-boxes") { + attributes["multiple-features"] = true; + } + + if ("for" in this.options) { + attributes.for = this.options.for; + } else { + // We need to create a map + const eoxmapEl = document.createElement("eox-map"); + eoxmapEl.projection = "EPSG:4326"; + const mapId = "map-" + this.formname.replace(/[^\w\s]/gi, ""); + eoxmapEl.layers = [{ type: "Tile", source: { type: "OSM" } }]; + setAttributes(eoxmapEl, { + id: mapId, + style: "width: 100%; height: 300px;", + }); + this.container.appendChild(eoxmapEl); + drawtoolsEl.for = "eox-map#" + mapId; + } + setAttributes(drawtoolsEl, attributes); + + this.input = drawtoolsEl; + this.input.id = this.formname; + this.control = theme.getFormControl( + this.label, + this.input, + this.description, + this.infoButton + ); + + if (this.schema.readOnly || this.schema.readonly) { + this.disable(true); + this.input.disabled = true; + } + + // Add event listener for change events on the draw tools + this.input.addEventListener("drawupdate", (e) => { + e.preventDefault(); + e.stopPropagation(); + if (this.schema.format === "bounding-boxes") { + this.value = e.detail.map((val) => { + return val.getGeometry().getExtent(); + }); + } else if (e.detail.length > 0) { + this.value = e.detail[0].getGeometry().getExtent(); + } + this.onChange(true); + }); + + this.container.appendChild(this.control); + } + + // Destroy the editor and remove all associated elements + destroy() { + if (this.label && this.label.parentNode) + this.label.parentNode.removeChild(this.label); + if (this.description && this.description.parentNode) + this.description.parentNode.removeChild(this.description); + if (this.input && this.input.parentNode) + this.input.parentNode.removeChild(this.input); + super.destroy(); + } +} diff --git a/elements/jsonform/src/custom-inputs/index.js b/elements/jsonform/src/custom-inputs/index.js index 2f4b1065f..bdb2e2d7a 100644 --- a/elements/jsonform/src/custom-inputs/index.js +++ b/elements/jsonform/src/custom-inputs/index.js @@ -1,5 +1,6 @@ import { JSONEditor } from "@json-editor/json-editor/src/core.js"; import { MinMaxEditor } from "./minmax"; +import { BoundingBoxesEditor } from "./bounding-boxes"; // Define custom input types const inputs = [ @@ -8,6 +9,16 @@ const inputs = [ format: "minmax", func: MinMaxEditor, }, + { + type: "object", + format: "bounding-boxes", + func: BoundingBoxesEditor, + }, + { + type: "object", + format: "bounding-box", + func: BoundingBoxesEditor, + }, ]; /** diff --git a/elements/jsonform/stories/drawtools.js b/elements/jsonform/stories/drawtools.js new file mode 100644 index 000000000..f37b9e853 --- /dev/null +++ b/elements/jsonform/stories/drawtools.js @@ -0,0 +1,12 @@ +/** + * Drawtools component demonstrating the configuration options for eox-jsonform + * It renders drawtools based on json-form config + */ +import drawToolsSchema from "./public/drawToolsSchema.json"; + +const DrawTools = { + args: { + schema: drawToolsSchema, + }, +}; +export default DrawTools; diff --git a/elements/jsonform/stories/index.js b/elements/jsonform/stories/index.js index 9561faef6..699f476ae 100644 --- a/elements/jsonform/stories/index.js +++ b/elements/jsonform/stories/index.js @@ -4,3 +4,4 @@ export { default as CollectionStory } from "./collection"; // Input form based o export { default as ExternalStory } from "./external"; // Input form based on External URL export { default as MarkdownStory } from "./markdown"; // Input form based on Markdown Editor config export { default as UnStyledStory } from "./unstyled"; // Unstyled input form +export { default as DrawToolsStory } from "./drawtools"; // Input form based on drawtools diff --git a/elements/jsonform/stories/jsonform.stories.js b/elements/jsonform/stories/jsonform.stories.js index 63755ea5f..764ba4e5f 100644 --- a/elements/jsonform/stories/jsonform.stories.js +++ b/elements/jsonform/stories/jsonform.stories.js @@ -7,6 +7,7 @@ import { MarkdownStory, PrimaryStory, UnStyledStory, + DrawToolsStory, } from "./index.js"; export default { @@ -52,3 +53,8 @@ export const Markdown = MarkdownStory; * Unstyled JSON Form */ export const Unstyled = UnStyledStory; + +/** + * Unstyled JSON Form + */ +export const DrawTools = DrawToolsStory; diff --git a/elements/jsonform/stories/public/drawToolsSchema.json b/elements/jsonform/stories/public/drawToolsSchema.json new file mode 100644 index 000000000..bef4d0b83 --- /dev/null +++ b/elements/jsonform/stories/public/drawToolsSchema.json @@ -0,0 +1,17 @@ +{ + "type": "object", + "properties": { + "bboxes": { + "title": "Multi bbox example", + "type": "object", + "properties": {}, + "format": "bounding-boxes" + }, + "bbox": { + "title": "Single bbox example", + "type": "object", + "properties": {}, + "format": "bounding-box" + } + } +}