diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index 35d7ad36..4665fb09 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -537,38 +537,41 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ onDefine: function () { this.buildTabs() - this.showSymbols() + const value = this.value() + if (!value || value.startsWith('/')) this.showSymbolsTab() + else if (value.startsWith('http')) this.showURLTab() + else this.showCharsTab() }, buildTabs: function () { const symbol = L.DomUtil.add( 'button', - 'flat on', + 'flat tab-symbols', this.tabsContainer, L._('Symbol') ), char = L.DomUtil.add( 'button', - 'flat', + 'flat tab-chars', this.tabsContainer, L._('Emoji & Character') ) - url = L.DomUtil.add('button', 'flat', this.tabsContainer, L._('URL')) - toggle = (e) => { - L.DomUtil.removeClass(symbol, 'on') - L.DomUtil.removeClass(char, 'on') - L.DomUtil.removeClass(url, 'on') - L.DomUtil.addClass(e.target, 'on') - } + url = L.DomUtil.add('button', 'flat tab-url', this.tabsContainer, L._('URL')) L.DomEvent.on(symbol, 'click', L.DomEvent.stop) - .on(symbol, 'click', this.showSymbols, this) - .on(symbol, 'click', toggle) + .on(symbol, 'click', this.showSymbolsTab, this) L.DomEvent.on(char, 'click', L.DomEvent.stop) - .on(char, 'click', this.showChars, this) - .on(char, 'click', toggle) + .on(char, 'click', this.showCharsTab, this) L.DomEvent.on(url, 'click', L.DomEvent.stop) - .on(url, 'click', this.showURL, this) - .on(url, 'click', toggle) + .on(url, 'click', this.showURLTab, this) + }, + + highlightTab: function (name) { + const els = this.tabsContainer.querySelectorAll('button') + for (let el of els) { + L.DomUtil.removeClass(el, 'on') + } + let el = this.tabsContainer.querySelector(`.tab-${name}`) + L.DomUtil.addClass(el, 'on') }, isUrl: function () { @@ -586,25 +589,33 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ const img = L.DomUtil.create( 'img', '', - L.DomUtil.create('div', 'umap-pictogram-choice visible', this.buttonsContainer) + L.DomUtil.create( + 'div', + 'umap-pictogram-choice visible', + this.buttonsContainer + ) ) img.src = this.value() - L.DomEvent.on(img, 'click', this.showSymbols, this) + L.DomEvent.on(img, 'click', this.showSymbolsTab, this) } else { const el = L.DomUtil.create( 'span', '', - L.DomUtil.create('div', 'umap-pictogram-choice visible', this.buttonsContainer) + L.DomUtil.create( + 'div', + 'umap-pictogram-choice visible', + this.buttonsContainer + ) ) el.textContent = this.value() - L.DomEvent.on(el, 'click', this.showSymbols, this) + L.DomEvent.on(el, 'click', this.showSymbolsTab, this) } } this.button = L.DomUtil.createButton( 'button action-button', this.buttonsContainer, this.value() ? L._('Change') : L._('Add'), - this.showSymbols, + this.onDefine, this ) }, @@ -613,7 +624,9 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ const baseClass = 'umap-pictogram-choice visible', value = pictogram.src, search = this.searchInput.value.toLowerCase(), - title = pictogram.attribution ? `${pictogram.name} — © ${pictogram.attribution}` : pictogram.name + title = pictogram.attribution + ? `${pictogram.name} — © ${pictogram.attribution}` + : pictogram.name if (search && title.toLowerCase().indexOf(search) === -1) return const className = value === this.value() ? `${baseClass} selected` : baseClass, container = L.DomUtil.create('div', className, parent), @@ -631,7 +644,7 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ }, this ) - return true // Icon has been added (not filtered) + return true // Icon has been added (not filtered) }, clear: function () { @@ -643,10 +656,7 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ }, addCategory: function (category, items) { - const parent = L.DomUtil.create( - 'div', - 'umap-pictogram-category', - ), + const parent = L.DomUtil.create('div', 'umap-pictogram-category'), title = L.DomUtil.add('h6', '', parent, category), grid = L.DomUtil.create('div', 'umap-pictogram-grid', parent) let status = false @@ -677,16 +687,18 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ return !this.value() || this.value() === this.obj.getMap().options.default_iconUrl }, - showChars: function () { + showCharsTab: function () { // Do not show default value here, as it's not a character // and it has not been explicitely chosen by the user. + this.highlightTab('chars') if (this.isDefault()) this.input.value = '' this.input.type = 'text' this.input.placeholder = L._('Type char or paste emoji') this.pictogramsContainer.innerHTML = '' }, - showSymbols: function () { + showSymbolsTab: function () { + this.highlightTab('symbols') this.input.type = 'hidden' this.buttonsContainer.innerHTML = '' this.searchInput = L.DomUtil.create('input', '', this.pictogramsContainer) @@ -719,7 +731,8 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({ } }, - showURL: function () { + showURLTab: function () { + this.highlightTab('url') this.input.type = 'url' this.input.placeholder = L._('Add URL') this.pictogramsContainer.innerHTML = '' diff --git a/umap/tests/integration/test_picto.py b/umap/tests/integration/test_picto.py index 2856fd00..c0c12115 100644 --- a/umap/tests/integration/test_picto.py +++ b/umap/tests/integration/test_picto.py @@ -134,3 +134,84 @@ def test_can_change_picto_at_marker_level(map, live_server, page, pictos): expect(marker).to_have_attribute("src", "/uploads/pictogram/circle.svg") undefine.click() expect(marker).to_have_attribute("src", "/uploads/pictogram/star.svg") + + +def test_can_use_remote_url_as_picto(map, live_server, page, pictos): + # Faster than doing a login + map.edit_status = Map.ANONYMOUS + map.save() + DataLayerFactory(map=map, data=DATALAYER_DATA) + page.goto(f"{live_server.url}{map.get_absolute_url()}?edit") + marker = page.locator(".umap-div-icon img") + expect(marker).to_have_count(1) + # Should have default img + expect(marker).to_have_attribute("src", "/static/umap/img/marker.png") + edit_settings = page.get_by_title("Edit map settings") + expect(edit_settings).to_be_visible() + edit_settings.click() + shape_settings = page.get_by_text("Default shape properties") + expect(shape_settings).to_be_visible() + shape_settings.click() + define = page.locator(".umap-field-iconUrl .define") + expect(define).to_be_visible() + define.click() + url_tab = page.get_by_role("button", name="URL") + input_el = page.locator("input[name='iconUrl']") + expect(input_el).to_be_hidden() + expect(url_tab).to_be_visible() + url_tab.click() + expect(input_el).to_be_visible() + input_el.fill("https://foo.bar/img.jpg") + input_el.blur() + expect(marker).to_have_attribute("src", "https://foo.bar/img.jpg") + # Now close and reopen the form, it should still be the URL tab + close = page.locator("#umap-ui-container").get_by_text("Close") + expect(close).to_be_visible() + close.click() + edit_settings.click() + shape_settings.click() + modify = page.locator(".umap-field-iconUrl").get_by_text("Change") + expect(modify).to_be_visible() + modify.click() + # Should be on URL tab + expect(input_el).to_be_visible() + + +def test_can_use_char_as_picto(map, live_server, page, pictos): + # Faster than doing a login + map.edit_status = Map.ANONYMOUS + map.save() + DataLayerFactory(map=map, data=DATALAYER_DATA) + page.goto(f"{live_server.url}{map.get_absolute_url()}?edit") + marker = page.locator(".umap-div-icon span") + # Should have default img, so not a span + expect(marker).to_have_count(0) + edit_settings = page.get_by_title("Edit map settings") + expect(edit_settings).to_be_visible() + edit_settings.click() + shape_settings = page.get_by_text("Default shape properties") + expect(shape_settings).to_be_visible() + shape_settings.click() + define = page.locator(".umap-field-iconUrl .define") + define.click() + url_tab = page.get_by_role("button", name="Emoji & Character") + input_el = page.locator("input[name='iconUrl']") + expect(input_el).to_be_hidden() + expect(url_tab).to_be_visible() + url_tab.click() + expect(input_el).to_be_visible() + input_el.fill("♩") + input_el.blur() + expect(marker).to_have_count(1) + expect(marker).to_have_text("♩") + # Now close and reopen the form, it should still be the URL tab + close = page.locator("#umap-ui-container").get_by_text("Close") + expect(close).to_be_visible() + close.click() + edit_settings.click() + shape_settings.click() + modify = page.locator(".umap-field-iconUrl").get_by_text("Change") + expect(modify).to_be_visible() + modify.click() + # Should be on URL tab + expect(input_el).to_be_visible()