feat: show last used pictograms in list
This feature was planned in the initial rework of the pictogram form UI, but not yet done. Some recent discussion in the OSM French forum reactivated the need for it. cf https://forum.openstreetmap.fr/t/marker-and-marker-colors/21051
This commit is contained in:
parent
188a535f7d
commit
126e47eef9
3 changed files with 48 additions and 25 deletions
|
@ -537,9 +537,13 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
||||||
this.on('define', this.onDefine)
|
this.on('define', this.onDefine)
|
||||||
},
|
},
|
||||||
|
|
||||||
onDefine: function () {
|
onDefine: async function () {
|
||||||
this.buttons.innerHTML = ''
|
this.buttons.innerHTML = ''
|
||||||
this.footer.innerHTML = ''
|
this.footer.innerHTML = ''
|
||||||
|
const [{ pictogram_list }, response, error] = await this.builder.map.server.get(
|
||||||
|
this.builder.map.options.urls.pictogram_list_json
|
||||||
|
)
|
||||||
|
if (!error) this.pictogram_list = pictogram_list
|
||||||
this.buildTabs()
|
this.buildTabs()
|
||||||
const value = this.value()
|
const value = this.value()
|
||||||
if (!value || L.Util.isPath(value)) this.showSymbolsTab()
|
if (!value || L.Util.isPath(value)) this.showSymbolsTab()
|
||||||
|
@ -624,12 +628,11 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
||||||
search = L.Util.normalize(this.searchInput.value),
|
search = L.Util.normalize(this.searchInput.value),
|
||||||
title = pictogram.attribution
|
title = pictogram.attribution
|
||||||
? `${pictogram.name} — © ${pictogram.attribution}`
|
? `${pictogram.name} — © ${pictogram.attribution}`
|
||||||
: pictogram.name
|
: pictogram.name || pictogram.src
|
||||||
if (search && L.Util.normalize(title).indexOf(search) === -1) return
|
if (search && L.Util.normalize(title).indexOf(search) === -1) return
|
||||||
const className = value === this.value() ? `${baseClass} selected` : baseClass,
|
const className = value === this.value() ? `${baseClass} selected` : baseClass,
|
||||||
container = L.DomUtil.create('div', className, parent),
|
container = L.DomUtil.create('div', className, parent)
|
||||||
img = L.DomUtil.create('img', '', container)
|
U.Icon.makeIconElement(value, container)
|
||||||
img.src = value
|
|
||||||
container.title = title
|
container.title = title
|
||||||
L.DomEvent.on(
|
L.DomEvent.on(
|
||||||
container,
|
container,
|
||||||
|
@ -664,6 +667,15 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
||||||
if (status) this.grid.appendChild(parent)
|
if (status) this.grid.appendChild(parent)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showLastUsed: function () {
|
||||||
|
if (U.Icon.LAST_USED.length) {
|
||||||
|
const items = U.Icon.LAST_USED.map((src) => ({
|
||||||
|
src,
|
||||||
|
}))
|
||||||
|
this.addCategory(L._('Used in this map'), items)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
buildSymbolsList: function () {
|
buildSymbolsList: function () {
|
||||||
this.grid.innerHTML = ''
|
this.grid.innerHTML = ''
|
||||||
const categories = {}
|
const categories = {}
|
||||||
|
@ -676,6 +688,7 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
||||||
const sorted = Object.entries(categories).toSorted(([a], [b]) =>
|
const sorted = Object.entries(categories).toSorted(([a], [b]) =>
|
||||||
L.Util.naturalSort(a, b)
|
L.Util.naturalSort(a, b)
|
||||||
)
|
)
|
||||||
|
this.showLastUsed()
|
||||||
for (let [category, items] of sorted) {
|
for (let [category, items] of sorted) {
|
||||||
this.addCategory(category, items)
|
this.addCategory(category, items)
|
||||||
}
|
}
|
||||||
|
@ -692,17 +705,7 @@ L.FormBuilder.IconUrl = L.FormBuilder.BlurInput.extend({
|
||||||
this.searchInput.placeholder = L._('Search')
|
this.searchInput.placeholder = L._('Search')
|
||||||
this.grid = L.DomUtil.create('div', '', this.body)
|
this.grid = L.DomUtil.create('div', '', this.body)
|
||||||
L.DomEvent.on(this.searchInput, 'input', this.buildSymbolsList, this)
|
L.DomEvent.on(this.searchInput, 'input', this.buildSymbolsList, this)
|
||||||
if (this.pictogram_list) {
|
this.buildSymbolsList()
|
||||||
this.buildSymbolsList()
|
|
||||||
} else {
|
|
||||||
const [{ pictogram_list }, response, error] = await this.builder.map.server.get(
|
|
||||||
this.builder.map.options.urls.pictogram_list_json
|
|
||||||
)
|
|
||||||
if (!error) {
|
|
||||||
this.pictogram_list = pictogram_list
|
|
||||||
this.buildSymbolsList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showCharsTab: function () {
|
showCharsTab: function () {
|
||||||
|
@ -989,10 +992,7 @@ L.FormBuilder.ManageEditors = L.FormBuilder.Element.extend({
|
||||||
on_select: L.bind(this.onSelect, this),
|
on_select: L.bind(this.onSelect, this),
|
||||||
on_unselect: L.bind(this.onUnselect, this),
|
on_unselect: L.bind(this.onUnselect, this),
|
||||||
}
|
}
|
||||||
this.autocomplete = new U.AutoComplete.Ajax.SelectMultiple(
|
this.autocomplete = new U.AutoComplete.Ajax.SelectMultiple(this.parentNode, options)
|
||||||
this.parentNode,
|
|
||||||
options
|
|
||||||
)
|
|
||||||
this._values = this.toHTML()
|
this._values = this.toHTML()
|
||||||
if (this._values)
|
if (this._values)
|
||||||
for (let i = 0; i < this._values.length; i++)
|
for (let i = 0; i < this._values.length; i++)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
U.Icon = L.DivIcon.extend({
|
U.Icon = L.DivIcon.extend({
|
||||||
|
statics: {
|
||||||
|
LAST_USED: [],
|
||||||
|
},
|
||||||
initialize: function (map, options) {
|
initialize: function (map, options) {
|
||||||
this.map = map
|
this.map = map
|
||||||
const default_options = {
|
const default_options = {
|
||||||
|
@ -14,11 +17,22 @@ U.Icon = L.DivIcon.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_setLastUsed: function (url) {
|
||||||
|
if (L.Util.hasVar(url)) return
|
||||||
|
if (url === this.map.options.default_iconUrl) return
|
||||||
|
if (U.Icon.LAST_USED.indexOf(url) === -1) {
|
||||||
|
U.Icon.LAST_USED.push(url)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
_getIconUrl: function (name) {
|
_getIconUrl: function (name) {
|
||||||
let url
|
let url
|
||||||
if (this.feature && this.feature._getIconUrl(name))
|
if (this.feature && this.feature._getIconUrl(name)) {
|
||||||
url = this.feature._getIconUrl(name)
|
url = this.feature._getIconUrl(name)
|
||||||
else url = this.options[`${name}Url`]
|
this._setLastUsed(url)
|
||||||
|
} else {
|
||||||
|
url = this.options[`${name}Url`]
|
||||||
|
}
|
||||||
return this.formatUrl(url, this.feature)
|
return this.formatUrl(url, this.feature)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -216,7 +230,7 @@ U.Icon.setIconContrast = function (icon, parent, src, bgcolor) {
|
||||||
* src: the raw "icon" value, can be an URL, a path, text, emoticon, etc.
|
* src: the raw "icon" value, can be an URL, a path, text, emoticon, etc.
|
||||||
* bgcolor: the background color, used for caching and in case we cannot guess the
|
* bgcolor: the background color, used for caching and in case we cannot guess the
|
||||||
* parent background color
|
* parent background color
|
||||||
*/
|
*/
|
||||||
if (!icon) return
|
if (!icon) return
|
||||||
|
|
||||||
if (L.DomUtil.contrastedColor(parent, bgcolor)) {
|
if (L.DomUtil.contrastedColor(parent, bgcolor)) {
|
||||||
|
|
|
@ -94,7 +94,7 @@ def test_can_change_picto_at_datalayer_level(map, live_server, page, pictos):
|
||||||
expect(undefine).to_be_hidden()
|
expect(undefine).to_be_hidden()
|
||||||
define.click()
|
define.click()
|
||||||
symbols = page.locator(".umap-pictogram-choice")
|
symbols = page.locator(".umap-pictogram-choice")
|
||||||
expect(symbols).to_have_count(2)
|
expect(symbols).to_have_count(3)
|
||||||
search = page.locator(".umap-pictogram-body input")
|
search = page.locator(".umap-pictogram-body input")
|
||||||
search.type("circle")
|
search.type("circle")
|
||||||
expect(symbols).to_have_count(1)
|
expect(symbols).to_have_count(1)
|
||||||
|
@ -128,7 +128,7 @@ def test_can_change_picto_at_marker_level(map, live_server, page, pictos):
|
||||||
expect(undefine).to_be_hidden()
|
expect(undefine).to_be_hidden()
|
||||||
define.click()
|
define.click()
|
||||||
symbols = page.locator(".umap-pictogram-choice")
|
symbols = page.locator(".umap-pictogram-choice")
|
||||||
expect(symbols).to_have_count(2)
|
expect(symbols).to_have_count(3) # Include "Last used" picto
|
||||||
search = page.locator(".umap-pictogram-body input")
|
search = page.locator(".umap-pictogram-body input")
|
||||||
search.type("circle")
|
search.type("circle")
|
||||||
expect(symbols).to_have_count(1)
|
expect(symbols).to_have_count(1)
|
||||||
|
@ -157,6 +157,10 @@ def test_can_use_remote_url_as_picto(map, live_server, page, pictos):
|
||||||
define = page.locator(".umap-field-iconUrl .define")
|
define = page.locator(".umap-field-iconUrl .define")
|
||||||
expect(define).to_be_visible()
|
expect(define).to_be_visible()
|
||||||
define.click()
|
define.click()
|
||||||
|
expect(page.get_by_text("Used in this map")).to_be_hidden()
|
||||||
|
# Only default symbols
|
||||||
|
symbols = page.locator(".umap-pictogram-choice")
|
||||||
|
expect(symbols).to_have_count(2)
|
||||||
url_tab = page.get_by_role("button", name="URL")
|
url_tab = page.get_by_role("button", name="URL")
|
||||||
input_el = page.get_by_placeholder("Add image URL")
|
input_el = page.get_by_placeholder("Add image URL")
|
||||||
expect(input_el).to_be_hidden()
|
expect(input_el).to_be_hidden()
|
||||||
|
@ -177,6 +181,11 @@ def test_can_use_remote_url_as_picto(map, live_server, page, pictos):
|
||||||
modify.click()
|
modify.click()
|
||||||
# Should be on URL tab
|
# Should be on URL tab
|
||||||
expect(input_el).to_be_visible()
|
expect(input_el).to_be_visible()
|
||||||
|
# Symbol should be visible in symbols b
|
||||||
|
symbols_tab = page.get_by_role("button", name="Symbol")
|
||||||
|
symbols_tab.click()
|
||||||
|
expect(page.get_by_text("Used in this map")).to_be_visible()
|
||||||
|
expect(symbols).to_have_count(3)
|
||||||
|
|
||||||
|
|
||||||
def test_can_use_char_as_picto(map, live_server, page, pictos):
|
def test_can_use_char_as_picto(map, live_server, page, pictos):
|
||||||
|
|
Loading…
Reference in a new issue