diff --git a/umap/static/umap/base.css b/umap/static/umap/base.css index e8321da75..a9f3929b5 100644 --- a/umap/static/umap/base.css +++ b/umap/static/umap/base.css @@ -157,6 +157,9 @@ dt { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); } +.grid-container.by4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); +} .grid-container > * { text-align: center; } diff --git a/umap/static/umap/css/form.css b/umap/static/umap/css/form.css index 912c27978..e2f536eef 100644 --- a/umap/static/umap/css/form.css +++ b/umap/static/umap/css/form.css @@ -602,3 +602,6 @@ input[type=hidden].blur + [type="button"] { input.highlightable:not(:placeholder-shown) { border: 1px solid var(--color-brightCyan); } +.umap-upload [type=url] { + margin-bottom: 0; +} diff --git a/umap/static/umap/css/icon.css b/umap/static/umap/css/icon.css index 43042a540..96bd85e91 100644 --- a/umap/static/umap/css/icon.css +++ b/umap/static/umap/css/icon.css @@ -110,6 +110,9 @@ html[dir="rtl"] .icon { .icon-list { background-position: var(--tile) calc(var(--tile) * 4); } +.icon-magic { + background-position: calc(var(--tile) * 7) 0; +} .icon-marker { background-position: calc(var(--tile) * 3) calc(var(--tile) * 5); } diff --git a/umap/static/umap/js/modules/importer.js b/umap/static/umap/js/modules/importer.js index 9ea95233f..43560e3d7 100644 --- a/umap/static/umap/js/modules/importer.js +++ b/umap/static/umap/js/modules/importer.js @@ -11,13 +11,9 @@ const TEMPLATE = `
${translate('Choose data')} - - + +
${translate( @@ -49,6 +45,14 @@ const TEMPLATE = ` ` +const GRID_TEMPLATE = ` +
+

${translate('Import helpers')}

+

${translate('Import helpers will fill the URL field for you.')}

+
    +
    +` + export default class Importer extends Utils.WithTemplate { constructor(umap) { super() @@ -56,7 +60,7 @@ export default class Importer extends Utils.WithTemplate { this.TYPES = ['geojson', 'csv', 'gpx', 'kml', 'osm', 'georss', 'umap'] this.IMPORTERS = [] this.loadImporters() - this.dialog = new Dialog() + this.dialog = new Dialog({ className: 'importers dark' }) } loadImporters() { @@ -149,20 +153,26 @@ export default class Importer extends Utils.WithTemplate { ) } + showImporters() { + if (!this.IMPORTERS.length) return + const [element, { grid }] = Utils.loadTemplateWithRefs(GRID_TEMPLATE) + for (const plugin of this.IMPORTERS.sort((a, b) => (a.id > b.id ? 1 : -1))) { + const button = Utils.loadTemplate( + `
  • ` + ) + button.addEventListener('click', () => plugin.open(this)) + grid.appendChild(button) + } + this.dialog.open({ template: element, cancel: false, accept: false }) + } + build() { - this.container = DomUtil.create('div', 'umap-upload') - this.container.innerHTML = TEMPLATE + this.container = this.loadTemplate(TEMPLATE) if (this.IMPORTERS.length) { - const parent = this.container.querySelector('.importers ul') - for (const plugin of this.IMPORTERS.sort((a, b) => (a.id > b.id ? 1 : -1))) { - L.DomUtil.createButton( - plugin.id, - DomUtil.element({ tagName: 'li', parent }), - plugin.name, - () => plugin.open(this) - ) - } - this.qs('.importers').toggleAttribute('hidden', false) + // TODO use this.elements instead of this.qs + const button = this.qs('[data-ref=importersButton]') + button.addEventListener('click', () => this.showImporters()) + button.toggleAttribute('hidden', false) } for (const type of this.TYPES) { DomUtil.element({ diff --git a/umap/tests/integration/test_import.py b/umap/tests/integration/test_import.py index dd4b8a7ca..11413eaab 100644 --- a/umap/tests/integration/test_import.py +++ b/umap/tests/integration/test_import.py @@ -607,6 +607,7 @@ def test_overpass_import_with_bbox(page, live_server, tilelayer, settings): } page.goto(f"{live_server.url}/map/new/") page.get_by_role("link", name="Import data").click() + page.get_by_role("button", name="Import helpers").click() page.get_by_role("button", name="Overpass").click() page.get_by_placeholder("amenity=drinking_water").fill("building") page.get_by_role("button", name="Choose this data").click() @@ -657,6 +658,7 @@ def handle(route): page.route(re.compile("https://foobar.io/api.*"), handle) page.goto(f"{live_server.url}/map/new/") page.get_by_role("link", name="Import data").click() + page.get_by_role("button", name="Import helpers").click() page.get_by_role("button", name="Overpass").click() page.get_by_placeholder("amenity=drinking_water").fill("building") page.get_by_placeholder("Type area name, or let empty").click() @@ -669,6 +671,7 @@ def handle(route): expect(page.get_by_placeholder("Provide an URL here")).to_have_value( "https://my.overpass.io/interpreter?data=[out:json];nwr[building](area:3601393025);out geom;" ) + page.get_by_role("button", name="Import helpers").click() page.get_by_role("button", name="Overpass").click() expect(page.locator("#area")).to_contain_text( "Bray-sur-Seine, Seine-et-Marne, Île-de-France, France" @@ -710,6 +713,7 @@ def handle(route): page.goto(f"{live_server.url}/map/new/") expect(page.locator(".leaflet-marker-icon")).to_be_hidden() page.get_by_role("link", name="Import data").click() + page.get_by_role("button", name="Import helpers").click() page.get_by_role("button", name="Datasets").click() page.get_by_role("dialog").get_by_role("combobox").select_option( "https://remote.org/data.json"