mirror of
https://github.com/umap-project/umap.git
synced 2025-04-28 19:42:36 +02:00
chore: use our contexmenu class for inplace toolbar (#2510)
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:  After:  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:
commit
fcac4df30b
19 changed files with 132 additions and 281 deletions
|
@ -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/
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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()
|
||||||
})
|
})
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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"
|
||||||
)
|
)
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)")
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue