diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js index 210271b8..4fcd3fc1 100644 --- a/umap/static/umap/js/umap.controls.js +++ b/umap/static/umap/js/umap.controls.js @@ -763,6 +763,7 @@ const ControlsMixin = { U.TileLayerControl = L.Control.IconLayers.extend({ initialize: function (map, options) { this.map = map + this.maxShown = 9 L.Control.IconLayers.prototype.initialize.call(this, { position: 'topleft', manageLayers: false, @@ -794,10 +795,26 @@ U.TileLayerControl = L.Control.IconLayers.extend({ } }) } - const maxShown = 10 - L.Control.IconLayers.prototype.setLayers.call(this, layers.slice(0, maxShown)) + L.Control.IconLayers.prototype.setLayers.call(this, layers.slice(0, this.maxShown)) if (this.map.selected_tilelayer) this.setActiveLayer(this.map.selected_tilelayer) }, + + _createLayerElements: function () { + L.Control.IconLayers.prototype._createLayerElements.call(this) + if (Object.keys(this._layers) <= this.maxShown) return + const lastRow = this._container.querySelector( + '.leaflet-iconLayers-layersRow:last-child' + ) + const button = L.DomUtil.element({ + tagName: 'button', + className: 'leaflet-iconLayers-layerCell leaflet-iconLayers-layerCell-plus button', + textContent: '+', + parent: lastRow, + }) + L.DomEvent.on(button, 'click', () => + this.map._controls.tilelayersChooser.openSwitcher() + ) + }, }) /* Used in edit mode to define the default tilelayer */ @@ -806,7 +823,7 @@ U.TileLayerChooser = L.Control.extend({ position: 'topleft', }, - initialize: function (map, options) { + initialize: function (map, options = {}) { this.map = map L.Control.prototype.initialize.call(this, options) }, @@ -824,15 +841,13 @@ U.TileLayerChooser = L.Control.extend({ return container }, - openSwitcher: function (options) { + openSwitcher: function (options = {}) { const container = L.DomUtil.create('div', 'umap-tilelayer-switcher-container') L.DomUtil.createTitle(container, L._('Change tilelayers'), 'icon-tilelayer') this._tilelayers_container = L.DomUtil.create('ul', '', container) this.buildList(options) - this.map.editPanel.open({ - content: container, - className: options.className, - }) + const panel = options.edit ? this.map.editPanel : this.map.panel + panel.open({ content: container }) }, buildList: function (options) { diff --git a/umap/static/umap/js/umap.js b/umap/static/umap/js/umap.js index 7b1b8779..ef2224c3 100644 --- a/umap/static/umap/js/umap.js +++ b/umap/static/umap/js/umap.js @@ -843,11 +843,9 @@ U.Map = L.Map.extend({ this.options.tilelayer = tilelayer.toJSON() this.isDirty = true } - if (this._controls.tilelayersChooser) - this._controls.tilelayersChooser.openSwitcher({ - callback: callback, - className: 'dark', - }) + if (this._controls.tilelayersChooser) { + this._controls.tilelayersChooser.openSwitcher({ callback, edit: true }) + } }, toGeoJSON: function () { diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css index 697d09db..dbadbf09 100644 --- a/umap/static/umap/map.css +++ b/umap/static/umap/map.css @@ -193,8 +193,8 @@ .leaflet-iconLayers-layer { width: 38px; height: 38px; - box-shadow: 0px 0px 2px #444; - border: 1px solid #bbb; + box-shadow: none; + border: 1px solid var(--color-lightGray); border-radius: 4px; } .leaflet-iconLayers-layerTitleContainer { @@ -218,6 +218,25 @@ .leaflet-iconLayers-layerCell:hover .leaflet-iconLayers-layerTitleContainer { height: initial; } +.leaflet-iconLayers-layerCell-plus { + width: 80px; + height: 80px; + background-color: var(--background-color); + vertical-align: middle; + text-align: center; + font-size: 3rem; + display: none; + line-height: 100%; + border-radius: var(--border-radius); + margin-bottom: 0; + border: 1px solid var(--color-lightGray); +} +.leaflet-iconLayers-layerCell-plus:hover { + background-color: var(--color-lightGray); +} +.leaflet-iconLayers:hover .leaflet-iconLayers-layerCell-plus { + display: block; +} diff --git a/umap/tests/integration/test_tilelayer.py b/umap/tests/integration/test_tilelayer.py index e055d356..53e1b606 100644 --- a/umap/tests/integration/test_tilelayer.py +++ b/umap/tests/integration/test_tilelayer.py @@ -122,3 +122,20 @@ def test_can_have_smart_text_in_attribution(tilelayer, map, live_server, page): page.goto(f"{live_server.url}{map.get_absolute_url()}") expect(page.get_by_text("© OpenStreetMap contributors")).to_be_visible() expect(page.get_by_role("link", name="OpenStreetMap")).to_be_visible() + + +def test_map_should_display_a_more_button(map, live_server, tilelayers, page): + map.settings["properties"]["tilelayersControl"] = True + map.save() + page.goto(f"{live_server.url}{map.get_absolute_url()}") + page.locator(".leaflet-iconLayers").hover() + page.get_by_role("button", name="+").click() + panel = page.locator(".panel.left.on") + expect(panel).to_be_visible() + expect(panel.get_by_text("Forte")).to_be_visible() + panel.get_by_text("Forte").click() + tiles = page.locator(".leaflet-tile-pane img") + url_pattern = re.compile( + r"https://[abc]{1}.forte.tiles.quaidorsay.fr/fr/\d+/\d+/\d+.png" + ) + expect(tiles.first).to_have_attribute("src", url_pattern)