chore: use our contexmenu class for inplace toolbar (#2510)
Some checks failed
Test & Docs / tests (postgresql, 3.10) (push) Has been cancelled
Test & Docs / tests (postgresql, 3.12) (push) Has been cancelled
Test & Docs / lint (push) Has been cancelled

And remove Leaflet.Toolbar dependency.
This also teach ContextMenu how to display icons instead of text and how
to render in horizontal orientation instead of vertical.

Before:

![image](https://github.com/user-attachments/assets/196b17c4-ec6c-4023-b5bf-32033caf4408)

After:


![image](https://github.com/user-attachments/assets/29ad8628-01a6-4028-a99a-bc679c5db18d)

We've lost the bottom tip in the process, should I add this to the
ContextMenu class ?

Also, the automatic border for the focused button is a bit noisy imho,
not sure how to deal with that.
This commit is contained in:
Yohan Boniface 2025-02-14 17:25:13 +01:00 committed by GitHub
commit fcac4df30b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 132 additions and 281 deletions

View file

@ -16,7 +16,6 @@ mkdir -p umap/static/umap/vendors/markercluster/ && cp -r node_modules/leaflet.m
mkdir -p umap/static/umap/vendors/markercluster/ && cp -r node_modules/leaflet.markercluster/dist/MarkerCluster.* umap/static/umap/vendors/markercluster/ mkdir -p umap/static/umap/vendors/markercluster/ && cp -r node_modules/leaflet.markercluster/dist/MarkerCluster.* umap/static/umap/vendors/markercluster/
mkdir -p umap/static/umap/vendors/heat/ && cp -r node_modules/leaflet.heat/dist/leaflet-heat.js umap/static/umap/vendors/heat/ mkdir -p umap/static/umap/vendors/heat/ && cp -r node_modules/leaflet.heat/dist/leaflet-heat.js umap/static/umap/vendors/heat/
mkdir -p umap/static/umap/vendors/fullscreen/ && cp -r node_modules/leaflet-fullscreen/dist/** umap/static/umap/vendors/fullscreen/ mkdir -p umap/static/umap/vendors/fullscreen/ && cp -r node_modules/leaflet-fullscreen/dist/** umap/static/umap/vendors/fullscreen/
mkdir -p umap/static/umap/vendors/toolbar/ && cp -r node_modules/leaflet-toolbar/dist/leaflet.toolbar.* umap/static/umap/vendors/toolbar/
mkdir -p umap/static/umap/vendors/measurable/ && cp -r node_modules/leaflet-measurable/Leaflet.Measurable.* umap/static/umap/vendors/measurable/ mkdir -p umap/static/umap/vendors/measurable/ && cp -r node_modules/leaflet-measurable/Leaflet.Measurable.* umap/static/umap/vendors/measurable/
mkdir -p umap/static/umap/vendors/photon/ && cp -r node_modules/leaflet.photon/leaflet.photon.js umap/static/umap/vendors/photon/ mkdir -p umap/static/umap/vendors/photon/ && cp -r node_modules/leaflet.photon/leaflet.photon.js umap/static/umap/vendors/photon/
mkdir -p umap/static/umap/vendors/csv2geojson/ && cp -r node_modules/csv2geojson/csv2geojson.js umap/static/umap/vendors/csv2geojson/ mkdir -p umap/static/umap/vendors/csv2geojson/ && cp -r node_modules/csv2geojson/csv2geojson.js umap/static/umap/vendors/csv2geojson/

View file

@ -1,12 +1,20 @@
.umap-contextmenu { .umap-contextmenu {
background-color: var(--background-color); background-color: var(--background-color);
padding: calc(var(--box-padding) / 2) var(--box-padding); padding: calc(var(--box-padding) / 2) calc(var(--box-padding) / 2);
position: fixed; position: fixed;
z-index: var(--zindex-contextmenu); z-index: var(--zindex-contextmenu);
border-radius: var(--border-radius); border-radius: var(--border-radius);
box-shadow: var(--block-shadow); box-shadow: var(--block-shadow);
display: flex;
flex-direction: column;
} }
.umap-contextmenu li + li { .umap-contextmenu-rows {
flex-direction: row;
align-items: center;
justify-content: center;
align-content: center;
}
.umap-contextmenu:not(.umap-contextmenu-rows) li + li {
margin-top: var(--text-margin); margin-top: var(--text-margin);
} }
@ -14,3 +22,7 @@
margin-top: var(--text-margin); margin-top: var(--text-margin);
margin-bottom: var(--text-margin); margin-bottom: var(--text-margin);
} }
.dark.umap-contextmenu li button .icon:hover {
background-color: var(--color-mediumGray);
}

View file

@ -68,12 +68,21 @@ html[dir="rtl"] .icon {
.icon-close { .icon-close {
background-position: var(--tile) 0px; background-position: var(--tile) 0px;
} }
.icon-continue-line {
background-position: calc(var(--tile) * 4) 0;
}
.icon-copy { .icon-copy {
background-position: calc(var(--tile) * 2) calc(var(--tile) * 4); background-position: calc(var(--tile) * 2) calc(var(--tile) * 4);
} }
.icon-delete { .icon-delete {
background-position: calc(var(--tile) * 5) calc(var(--tile) * 2); background-position: calc(var(--tile) * 5) calc(var(--tile) * 2);
} }
.icon-delete-shape {
background-position: calc(var(--tile) * 4) calc(var(--tile) * 3);
}
.icon-delete-vertex {
background-position: calc(var(--tile) * 5) calc(var(--tile) * 4);
}
.readonly .icon-delete, .readonly .icon-delete,
.off .icon-delete { .off .icon-delete {
background-position: calc(var(--tile) * 5) calc(var(--tile) * 5); background-position: calc(var(--tile) * 5) calc(var(--tile) * 5);
@ -98,6 +107,9 @@ html[dir="rtl"] .icon {
.off .icon-edit { .off .icon-edit {
background-position: calc(var(--tile) * 2) calc(var(--tile) * 3); background-position: calc(var(--tile) * 2) calc(var(--tile) * 3);
} }
.icon-extract-shape {
background-position: calc(var(--tile) * 5) 0;
}
.icon-filters { .icon-filters {
background-position: 0px var(--tile); background-position: 0px var(--tile);
} }
@ -107,6 +119,9 @@ html[dir="rtl"] .icon {
.icon-help { .icon-help {
background-position: 0 0; background-position: 0 0;
} }
.icon-hole {
background-position: calc(var(--tile) * 3) calc(var(--tile) * 4);
}
.icon-key { .icon-key {
background-position: calc(var(--tile) * 6) calc(var(--tile) * 5); background-position: calc(var(--tile) * 6) calc(var(--tile) * 5);
} }
@ -165,6 +180,9 @@ html[dir="rtl"] .icon {
.icon-share { .icon-share {
background-position: 0px calc(var(--tile) * 5); background-position: 0px calc(var(--tile) * 5);
} }
.icon-split-line {
background-position: calc(var(--tile) * 5) var(--tile);
}
.icon-star { .icon-star {
background-position: var(--tile) calc(var(--tile) * 7); background-position: var(--tile) calc(var(--tile) * 7);
} }

View file

@ -270,6 +270,10 @@ class Feature {
if (!this.ui.isOnScreen(this._umap._leafletMap.getBounds())) this.zoomTo(event) if (!this.ui.isOnScreen(this._umap._leafletMap.getBounds())) this.zoomTo(event)
} }
toggleEditing() {
this.edit()
}
getAdvancedEditActions(container) { getAdvancedEditActions(container) {
const button = Utils.loadTemplate(` const button = Utils.loadTemplate(`
<button class="button" type="button"> <button class="button" type="button">
@ -508,8 +512,19 @@ class Feature {
}) })
} }
getInplaceToolbarActions() { getInplaceEditMenu() {
return [U.ToggleEditAction, U.DeleteFeatureAction] return [
{
action: () => this.toggleEditing(),
title: translate('Toggle edit mode (⇧+Click)'),
icon: 'icon-edit',
},
{
action: () => this.confirmDelete(),
title: translate('Delete this feature'),
icon: 'icon-delete',
},
]
} }
isFiltered() { isFiltered() {
@ -785,17 +800,15 @@ class Path extends Feature {
} }
} }
_toggleEditing(event) { toggleEditing() {
if (this._umap.editEnabled) { if (this._umap.editEnabled) {
if (this.ui.editEnabled()) { if (this.ui.editEnabled()) {
this.endEdit() this.endEdit()
this._umap.editPanel.close() this._umap.editPanel.close()
} else { } else {
this.edit(event) this.edit()
} }
} }
// FIXME: disable when disabling global edit
L.DomEvent.stop(event)
} }
getShapeOptions() { getShapeOptions() {
@ -846,15 +859,33 @@ class Path extends Feature {
return other return other
} }
getInplaceToolbarActions(event) { getInplaceEditMenu(event) {
const items = super.getInplaceToolbarActions(event) const items = super.getInplaceEditMenu()
if (this.isMulti()) { if (this.isMulti()) {
items.push(U.DeleteShapeAction) items.push({
items.push(U.ExtractShapeFromMultiAction) action: () => this.ui.enableEdit().deleteShapeAt(event.latlng),
title: translate('Delete this shape'),
icon: 'icon-delete-shape',
})
items.push({
action: () => this.ui.isolateShape(event.latlng),
title: translate('Extract shape to separate feature'),
icon: 'icon-extract-shape',
})
} }
return items return items
} }
getInplaceEditVertexMenu(event) {
return [
{
action: () => event.vertex.delete(),
title: translate('Delete this vertex (Alt+Click)'),
icon: 'icon-delete-vertex',
},
]
}
zoomTo({ easing, callback }) { zoomTo({ easing, callback }) {
// Use bounds instead of centroid for paths. // Use bounds instead of centroid for paths.
easing = easing || this._umap.getProperty('easing') easing = easing || this._umap.getProperty('easing')
@ -1077,6 +1108,25 @@ export class LineString extends Path {
const [gain, loss] = this.ui.getElevation() const [gain, loss] = this.ui.getElevation()
return Object.assign({ gain, loss }, super.extendedProperties()) return Object.assign({ gain, loss }, super.extendedProperties())
} }
getInplaceEditVertexMenu(event) {
const items = super.getInplaceEditVertexMenu(event)
const index = event.vertex.getIndex()
if (index === 0 || index === event.vertex.getLastIndex()) {
items.push({
action: () => event.vertex.continue(),
title: translate('Continue line'),
icon: 'icon-continue-line',
})
} else {
items.push({
action: () => event.vertex.split(),
title: translate('Split line'),
icon: 'icon-split-line',
})
}
return items
}
} }
export class Polygon extends Path { export class Polygon extends Path {
@ -1182,9 +1232,13 @@ export class Polygon extends Path {
) )
} }
getInplaceToolbarActions(event) { getInplaceEditMenu(event) {
const items = super.getInplaceToolbarActions(event) const items = super.getInplaceEditMenu()
items.push(U.CreateHoleAction) items.push({
action: () => this.ui.startHole(event),
title: translate('Start a hole here'),
icon: 'icon-hole',
})
return items return items
} }

View file

@ -250,7 +250,6 @@ export const LeafletMap = BaseMap.extend({
DomEvent.on(document.body, 'dataload', (event) => DomEvent.on(document.body, 'dataload', (event) =>
this.fire('dataload', event.detail) this.fire('dataload', event.detail)
) )
this.on('click', this.closeInplaceToolbar)
} }
this.on('baselayerchange', (e) => { this.on('baselayerchange', (e) => {
@ -284,11 +283,6 @@ export const LeafletMap = BaseMap.extend({
this.handleLimitBounds() this.handleLimitBounds()
}, },
closeInplaceToolbar: function () {
const toolbar = this._toolbars[L.Toolbar.Popup._toolbar_class_id]
if (toolbar) toolbar.remove()
},
latLng: (a, b, c) => { latLng: (a, b, c) => {
// manage geojson case and call original method // manage geojson case and call original method
if (!(a instanceof L.LatLng) && a.coordinates) { if (!(a instanceof L.LatLng) && a.coordinates) {

View file

@ -64,11 +64,10 @@ const FeatureMixin = {
else this.feature.edit(event) else this.feature.edit(event)
} }
} else if (!this._map.editTools?.drawing()) { } else if (!this._map.editTools?.drawing()) {
new L.Toolbar.Popup(event.latlng, { this._map._umap.editContextmenu.open(
className: 'leaflet-inplace-toolbar', event.originalEvent,
anchor: this.getPopupToolbarAnchor(), this.feature.getInplaceEditMenu(event)
actions: this.feature.getInplaceToolbarActions(event), )
}).addTo(this._map, this.feature, event.latlng)
} }
} }
DomEvent.stop(event) DomEvent.stop(event)
@ -105,8 +104,6 @@ const FeatureMixin = {
this.feature.pullGeometry(false) this.feature.pullGeometry(false)
this.feature.onCommit() this.feature.onCommit()
}, },
getPopupToolbarAnchor: () => [0, 0],
} }
const PointMixin = { const PointMixin = {
@ -248,10 +245,6 @@ export const LeafletMarker = Marker.extend({
this._redraw() this._redraw()
this._resetZIndex() this._resetZIndex()
}, },
getPopupToolbarAnchor: function () {
return this.options.icon.options.popupAnchor
},
}) })
const PathMixin = { const PathMixin = {
@ -341,13 +334,11 @@ const PathMixin = {
this.resetTooltip() this.resetTooltip()
}, },
getVertexActions: () => [U.DeleteVertexAction],
onVertexRawClick: function (event) { onVertexRawClick: function (event) {
new L.Toolbar.Popup(event.latlng, { this._map._umap.editContextmenu.open(
className: 'leaflet-inplace-toolbar', event.originalEvent,
actions: this.getVertexActions(event), this.feature.getInplaceEditVertexMenu(event)
}).addTo(this._map, this, event.latlng, event.vertex) )
}, },
isolateShape: function (atLatLng) { isolateShape: function (atLatLng) {
@ -383,17 +374,6 @@ export const LeafletPolyline = Polyline.extend({
getClass: () => LeafletPolyline, getClass: () => LeafletPolyline,
getVertexActions: function (event) {
const actions = PathMixin.getVertexActions.call(this, event)
const index = event.vertex.getIndex()
if (index === 0 || index === event.vertex.getLastIndex()) {
actions.push(U.ContinueLineAction)
} else {
actions.push(U.SplitLineAction)
}
return actions
},
getMeasure: function (shape) { getMeasure: function (shape) {
let shapes let shapes
if (shape) { if (shape) {

View file

@ -10,6 +10,9 @@ export default class ContextMenu extends Positioned {
if (options.className) { if (options.className) {
this.container.classList.add(options.className) this.container.classList.add(options.className)
} }
if (options.orientation === 'rows') {
this.container.classList.add('umap-contextmenu-rows')
}
this.container.addEventListener('focusout', (event) => { this.container.addEventListener('focusout', (event) => {
if (!this.container.contains(event.relatedTarget)) this.close() if (!this.container.contains(event.relatedTarget)) this.close()
}) })
@ -37,10 +40,14 @@ export default class ContextMenu extends Positioned {
) )
this.container.appendChild(li) this.container.appendChild(li)
} else { } else {
let content = item.label || ''
if (item.icon) {
content = `<i class="icon icon-16 ${item.icon}"></i>${content}`
}
const li = loadTemplate( const li = loadTemplate(
`<li class="${item.className || ''}"><button tabindex="0" class="flat">${item.label}</button></li>` `<li class="${item.className || ''}"><button tabindex="0" class="flat" title="${item.title || ''}">${content}</button></li>`
) )
li.addEventListener('click', () => { li.firstChild.addEventListener('click', () => {
this.close() this.close()
item.action() item.action()
}) })

View file

@ -120,6 +120,7 @@ export default class Umap extends ServerStored {
) )
this.tooltip = new Tooltip(this._leafletMap._controlContainer) this.tooltip = new Tooltip(this._leafletMap._controlContainer)
this.contextmenu = new ContextMenu() this.contextmenu = new ContextMenu()
this.editContextmenu = new ContextMenu({ className: 'dark', orientation: 'rows' })
this.server = new ServerRequest() this.server = new ServerRequest()
this.request = new Request() this.request = new Request()
this.facets = new Facets(this) this.facets = new Facets(this)
@ -1300,7 +1301,6 @@ export default class Umap extends ServerStored {
this.editPanel.close() this.editPanel.close()
this.fullPanel.close() this.fullPanel.close()
this.sync.stop() this.sync.stop()
this._leafletMap.closeInplaceToolbar()
} }
fire(name) { fire(name) {

View file

@ -1,186 +1,3 @@
U.BaseFeatureAction = L.ToolbarAction.extend({
initialize: function (map, feature, latlng) {
this.map = map
this.feature = feature
this.latlng = latlng
L.ToolbarAction.prototype.initialize.call(this)
this.postInit()
},
postInit: () => {},
hideToolbar: function () {
this.map.removeLayer(this.toolbar)
},
addHooks: function () {
this.onClick({ latlng: this.latlng })
this.hideToolbar()
},
})
U.CreateHoleAction = U.BaseFeatureAction.extend({
options: {
toolbarIcon: {
className: 'umap-new-hole',
tooltip: L._('Start a hole here'),
},
},
onClick: function (event) {
this.feature.ui.startHole(event)
},
})
U.ToggleEditAction = U.BaseFeatureAction.extend({
options: {
toolbarIcon: {
className: 'umap-toggle-edit',
tooltip: L._('Toggle edit mode (⇧+Click)'),
},
},
onClick: function (event) {
if (this.feature._toggleEditing) {
this.feature._toggleEditing(event) // Path
} else {
this.feature.edit(event) // Marker
}
},
})
U.DeleteFeatureAction = U.BaseFeatureAction.extend({
options: {
toolbarIcon: {
className: 'umap-delete-all',
tooltip: L._('Delete this feature'),
},
},
postInit: function () {
if (!this.feature.isMulti())
this.options.toolbarIcon.className = 'umap-delete-one-of-one'
},
onClick: function (e) {
this.feature.confirmDelete(e)
},
})
U.DeleteShapeAction = U.BaseFeatureAction.extend({
options: {
toolbarIcon: {
className: 'umap-delete-one-of-multi',
tooltip: L._('Delete this shape'),
},
},
onClick: function (e) {
this.feature.ui.enableEdit().deleteShapeAt(e.latlng)
},
})
U.ExtractShapeFromMultiAction = U.BaseFeatureAction.extend({
options: {
toolbarIcon: {
className: 'umap-extract-shape-from-multi',
tooltip: L._('Extract shape to separate feature'),
},
},
onClick: function (e) {
this.feature.ui.isolateShape(e.latlng)
},
})
U.BaseVertexAction = U.BaseFeatureAction.extend({
initialize: function (map, feature, latlng, vertex) {
this.vertex = vertex
U.BaseFeatureAction.prototype.initialize.call(this, map, feature, latlng)
},
})
U.DeleteVertexAction = U.BaseVertexAction.extend({
options: {
toolbarIcon: {
className: 'umap-delete-vertex',
tooltip: L._('Delete this vertex (Alt+Click)'),
},
},
onClick: function () {
this.vertex.delete()
},
})
U.SplitLineAction = U.BaseVertexAction.extend({
options: {
toolbarIcon: {
className: 'umap-split-line',
tooltip: L._('Split line'),
},
},
onClick: function () {
this.vertex.split()
},
})
U.ContinueLineAction = U.BaseVertexAction.extend({
options: {
toolbarIcon: {
className: 'umap-continue-line',
tooltip: L._('Continue line'),
},
},
onClick: function () {
this.vertex.continue()
},
})
// Leaflet.Toolbar doesn't allow twice same toolbar class…
U.SettingsToolbar = L.Toolbar.Control.extend({})
U.DrawToolbar = L.Toolbar.Control.extend({
initialize: function (options) {
L.Toolbar.Control.prototype.initialize.call(this, options)
this.map = this.options.map
this.map.on('seteditedfeature', this.redraw, this)
},
appendToContainer: function (container) {
this.options.actions = []
if (this.map._umap.properties.enableMarkerDraw) {
this.options.actions.push(U.DrawMarkerAction)
}
if (this.map._umap.properties.enablePolylineDraw) {
this.options.actions.push(U.DrawPolylineAction)
if (
this.map._umap.editedFeature &&
this.map._umap.editedFeature instanceof U.LineString
) {
this.options.actions.push(U.AddPolylineShapeAction)
}
}
if (this.map._umap.properties.enablePolygonDraw) {
this.options.actions.push(U.DrawPolygonAction)
if (
this.map._umap.editedFeature &&
this.map._umap.editedFeature instanceof U.Polygon
) {
this.options.actions.push(U.AddPolygonShapeAction)
}
}
L.Toolbar.Control.prototype.appendToContainer.call(this, container)
},
redraw: function () {
const container = this._control.getContainer()
container.innerHTML = ''
this.appendToContainer(container)
},
})
U.EditControl = L.Control.extend({ U.EditControl = L.Control.extend({
options: { options: {
position: 'topright', position: 'topright',

View file

@ -478,9 +478,6 @@ ul.photon-autocomplete {
.layer-edit { .layer-edit {
background-position: -50px -49px; background-position: -50px -49px;
} }
.umap-toggle-edit {
background-position: -44px -48px;
}
.readonly .layer-edit, .readonly .layer-edit,
.off .layer-edit { .off .layer-edit {
background-position: -50px -73px; background-position: -50px -73px;
@ -489,28 +486,6 @@ ul.photon-autocomplete {
.off .layer-delete { .off .layer-delete {
background-position: -122px -121px; background-position: -122px -121px;
} }
.umap-new-hole {
background-position: -71px -94px;
}
.umap-delete-one-of-multi {
background-position: -97px -70px;
}
.umap-delete-all,
.umap-delete-one-of-one {
background-position: -119px -48px;
}
.umap-delete-vertex {
background-position: -119px -94px;
}
.umap-continue-line {
background-position: -96px 1px;
}
.umap-split-line {
background-position: -119px -22px;
}
.umap-extract-shape-from-multi{
background-position: -119px 2px;
}
.umap-browser .feature-title { .umap-browser .feature-title {
width: inherit; width: inherit;
cursor: inherit; cursor: inherit;

View file

@ -1 +0,0 @@
.leaflet-toolbar-0{list-style:none;padding-left:0;box-shadow:0 1px 5px rgba(0,0,0,.65)}.leaflet-toolbar-0>li{position:relative}.leaflet-toolbar-0>li>.leaflet-toolbar-icon{display:block;width:26px;height:26px;line-height:26px;margin-right:0;padding-right:0;border-right:0;text-align:center;text-decoration:none;background-color:#fff}.leaflet-toolbar-0>li>.leaflet-toolbar-icon:hover{background-color:#f4f4f4}.leaflet-toolbar-0 .leaflet-toolbar-1{display:none;list-style:none}.leaflet-toolbar-tip-container{margin:0 auto;height:12px;position:relative;overflow:hidden}.leaflet-toolbar-tip{width:12px;height:12px;margin:-6px auto 0;background-color:#fff;box-shadow:0 1px 5px rgba(0,0,0,.65);-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);transform:rotate(45deg)}.leaflet-control-toolbar>li>.leaflet-toolbar-icon{border-bottom:1px solid #ccc}.leaflet-control-toolbar>li:first-child>.leaflet-toolbar-icon{border-top-left-radius:4px;border-top-right-radius:4px}.leaflet-control-toolbar>li:last-child>.leaflet-toolbar-icon{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom-width:0}.leaflet-control-toolbar .leaflet-toolbar-1{margin:0;padding:0;position:absolute;left:26px;top:0;white-space:nowrap;height:26px}.leaflet-control-toolbar .leaflet-toolbar-1>li{display:inline-block}.leaflet-control-toolbar .leaflet-toolbar-1>li>.leaflet-toolbar-icon{display:block;background-color:#919187;border-left:1px solid #aaa;color:#fff;font:11px/19px "Helvetica Neue",Arial,Helvetica,sans-serif;line-height:26px;text-decoration:none;padding-left:10px;padding-right:10px;height:26px}.leaflet-control-toolbar .leaflet-toolbar-1>li>.leaflet-toolbar-icon:hover{background-color:#a0a098}.leaflet-popup-toolbar{position:relative}.leaflet-popup-toolbar>li{float:left}.leaflet-popup-toolbar>li:first-child>.leaflet-toolbar-icon{border-top-left-radius:4px;border-bottom-left-radius:4px}.leaflet-popup-toolbar>li:last-child>.leaflet-toolbar-icon{border-top-right-radius:4px;border-bottom-right-radius:4px;border-bottom-width:0}.leaflet-popup-toolbar .leaflet-toolbar-1{position:absolute;top:26px;left:0;padding-left:0}.leaflet-popup-toolbar .leaflet-toolbar-1>li>.leaflet-toolbar-icon{position:relative;float:left;width:26px;height:26px}

File diff suppressed because one or more lines are too long

View file

@ -12,8 +12,6 @@
href="{% static 'umap/vendors/editinosm/Leaflet.EditInOSM.css' %}" /> href="{% static 'umap/vendors/editinosm/Leaflet.EditInOSM.css' %}" />
<link rel="stylesheet" <link rel="stylesheet"
href="{% static 'umap/vendors/minimap/Control.MiniMap.min.css' %}" /> href="{% static 'umap/vendors/minimap/Control.MiniMap.min.css' %}" />
<link rel="stylesheet"
href="{% static 'umap/vendors/toolbar/leaflet.toolbar.css' %}" />
<link rel="stylesheet" <link rel="stylesheet"
href="{% static 'umap/vendors/measurable/Leaflet.Measurable.css' %}" /> href="{% static 'umap/vendors/measurable/Leaflet.Measurable.css' %}" />
<link rel="stylesheet" <link rel="stylesheet"

View file

@ -29,7 +29,6 @@
<script src="{% static 'umap/vendors/photon/leaflet.photon.js' %}" defer></script> <script src="{% static 'umap/vendors/photon/leaflet.photon.js' %}" defer></script>
<script src="{% static 'umap/vendors/fullscreen/Leaflet.fullscreen.min.js' %}" <script src="{% static 'umap/vendors/fullscreen/Leaflet.fullscreen.min.js' %}"
defer></script> defer></script>
<script src="{% static 'umap/vendors/toolbar/leaflet.toolbar.js' %}" defer></script>
<script src="{% static 'umap/vendors/measurable/Leaflet.Measurable.js' %}" <script src="{% static 'umap/vendors/measurable/Leaflet.Measurable.js' %}"
defer></script> defer></script>
<script src="{% static 'umap/vendors/iconlayers/iconLayers.js' %}" defer></script> <script src="{% static 'umap/vendors/iconlayers/iconLayers.js' %}" defer></script>

View file

@ -10,7 +10,7 @@ def test_draw_polygon(page, live_server, tilelayer):
page.goto(f"{live_server.url}/en/map/new/") page.goto(f"{live_server.url}/en/map/new/")
# Click on the Draw a polygon button on a new map. # Click on the Draw a polygon button on a new map.
create_path = page.locator(".umap-edit-bar ").get_by_title("Draw a polygon") create_path = page.locator(".umap-edit-bar").get_by_title("Draw a polygon")
create_path.click() create_path.click()
# Check no polygon is present by default. # Check no polygon is present by default.
@ -180,7 +180,7 @@ def test_can_draw_hole(page, live_server, tilelayer):
# First vertex of the hole will be created here # First vertex of the hole will be created here
map.click(position={"x": 180, "y": 120}) map.click(position={"x": 180, "y": 120})
page.get_by_role("link", name="Start a hole here").click() page.get_by_role("button", name="Start a hole here").click()
map.click(position={"x": 180, "y": 180}) map.click(position={"x": 180, "y": 180})
map.click(position={"x": 120, "y": 180}) map.click(position={"x": 120, "y": 180})
map.click(position={"x": 120, "y": 120}) map.click(position={"x": 120, "y": 120})
@ -475,7 +475,7 @@ def test_vertexmarker_not_shown_if_too_many(live_server, map, page, settings):
page.locator('select[name="format"]').select_option("geojson") page.locator('select[name="format"]').select_option("geojson")
page.get_by_role("button", name="Import data", exact=True).click() page.get_by_role("button", name="Import data", exact=True).click()
page.locator("path").click() page.locator("path").click()
page.get_by_role("link", name="Toggle edit mode (⇧+Click)").click() page.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
expect(page.locator(".umap-tooltip-container")).to_contain_text( expect(page.locator(".umap-tooltip-container")).to_contain_text(
"Please zoom in to edit the geometry" "Please zoom in to edit the geometry"
) )

View file

@ -329,11 +329,11 @@ def test_can_delete_shape_using_toolbar(live_server, page, tilelayer, settings):
# Now split the line # Now split the line
map.click(position={"x": 100, "y": 100}) map.click(position={"x": 100, "y": 100})
page.get_by_role("link", name="Split line").click() page.get_by_role("button", name="Split line").click()
# Delete part of it # Delete part of it
map.click(position={"x": 125, "y": 100}) map.click(position={"x": 125, "y": 100})
page.get_by_role("link", name="Delete this shape").click() page.get_by_role("button", name="Delete this shape").click()
data = save_and_get_json(page) data = save_and_get_json(page)
assert len(data["features"]) == 1 assert len(data["features"]) == 1
assert data["features"][0]["geometry"]["type"] == "LineString" assert data["features"][0]["geometry"]["type"] == "LineString"

View file

@ -78,8 +78,8 @@ def test_marker_style_should_have_precedence(live_server, openmap, page, bootstr
def test_should_open_an_edit_toolbar_on_click(live_server, openmap, page, bootstrap): def test_should_open_an_edit_toolbar_on_click(live_server, openmap, page, bootstrap):
page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit") page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
page.locator(".leaflet-marker-icon").click() page.locator(".leaflet-marker-icon").click()
expect(page.get_by_role("link", name="Toggle edit mode")).to_be_visible() expect(page.get_by_role("button", name="Toggle edit mode")).to_be_visible()
expect(page.get_by_role("link", name="Delete this feature")).to_be_visible() expect(page.get_by_role("button", name="Delete this feature")).to_be_visible()
def test_should_update_open_popup_on_edit(live_server, openmap, page, bootstrap): def test_should_update_open_popup_on_edit(live_server, openmap, page, bootstrap):
@ -115,6 +115,6 @@ def test_should_follow_datalayer_style_when_changing_datalayer(
expect(marker).to_have_css("background-color", "rgb(0, 139, 139)") expect(marker).to_have_css("background-color", "rgb(0, 139, 139)")
# Change datalayer # Change datalayer
marker.click() marker.click()
page.get_by_role("link", name="Toggle edit mode (⇧+Click)").click() page.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
page.locator(".umap-field-datalayer select").select_option(label="other datalayer") page.locator(".umap-field-datalayer select").select_option(label="other datalayer")
expect(marker).to_have_css("background-color", "rgb(148, 0, 211)") expect(marker).to_have_css("background-color", "rgb(148, 0, 211)")

View file

@ -88,8 +88,8 @@ def test_marker_style_should_have_precedence(live_server, openmap, page, bootstr
def test_should_open_an_edit_toolbar_on_click(live_server, openmap, page, bootstrap): def test_should_open_an_edit_toolbar_on_click(live_server, openmap, page, bootstrap):
page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit") page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
page.locator("path").click() page.locator("path").click()
expect(page.get_by_role("link", name="Toggle edit mode")).to_be_visible() expect(page.get_by_role("button", name="Toggle edit mode")).to_be_visible()
expect(page.get_by_role("link", name="Delete this feature")).to_be_visible() expect(page.get_by_role("button", name="Delete this feature")).to_be_visible()
def test_can_remove_stroke(live_server, openmap, page, bootstrap): def test_can_remove_stroke(live_server, openmap, page, bootstrap):
@ -98,7 +98,7 @@ def test_can_remove_stroke(live_server, openmap, page, bootstrap):
1 1
) )
page.locator("path").click() page.locator("path").click()
page.get_by_role("link", name="Toggle edit mode").click() page.get_by_role("button", name="Toggle edit mode").click()
page.get_by_text("Shape properties").click() page.get_by_text("Shape properties").click()
page.locator(".umap-field-stroke .define").first.click() page.locator(".umap-field-stroke .define").first.click()
page.locator(".umap-field-stroke .show-on-defined label").first.click() page.locator(".umap-field-stroke .show-on-defined label").first.click()

View file

@ -59,7 +59,7 @@ def test_websocket_connection_can_sync_markers(new_page, asgi_live_server, tilel
peerA.wait_for_timeout(300) peerA.wait_for_timeout(300)
peerB.locator(".leaflet-marker-icon").first.click() peerB.locator(".leaflet-marker-icon").first.click()
peerB.get_by_role("link", name="Toggle edit mode (⇧+Click)").click() peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
expect(peerB.locator('input[name="name"]')).to_have_value("Synced name") expect(peerB.locator('input[name="name"]')).to_have_value("Synced name")
a_first_marker = peerA.locator("div:nth-child(4) > div:nth-child(2)").first a_first_marker = peerA.locator("div:nth-child(4) > div:nth-child(2)").first
@ -139,7 +139,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
assert b_polygon_bbox_t1 == a_polygon_bbox_t1 assert b_polygon_bbox_t1 == a_polygon_bbox_t1
b_polygon.click() b_polygon.click()
peerB.get_by_role("link", name="Toggle edit mode (⇧+Click)").click() peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
edited_vertex = peerB.locator("div:nth-child(6)").first edited_vertex = peerB.locator("div:nth-child(6)").first
edited_vertex.drag_to(b_map_el, target_position={"x": 233, "y": 126}) edited_vertex.drag_to(b_map_el, target_position={"x": 233, "y": 126})
@ -153,7 +153,7 @@ def test_websocket_connection_can_sync_polygons(context, asgi_live_server, tilel
# Move the polygon on peer B and check it moved also on peer A # Move the polygon on peer B and check it moved also on peer A
b_polygon.click() b_polygon.click()
peerB.get_by_role("link", name="Toggle edit mode (⇧+Click)").click() peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
b_polygon.drag_to(b_map_el, target_position={"x": 400, "y": 400}) b_polygon.drag_to(b_map_el, target_position={"x": 400, "y": 400})
peerB.keyboard.press("Escape") peerB.keyboard.press("Escape")
@ -343,7 +343,7 @@ def test_websocket_connection_can_sync_late_joining_peer(
# Verify marker properties # Verify marker properties
peerB.locator(".leaflet-marker-icon").first.click() peerB.locator(".leaflet-marker-icon").first.click()
peerB.get_by_role("link", name="Toggle edit mode (⇧+Click)").click() peerB.get_by_role("button", name="Toggle edit mode (⇧+Click)").click()
expect(peerB.locator('input[name="name"]')).to_have_value("First marker") expect(peerB.locator('input[name="name"]')).to_have_value("First marker")
# Verify polygon exists (we've already checked the count) # Verify polygon exists (we've already checked the count)