diff --git a/umap/static/umap/content.css b/umap/static/umap/content.css index 24d384c1..743af27e 100644 --- a/umap/static/umap/content.css +++ b/umap/static/umap/content.css @@ -248,7 +248,7 @@ input[type="submit"], ul.umap-autocomplete { position: absolute; background-color: white; - z-index: 1010; + z-index: 10100; box-shadow: 0 4px 9px #999999; } .umap-autocomplete li { diff --git a/umap/static/umap/js/modules/global.js b/umap/static/umap/js/modules/global.js index f42ce016..94c3e7f5 100644 --- a/umap/static/umap/js/modules/global.js +++ b/umap/static/umap/js/modules/global.js @@ -18,6 +18,8 @@ import { uMapAlertCreation as AlertCreation, uMapAlertConflict as AlertConflict, } from '../components/alerts/alert.js' +import { Plugin as GeoDataMine } from './plugins/geodatamine.js' +import { Plugin as Communes } from './plugins/communes.js' // Import modules and export them to the global scope. // For the not yet module-compatible JS out there. @@ -49,4 +51,6 @@ window.U = { Tooltip, URLs, Utils, + GeoDataMine, + Communes, } diff --git a/umap/static/umap/js/modules/importer.js b/umap/static/umap/js/modules/importer.js index 889d7ec3..95ce108a 100644 --- a/umap/static/umap/js/modules/importer.js +++ b/umap/static/umap/js/modules/importer.js @@ -37,7 +37,17 @@ export default class Importer { parent: this.container, placeholder: translate('Paste your data here'), }) - this.typeLabel = DomUtil.add( + DomUtil.element({ + tagName: 'h4', + parent: this.container, + textContent: translate('Import from:'), + }) + const plugins = L.DomUtil.element({tagName: 'div', className: 'umap-multiplechoice by2', parent: this.container}) + for (const plugin of this.map.plugins) { + const {name, callback} = plugin.addImporter() + L.DomUtil.createButton('flat', plugins, name, () => callback.bind(plugin)(this)) + } + this.typeLabel = L.DomUtil.add( 'label', '', this.container, diff --git a/umap/static/umap/js/modules/plugins/geodatamine.js b/umap/static/umap/js/modules/plugins/geodatamine.js new file mode 100644 index 00000000..a882dffe --- /dev/null +++ b/umap/static/umap/js/modules/plugins/geodatamine.js @@ -0,0 +1,103 @@ +import { DomUtil, DomEvent, stamp } from '../../../vendors/leaflet/leaflet-src.esm.js' +import { translate } from '../i18n.js' +import { AjaxAutocomplete } from '../autocomplete.js' +import { Request } from '../request.js' +import Alert from '../ui/alert.js' +import Dialog from '../ui/dialog.js' + +class Autocomplete extends AjaxAutocomplete { + constructor(request, el, options) { + super(el, options) + this.request = request + } + + createResult(item) { + return super.createResult({ + value: item.id, + label: `${item.name} (${item.ref})`, + }) + } + + async search() { + let val = this.input.value + if (val.length < this.options.minChar) { + this.clear() + return + } + if (`${val}` === `${this.cache}`) return + else this.cache = val + val = val.toLowerCase() + const response = await this.request.get( + `https://geodatamine.fr/boundaries/search?text=${encodeURIComponent(val)}` + ) + if (response && response.ok) { + const data = await response.json() + this.handleResults(data) + } + } +} + +export class Plugin { + constructor(map) { + this.map = map + this.name = 'GeoDataMine' + this.baseUrl = 'https://geodatamine.fr' + this.type = 'importer' + this.dialog = new Dialog(this.map._controlContainer) + this.map.registerPlugin(this) + this.options = { + theme: null, + boundary: null, + aspoint: false, + } + const alert = new Alert(document.querySelector('header')) + this.request = new Request(alert) + } + + addImporter() { + return { + name: this.name, + callback: this.open, + } + } + + async open(importer) { + const container = DomUtil.create('div') + DomUtil.createTitle(container, this.name) + const response = await this.request.get(`${this.baseUrl}/themes`) + const select = DomUtil.element({ tagName: 'select', parent: container }) + if (response && response.ok) { + const { themes } = await response.json() + for (const theme of themes) { + DomUtil.element({ + tagName: 'option', + value: theme.id, + textContent: theme['name:fr'], + parent: select, + }) + } + } else { + console.error(response) + } + const options = { + className: 'edit-owner', + on_select: (choice) => this.onSelect(choice), + } + this.autocomplete = new Autocomplete(this.request, container, options) + const confirm = () => { + importer.urlInput.value = `${this.baseUrl}/data/${select.value}/${this.options.boundary}?format=geojson` + importer.typeInput.value = 'geojson' + this.dialog.close() + } + L.DomUtil.createButton('', container, 'OK', confirm) + + this.dialog.open({ + content: container, + className: 'geodatamine dark', + }) + } + + onSelect(choice) { + this.options.boundary = choice.item.value + } +} diff --git a/umap/static/umap/js/modules/ui/dialog.js b/umap/static/umap/js/modules/ui/dialog.js index 24aa825a..417f82bc 100644 --- a/umap/static/umap/js/modules/ui/dialog.js +++ b/umap/static/umap/js/modules/ui/dialog.js @@ -24,7 +24,7 @@ export default class Dialog { if (modal) this.container.showModal() else this.container.show() if (className) { - this.container.classList.add(className) + this.container.classList.add(...className.split(' ')) } const buttonsContainer = DomUtil.create('ul', 'buttons', this.container) const closeButton = DomUtil.createButtonIcon( diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 2601b1fb..f3fbf26a 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -69,6 +69,9 @@ U.Map = L.Map.extend({ L.DomEvent.on(document.body, 'dataload', (e) => this.fire('dataload', e)) this.server = new U.ServerRequest() this.request = new U.Request() + this.plugins = [] + new U.GeoDataMine(this) + new U.Communes(this) this.initLoader() this.name = this.options.name @@ -352,6 +355,10 @@ U.Map = L.Map.extend({ } }, + registerPlugin: function (plugin) { + this.plugins.push(plugin) + }, + initControls: function () { this.helpMenuActions = {} this._controls = {}