diff --git a/umap/static/umap/css/icon.css b/umap/static/umap/css/icon.css index 6da14e7d..b76020b1 100644 --- a/umap/static/umap/css/icon.css +++ b/umap/static/umap/css/icon.css @@ -112,6 +112,9 @@ html[dir="rtl"] .icon { .icon-polyline { background-position: 0 calc(var(--tile) * 3); } +.icon-profile { + background-position: 0 calc(var(--tile) * 4); +} .icon-resize { background-position: calc(var(--tile) * 3) calc(var(--tile) * 6); } diff --git a/umap/static/umap/img/16-white.svg b/umap/static/umap/img/16-white.svg index ceabb640..86704816 100644 --- a/umap/static/umap/img/16-white.svg +++ b/umap/static/umap/img/16-white.svg @@ -190,5 +190,11 @@ + + + + + + diff --git a/umap/static/umap/img/source/16-white.svg b/umap/static/umap/img/source/16-white.svg index 0333e0af..9e99a16a 100644 --- a/umap/static/umap/img/source/16-white.svg +++ b/umap/static/umap/img/source/16-white.svg @@ -16,7 +16,7 @@ - + @@ -212,5 +212,11 @@ + + + + + + diff --git a/umap/static/umap/js/modules/ui/contextmenu.js b/umap/static/umap/js/modules/ui/contextmenu.js index 9231129a..fd61c84a 100644 --- a/umap/static/umap/js/modules/ui/contextmenu.js +++ b/umap/static/umap/js/modules/ui/contextmenu.js @@ -15,11 +15,16 @@ export default class ContextMenu extends Positioned { }) } - open([x, y], items) { + open([left, top], items) { this.container.innerHTML = '' for (const item of items) { if (item === '-') { this.container.appendChild(document.createElement('hr')) + } else if (typeof item.action === 'string') { + const li = loadTemplate( + `
  • ${item.label}
  • ` + ) + this.container.appendChild(li) } else { const li = loadTemplate( `
  • ` @@ -32,14 +37,22 @@ export default class ContextMenu extends Positioned { } } document.body.appendChild(this.container) - this.computePosition([x, y]) - this.container.querySelector('button').focus() - this.container.addEventListener('keydown', (event) => { - if (event.key === 'Escape') { - event.stopPropagation() - this.close() - } - }) + if (this.options.fixed) { + this.setPosition({ left, top }) + } else { + this.computePosition([left, top]) + } + this.container.querySelector('li > *').focus() + this.container.addEventListener( + 'keydown', + (event) => { + if (event.key === 'Escape') { + event.stopPropagation() + this.close() + } + }, + { once: true } + ) } close() { diff --git a/umap/static/umap/js/modules/urls.js b/umap/static/umap/js/modules/urls.js index 171ca91b..c3cb8a2a 100644 --- a/umap/static/umap/js/modules/urls.js +++ b/umap/static/umap/js/modules/urls.js @@ -5,10 +5,14 @@ export default class URLs { this.urls = serverUrls } + has(urlName) { + return urlName in this.urls + } + get(urlName, params) { if (typeof this[urlName] === 'function') return this[urlName](params) - if (this.urls.hasOwnProperty(urlName)) { + if (this.has(urlName)) { return template(this.urls[urlName], params) } throw `Unable to find a URL for route ${urlName}` diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js index 869a7211..5bad389a 100644 --- a/umap/static/umap/js/umap.controls.js +++ b/umap/static/umap/js/umap.controls.js @@ -632,14 +632,39 @@ const ControlsMixin = { L.DomEvent.on(shareStatusButton, 'click', this.permissions.edit, this.permissions) } if (this.options.user?.id) { - L.DomUtil.createLink( - 'umap-user', - rightContainer, - L._('My Dashboard ({username})', { - username: this.options.user.name, - }), - this.options.user.url - ) + const button = U.Utils.loadTemplate(` + + `) + rightContainer.appendChild(button) + const menu = new U.ContextMenu({ className: 'dark', fixed: true }) + const actions = [ + { + label: L._('New map'), + action: this.urls.get('map_new'), + }, + { + label: L._('My maps'), + action: this.urls.get('user_dashboard'), + }, + { + label: L._('My teams'), + action: this.urls.get('user_teams'), + }, + ] + if (this.urls.has('user_profile')) { + actions.push({ + label: L._('My profile'), + action: this.urls.get('user_profile'), + }) + } + button.addEventListener('click', () => { + const x = button.offsetLeft + const y = button.offsetTop + button.offsetHeight + menu.open([x, y], actions) + }) } this.help.getStartedLink(rightContainer) const controlEditCancel = L.DomUtil.createButton( @@ -799,7 +824,8 @@ U.TileLayerControl = L.Control.IconLayers.extend({ ) const button = L.DomUtil.element({ tagName: 'button', - className: 'leaflet-iconLayers-layerCell leaflet-iconLayers-layerCell-plus button', + className: + 'leaflet-iconLayers-layerCell leaflet-iconLayers-layerCell-plus button', textContent: '+', parent: lastRow, }) diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css index c330e00b..4c57acf9 100644 --- a/umap/static/umap/map.css +++ b/umap/static/umap/map.css @@ -592,17 +592,16 @@ ul.photon-autocomplete { left: 0; right: 0; height: 46px; - background-color: var(--color-darkGray); padding: 0 10px; text-align: start; line-height: var(--control-size); cursor: auto; border-bottom: 1px solid #222; z-index: var(--zindex-panels); - opacity: 0.98; - color: #fff; display: flex; justify-content: space-between; + background-color: var(--background-color); + color: var(--text-color); } .umap-left-edit-toolbox, .umap-right-edit-toolbox { @@ -1488,9 +1487,6 @@ span.popup-icon { .umap-main-edit-toolbox .umap-user { margin-inline-end: 10px; } - .umap-main-edit-toolbox .umap-user:after { - display: none; - } } @media all and (max-width: 640px) { .umap-main-edit-toolbox .umap-user { diff --git a/umap/tests/integration/test_basics.py b/umap/tests/integration/test_basics.py index c19c4a96..3ea7c2a7 100644 --- a/umap/tests/integration/test_basics.py +++ b/umap/tests/integration/test_basics.py @@ -94,4 +94,4 @@ def test_login_from_map_page(live_server, page, tilelayer, settings, user, conte # Save should have proceed assert Map.objects.count() == 1 # Use name should now appear on the header toolbar - expect(page.get_by_text("My Dashboard (Joe)")).to_be_visible() + expect(page.get_by_role("button", name="Joe")).to_be_visible()