Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsoneditor element and userlayer plugin #1857

Open
wants to merge 10 commits into
base: minor
Choose a base branch
from
38 changes: 21 additions & 17 deletions lib/plugins/_plugins.mjs
Original file line number Diff line number Diff line change
@@ -1,46 +1,50 @@
/**
## mapp.plugins{}
This module serves as a collection of plugin modules for the application.
## /plugins

The module exports a collection of core mapp plugins.

@module /plugins

@requires module:/plugins/admin
@requires module:/plugins/feature_info
@requires module:/plugins/fullscreen
@requires module:/plugins/keyvalue_dictionary
@requires module:/plugins/link_button
@requires module:/plugins/locator
@requires module:/plugins/login
@requires module:/plugins/svg_templates
@requires module:/plugins/userLayer
@requires module:/plugins/userLocale
@requires module:/plugins/zoomBtn
@requires module:/plugins/zoomToArea
*/

import { admin } from './admin.mjs';
import { feature_info } from './feature_info.mjs';
import { fullscreen } from './fullscreen.mjs';
import { keyvalue_dictionary } from './keyvalue_dictionary.mjs';
import { link_button } from './link_button.mjs';
import { locator } from './locator.mjs';
import { login } from './login.mjs';
import { svg_templates } from './svg_templates.mjs';
import { userLayer } from './userLayer.mjs';
import { userLocale } from './userLocale.mjs';
import { zoomBtn } from './zoomBtn.mjs';
import { zoomToArea } from './zoomToArea.mjs';
import { link_button } from './link_button.mjs';
/**
@typedef {Object} plugins
@property {function} admin The admin plugin module.
@property {function} feature_info Show feature properties in popup.
@property {function} fullscreen The fullscreen plugin module.
@property {function} keyvalue_dictionary The keyvalue_dictionary plugin module.
@property {function} locator The locator plugin module.
@property {function} login The login plugin module.
@property {function} svg_templates The svg_templates plugin module.
@property {function} zoomBtn The zoomBtn plugin module.
@property {function} zoomToArea The zoomToArea plugin module.
@property {function} link_button The link_button plugin module.
*/

const plugins = {
admin,
feature_info,
fullscreen,
keyvalue_dictionary,
link_button,
locator,
login,
svg_templates,
userLayer,
userLocale,
zoomBtn,
zoomToArea,
link_button,
};

export default plugins;
99 changes: 99 additions & 0 deletions lib/plugins/userLayer.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/**
## /plugins/userLayer

The developer plugin provides and interface to test the jsoneditor control and allows to test adding layer from json.

@module /plugins/userLayer

@requires module:/ui/elements/jsoneditor
*/

/**
@function userLayer
@async

@description
The userLayer plugin method adds a button to the layer control to open a jsoneditor dialog.

The jsoneditor dialog allows to validate a layer json configuration to add as user layer to the mapview.

@param {Object} plugin The object holds the plugin configuration.
@param {mapview} mapview The mapview to which a user layer should be added.
*/
export async function userLayer(plugin, mapview) {
plugin.layersNode = document.getElementById('layers');

if (!plugin.layersNode) return;

// Create a content div for the dialog.
const content = mapp.utils.html.node`<div>`;

// Use the content as target for the jsoneditor control.
plugin.jsoneditor = await mapp.ui.elements.jsoneditor({
target: content,
props: {
onRenderMenu: renderMenu,
},
});

// Create a custom menu for the userLayer jsoneditor control.
function renderMenu(items) {
// Push button to add layer to mapview layers.
items.push({
type: 'button',
icon: {
prefix: 'fas',
iconName: 'floppy-disk',
icon: [
448,
512,
[128190, 128426, 'save'],
'f0c7',
'M64 32C28.7 32 0 60.7 0 96L0 416c0 35.3 28.7 64 64 64l320 0c35.3 0 64-28.7 64-64l0-242.7c0-17-6.7-33.3-18.7-45.3L352 50.7C340 38.7 323.7 32 306.7 32L64 32zm0 96c0-17.7 14.3-32 32-32l192 0c17.7 0 32 14.3 32 32l0 64c0 17.7-14.3 32-32 32L96 224c-17.7 0-32-14.3-32-32l0-64zM224 288a64 64 0 1 1 0 128 64 64 0 1 1 0-128z',
],
},
title: 'Add Layer',
onClick: addLayer,
});

return items
.filter((item) => item.text !== 'table')
.filter((item) => item.type !== 'separator')
.filter((item) => item.className !== 'jse-undo')
.filter((item) => item.className !== 'jse-redo')
.filter((item) => item.className !== 'jse-search')
.filter((item) => item.className !== 'jse-contextmenu')
.filter((item) => item.className !== 'jse-sort')
.filter((item) => item.className !== 'jse-transform');
}

async function addLayer() {
const content = plugin.jsoneditor.get();

const jsonLayer = JSON.parse(content.text);

const layers = await mapview.addLayer(jsonLayer);

const layer = layers[0];

mapp.ui.layers.view(layer);

plugin.layersNode.append(layer.view);
}

const dialog = {
header: 'Add Layer',
content,
target: document.getElementById('Map'),
closeBtn: true,
};

plugin.btn = mapp.utils.html.node`<button
class="raised"
onclick=${() => {
mapp.ui.elements.dialog(dialog);
}}>Add Layer`;

// Append the plugin btn to the btnColumn.
plugin.layersNode.append(plugin.btn);
}
78 changes: 40 additions & 38 deletions lib/ui/elements/_elements.mjs
Original file line number Diff line number Diff line change
@@ -1,71 +1,73 @@
/**
## mapp/ui/elements
## /ui/elements

The module exports a collection of ui element modules.

@module /ui/elements

@requires module:/ui/elements/alert
@requires module:/ui/elements/btnPanel
@requires module:/ui/elements/card
@requires module:/ui/elements/chkbox
@requires module:/ui/elements/confirm
@requires module:/ui/elements/contextMenu
@requires module:/ui/elements/dialog
@requires module:/ui/elements/drawer
@requires module:/ui/elements/drawing
@requires module:/ui/elements/dropdown
@requires module:/ui/elements/dropdown_multi
@requires module:/ui/elements/helpDialog
@requires module:/ui/elements/jsoneditor
@requires module:/ui/elements/layerStyle
@requires module:/ui/elements/legendIcon
@requires module:/ui/elements/numericInput
@requires module:/ui/elements/pills
@requires module:/ui/elements/searchbox
@requires module:/ui/elements/slider
@requires module:/ui/elements/slider_ab
@requires module:/ui/elements/themeLegendSwitch
*/

import alert from './alert.mjs';
import btnPanel from './btnPanel.mjs';
import card from './card.mjs';
import chkbox from './chkbox.mjs';
import confirm from './confirm.mjs';
import contextMenu from './contextMenu.mjs';
import dialog from './dialog.mjs';
import drawer from './drawer.mjs';
import drawing from './drawing.mjs';
import dropdown from './dropdown.mjs';
import dropdown_multi from './dropdown_multi.mjs';
import btnPanel from './btnPanel.mjs';
import legendIcon from './legendIcon.mjs';
import dialog from './dialog.mjs';
import alert from './alert.mjs';
import confirm from './confirm.mjs';
import helpDialog from './helpDialog.mjs';
import jsoneditor from './jsoneditor.mjs';
import layerStyle from './layerStyle.mjs';
import legendIcon from './legendIcon.mjs';
import numericInput from './numericInput.mjs';
import pills from './pills.mjs';
import searchbox from './searchbox.mjs';
import slider from './slider.mjs';
import slider_ab from './slider_ab.mjs';
import layerStyle from './layerStyle.mjs';
import pills from './pills.mjs';
import numericInput from './numericInput.mjs';
import themeLegendSwitch from './themeLegendSwitch.mjs';

/**
UI elements object containing various UI components.
@typedef {Object} UIElements
@property {Function} btnPanel - Button panel component.
@property {Function} card - Card component.
@property {Function} chkbox - Checkbox component.
@property {Function} contextMenu - Context menu component.
@property {Function} drawer - Drawer component.
@property {Function} drawing - Drawing component.
@property {Function} dropdown - Dropdown component.
@property {Function} dropdown_multi - Multi-select dropdown component.
@property {Function} legendIcon - Legend icon component.
@property {Function} dialog - Dialog component.
@property {Function} alert - Alert component.
@property {Function} confirm - Confirm component.
@property {Function} helpDialog - Help Dialog component.
@property {Function} searchbox - Searchbox component.
@property {Function} slider - Slider component.
@property {Function} slider_ab - Slider with A/B comparison component.
@property {Function} pills - pills component.

Exporting UI elements.
@type {UIElements}
*/
export default {
alert,
btnPanel,
card,
chkbox,
confirm,
contextMenu,
dialog,
drawer,
drawing,
dropdown,
dropdown_multi,
numericInput,
helpDialog,
jsoneditor,
layerStyle,
legendIcon,
dialog,
alert,
confirm,
numericInput,
pills,
helpDialog,
searchbox,
slider,
slider_ab,
Expand Down
66 changes: 66 additions & 0 deletions lib/ui/elements/jsoneditor.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
### /ui/elements/jsoneditor

The module dynamically imports the [vanilla-jsoneditor]{@link https://www.npmjs.com/package/vanilla-jsoneditor} from esm.sh and exports a utility method to create a jsoneditor control.

@module /ui/elements/jsoneditor
*/

let promise, mod;

/**
@function esmImport
@async

@description
The method dynamically imports the jsoneditor module from esm.sh and asssigns the module to the esm variable.

A promise for the import will be assigned to the promise variable on first call.

The method awaits the import promise to resolve the esm module.
*/
async function esmImport() {
promise ??= new Promise((resolve) => {
import('https://esm.sh/[email protected]').then((esm) => {
mod = esm;
resolve();
});
});

await promise;
}

/**
@function esmImport
@async

@description
The method dynamically imports the jsoneditor module from esm.sh and asssigns the module to the esm variable.

@param {Object} params Parameter for the creation of a jsoneditor element.
@property {Object} params.props Custom property for the createJSONEditor method.
@property {Object} params.data JSON data for the jsoneditor content.

@returns {object} Exports a jsoneditor instance.
*/
export default async function createJSONEditor(params) {
await esmImport();

const content = {};

if (typeof params.data === 'object') {
content.json = params.data;
} else {
content.text = '';
}

const editor = mod.createJSONEditor({
target: params.target,
props: {
content,
...params.props,
},
});

return editor;
}
Loading