umap-project 3.4.0b3__py3-none-any.whl → 3.4.2__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.
- umap/__init__.py +1 -1
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +18 -14
- umap/locale/en/LC_MESSAGES/django.po +5 -1
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +20 -16
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +18 -14
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +72 -71
- umap/static/umap/content.css +0 -3
- umap/static/umap/css/bar.css +9 -6
- umap/static/umap/css/form.css +25 -9
- umap/static/umap/css/popup.css +1 -0
- umap/static/umap/js/components/copiable.js +47 -0
- umap/static/umap/js/modules/autocomplete.js +31 -58
- umap/static/umap/js/modules/browser.js +4 -4
- umap/static/umap/js/modules/data/features.js +32 -35
- umap/static/umap/js/modules/data/fields.js +189 -23
- umap/static/umap/js/modules/data/layer.js +72 -87
- umap/static/umap/js/modules/domutils.js +21 -1
- umap/static/umap/js/modules/filters.js +13 -40
- umap/static/umap/js/modules/form/fields.js +4 -4
- umap/static/umap/js/modules/formatter.js +9 -1
- umap/static/umap/js/modules/help.js +12 -13
- umap/static/umap/js/modules/importer.js +17 -26
- umap/static/umap/js/modules/importers/banfr.js +0 -1
- umap/static/umap/js/modules/importers/cadastrefr.js +19 -19
- umap/static/umap/js/modules/importers/communesfr.js +7 -8
- umap/static/umap/js/modules/importers/datasets.js +14 -14
- umap/static/umap/js/modules/importers/geodatamine.js +20 -22
- umap/static/umap/js/modules/importers/opendata.js +10 -0
- umap/static/umap/js/modules/importers/overpass.js +19 -18
- umap/static/umap/js/modules/managers.js +1 -1
- umap/static/umap/js/modules/permissions.js +5 -3
- umap/static/umap/js/modules/rendering/controls.js +2 -2
- umap/static/umap/js/modules/rendering/icon.js +5 -9
- umap/static/umap/js/modules/rendering/layers/base.js +1 -1
- umap/static/umap/js/modules/rendering/layers/classified.js +15 -10
- umap/static/umap/js/modules/rendering/layers/heat.js +1 -0
- umap/static/umap/js/modules/rendering/map.js +22 -22
- umap/static/umap/js/modules/rendering/popup.js +6 -3
- umap/static/umap/js/modules/rendering/template.js +28 -34
- umap/static/umap/js/modules/rendering/ui.js +1 -2
- umap/static/umap/js/modules/rules.js +34 -41
- umap/static/umap/js/modules/schema.js +0 -7
- umap/static/umap/js/modules/share.js +36 -69
- umap/static/umap/js/modules/slideshow.js +3 -3
- umap/static/umap/js/modules/tableeditor.js +0 -1
- umap/static/umap/js/modules/ui/bar.js +51 -32
- umap/static/umap/js/modules/ui/panel.js +26 -21
- umap/static/umap/js/modules/ui/tooltip.js +1 -1
- umap/static/umap/js/modules/umap.js +75 -80
- umap/static/umap/js/modules/utils.js +12 -3
- umap/static/umap/js/umap.controls.js +33 -14
- umap/static/umap/locale/am_ET.js +6 -4
- umap/static/umap/locale/am_ET.json +6 -4
- umap/static/umap/locale/ar.js +6 -4
- umap/static/umap/locale/ar.json +6 -4
- umap/static/umap/locale/ast.js +6 -4
- umap/static/umap/locale/ast.json +6 -4
- umap/static/umap/locale/bg.js +6 -4
- umap/static/umap/locale/bg.json +6 -4
- umap/static/umap/locale/br.js +19 -8
- umap/static/umap/locale/br.json +19 -8
- umap/static/umap/locale/ca.js +6 -4
- umap/static/umap/locale/ca.json +6 -4
- umap/static/umap/locale/cs_CZ.js +7 -5
- umap/static/umap/locale/cs_CZ.json +7 -5
- umap/static/umap/locale/da.js +8 -6
- umap/static/umap/locale/da.json +8 -6
- umap/static/umap/locale/de.js +38 -36
- umap/static/umap/locale/de.json +38 -36
- umap/static/umap/locale/el.js +7 -5
- umap/static/umap/locale/el.json +7 -5
- umap/static/umap/locale/en.js +7 -5
- umap/static/umap/locale/en.json +7 -5
- umap/static/umap/locale/en_US.json +6 -4
- umap/static/umap/locale/es.js +19 -17
- umap/static/umap/locale/es.json +19 -17
- umap/static/umap/locale/et.js +7 -5
- umap/static/umap/locale/et.json +7 -5
- umap/static/umap/locale/eu.js +23 -21
- umap/static/umap/locale/eu.json +23 -21
- umap/static/umap/locale/fa_IR.js +7 -5
- umap/static/umap/locale/fa_IR.json +7 -5
- umap/static/umap/locale/fi.js +6 -4
- umap/static/umap/locale/fi.json +6 -4
- umap/static/umap/locale/fr.js +8 -6
- umap/static/umap/locale/fr.json +8 -6
- umap/static/umap/locale/gl.js +147 -145
- umap/static/umap/locale/gl.json +147 -145
- umap/static/umap/locale/he.js +6 -4
- umap/static/umap/locale/he.json +6 -4
- umap/static/umap/locale/hr.js +6 -4
- umap/static/umap/locale/hr.json +6 -4
- umap/static/umap/locale/hu.js +7 -5
- umap/static/umap/locale/hu.json +7 -5
- umap/static/umap/locale/id.js +6 -4
- umap/static/umap/locale/id.json +6 -4
- umap/static/umap/locale/is.js +7 -5
- umap/static/umap/locale/is.json +7 -5
- umap/static/umap/locale/it.js +7 -5
- umap/static/umap/locale/it.json +7 -5
- umap/static/umap/locale/ja.js +6 -4
- umap/static/umap/locale/ja.json +6 -4
- umap/static/umap/locale/ko.js +6 -4
- umap/static/umap/locale/ko.json +6 -4
- umap/static/umap/locale/lt.js +6 -4
- umap/static/umap/locale/lt.json +6 -4
- umap/static/umap/locale/ms.js +7 -5
- umap/static/umap/locale/ms.json +7 -5
- umap/static/umap/locale/nl.js +7 -5
- umap/static/umap/locale/nl.json +7 -5
- umap/static/umap/locale/no.js +6 -4
- umap/static/umap/locale/no.json +6 -4
- umap/static/umap/locale/pl.js +53 -51
- umap/static/umap/locale/pl.json +53 -51
- umap/static/umap/locale/pl_PL.json +6 -4
- umap/static/umap/locale/pt.js +7 -5
- umap/static/umap/locale/pt.json +7 -5
- umap/static/umap/locale/pt_BR.js +6 -4
- umap/static/umap/locale/pt_BR.json +6 -4
- umap/static/umap/locale/pt_PT.js +6 -4
- umap/static/umap/locale/pt_PT.json +6 -4
- umap/static/umap/locale/ro.js +6 -4
- umap/static/umap/locale/ro.json +6 -4
- umap/static/umap/locale/ru.js +6 -4
- umap/static/umap/locale/ru.json +6 -4
- umap/static/umap/locale/sk_SK.js +6 -4
- umap/static/umap/locale/sk_SK.json +6 -4
- umap/static/umap/locale/sl.js +6 -4
- umap/static/umap/locale/sl.json +6 -4
- umap/static/umap/locale/sr.js +6 -4
- umap/static/umap/locale/sr.json +6 -4
- umap/static/umap/locale/sv.js +6 -4
- umap/static/umap/locale/sv.json +6 -4
- umap/static/umap/locale/th_TH.js +6 -4
- umap/static/umap/locale/th_TH.json +6 -4
- umap/static/umap/locale/tr.js +6 -4
- umap/static/umap/locale/tr.json +6 -4
- umap/static/umap/locale/uk_UA.js +6 -4
- umap/static/umap/locale/uk_UA.json +6 -4
- umap/static/umap/locale/vi.js +6 -4
- umap/static/umap/locale/vi.json +6 -4
- umap/static/umap/locale/vi_VN.json +6 -4
- umap/static/umap/locale/zh.js +6 -4
- umap/static/umap/locale/zh.json +6 -4
- umap/static/umap/locale/zh_CN.json +6 -4
- umap/static/umap/locale/zh_TW.Big5.json +6 -4
- umap/static/umap/locale/zh_TW.js +20 -18
- umap/static/umap/locale/zh_TW.json +20 -18
- umap/static/umap/map.css +5 -4
- umap/static/umap/unittests/utils.js +7 -7
- umap/templates/umap/content_footer.html +1 -0
- umap/templates/umap/css.html +0 -2
- umap/templates/umap/js.html +1 -3
- umap/tests/integration/conftest.py +3 -2
- umap/tests/integration/test_anonymous_owned_map.py +1 -1
- umap/tests/integration/test_conditional_rules.py +106 -51
- umap/tests/integration/test_draw_polygon.py +4 -0
- umap/tests/integration/test_draw_polyline.py +11 -0
- umap/tests/integration/test_edit_datalayer.py +1 -1
- umap/tests/integration/test_fields.py +19 -0
- umap/tests/integration/test_iframe.py +1 -1
- umap/tests/integration/test_import.py +23 -0
- umap/tests/integration/test_map.py +2 -2
- umap/tests/integration/test_owned_map.py +2 -2
- umap/tests/integration/test_popup.py +31 -0
- umap/tests/integration/test_remote_data.py +4 -4
- umap/tests/integration/test_search.py +41 -0
- umap/tests/integration/test_share.py +2 -2
- umap/tests/integration/test_team.py +1 -1
- umap/tests/integration/test_websocket_sync.py +6 -1
- umap/tests/test_utils.py +4 -1
- umap/utils.py +1 -0
- {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/METADATA +15 -15
- {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/RECORD +181 -183
- umap/static/umap/js/umap.core.js +0 -93
- umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.css +0 -46
- umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.js +0 -240
- umap/static/umap/vendors/editinosm/edit-in-osm.png +0 -0
- {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/WHEEL +0 -0
- {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/entry_points.txt +0 -0
- {umap_project-3.4.0b3.dist-info → umap_project-3.4.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DomEvent,
|
|
3
|
-
DomUtil,
|
|
4
|
-
Util,
|
|
5
|
-
setOptions,
|
|
6
|
-
} from '../../vendors/leaflet/leaflet-src.esm.js'
|
|
1
|
+
import { DomEvent, Util, setOptions } from '../../vendors/leaflet/leaflet-src.esm.js'
|
|
7
2
|
import { translate } from './i18n.js'
|
|
8
3
|
import { Request, ServerRequest } from './request.js'
|
|
9
4
|
import { escapeHTML, generateId } from './utils.js'
|
|
10
5
|
import * as Utils from './utils.js'
|
|
6
|
+
import * as DOMUtils from './domutils.js'
|
|
11
7
|
|
|
12
8
|
export class BaseAutocomplete {
|
|
13
9
|
constructor(parent, options) {
|
|
@@ -41,26 +37,18 @@ export class BaseAutocomplete {
|
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
createInput() {
|
|
44
|
-
this.input =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
name: this.options.name || 'autocomplete',
|
|
52
|
-
})
|
|
53
|
-
DomEvent.on(this.input, 'keydown', this.onKeyDown, this)
|
|
54
|
-
DomEvent.on(this.input, 'keyup', this.onKeyUp, this)
|
|
55
|
-
DomEvent.on(this.input, 'blur', this.onBlur, this)
|
|
40
|
+
this.input = DOMUtils.loadTemplate(`
|
|
41
|
+
<input type="text" placeholder="${this.options.placeholder}" autocomplete="off" class="${this.options.className}" name="${this.options.name || 'autocomplete'}">
|
|
42
|
+
`)
|
|
43
|
+
this.parent.appendChild(this.input)
|
|
44
|
+
this.input.addEventListener('keydown', (event) => this.onKeyDown(event))
|
|
45
|
+
this.input.addEventListener('keyup', (event) => this.onKeyUp(event))
|
|
46
|
+
this.input.addEventListener('blur', (event) => this.onBlur(event))
|
|
56
47
|
}
|
|
57
48
|
|
|
58
49
|
createContainer() {
|
|
59
|
-
this.container =
|
|
60
|
-
|
|
61
|
-
parent: document.body,
|
|
62
|
-
className: 'umap-autocomplete',
|
|
63
|
-
})
|
|
50
|
+
this.container = DOMUtils.loadTemplate('<ul class="umap-autocomplete"></ul>')
|
|
51
|
+
document.body.appendChild(this.container)
|
|
64
52
|
}
|
|
65
53
|
|
|
66
54
|
resizeContainer() {
|
|
@@ -167,20 +155,17 @@ export class BaseAutocomplete {
|
|
|
167
155
|
}
|
|
168
156
|
|
|
169
157
|
createResult(item) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
parent: this.container,
|
|
173
|
-
textContent: item.label,
|
|
174
|
-
})
|
|
158
|
+
const li = DOMUtils.loadTemplate(`<li>${item.label}</li>`)
|
|
159
|
+
this.container.appendChild(li)
|
|
175
160
|
const result = {
|
|
176
161
|
item: item,
|
|
177
|
-
el:
|
|
162
|
+
el: li,
|
|
178
163
|
}
|
|
179
|
-
|
|
164
|
+
li.addEventListener('mouseover', () => {
|
|
180
165
|
this.current = result
|
|
181
166
|
this.highlight()
|
|
182
167
|
})
|
|
183
|
-
|
|
168
|
+
li.addEventListener('mousedown', () => this.setChoice())
|
|
184
169
|
return result
|
|
185
170
|
}
|
|
186
171
|
|
|
@@ -202,8 +187,7 @@ export class BaseAutocomplete {
|
|
|
202
187
|
|
|
203
188
|
highlight() {
|
|
204
189
|
this.results.forEach((result, index) => {
|
|
205
|
-
|
|
206
|
-
else DomUtil.removeClass(result.el, 'on')
|
|
190
|
+
result.el.classList.toggle('on', index === this.current)
|
|
207
191
|
})
|
|
208
192
|
}
|
|
209
193
|
|
|
@@ -298,19 +282,15 @@ export const SingleMixin = (Base) =>
|
|
|
298
282
|
}
|
|
299
283
|
|
|
300
284
|
displaySelected(result) {
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
parent: result_el,
|
|
309
|
-
className: 'close',
|
|
310
|
-
textContent: '×',
|
|
311
|
-
})
|
|
285
|
+
const [root, { close }] = DOMUtils.loadTemplateWithRefs(`
|
|
286
|
+
<div class="with-toolbox">
|
|
287
|
+
${result.item.label}
|
|
288
|
+
<button type="button" class="icon icon-16 icon-close" title="${translate('Close')}" data-ref="close"></button>
|
|
289
|
+
</div>
|
|
290
|
+
`)
|
|
291
|
+
this.selectedContainer.appendChild(root)
|
|
312
292
|
this.input.style.display = 'none'
|
|
313
|
-
|
|
293
|
+
close.addEventListener('click', () => {
|
|
314
294
|
this.selectedContainer.innerHTML = ''
|
|
315
295
|
this.input.style.display = 'block'
|
|
316
296
|
this.options.on_unselect?.(result)
|
|
@@ -328,19 +308,12 @@ export const MultipleMixin = (Base) =>
|
|
|
328
308
|
}
|
|
329
309
|
|
|
330
310
|
displaySelected(result) {
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
tagName: 'span',
|
|
338
|
-
parent: result_el,
|
|
339
|
-
className: 'close',
|
|
340
|
-
textContent: '×',
|
|
341
|
-
})
|
|
342
|
-
DomEvent.on(close, 'click', () => {
|
|
343
|
-
this.selectedContainer.removeChild(result_el)
|
|
311
|
+
const [li, { close }] = DOMUtils.loadTemplateWithRefs(`
|
|
312
|
+
<li class="with-toolbox">${result.item.label} <button class="icon icon-16 icon-close" type="button" data-ref="close"></button></li>
|
|
313
|
+
`)
|
|
314
|
+
this.selectedContainer.appendChild(li)
|
|
315
|
+
close.addEventListener('click', () => {
|
|
316
|
+
this.selectedContainer.removeChild(li)
|
|
344
317
|
this.options.on_unselect?.(result)
|
|
345
318
|
})
|
|
346
319
|
this.hide()
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DomEvent,
|
|
1
|
+
import { DomEvent, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
|
|
2
2
|
import { Form } from './form/builder.js'
|
|
3
3
|
import { EXPORT_FORMATS } from './formatter.js'
|
|
4
4
|
import { translate } from './i18n.js'
|
|
@@ -133,9 +133,9 @@ export default class Browser {
|
|
|
133
133
|
update() {
|
|
134
134
|
if (!this.isOpen()) return
|
|
135
135
|
this.dataContainer.innerHTML = ''
|
|
136
|
-
this._umap.datalayers.browsable()
|
|
136
|
+
for (const datalayer of this._umap.datalayers.browsable()) {
|
|
137
137
|
this.addDataLayer(datalayer, this.dataContainer)
|
|
138
|
-
}
|
|
138
|
+
}
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
open(mode) {
|
|
@@ -260,7 +260,7 @@ export default class Browser {
|
|
|
260
260
|
if (datalayer.isVisible()) allHidden = false
|
|
261
261
|
})
|
|
262
262
|
this._umap.datalayers.browsable().map((datalayer) => {
|
|
263
|
-
datalayer.
|
|
263
|
+
datalayer.autoVisibility = false
|
|
264
264
|
if (allHidden) {
|
|
265
265
|
datalayer.show()
|
|
266
266
|
} else {
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DomEvent,
|
|
3
|
-
DomUtil,
|
|
4
|
-
GeoJSON,
|
|
5
|
-
LineUtil,
|
|
6
|
-
} from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
1
|
+
import { GeoJSON, LineUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
|
|
7
2
|
import { uMapAlert as Alert } from '../../components/alerts/alert.js'
|
|
8
3
|
import { MutatingForm } from '../form/builder.js'
|
|
9
|
-
import { translate } from '../i18n.js'
|
|
4
|
+
import { translate, getLocale } from '../i18n.js'
|
|
10
5
|
import {
|
|
11
6
|
PREFERENCES as ORS_PREFERENCES,
|
|
12
7
|
PROFILES as ORS_PROFILES,
|
|
@@ -243,12 +238,11 @@ class Feature {
|
|
|
243
238
|
if (this._umap.editedFeature === this && !event?.force) return
|
|
244
239
|
// If this feature is active (popup open), let's close it.
|
|
245
240
|
this.deactivate()
|
|
246
|
-
const container =
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
)
|
|
241
|
+
const container = DOMUtils.loadTemplate(`
|
|
242
|
+
<div class="umap-feature-container">
|
|
243
|
+
<h3><i class="icon icon-16 icon-${this.getClassName()}"></i> ${translate('Feature properties')}</h3>
|
|
244
|
+
</div>
|
|
245
|
+
`)
|
|
252
246
|
|
|
253
247
|
let builder = new MutatingForm(this, [
|
|
254
248
|
['datalayer', { handler: 'EditableDataLayerSwitcher' }],
|
|
@@ -260,17 +254,19 @@ class Feature {
|
|
|
260
254
|
const properties = []
|
|
261
255
|
for (const field of this.fields) {
|
|
262
256
|
const options = { handler: 'Input', label: field.key }
|
|
263
|
-
if (field.key === 'description' || field.
|
|
257
|
+
if (field.key === 'description' || field.TYPE === 'Text') {
|
|
264
258
|
options.handler = 'Textarea'
|
|
265
259
|
options.helpEntries = ['textFormatting']
|
|
266
|
-
} else if (field.
|
|
260
|
+
} else if (field.TYPE === 'Number') {
|
|
267
261
|
options.handler = 'FloatInput'
|
|
268
|
-
} else if (field.
|
|
262
|
+
} else if (field.TYPE === 'Date') {
|
|
269
263
|
options.handler = 'DateInput'
|
|
270
|
-
} else if (field.
|
|
264
|
+
} else if (field.TYPE === 'Datetime') {
|
|
271
265
|
options.handler = 'DateTimeInput'
|
|
272
|
-
} else if (field.
|
|
266
|
+
} else if (field.TYPE === 'Boolean') {
|
|
273
267
|
options.handler = 'Switch'
|
|
268
|
+
} else if (field.TYPE === 'Enum') {
|
|
269
|
+
options.helpText = translate('Comma separated list of values')
|
|
274
270
|
}
|
|
275
271
|
properties.push([`properties.${field.key}`, options])
|
|
276
272
|
}
|
|
@@ -331,7 +327,7 @@ class Feature {
|
|
|
331
327
|
let builder = new MutatingForm(this, optionsFields, {
|
|
332
328
|
id: 'umap-feature-shape-properties',
|
|
333
329
|
})
|
|
334
|
-
const shapeProperties =
|
|
330
|
+
const shapeProperties = DOMUtils.createFieldset(
|
|
335
331
|
container,
|
|
336
332
|
translate('Shape properties')
|
|
337
333
|
)
|
|
@@ -343,7 +339,7 @@ class Feature {
|
|
|
343
339
|
builder = new MutatingForm(this, advancedOptions, {
|
|
344
340
|
id: 'umap-feature-advanced-properties',
|
|
345
341
|
})
|
|
346
|
-
const advancedProperties =
|
|
342
|
+
const advancedProperties = DOMUtils.createFieldset(
|
|
347
343
|
container,
|
|
348
344
|
translate('Advanced properties')
|
|
349
345
|
)
|
|
@@ -351,7 +347,7 @@ class Feature {
|
|
|
351
347
|
|
|
352
348
|
const interactionOptions = this.getInteractionOptions()
|
|
353
349
|
builder = new MutatingForm(this, interactionOptions)
|
|
354
|
-
const popupFieldset =
|
|
350
|
+
const popupFieldset = DOMUtils.createFieldset(
|
|
355
351
|
container,
|
|
356
352
|
translate('Interaction options')
|
|
357
353
|
)
|
|
@@ -442,7 +438,7 @@ class Feature {
|
|
|
442
438
|
this.properties = Object.fromEntries(
|
|
443
439
|
Object.entries(geojson.properties || {}).map(this.cleanProperty)
|
|
444
440
|
)
|
|
445
|
-
this.properties._umap_options =
|
|
441
|
+
this.properties._umap_options = Object.assign(
|
|
446
442
|
{},
|
|
447
443
|
this.properties._storage_options,
|
|
448
444
|
this.properties._umap_options
|
|
@@ -514,8 +510,8 @@ class Feature {
|
|
|
514
510
|
}
|
|
515
511
|
|
|
516
512
|
cloneProperties() {
|
|
517
|
-
const properties =
|
|
518
|
-
properties._umap_options =
|
|
513
|
+
const properties = Object.assign({}, this.properties)
|
|
514
|
+
properties._umap_options = Object.assign({}, properties._umap_options)
|
|
519
515
|
if (Object.keys && Object.keys(properties._umap_options).length === 0) {
|
|
520
516
|
delete properties._umap_options // It can make a difference on big data sets
|
|
521
517
|
}
|
|
@@ -591,9 +587,10 @@ class Feature {
|
|
|
591
587
|
}
|
|
592
588
|
|
|
593
589
|
extendedProperties() {
|
|
590
|
+
console.trace()
|
|
594
591
|
// Include context properties
|
|
595
592
|
const properties = this._umap.getGeoContext()
|
|
596
|
-
const locale =
|
|
593
|
+
const locale = getLocale()
|
|
597
594
|
if (locale) properties.locale = locale
|
|
598
595
|
if (U.lang) properties.lang = U.lang
|
|
599
596
|
properties.rank = this.getRank() + 1
|
|
@@ -788,7 +785,7 @@ export class Point extends Feature {
|
|
|
788
785
|
]
|
|
789
786
|
const builder = new MutatingForm(this, coordinatesOptions)
|
|
790
787
|
builder.on('set', () => {
|
|
791
|
-
if (!this.ui._latlng
|
|
788
|
+
if (!Utils.LatLngIsValid(this.ui._latlng)) {
|
|
792
789
|
Alert.error(translate('Invalid latitude or longitude'))
|
|
793
790
|
builder.restoreField('ui._latlng.lat')
|
|
794
791
|
builder.restoreField('ui._latlng.lng')
|
|
@@ -796,7 +793,7 @@ export class Point extends Feature {
|
|
|
796
793
|
this.pullGeometry()
|
|
797
794
|
this.zoomTo({ easing: false })
|
|
798
795
|
})
|
|
799
|
-
const fieldset =
|
|
796
|
+
const fieldset = DOMUtils.createFieldset(container, translate('Coordinates'))
|
|
800
797
|
fieldset.appendChild(builder.build())
|
|
801
798
|
}
|
|
802
799
|
|
|
@@ -964,7 +961,7 @@ class Path extends Feature {
|
|
|
964
961
|
const builder = new MutatingForm(this, options, {
|
|
965
962
|
id: 'umap-feature-line-decoration',
|
|
966
963
|
})
|
|
967
|
-
const fieldset =
|
|
964
|
+
const fieldset = DOMUtils.createFieldset(container, translate('Line decoration'))
|
|
968
965
|
fieldset.appendChild(builder.build())
|
|
969
966
|
}
|
|
970
967
|
}
|
|
@@ -1077,7 +1074,7 @@ export class LineString extends Path {
|
|
|
1077
1074
|
getAdvancedEditActions(container) {
|
|
1078
1075
|
super.getAdvancedEditActions(container)
|
|
1079
1076
|
const button = Utils.loadTemplate(`
|
|
1080
|
-
<button
|
|
1077
|
+
<button type="button"><i class="icon icon-24 icon-polygon"></i>${translate('Transform to polygon')}</button>
|
|
1081
1078
|
`)
|
|
1082
1079
|
container.appendChild(button)
|
|
1083
1080
|
button.addEventListener('click', () => this.toPolygon())
|
|
@@ -1383,13 +1380,13 @@ export class Polygon extends Path {
|
|
|
1383
1380
|
|
|
1384
1381
|
getAdvancedEditActions(container) {
|
|
1385
1382
|
super.getAdvancedEditActions(container)
|
|
1386
|
-
const toLineString =
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
this.toLineString,
|
|
1391
|
-
this
|
|
1383
|
+
const toLineString = DOMUtils.loadTemplate(
|
|
1384
|
+
`<button type="button" class="umap-to-polyline">
|
|
1385
|
+
<i class="icon icon-24 icon-polyline"></i>${translate('Transform to lines')}
|
|
1386
|
+
</button>`
|
|
1392
1387
|
)
|
|
1388
|
+
container.appendChild(toLineString)
|
|
1389
|
+
toLineString.addEventListener('click', () => this.toLineString())
|
|
1393
1390
|
}
|
|
1394
1391
|
|
|
1395
1392
|
isMulti() {
|
|
@@ -9,6 +9,180 @@ export const getDefaultFields = () => [
|
|
|
9
9
|
{ key: 'description', type: 'Text' },
|
|
10
10
|
]
|
|
11
11
|
|
|
12
|
+
export const Registry = {}
|
|
13
|
+
|
|
14
|
+
class BaseField {
|
|
15
|
+
constructor(key) {
|
|
16
|
+
this.key = key
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
values(features) {
|
|
20
|
+
return features
|
|
21
|
+
.map((feature) => this.parse(feature.properties[this.key]))
|
|
22
|
+
.filter((val, idx, arr) => arr.indexOf(val) === idx)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
equal(expected, other) {
|
|
26
|
+
return expected === other
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
not_equal(expected, other) {
|
|
30
|
+
return expected !== other
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
gt(expected, other) {
|
|
34
|
+
return other > expected
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
lt(expected, other) {
|
|
38
|
+
return other < expected
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
render(value) {
|
|
42
|
+
return Utils.escapeHTML(value).trim()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
dumps() {
|
|
46
|
+
return {
|
|
47
|
+
key: this.key,
|
|
48
|
+
type: this.TYPE,
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Registry.String = class extends BaseField {
|
|
54
|
+
constructor(key) {
|
|
55
|
+
super(key)
|
|
56
|
+
// FIXME make it dynamic from class name
|
|
57
|
+
this.TYPE = 'String'
|
|
58
|
+
this.LABEL = translate('Short text')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
parse(value) {
|
|
62
|
+
return String(value ?? '')
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
render(value) {
|
|
66
|
+
value = super.render(value)
|
|
67
|
+
// TODO, manage links (url, mailto, wikipedia...)
|
|
68
|
+
if (value.indexOf('http') === 0) {
|
|
69
|
+
value = `<a href="${value}" target="_blank">${value}</a>`
|
|
70
|
+
}
|
|
71
|
+
return value
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
Registry.Text = class extends Registry.String {
|
|
76
|
+
constructor(key) {
|
|
77
|
+
super(key)
|
|
78
|
+
// FIXME make it dynamic from class name
|
|
79
|
+
this.TYPE = 'Text'
|
|
80
|
+
this.LABEL = translate('Text')
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
render(value) {
|
|
84
|
+
return Utils.toHTML(value)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
Registry.Number = class extends BaseField {
|
|
89
|
+
constructor(key) {
|
|
90
|
+
super(key)
|
|
91
|
+
// FIXME make it dynamic from class name
|
|
92
|
+
this.TYPE = 'Number'
|
|
93
|
+
this.LABEL = translate('Number')
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
parse(value) {
|
|
97
|
+
return Number.parseFloat(value)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
Registry.Datetime = class extends BaseField {
|
|
102
|
+
constructor(key) {
|
|
103
|
+
super(key)
|
|
104
|
+
// FIXME make it dynamic from class name
|
|
105
|
+
this.TYPE = 'Datetime'
|
|
106
|
+
this.LABEL = translate('Date and time')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
parse(value) {
|
|
110
|
+
return new Date(value)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
Registry.Date = class extends BaseField {
|
|
115
|
+
constructor(key) {
|
|
116
|
+
super(key)
|
|
117
|
+
// FIXME make it dynamic from class name
|
|
118
|
+
this.TYPE = 'Date'
|
|
119
|
+
this.LABEL = translate('Date')
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
parse(value) {
|
|
123
|
+
return Utils.parseNaiveDate(value)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
Registry.Boolean = class extends BaseField {
|
|
128
|
+
constructor(key) {
|
|
129
|
+
super(key)
|
|
130
|
+
// FIXME make it dynamic from class name
|
|
131
|
+
this.TYPE = 'Boolean'
|
|
132
|
+
this.LABEL = translate('Yes / No')
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
parse(value) {
|
|
136
|
+
// 'yes' is used in OpenStreetMap data
|
|
137
|
+
return ['true', '1', 'yes'].includes(`${value}`.toLowerCase())
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
Registry.Enum = class extends BaseField {
|
|
142
|
+
constructor(key) {
|
|
143
|
+
super(key)
|
|
144
|
+
// FIXME make it dynamic from class name
|
|
145
|
+
this.TYPE = 'Enum'
|
|
146
|
+
this.LABEL = translate('List of values')
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
parse(value) {
|
|
150
|
+
return String(value || '')
|
|
151
|
+
.split(',')
|
|
152
|
+
.map((s) => s.trim())
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
values(features) {
|
|
156
|
+
return features
|
|
157
|
+
.reduce(
|
|
158
|
+
(acc, feature) => acc.concat(this.parse(feature.properties[this.key])),
|
|
159
|
+
[]
|
|
160
|
+
)
|
|
161
|
+
.filter((val, idx, arr) => arr.indexOf(val) === idx)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
equal(expected, other) {
|
|
165
|
+
return Boolean(new Set(other).intersection(new Set(expected)).size)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
not_equal(expected, other) {
|
|
169
|
+
return !new Set(other).intersection(new Set(expected)).size
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
gt(expected, other) {
|
|
173
|
+
return false
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
lt(expected, other) {
|
|
177
|
+
return false
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const FIELD_TYPES = Object.entries(Registry).map(([name, klass]) => [
|
|
182
|
+
name,
|
|
183
|
+
new klass().LABEL,
|
|
184
|
+
])
|
|
185
|
+
|
|
12
186
|
export class Fields extends Map {
|
|
13
187
|
constructor(parent, dialog) {
|
|
14
188
|
super()
|
|
@@ -38,7 +212,7 @@ export class Fields extends Map {
|
|
|
38
212
|
this.parent.properties.fields = this.all().map((field) => {
|
|
39
213
|
// We don't want to keep the reference, otherwise editing
|
|
40
214
|
// it will also change the old value
|
|
41
|
-
return { ...field }
|
|
215
|
+
return { ...field.dumps() }
|
|
42
216
|
})
|
|
43
217
|
}
|
|
44
218
|
|
|
@@ -60,10 +234,8 @@ export class Fields extends Map {
|
|
|
60
234
|
console.error('Invalid field', field)
|
|
61
235
|
return
|
|
62
236
|
}
|
|
63
|
-
field.type
|
|
64
|
-
|
|
65
|
-
// when edited.
|
|
66
|
-
this.set(field.key, { ...field })
|
|
237
|
+
const klass = Registry[field.type] || Registry.String
|
|
238
|
+
this.set(field.key, new klass(field.key))
|
|
67
239
|
this.push()
|
|
68
240
|
}
|
|
69
241
|
|
|
@@ -103,7 +275,7 @@ export class Fields extends Map {
|
|
|
103
275
|
const [row, { edit, del, addFilter, editFilter }] = Utils.loadTemplateWithRefs(
|
|
104
276
|
`<li class="orderable with-toolbox" data-key="${field.key}">
|
|
105
277
|
<span>
|
|
106
|
-
<i class="icon icon-16 icon-field-${field.
|
|
278
|
+
<i class="icon icon-16 icon-field-${field.TYPE}" title="${field.LABEL}"></i>
|
|
107
279
|
${field.key}
|
|
108
280
|
</span>
|
|
109
281
|
<span>
|
|
@@ -161,16 +333,8 @@ export class Fields extends Map {
|
|
|
161
333
|
|
|
162
334
|
async editField(name) {
|
|
163
335
|
if (!name && this.parent.isRemoteLayer?.()) return
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
['Text', translate('Text')],
|
|
167
|
-
['Number', translate('Number')],
|
|
168
|
-
['Date', translate('Date')],
|
|
169
|
-
['Datetime', translate('Date and time')],
|
|
170
|
-
['Enum', translate('List of values')],
|
|
171
|
-
['Boolean', translate('Yes / No')],
|
|
172
|
-
]
|
|
173
|
-
const field = this.get(name) || {}
|
|
336
|
+
const field = this.get(name)
|
|
337
|
+
const data = field?.dumps() || {}
|
|
174
338
|
const metadatas = [
|
|
175
339
|
[
|
|
176
340
|
'key',
|
|
@@ -189,7 +353,7 @@ export class Fields extends Map {
|
|
|
189
353
|
},
|
|
190
354
|
],
|
|
191
355
|
]
|
|
192
|
-
const form = new Form(
|
|
356
|
+
const form = new Form(data, metadatas)
|
|
193
357
|
|
|
194
358
|
const [container, { body, addFilter }] = Utils.loadTemplateWithRefs(`
|
|
195
359
|
<div>
|
|
@@ -202,32 +366,34 @@ export class Fields extends Map {
|
|
|
202
366
|
if (this.parent.filters) {
|
|
203
367
|
addFilter.addEventListener('click', () => {
|
|
204
368
|
this.dialog.accept().then(() => {
|
|
205
|
-
this.parent.filters.createFilterForm(
|
|
369
|
+
this.parent.filters.createFilterForm(data.key)
|
|
206
370
|
})
|
|
207
371
|
})
|
|
208
372
|
addFilter.hidden = false
|
|
209
373
|
}
|
|
210
374
|
|
|
211
375
|
return this.dialog.open({ template: container }).then(() => {
|
|
212
|
-
if (!this.validateName(
|
|
376
|
+
if (!this.validateName(data.key, data.key !== name)) {
|
|
213
377
|
this.pull()
|
|
214
378
|
return
|
|
215
379
|
}
|
|
216
380
|
this.parent.sync.startBatch()
|
|
217
381
|
const oldFields = Utils.CopyJSON(this.parent.properties.fields)
|
|
218
382
|
if (!name) {
|
|
219
|
-
this.add(
|
|
220
|
-
} else if (name !== field.
|
|
383
|
+
this.add(data)
|
|
384
|
+
} else if (name !== data.key || field.TYPE !== data.type) {
|
|
221
385
|
this.clear()
|
|
222
386
|
// Keep order on rename
|
|
223
387
|
for (const old of oldFields) {
|
|
224
388
|
if (old.key === name) {
|
|
225
|
-
this.add(
|
|
389
|
+
this.add(data)
|
|
226
390
|
} else {
|
|
227
391
|
this.add(old)
|
|
228
392
|
}
|
|
229
393
|
}
|
|
230
|
-
|
|
394
|
+
if (name !== data.key) {
|
|
395
|
+
this.parent.renameField(name, data.key)
|
|
396
|
+
}
|
|
231
397
|
} else {
|
|
232
398
|
this.push()
|
|
233
399
|
}
|