umap-project 2.5.1__py3-none-any.whl → 2.6.0b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of umap-project might be problematic. Click here for more details.

Files changed (193) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +6 -1
  3. umap/context_processors.py +2 -1
  4. umap/decorators.py +13 -2
  5. umap/forms.py +26 -2
  6. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/br/LC_MESSAGES/django.po +252 -146
  8. umap/locale/ca/LC_MESSAGES/django.mo +0 -0
  9. umap/locale/ca/LC_MESSAGES/django.po +274 -162
  10. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/cs_CZ/LC_MESSAGES/django.po +261 -150
  12. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/de/LC_MESSAGES/django.po +299 -187
  14. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/el/LC_MESSAGES/django.po +215 -159
  16. umap/locale/en/LC_MESSAGES/django.po +211 -155
  17. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  18. umap/locale/es/LC_MESSAGES/django.po +255 -144
  19. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  20. umap/locale/eu/LC_MESSAGES/django.po +254 -198
  21. umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
  22. umap/locale/fa_IR/LC_MESSAGES/django.po +346 -234
  23. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  24. umap/locale/fr/LC_MESSAGES/django.po +216 -160
  25. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  26. umap/locale/hu/LC_MESSAGES/django.po +215 -159
  27. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  28. umap/locale/it/LC_MESSAGES/django.po +252 -146
  29. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  30. umap/locale/ms/LC_MESSAGES/django.po +252 -146
  31. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  32. umap/locale/pl/LC_MESSAGES/django.po +254 -148
  33. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  34. umap/locale/pt/LC_MESSAGES/django.po +215 -159
  35. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  36. umap/locale/sv/LC_MESSAGES/django.po +254 -143
  37. umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
  38. umap/locale/th_TH/LC_MESSAGES/django.po +125 -70
  39. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  40. umap/locale/zh_TW/LC_MESSAGES/django.po +256 -145
  41. umap/migrations/0022_add_team.py +94 -0
  42. umap/models.py +45 -10
  43. umap/settings/__init__.py +2 -0
  44. umap/settings/base.py +3 -2
  45. umap/static/umap/base.css +32 -41
  46. umap/static/umap/content.css +19 -25
  47. umap/static/umap/css/icon.css +63 -37
  48. umap/static/umap/css/importers.css +1 -1
  49. umap/static/umap/css/slideshow.css +7 -5
  50. umap/static/umap/css/tableeditor.css +4 -3
  51. umap/static/umap/img/16-white.svg +1 -4
  52. umap/static/umap/img/16.svg +2 -6
  53. umap/static/umap/img/24-white.svg +4 -4
  54. umap/static/umap/img/24.svg +6 -6
  55. umap/static/umap/img/source/16-white.svg +2 -5
  56. umap/static/umap/img/source/16.svg +3 -7
  57. umap/static/umap/img/source/24-white.svg +7 -14
  58. umap/static/umap/img/source/24.svg +10 -17
  59. umap/static/umap/js/components/alerts/alert.css +20 -8
  60. umap/static/umap/js/modules/autocomplete.js +3 -3
  61. umap/static/umap/js/modules/browser.js +4 -3
  62. umap/static/umap/js/modules/caption.js +9 -11
  63. umap/static/umap/js/modules/data/features.js +994 -0
  64. umap/static/umap/js/modules/data/layer.js +1210 -0
  65. umap/static/umap/js/modules/formatter.js +12 -3
  66. umap/static/umap/js/modules/global.js +21 -5
  67. umap/static/umap/js/modules/permissions.js +280 -0
  68. umap/static/umap/js/{umap.icon.js → modules/rendering/icon.js} +77 -56
  69. umap/static/umap/js/modules/rendering/layers/base.js +105 -0
  70. umap/static/umap/js/modules/rendering/layers/classified.js +484 -0
  71. umap/static/umap/js/modules/rendering/layers/cluster.js +103 -0
  72. umap/static/umap/js/modules/rendering/layers/heat.js +182 -0
  73. umap/static/umap/js/modules/rendering/popup.js +99 -0
  74. umap/static/umap/js/modules/rendering/template.js +217 -0
  75. umap/static/umap/js/modules/rendering/ui.js +573 -0
  76. umap/static/umap/js/modules/schema.js +24 -0
  77. umap/static/umap/js/modules/share.js +66 -45
  78. umap/static/umap/js/modules/sync/updaters.js +9 -10
  79. umap/static/umap/js/modules/tableeditor.js +7 -7
  80. umap/static/umap/js/modules/ui/dialog.js +8 -4
  81. umap/static/umap/js/modules/utils.js +22 -13
  82. umap/static/umap/js/umap.controls.js +79 -146
  83. umap/static/umap/js/umap.core.js +9 -9
  84. umap/static/umap/js/umap.forms.js +32 -12
  85. umap/static/umap/js/umap.js +65 -63
  86. umap/static/umap/locale/br.js +35 -35
  87. umap/static/umap/locale/br.json +35 -35
  88. umap/static/umap/locale/ca.js +50 -50
  89. umap/static/umap/locale/ca.json +50 -50
  90. umap/static/umap/locale/de.js +136 -136
  91. umap/static/umap/locale/de.json +136 -136
  92. umap/static/umap/locale/el.js +47 -47
  93. umap/static/umap/locale/el.json +47 -47
  94. umap/static/umap/locale/en.js +7 -1
  95. umap/static/umap/locale/en.json +7 -1
  96. umap/static/umap/locale/fa_IR.js +44 -44
  97. umap/static/umap/locale/fa_IR.json +44 -44
  98. umap/static/umap/locale/fr.js +8 -2
  99. umap/static/umap/locale/fr.json +8 -2
  100. umap/static/umap/locale/pt.js +17 -17
  101. umap/static/umap/locale/pt.json +17 -17
  102. umap/static/umap/locale/pt_PT.js +207 -207
  103. umap/static/umap/locale/pt_PT.json +207 -207
  104. umap/static/umap/locale/th_TH.js +25 -25
  105. umap/static/umap/locale/th_TH.json +25 -25
  106. umap/static/umap/map.css +107 -104
  107. umap/static/umap/nav.css +19 -10
  108. umap/static/umap/unittests/utils.js +230 -107
  109. umap/static/umap/vendors/csv2geojson/csv2geojson.js +62 -40
  110. umap/static/umap/vendors/markercluster/MarkerCluster.Default.css +1 -1
  111. umap/storage.py +1 -0
  112. umap/templates/404.html +5 -1
  113. umap/templates/500.html +3 -1
  114. umap/templates/auth/user_detail.html +8 -2
  115. umap/templates/auth/user_form.html +19 -10
  116. umap/templates/auth/user_stars.html +8 -2
  117. umap/templates/base.html +1 -0
  118. umap/templates/registration/login.html +18 -3
  119. umap/templates/umap/about.html +1 -0
  120. umap/templates/umap/about_summary.html +22 -7
  121. umap/templates/umap/components/alerts/alert.html +42 -21
  122. umap/templates/umap/content.html +2 -0
  123. umap/templates/umap/content_footer.html +6 -2
  124. umap/templates/umap/css.html +1 -0
  125. umap/templates/umap/dashboard_menu.html +15 -0
  126. umap/templates/umap/home.html +14 -4
  127. umap/templates/umap/js.html +4 -9
  128. umap/templates/umap/login_popup_end.html +10 -4
  129. umap/templates/umap/map_detail.html +8 -2
  130. umap/templates/umap/map_fragment.html +3 -1
  131. umap/templates/umap/map_init.html +2 -1
  132. umap/templates/umap/map_list.html +4 -3
  133. umap/templates/umap/map_table.html +36 -12
  134. umap/templates/umap/messages.html +0 -1
  135. umap/templates/umap/navigation.html +2 -1
  136. umap/templates/umap/password_change.html +5 -1
  137. umap/templates/umap/password_change_done.html +8 -2
  138. umap/templates/umap/search.html +8 -2
  139. umap/templates/umap/search_bar.html +1 -0
  140. umap/templates/umap/team_confirm_delete.html +19 -0
  141. umap/templates/umap/team_detail.html +27 -0
  142. umap/templates/umap/team_form.html +60 -0
  143. umap/templates/umap/user_dashboard.html +7 -9
  144. umap/templates/umap/user_teams.html +51 -0
  145. umap/tests/base.py +8 -1
  146. umap/tests/conftest.py +6 -0
  147. umap/tests/fixtures/test_circles_layer.geojson +219 -0
  148. umap/tests/fixtures/test_upload_georss.xml +20 -0
  149. umap/tests/integration/conftest.py +18 -4
  150. umap/tests/integration/helpers.py +12 -0
  151. umap/tests/integration/test_anonymous_owned_map.py +23 -0
  152. umap/tests/integration/test_basics.py +29 -0
  153. umap/tests/integration/test_caption.py +20 -0
  154. umap/tests/integration/test_circles_layer.py +69 -0
  155. umap/tests/integration/test_draw_polygon.py +110 -13
  156. umap/tests/integration/test_draw_polyline.py +8 -18
  157. umap/tests/integration/test_edit_datalayer.py +1 -1
  158. umap/tests/integration/test_import.py +64 -5
  159. umap/tests/integration/test_owned_map.py +21 -13
  160. umap/tests/integration/test_team.py +47 -0
  161. umap/tests/integration/test_tilelayer.py +19 -2
  162. umap/tests/integration/test_view_marker.py +28 -1
  163. umap/tests/integration/test_websocket_sync.py +5 -5
  164. umap/tests/test_datalayer.py +32 -7
  165. umap/tests/test_datalayer_views.py +1 -1
  166. umap/tests/test_map.py +30 -4
  167. umap/tests/test_map_views.py +2 -2
  168. umap/tests/test_statics.py +40 -0
  169. umap/tests/test_team_views.py +131 -0
  170. umap/tests/test_views.py +15 -1
  171. umap/urls.py +23 -13
  172. umap/views.py +116 -10
  173. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/METADATA +9 -9
  174. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/RECORD +177 -170
  175. umap/static/umap/js/umap.datalayer.permissions.js +0 -70
  176. umap/static/umap/js/umap.features.js +0 -1290
  177. umap/static/umap/js/umap.layer.js +0 -1837
  178. umap/static/umap/js/umap.permissions.js +0 -208
  179. umap/static/umap/js/umap.popup.js +0 -341
  180. umap/static/umap/test/TableEditor.js +0 -104
  181. umap/static/umap/vendors/leaflet/leaflet-src.js +0 -14512
  182. umap/static/umap/vendors/leaflet/leaflet-src.js.map +0 -1
  183. umap/static/umap/vendors/leaflet/leaflet.js +0 -6
  184. umap/static/umap/vendors/leaflet/leaflet.js.map +0 -1
  185. umap/static/umap/vendors/markercluster/WhereAreTheJavascriptFiles.txt +0 -5
  186. umap/static/umap/vendors/markercluster/leaflet.markercluster-src.js +0 -2718
  187. umap/static/umap/vendors/markercluster/leaflet.markercluster-src.js.map +0 -1
  188. umap/static/umap/vendors/toolbar/leaflet.toolbar-src.css +0 -117
  189. umap/static/umap/vendors/toolbar/leaflet.toolbar-src.js +0 -365
  190. umap/tests/integration/test_statics.py +0 -47
  191. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/WHEEL +0 -0
  192. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/entry_points.txt +0 -0
  193. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,573 @@
1
+ // Goes here all code related to Leaflet, DOM and user interactions.
2
+ import {
3
+ Marker,
4
+ Polyline,
5
+ Polygon,
6
+ CircleMarker as BaseCircleMarker,
7
+ DomUtil,
8
+ LineUtil,
9
+ latLng,
10
+ LatLng,
11
+ LatLngBounds,
12
+ } from '../../../vendors/leaflet/leaflet-src.esm.js'
13
+ import { translate } from '../i18n.js'
14
+ import { uMapAlert as Alert } from '../../components/alerts/alert.js'
15
+ import * as Utils from '../utils.js'
16
+ import * as Icon from './icon.js'
17
+
18
+ const FeatureMixin = {
19
+ initialize: function (feature, latlngs) {
20
+ this.feature = feature
21
+ this.parentClass.prototype.initialize.call(this, latlngs)
22
+ },
23
+
24
+ onAdd: function (map) {
25
+ this.addInteractions()
26
+ return this.parentClass.prototype.onAdd.call(this, map)
27
+ },
28
+
29
+ onRemove: function (map) {
30
+ this.parentClass.prototype.onRemove.call(this, map)
31
+ if (map.editedFeature === this.feature) {
32
+ this.feature._marked_for_deletion = true
33
+ this.feature.endEdit()
34
+ map.editPanel.close()
35
+ }
36
+ },
37
+
38
+ addInteractions: function () {
39
+ this.on('contextmenu editable:vertex:contextmenu', this._showContextMenu)
40
+ this.on('click', this.onClick)
41
+ },
42
+
43
+ onClick: function (event) {
44
+ if (this._map.measureTools?.enabled()) return
45
+ this._popupHandlersAdded = true // Prevent leaflet from managing event
46
+ if (!this._map.editEnabled) {
47
+ this.feature.view(event)
48
+ } else if (!this.feature.isReadOnly()) {
49
+ if (event.originalEvent.shiftKey) {
50
+ if (event.originalEvent.ctrlKey || event.originalEvent.metaKey) {
51
+ this.feature.datalayer.edit(event)
52
+ } else {
53
+ if (this.feature._toggleEditing) this.feature._toggleEditing(event)
54
+ else this.feature.edit(event)
55
+ }
56
+ } else if (!this._map.editTools?.drawing()) {
57
+ new L.Toolbar.Popup(event.latlng, {
58
+ className: 'leaflet-inplace-toolbar',
59
+ anchor: this.getPopupToolbarAnchor(),
60
+ actions: this.feature.getInplaceToolbarActions(event),
61
+ }).addTo(this._map, this.feature, event.latlng)
62
+ }
63
+ }
64
+ L.DomEvent.stop(event)
65
+ },
66
+
67
+ resetTooltip: function () {
68
+ if (!this.feature.hasGeom()) return
69
+ const displayName = this.feature.getDisplayName(null)
70
+ let showLabel = this.feature.getOption('showLabel')
71
+ const oldLabelHover = this.feature.getOption('labelHover')
72
+
73
+ const options = {
74
+ direction: this.feature.getOption('labelDirection'),
75
+ interactive: this.feature.getOption('labelInteractive'),
76
+ }
77
+
78
+ if (oldLabelHover && showLabel) showLabel = null // Retrocompat.
79
+ options.permanent = showLabel === true
80
+ this.unbindTooltip()
81
+ if ((showLabel === true || showLabel === null) && displayName) {
82
+ this.bindTooltip(Utils.escapeHTML(displayName), options)
83
+ }
84
+ },
85
+
86
+ _showContextMenu: function (event) {
87
+ L.DomEvent.stop(event)
88
+ const pt = this._map.mouseEventToContainerPoint(event.originalEvent)
89
+ event.relatedTarget = this
90
+ this._map.contextmenu.showAt(pt, event)
91
+ },
92
+
93
+ getContextMenuItems: function (event) {
94
+ const permalink = this.feature.getPermalink()
95
+ let items = []
96
+ if (permalink)
97
+ items.push({
98
+ text: translate('Permalink'),
99
+ callback: () => {
100
+ window.open(permalink)
101
+ },
102
+ })
103
+ if (this._map.editEnabled && !this.feature.isReadOnly()) {
104
+ items = items.concat(this.getContextMenuEditItems(event))
105
+ }
106
+ return items
107
+ },
108
+
109
+ getContextMenuEditItems: function () {
110
+ let items = ['-']
111
+ if (this._map.editedFeature !== this) {
112
+ items.push({
113
+ text: `${translate('Edit this feature')} (⇧+Click)`,
114
+ callback: this.feature.edit,
115
+ context: this.feature,
116
+ iconCls: 'umap-edit',
117
+ })
118
+ }
119
+ items = items.concat(
120
+ {
121
+ text: this._map.help.displayLabel('EDIT_FEATURE_LAYER'),
122
+ callback: this.feature.datalayer.edit,
123
+ context: this.feature.datalayer,
124
+ iconCls: 'umap-edit',
125
+ },
126
+ {
127
+ text: translate('Delete this feature'),
128
+ callback: this.feature.confirmDelete,
129
+ context: this.feature,
130
+ iconCls: 'umap-delete',
131
+ },
132
+ {
133
+ text: translate('Clone this feature'),
134
+ callback: this.feature.clone,
135
+ context: this.feature,
136
+ }
137
+ )
138
+ return items
139
+ },
140
+
141
+ onCommit: function () {
142
+ this.feature.pullGeometry(false)
143
+ this.feature.onCommit()
144
+ },
145
+
146
+ getPopupToolbarAnchor: () => [0, 0],
147
+ }
148
+
149
+ export const LeafletMarker = Marker.extend({
150
+ parentClass: Marker,
151
+ includes: [FeatureMixin],
152
+
153
+ initialize: function (feature, latlng) {
154
+ FeatureMixin.initialize.call(this, feature, latlng)
155
+ this.setIcon(this.getIcon())
156
+ },
157
+
158
+ getClass: () => LeafletMarker,
159
+
160
+ // Make API consistent with path
161
+ getLatLngs: function () {
162
+ return this.getLatLng()
163
+ },
164
+
165
+ setLatLngs: function (latlng) {
166
+ return this.setLatLng(latlng)
167
+ },
168
+
169
+ addInteractions() {
170
+ FeatureMixin.addInteractions.call(this)
171
+ this.on('dragend', (event) => {
172
+ this.isDirty = true
173
+ this.feature.edit(event)
174
+ this.feature.pullGeometry()
175
+ })
176
+ this.on('editable:drawing:commit', this.onCommit)
177
+ if (!this.feature.isReadOnly()) this.on('mouseover', this._enableDragging)
178
+ this.on('mouseout', this._onMouseOut)
179
+ this._popupHandlersAdded = true // prevent Leaflet from binding event on bindPopup
180
+ this.on('popupopen', this.highlight)
181
+ this.on('popupclose', this.resetHighlight)
182
+ },
183
+
184
+ _onMouseOut: function () {
185
+ if (this.dragging?._draggable && !this.dragging._draggable._moving) {
186
+ // Do not disable if the mouse went out while dragging
187
+ this._disableDragging()
188
+ }
189
+ },
190
+
191
+ _enableDragging: function () {
192
+ // TODO: start dragging after 1 second on mouse down
193
+ if (this._map.editEnabled) {
194
+ if (!this.editEnabled()) this.enableEdit()
195
+ // Enabling dragging on the marker override the Draggable._OnDown
196
+ // event, which, as it stopPropagation, refrain the call of
197
+ // _onDown with map-pane element, which is responsible to
198
+ // set the _moved to false, and thus to enable the click.
199
+ // We should find a cleaner way to handle this.
200
+ this._map.dragging._draggable._moved = false
201
+ }
202
+ },
203
+
204
+ _disableDragging: function () {
205
+ if (this._map.editEnabled) {
206
+ if (this.editor?.drawing) return // when creating a new marker, the mouse can trigger the mouseover/mouseout event
207
+ // do not listen to them
208
+ this.disableEdit()
209
+ }
210
+ },
211
+
212
+ _initIcon: function () {
213
+ this.options.icon = this.getIcon()
214
+ Marker.prototype._initIcon.call(this)
215
+ // Allow to run code when icon is actually part of the DOM
216
+ this.options.icon.onAdd()
217
+ this.resetTooltip()
218
+ },
219
+
220
+ getIconClass: function () {
221
+ return this.feature.getOption('iconClass')
222
+ },
223
+
224
+ getIcon: function () {
225
+ const Class = Icon.getClass(this.getIconClass())
226
+ return new Class({ feature: this.feature })
227
+ },
228
+
229
+ _getTooltipAnchor: function () {
230
+ const anchor = this.options.icon.options.tooltipAnchor.clone()
231
+ const direction = this.feature.getOption('labelDirection')
232
+ if (direction === 'left') {
233
+ anchor.x *= -1
234
+ } else if (direction === 'bottom') {
235
+ anchor.x = 0
236
+ anchor.y = 0
237
+ } else if (direction === 'top') {
238
+ anchor.x = 0
239
+ }
240
+ return anchor
241
+ },
242
+
243
+ _redraw: function () {
244
+ // May no be on the map when in a cluster.
245
+ if (this._map) {
246
+ this._initIcon()
247
+ this.update()
248
+ }
249
+ },
250
+
251
+ getCenter: function () {
252
+ return this._latlng
253
+ },
254
+
255
+ highlight: function () {
256
+ DomUtil.addClass(this.options.icon.elements.main, 'umap-icon-active')
257
+ },
258
+
259
+ resetHighlight: function () {
260
+ DomUtil.removeClass(this.options.icon.elements.main, 'umap-icon-active')
261
+ },
262
+
263
+ getPopupToolbarAnchor: function () {
264
+ return this.options.icon.options.popupAnchor
265
+ },
266
+ })
267
+
268
+ const PathMixin = {
269
+ _onMouseOver: function () {
270
+ if (this._map.measureTools?.enabled()) {
271
+ this._map.tooltip.open({ content: this.getMeasure(), anchor: this })
272
+ } else if (this._map.editEnabled && !this._map.editedFeature) {
273
+ this._map.tooltip.open({ content: translate('Click to edit'), anchor: this })
274
+ }
275
+ },
276
+
277
+ addInteractions: function () {
278
+ FeatureMixin.addInteractions.call(this)
279
+ this.on('editable:disable', this.onCommit)
280
+ this.on('mouseover', this._onMouseOver)
281
+ this.on('drag editable:drag', this._onDrag)
282
+ this.on('popupopen', this.highlightPath)
283
+ this.on('popupclose', this._redraw)
284
+ },
285
+
286
+ highlightPath: function () {
287
+ this.parentClass.prototype.setStyle.call(this, {
288
+ fillOpacity: Math.sqrt(this.feature.getDynamicOption('fillOpacity', 1.0)),
289
+ opacity: 1.0,
290
+ weight: 1.3 * this.feature.getDynamicOption('weight'),
291
+ })
292
+ },
293
+
294
+ _onDrag: function () {
295
+ if (this._tooltip) this._tooltip.setLatLng(this.getCenter())
296
+ },
297
+
298
+ onAdd: function (map) {
299
+ this._container = null
300
+ FeatureMixin.onAdd.call(this, map)
301
+ this.setStyle()
302
+ if (this.editing?.enabled()) this.editing.addHooks()
303
+ this.resetTooltip()
304
+ this._path.dataset.feature = this.feature.id
305
+ },
306
+
307
+ onRemove: function (map) {
308
+ if (this.editing?.enabled()) this.editing.removeHooks()
309
+ FeatureMixin.onRemove.call(this, map)
310
+ },
311
+
312
+ setStyle: function (options = {}) {
313
+ for (const option of this.getStyleOptions()) {
314
+ options[option] = this.feature.getDynamicOption(option)
315
+ }
316
+ options.pointerEvents = options.interactive ? 'visiblePainted' : 'stroke'
317
+ this.parentClass.prototype.setStyle.call(this, options)
318
+ },
319
+
320
+ _redraw: function () {
321
+ this.setStyle()
322
+ this.resetTooltip()
323
+ },
324
+
325
+ getVertexActions: () => [U.DeleteVertexAction],
326
+
327
+ onVertexRawClick: function (event) {
328
+ new L.Toolbar.Popup(event.latlng, {
329
+ className: 'leaflet-inplace-toolbar',
330
+ actions: this.getVertexActions(event),
331
+ }).addTo(this._map, this, event.latlng, event.vertex)
332
+ },
333
+
334
+ getContextMenuItems: function (event) {
335
+ let items = FeatureMixin.getContextMenuItems.call(this, event)
336
+ items.push({
337
+ text: translate('Display measure'),
338
+ callback: () => Alert.info(this.getMeasure()),
339
+ })
340
+ if (this._map.editEnabled && !this.feature.isReadOnly() && this.feature.isMulti()) {
341
+ items = items.concat(this.getContextMenuMultiItems(event))
342
+ }
343
+ return items
344
+ },
345
+
346
+ getContextMenuMultiItems: function (event) {
347
+ const items = [
348
+ '-',
349
+ {
350
+ text: translate('Remove shape from the multi'),
351
+ callback: () => {
352
+ this.enableEdit().deleteShapeAt(event.latlng)
353
+ },
354
+ },
355
+ ]
356
+ const shape = this.shapeAt(event.latlng)
357
+ if (this._latlngs.indexOf(shape) > 0) {
358
+ items.push({
359
+ text: translate('Make main shape'),
360
+ callback: () => {
361
+ this.enableEdit().deleteShape(shape)
362
+ this.editor.prependShape(shape)
363
+ },
364
+ })
365
+ }
366
+ return items
367
+ },
368
+
369
+ getContextMenuEditItems: function (event) {
370
+ const items = FeatureMixin.getContextMenuEditItems.call(this, event)
371
+ if (
372
+ this._map?.editedFeature !== this &&
373
+ this.feature.isSameClass(this._map.editedFeature)
374
+ ) {
375
+ items.push({
376
+ text: translate('Transfer shape to edited feature'),
377
+ callback: () => {
378
+ this.feature.transferShape(event.latlng, this._map.editedFeature)
379
+ },
380
+ })
381
+ }
382
+ if (this.feature.isMulti()) {
383
+ items.push({
384
+ text: translate('Extract shape to separate feature'),
385
+ callback: () => {
386
+ this.isolateShape(event.latlng)
387
+ },
388
+ })
389
+ }
390
+ return items
391
+ },
392
+
393
+ isolateShape: function (atLatLng) {
394
+ if (!this.feature.isMulti()) return
395
+ const shape = this.enableEdit().deleteShapeAt(atLatLng)
396
+ this.feature.pullGeometry()
397
+ this.disableEdit()
398
+ if (!shape) return
399
+ return this.feature.isolateShape(shape)
400
+ },
401
+
402
+ getStyleOptions: () => [
403
+ 'smoothFactor',
404
+ 'color',
405
+ 'opacity',
406
+ 'stroke',
407
+ 'weight',
408
+ 'fill',
409
+ 'fillColor',
410
+ 'fillOpacity',
411
+ 'dashArray',
412
+ 'interactive',
413
+ ],
414
+ }
415
+
416
+ export const LeafletPolyline = Polyline.extend({
417
+ parentClass: Polyline,
418
+ includes: [FeatureMixin, PathMixin],
419
+
420
+ getClass: () => LeafletPolyline,
421
+
422
+ getVertexActions: function (event) {
423
+ const actions = PathMixin.getVertexActions.call(this, event)
424
+ const index = event.vertex.getIndex()
425
+ if (index === 0 || index === event.vertex.getLastIndex()) {
426
+ actions.push(U.ContinueLineAction)
427
+ } else {
428
+ actions.push(U.SplitLineAction)
429
+ }
430
+ return actions
431
+ },
432
+
433
+ getContextMenuEditItems: function (event) {
434
+ const items = PathMixin.getContextMenuEditItems.call(this, event)
435
+ const vertexClicked = event.vertex
436
+ let index
437
+ if (!this.feature.isMulti()) {
438
+ items.push({
439
+ text: translate('Transform to polygon'),
440
+ callback: this.feature.toPolygon,
441
+ context: this.feature,
442
+ })
443
+ }
444
+ if (vertexClicked) {
445
+ index = event.vertex.getIndex()
446
+ if (index !== 0 && index !== event.vertex.getLastIndex()) {
447
+ items.push({
448
+ text: translate('Split line'),
449
+ callback: event.vertex.split,
450
+ context: event.vertex,
451
+ })
452
+ } else if (index === 0 || index === event.vertex.getLastIndex()) {
453
+ items.push({
454
+ text: this._map.help.displayLabel('CONTINUE_LINE'),
455
+ callback: event.vertex.continue,
456
+ context: event.vertex.continue,
457
+ })
458
+ }
459
+ }
460
+ return items
461
+ },
462
+
463
+ getContextMenuMultiItems: function (event) {
464
+ const items = PathMixin.getContextMenuMultiItems.call(this, event)
465
+ items.push({
466
+ text: translate('Merge lines'),
467
+ callback: this.feature.mergeShapes,
468
+ context: this.feature,
469
+ })
470
+ return items
471
+ },
472
+
473
+ getMeasure: function (shape) {
474
+ // FIXME: compute from data in feature (with TurfJS)
475
+ const length = L.GeoUtil.lineLength(this._map, shape || this._defaultShape())
476
+ return L.GeoUtil.readableDistance(length, this._map.measureTools.getMeasureUnit())
477
+ },
478
+ })
479
+
480
+ export const LeafletPolygon = Polygon.extend({
481
+ parentClass: Polygon,
482
+ includes: [FeatureMixin, PathMixin],
483
+
484
+ getClass: () => LeafletPolygon,
485
+
486
+ getContextMenuEditItems: function (event) {
487
+ const items = PathMixin.getContextMenuEditItems.call(this, event)
488
+ const shape = this.shapeAt(event.latlng)
489
+ // No multi and no holes.
490
+ if (
491
+ shape &&
492
+ !this.feature.isMulti() &&
493
+ (LineUtil.isFlat(shape) || shape.length === 1)
494
+ ) {
495
+ items.push({
496
+ text: translate('Transform to lines'),
497
+ callback: this.feature.toLineString,
498
+ context: this.feature,
499
+ })
500
+ }
501
+ items.push({
502
+ text: translate('Start a hole here'),
503
+ callback: this.startHole,
504
+ context: this,
505
+ })
506
+ return items
507
+ },
508
+
509
+ startHole: function (event) {
510
+ this.enableEdit().newHole(event.latlng)
511
+ },
512
+
513
+ getMeasure: function (shape) {
514
+ const area = L.GeoUtil.geodesicArea(shape || this._defaultShape())
515
+ return L.GeoUtil.readableArea(area, this._map.measureTools.getMeasureUnit())
516
+ },
517
+ })
518
+ const WORLD = [
519
+ latLng([90, 180]),
520
+ latLng([90, -180]),
521
+ latLng([-90, -180]),
522
+ latLng([-90, 180]),
523
+ ]
524
+
525
+ export const MaskPolygon = LeafletPolygon.extend({
526
+ getClass: () => MaskPolygon,
527
+
528
+ getLatLngs: function () {
529
+ // Exclude World coordinates.
530
+ return LeafletPolygon.prototype.getLatLngs.call(this).slice(1)
531
+ },
532
+
533
+ _setLatLngs: function (latlngs) {
534
+ const newLatLngs = []
535
+ newLatLngs.push(WORLD)
536
+
537
+ if (!this.feature.isMulti()) {
538
+ latlngs = [latlngs]
539
+ }
540
+ for (const ring of latlngs) {
541
+ newLatLngs.push(ring)
542
+ }
543
+ LeafletPolygon.prototype._setLatLngs.call(this, newLatLngs)
544
+ this._bounds = new LatLngBounds(latlngs)
545
+ },
546
+
547
+ _defaultShape: function () {
548
+ // Do not compute with world coordinates (eg. for centering the popup).
549
+ return this._latlngs[1]
550
+ },
551
+ })
552
+
553
+ export const CircleMarker = BaseCircleMarker.extend({
554
+ parentClass: BaseCircleMarker,
555
+ includes: [FeatureMixin, PathMixin],
556
+ initialize: function (feature, latlng) {
557
+ if (Array.isArray(latlng) && !(latlng[0] instanceof Number)) {
558
+ // Must be a line or polygon
559
+ const bounds = new LatLngBounds(latlng)
560
+ latlng = bounds.getCenter()
561
+ }
562
+ FeatureMixin.initialize.call(this, feature, latlng)
563
+ },
564
+ getClass: () => CircleMarker,
565
+ getStyleOptions: function () {
566
+ const options = PathMixin.getStyleOptions.call(this)
567
+ options.push('radius')
568
+ return options
569
+ },
570
+ getCenter: function () {
571
+ return this._latlng
572
+ },
573
+ })
@@ -57,6 +57,10 @@ export const SCHEMA = {
57
57
  type: Object,
58
58
  impacts: ['data'],
59
59
  },
60
+ circles: {
61
+ type: Object,
62
+ impacts: ['data'],
63
+ },
60
64
  cluster: {
61
65
  type: Object,
62
66
  impacts: ['data'],
@@ -112,6 +116,7 @@ export const SCHEMA = {
112
116
  type: Boolean,
113
117
  impacts: [],
114
118
  default: false,
119
+ label: translate('Animated transitions'),
115
120
  },
116
121
  editinosmControl: {
117
122
  type: Boolean,
@@ -130,6 +135,9 @@ export const SCHEMA = {
130
135
  facetKey: {
131
136
  type: String,
132
137
  impacts: ['ui'],
138
+ helpEntries: ['facetKey'],
139
+ placeholder: translate('Example: key1,key2|Label 2,key3|Label 3|checkbox'),
140
+ label: translate('Filters keys'),
133
141
  },
134
142
  fill: {
135
143
  type: Boolean,
@@ -160,6 +168,10 @@ export const SCHEMA = {
160
168
  filterKey: {
161
169
  type: String,
162
170
  impacts: [],
171
+ helpEntries: ['filterKey'],
172
+ placeholder: translate('Default: name'),
173
+ label: translate('Search keys'),
174
+ inheritable: true,
163
175
  },
164
176
  fromZoom: {
165
177
  type: Number,
@@ -279,6 +291,11 @@ export const SCHEMA = {
279
291
  nullable: true,
280
292
  label: translate('Display the measure control'),
281
293
  },
294
+ mask: {
295
+ type: Boolean,
296
+ impacts: ['data'],
297
+ label: translate('Display the polygon inverted'),
298
+ },
282
299
  miniMap: {
283
300
  type: Boolean,
284
301
  impacts: ['ui'],
@@ -437,6 +454,9 @@ export const SCHEMA = {
437
454
  slugKey: {
438
455
  type: String,
439
456
  impacts: [],
457
+ helpEntries: ['slugKey'],
458
+ placeholder: translate('Default: name'),
459
+ label: translate('Feature identifier key'),
440
460
  },
441
461
  smoothFactor: {
442
462
  type: Number,
@@ -452,6 +472,10 @@ export const SCHEMA = {
452
472
  sortKey: {
453
473
  type: String,
454
474
  impacts: ['datalayer-index', 'data'],
475
+ helpEntries: ['sortKey'],
476
+ placeholder: translate('Default: name'),
477
+ label: translate('Sort key'),
478
+ inheritable: true,
455
479
  },
456
480
  starControl: {
457
481
  type: Boolean,