umap-project 3.3.2__py3-none-any.whl → 3.4.0__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/context_processors.py +4 -1
- umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- umap/locale/cs_CZ/LC_MESSAGES/django.po +43 -33
- umap/locale/da/LC_MESSAGES/django.mo +0 -0
- umap/locale/da/LC_MESSAGES/django.po +43 -33
- umap/locale/de/LC_MESSAGES/django.mo +0 -0
- umap/locale/de/LC_MESSAGES/django.po +64 -53
- umap/locale/el/LC_MESSAGES/django.mo +0 -0
- umap/locale/el/LC_MESSAGES/django.po +35 -29
- umap/locale/en/LC_MESSAGES/django.po +47 -41
- umap/locale/es/LC_MESSAGES/django.mo +0 -0
- umap/locale/es/LC_MESSAGES/django.po +43 -33
- umap/locale/et/LC_MESSAGES/django.mo +0 -0
- umap/locale/et/LC_MESSAGES/django.po +58 -54
- umap/locale/eu/LC_MESSAGES/django.mo +0 -0
- umap/locale/eu/LC_MESSAGES/django.po +43 -33
- umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
- umap/locale/fa_IR/LC_MESSAGES/django.po +43 -33
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +36 -30
- umap/locale/gl/LC_MESSAGES/django.mo +0 -0
- umap/locale/gl/LC_MESSAGES/django.po +43 -33
- umap/locale/hu/LC_MESSAGES/django.mo +0 -0
- umap/locale/hu/LC_MESSAGES/django.po +35 -29
- umap/locale/is/LC_MESSAGES/django.mo +0 -0
- umap/locale/is/LC_MESSAGES/django.po +43 -33
- umap/locale/it/LC_MESSAGES/django.mo +0 -0
- umap/locale/it/LC_MESSAGES/django.po +43 -33
- umap/locale/nl/LC_MESSAGES/django.mo +0 -0
- umap/locale/nl/LC_MESSAGES/django.po +35 -29
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +114 -103
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +43 -33
- umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
- umap/locale/th_TH/LC_MESSAGES/django.po +310 -109
- umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
- umap/locale/zh_TW/LC_MESSAGES/django.po +80 -70
- umap/management/commands/switch_user.py +2 -2
- umap/migrations/0018_datalayer_uuid.py +1 -1
- umap/models.py +7 -3
- umap/settings/local.py.sample +1 -1
- umap/static/umap/base.css +89 -32
- umap/static/umap/content.css +129 -33
- umap/static/umap/css/bar.css +82 -20
- umap/static/umap/css/browser.css +163 -0
- umap/static/umap/css/contextmenu.css +15 -0
- umap/static/umap/css/dialog.css +36 -16
- umap/static/umap/css/form.css +123 -33
- umap/static/umap/css/icon.css +46 -3
- umap/static/umap/css/panel.css +7 -3
- umap/static/umap/css/popup.css +34 -8
- umap/static/umap/css/tooltip.css +8 -4
- umap/static/umap/img/16-white.svg +26 -8
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/source/16-white.svg +36 -18
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/js/components/alerts/alert.css +69 -31
- umap/static/umap/js/components/alerts/alert.js +20 -2
- umap/static/umap/js/components/base.js +1 -1
- umap/static/umap/js/modules/browser.js +69 -61
- umap/static/umap/js/modules/caption.js +10 -7
- umap/static/umap/js/modules/data/features.js +89 -63
- umap/static/umap/js/modules/data/fields.js +446 -0
- umap/static/umap/js/modules/data/layer.js +116 -196
- umap/static/umap/js/modules/domutils.js +109 -0
- umap/static/umap/js/modules/filters.js +780 -0
- umap/static/umap/js/modules/form/builder.js +8 -5
- umap/static/umap/js/modules/form/fields.js +111 -221
- umap/static/umap/js/modules/formatter.js +24 -1
- umap/static/umap/js/modules/help.js +4 -3
- umap/static/umap/js/modules/i18n.js +1 -1
- umap/static/umap/js/modules/importer.js +1 -1
- umap/static/umap/js/modules/importers/opendata.js +15 -0
- umap/static/umap/js/modules/importers/openrouteservice.js +6 -1
- umap/static/umap/js/modules/managers.js +2 -1
- umap/static/umap/js/modules/permissions.js +39 -31
- umap/static/umap/js/modules/rendering/controls.js +11 -9
- umap/static/umap/js/modules/rendering/icon.js +3 -8
- umap/static/umap/js/modules/rendering/layers/base.js +3 -3
- umap/static/umap/js/modules/rendering/layers/classified.js +18 -11
- umap/static/umap/js/modules/rendering/layers/cluster.js +23 -11
- umap/static/umap/js/modules/rendering/layers/heat.js +27 -21
- umap/static/umap/js/modules/rendering/map.js +1 -0
- umap/static/umap/js/modules/rendering/template.js +50 -23
- umap/static/umap/js/modules/rendering/ui.js +33 -25
- umap/static/umap/js/modules/rules.js +38 -44
- umap/static/umap/js/modules/schema.js +3 -6
- umap/static/umap/js/modules/share.js +5 -4
- umap/static/umap/js/modules/tableeditor.js +50 -38
- umap/static/umap/js/modules/templates.js +2 -3
- umap/static/umap/js/modules/ui/bar.js +55 -23
- umap/static/umap/js/modules/ui/dialog.js +38 -27
- umap/static/umap/js/modules/ui/panel.js +23 -8
- umap/static/umap/js/modules/ui/tooltip.js +6 -5
- umap/static/umap/js/modules/umap.js +158 -51
- umap/static/umap/js/modules/utils.js +24 -2
- umap/static/umap/js/umap.core.js +1 -110
- umap/static/umap/locale/am_ET.js +52 -17
- umap/static/umap/locale/am_ET.json +52 -17
- umap/static/umap/locale/ar.js +52 -17
- umap/static/umap/locale/ar.json +52 -17
- umap/static/umap/locale/ast.js +52 -17
- umap/static/umap/locale/ast.json +52 -17
- umap/static/umap/locale/bg.js +52 -17
- umap/static/umap/locale/bg.json +52 -17
- umap/static/umap/locale/br.js +48 -22
- umap/static/umap/locale/br.json +48 -22
- umap/static/umap/locale/ca.js +52 -17
- umap/static/umap/locale/ca.json +52 -17
- umap/static/umap/locale/cs_CZ.js +52 -17
- umap/static/umap/locale/cs_CZ.json +52 -17
- umap/static/umap/locale/da.js +54 -17
- umap/static/umap/locale/da.json +54 -17
- umap/static/umap/locale/de.js +102 -67
- umap/static/umap/locale/de.json +102 -67
- umap/static/umap/locale/el.js +52 -17
- umap/static/umap/locale/el.json +52 -17
- umap/static/umap/locale/en.js +54 -16
- umap/static/umap/locale/en.json +54 -16
- umap/static/umap/locale/en_US.json +52 -17
- umap/static/umap/locale/es.js +54 -17
- umap/static/umap/locale/es.json +54 -17
- umap/static/umap/locale/et.js +91 -56
- umap/static/umap/locale/et.json +91 -56
- umap/static/umap/locale/eu.js +84 -49
- umap/static/umap/locale/eu.json +84 -49
- umap/static/umap/locale/fa_IR.js +52 -17
- umap/static/umap/locale/fa_IR.json +52 -17
- umap/static/umap/locale/fi.js +52 -17
- umap/static/umap/locale/fi.json +52 -17
- umap/static/umap/locale/fr.js +54 -17
- umap/static/umap/locale/fr.json +54 -17
- umap/static/umap/locale/gl.js +52 -17
- umap/static/umap/locale/gl.json +52 -17
- umap/static/umap/locale/he.js +52 -17
- umap/static/umap/locale/he.json +52 -17
- umap/static/umap/locale/hr.js +52 -17
- umap/static/umap/locale/hr.json +52 -17
- umap/static/umap/locale/hu.js +59 -24
- umap/static/umap/locale/hu.json +59 -24
- umap/static/umap/locale/id.js +52 -17
- umap/static/umap/locale/id.json +52 -17
- umap/static/umap/locale/is.js +52 -17
- umap/static/umap/locale/is.json +52 -17
- umap/static/umap/locale/it.js +52 -17
- umap/static/umap/locale/it.json +52 -17
- umap/static/umap/locale/ja.js +52 -17
- umap/static/umap/locale/ja.json +52 -17
- umap/static/umap/locale/ko.js +52 -17
- umap/static/umap/locale/ko.json +52 -17
- umap/static/umap/locale/lt.js +52 -17
- umap/static/umap/locale/lt.json +52 -17
- umap/static/umap/locale/ms.js +52 -17
- umap/static/umap/locale/ms.json +52 -17
- umap/static/umap/locale/nl.js +52 -17
- umap/static/umap/locale/nl.json +52 -17
- umap/static/umap/locale/no.js +52 -17
- umap/static/umap/locale/no.json +52 -17
- umap/static/umap/locale/pl.js +53 -17
- umap/static/umap/locale/pl.json +53 -17
- umap/static/umap/locale/pl_PL.json +52 -17
- umap/static/umap/locale/pt.js +52 -17
- umap/static/umap/locale/pt.json +52 -17
- umap/static/umap/locale/pt_BR.js +52 -17
- umap/static/umap/locale/pt_BR.json +52 -17
- umap/static/umap/locale/pt_PT.js +52 -17
- umap/static/umap/locale/pt_PT.json +52 -17
- umap/static/umap/locale/ro.js +52 -17
- umap/static/umap/locale/ro.json +52 -17
- umap/static/umap/locale/ru.js +52 -17
- umap/static/umap/locale/ru.json +52 -17
- umap/static/umap/locale/si.js +1 -1
- umap/static/umap/locale/si.json +1 -1
- umap/static/umap/locale/sk_SK.js +52 -17
- umap/static/umap/locale/sk_SK.json +52 -17
- umap/static/umap/locale/sl.js +52 -17
- umap/static/umap/locale/sl.json +52 -17
- umap/static/umap/locale/sr.js +52 -17
- umap/static/umap/locale/sr.json +52 -17
- umap/static/umap/locale/sv.js +52 -17
- umap/static/umap/locale/sv.json +52 -17
- umap/static/umap/locale/th_TH.js +52 -17
- umap/static/umap/locale/th_TH.json +52 -17
- umap/static/umap/locale/tr.js +52 -17
- umap/static/umap/locale/tr.json +52 -17
- umap/static/umap/locale/uk_UA.js +52 -17
- umap/static/umap/locale/uk_UA.json +52 -17
- umap/static/umap/locale/vi.js +52 -17
- umap/static/umap/locale/vi.json +52 -17
- umap/static/umap/locale/vi_VN.json +52 -17
- umap/static/umap/locale/zh.js +52 -17
- umap/static/umap/locale/zh.json +52 -17
- umap/static/umap/locale/zh_CN.json +52 -17
- umap/static/umap/locale/zh_TW.Big5.json +52 -17
- umap/static/umap/locale/zh_TW.js +53 -17
- umap/static/umap/locale/zh_TW.json +53 -17
- umap/static/umap/map.css +63 -226
- umap/static/umap/unittests/utils.js +18 -0
- umap/static/umap/vars.css +23 -5
- umap/templates/umap/components/alerts/alert.html +32 -29
- umap/templates/umap/css.html +2 -1
- umap/templates/umap/login_popup_end.html +18 -9
- umap/templates/umap/user_map_table.html +7 -2
- umap/tests/integration/conftest.py +10 -6
- umap/tests/integration/test_anonymous_owned_map.py +90 -37
- umap/tests/integration/test_basics.py +25 -1
- umap/tests/integration/test_browser.py +37 -0
- umap/tests/integration/test_cluster.py +110 -0
- umap/tests/integration/test_conditional_rules.py +107 -52
- umap/tests/integration/test_datalayer.py +9 -16
- umap/tests/integration/test_draw_polygon.py +6 -0
- umap/tests/integration/test_draw_polyline.py +11 -0
- umap/tests/integration/test_edit_marker.py +12 -1
- umap/tests/integration/test_export_map.py +19 -0
- umap/tests/integration/test_fields.py +541 -0
- umap/tests/integration/test_filters.py +616 -0
- umap/tests/integration/test_iframe.py +1 -1
- umap/tests/integration/test_import.py +38 -42
- umap/tests/integration/test_map_preview.py +1 -1
- umap/tests/integration/test_picto.py +1 -1
- umap/tests/integration/test_popup.py +31 -0
- umap/tests/integration/test_remote_data.py +60 -4
- umap/tests/integration/test_save.py +1 -1
- umap/tests/integration/test_share.py +4 -4
- umap/tests/integration/test_tableeditor.py +31 -7
- umap/tests/integration/test_websocket_sync.py +71 -20
- umap/tests/test_dashboard.py +11 -1
- umap/tests/test_statics.py +2 -2
- umap/tests/test_utils.py +19 -2
- umap/tests/test_views.py +1 -1
- umap/urls.py +1 -0
- umap/utils.py +8 -1
- umap/views.py +5 -0
- {umap_project-3.3.2.dist-info → umap_project-3.4.0.dist-info}/METADATA +15 -15
- {umap_project-3.3.2.dist-info → umap_project-3.4.0.dist-info}/RECORD +240 -236
- umap/static/umap/js/modules/facets.js +0 -164
- umap/tests/integration/test_facets_browser.py +0 -279
- {umap_project-3.3.2.dist-info → umap_project-3.4.0.dist-info}/WHEEL +0 -0
- {umap_project-3.3.2.dist-info → umap_project-3.4.0.dist-info}/entry_points.txt +0 -0
- {umap_project-3.3.2.dist-info → umap_project-3.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -78,8 +78,7 @@ export default class Dialog extends WithTemplate {
|
|
|
78
78
|
if (!this.dialogSupported) {
|
|
79
79
|
this.elements.form.addEventListener('submit', (event) => {
|
|
80
80
|
event.preventDefault()
|
|
81
|
-
this.
|
|
82
|
-
this.close()
|
|
81
|
+
this.accept()
|
|
83
82
|
})
|
|
84
83
|
}
|
|
85
84
|
this.dialog.addEventListener('keydown', (e) => {
|
|
@@ -118,7 +117,6 @@ export default class Dialog extends WithTemplate {
|
|
|
118
117
|
this.elements.cancel.hidden = !dialog.cancel
|
|
119
118
|
this.elements.message.textContent = dialog.message
|
|
120
119
|
this.elements.message.hidden = !dialog.message
|
|
121
|
-
this.elements.target = dialog.target || ''
|
|
122
120
|
this.elements.template.innerHTML = ''
|
|
123
121
|
if (dialog.template?.nodeType === 1) {
|
|
124
122
|
this.elements.template.appendChild(dialog.template)
|
|
@@ -137,12 +135,13 @@ export default class Dialog extends WithTemplate {
|
|
|
137
135
|
if (currentZIndex) {
|
|
138
136
|
this.dialog.style.zIndex = currentZIndex + 1
|
|
139
137
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
138
|
+
if (this.dialogSupported) {
|
|
139
|
+
this.dialog.show()
|
|
140
|
+
} else {
|
|
141
|
+
this.dialog.hidden = false
|
|
142
|
+
}
|
|
143
143
|
if (this.hasFormData) this.focusable[0].focus()
|
|
144
144
|
else this.elements.accept.focus()
|
|
145
|
-
|
|
146
145
|
return this.waitForUser()
|
|
147
146
|
}
|
|
148
147
|
|
|
@@ -151,37 +150,49 @@ export default class Dialog extends WithTemplate {
|
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
close() {
|
|
154
|
-
this.
|
|
155
|
-
this.dialog.returnValue = undefined
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
toggle(open = false) {
|
|
153
|
+
this._closing = true
|
|
159
154
|
if (this.dialogSupported) {
|
|
160
|
-
|
|
161
|
-
else this.dialog.close()
|
|
155
|
+
this.dialog.close()
|
|
162
156
|
} else {
|
|
163
|
-
this.dialog.hidden =
|
|
164
|
-
|
|
165
|
-
this.elements.target.focus()
|
|
166
|
-
}
|
|
167
|
-
if (!open) {
|
|
168
|
-
this.dialog.dispatchEvent(new CustomEvent('close'))
|
|
169
|
-
}
|
|
157
|
+
this.dialog.hidden = true
|
|
158
|
+
this.dialog.dispatchEvent(new CustomEvent('close'))
|
|
170
159
|
}
|
|
171
160
|
}
|
|
172
161
|
|
|
173
|
-
|
|
162
|
+
accept() {
|
|
163
|
+
this.dialog.returnValue = 'accept'
|
|
174
164
|
return new Promise((resolve) => {
|
|
175
165
|
this.dialog.addEventListener(
|
|
176
166
|
'close',
|
|
177
|
-
(
|
|
178
|
-
|
|
179
|
-
const value = this.hasFormData ? this.collectFormData() : true
|
|
180
|
-
resolve(value)
|
|
181
|
-
}
|
|
167
|
+
() => {
|
|
168
|
+
resolve()
|
|
182
169
|
},
|
|
183
170
|
{ once: true }
|
|
184
171
|
)
|
|
172
|
+
this.close()
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
waitForUser() {
|
|
177
|
+
return new Promise((resolve) => {
|
|
178
|
+
const onClose = () => {
|
|
179
|
+
this._closing = false
|
|
180
|
+
if (this.dialog.returnValue === 'accept') {
|
|
181
|
+
const value = this.hasFormData ? this.collectFormData() : true
|
|
182
|
+
resolve(value)
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
const waitForClose = () => {
|
|
186
|
+
this.dialog.returnValue = undefined
|
|
187
|
+
this.dialog.addEventListener('close', () => onClose(), { once: true })
|
|
188
|
+
}
|
|
189
|
+
if (this._closing) {
|
|
190
|
+
// We are opening a new dialog while another is not fully closed,
|
|
191
|
+
// so let's first wait for that one to be fully closed
|
|
192
|
+
this.dialog.addEventListener('close', () => waitForClose(), { once: true })
|
|
193
|
+
} else {
|
|
194
|
+
waitForClose()
|
|
195
|
+
}
|
|
185
196
|
})
|
|
186
197
|
}
|
|
187
198
|
|
|
@@ -7,7 +7,7 @@ export class Panel {
|
|
|
7
7
|
this._umap = umap
|
|
8
8
|
this._leafletMap = leafletMap
|
|
9
9
|
this.container = DomUtil.create('div', '', this.parent)
|
|
10
|
-
// This will be set once according to the panel
|
|
10
|
+
// This will be set once according to the panel configured at load
|
|
11
11
|
// or by using panels as popups
|
|
12
12
|
this.mode = null
|
|
13
13
|
this.className = 'left'
|
|
@@ -26,12 +26,12 @@ export class Panel {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
open({ content, className, highlight, actions = [] } = {}) {
|
|
29
|
+
let isOpen = false
|
|
29
30
|
if (this.isOpen()) {
|
|
31
|
+
isOpen = true
|
|
30
32
|
this.onClose()
|
|
31
33
|
}
|
|
32
|
-
this.container.className = `with-transition panel window ${this.className} ${
|
|
33
|
-
this.mode || ''
|
|
34
|
-
}`
|
|
34
|
+
this.container.className = `with-transition panel window ${this.className} ${this.mode || ''} ${isOpen ? 'on' : ''}`
|
|
35
35
|
if (highlight) {
|
|
36
36
|
this.container.dataset.highlight = highlight
|
|
37
37
|
}
|
|
@@ -56,8 +56,22 @@ export class Panel {
|
|
|
56
56
|
}
|
|
57
57
|
if (className) DomUtil.addClass(body, className)
|
|
58
58
|
const promise = new Promise((resolve, reject) => {
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
if (isOpen) {
|
|
60
|
+
resolve(this)
|
|
61
|
+
} else {
|
|
62
|
+
this.container.classList.add('on')
|
|
63
|
+
Promise.all(
|
|
64
|
+
this.container.getAnimations?.().map((animation) => animation.finished)
|
|
65
|
+
)
|
|
66
|
+
.then(() => {
|
|
67
|
+
resolve(this)
|
|
68
|
+
})
|
|
69
|
+
.catch(() => {
|
|
70
|
+
// Panel has been removed, so the DOM has changed, so the animations
|
|
71
|
+
// were cancelled, we want the new panel callback to be called anyway.
|
|
72
|
+
resolve(this)
|
|
73
|
+
})
|
|
74
|
+
}
|
|
61
75
|
})
|
|
62
76
|
DomEvent.on(closeButton, 'click', this.close, this)
|
|
63
77
|
DomEvent.on(resizeButton, 'click', this.resize, this)
|
|
@@ -83,11 +97,12 @@ export class Panel {
|
|
|
83
97
|
}
|
|
84
98
|
|
|
85
99
|
onClose() {
|
|
86
|
-
if (
|
|
87
|
-
|
|
100
|
+
if (this.container.classList.contains('on')) {
|
|
101
|
+
this.container.classList.remove('on')
|
|
88
102
|
this._leafletMap.invalidateSize({ pan: false })
|
|
89
103
|
}
|
|
90
104
|
}
|
|
105
|
+
|
|
91
106
|
scrollTo(selector) {
|
|
92
107
|
const fieldset = this.container.querySelector(selector)
|
|
93
108
|
if (!fieldset) return
|
|
@@ -4,11 +4,10 @@ import * as Utils from '../utils.js'
|
|
|
4
4
|
import { Positioned } from './base.js'
|
|
5
5
|
|
|
6
6
|
export default class Tooltip extends Positioned {
|
|
7
|
-
constructor(
|
|
7
|
+
constructor() {
|
|
8
8
|
super()
|
|
9
|
-
this.parent =
|
|
9
|
+
this.parent = document.body
|
|
10
10
|
this.container = Utils.loadTemplate('<div class="umap-tooltip-container"></div>')
|
|
11
|
-
this.parent.appendChild(this.container)
|
|
12
11
|
DomEvent.disableClickPropagation(this.container)
|
|
13
12
|
this.container.addEventListener('contextmenu', (event) => event.stopPropagation()) // Do not activate our custom context menu.
|
|
14
13
|
this.container.addEventListener('wheel', (event) => event.stopPropagation())
|
|
@@ -25,7 +24,7 @@ export default class Tooltip extends Positioned {
|
|
|
25
24
|
} else {
|
|
26
25
|
this.container.innerHTML = Utils.escapeHTML(opts.content)
|
|
27
26
|
}
|
|
28
|
-
this.parent.
|
|
27
|
+
this.parent.appendChild(this.container)
|
|
29
28
|
this.openAt(opts)
|
|
30
29
|
}
|
|
31
30
|
this.TOOLTIP_ID = window.setTimeout(L.bind(showIt, this), opts.delay || 0)
|
|
@@ -49,6 +48,8 @@ export default class Tooltip extends Positioned {
|
|
|
49
48
|
this.toggleClassPosition()
|
|
50
49
|
this.container.innerHTML = ''
|
|
51
50
|
this.setPosition({})
|
|
52
|
-
this.parent.
|
|
51
|
+
if (this.parent.contains(this.container)) {
|
|
52
|
+
this.parent.removeChild(this.container)
|
|
53
|
+
}
|
|
53
54
|
}
|
|
54
55
|
}
|
|
@@ -10,7 +10,8 @@ import {
|
|
|
10
10
|
import Browser from './browser.js'
|
|
11
11
|
import Caption from './caption.js'
|
|
12
12
|
import { DataLayer } from './data/layer.js'
|
|
13
|
-
import
|
|
13
|
+
import { Fields } from './data/fields.js'
|
|
14
|
+
import { Filters, migrateLegacyFilters } from './filters.js'
|
|
14
15
|
import { MutatingForm } from './form/builder.js'
|
|
15
16
|
import { Formatter } from './formatter.js'
|
|
16
17
|
import Help from './help.js'
|
|
@@ -32,6 +33,7 @@ import { EditPanel, FullPanel, Panel } from './ui/panel.js'
|
|
|
32
33
|
import Tooltip from './ui/tooltip.js'
|
|
33
34
|
import URLs from './urls.js'
|
|
34
35
|
import * as Utils from './utils.js'
|
|
36
|
+
import * as DOMUtils from './domutils.js'
|
|
35
37
|
import { DataLayerManager } from './managers.js'
|
|
36
38
|
import { Importer as OpenRouteService } from './importers/openrouteservice.js'
|
|
37
39
|
|
|
@@ -48,6 +50,7 @@ export default class Umap {
|
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
async init(element, geojson) {
|
|
53
|
+
this.migrateLegacyProperties(geojson.properties)
|
|
51
54
|
this.properties = Object.assign(
|
|
52
55
|
{
|
|
53
56
|
enableMarkerDraw: true,
|
|
@@ -131,7 +134,8 @@ export default class Umap {
|
|
|
131
134
|
this.contextmenu = new ContextMenu()
|
|
132
135
|
this.server = new ServerRequest()
|
|
133
136
|
this.request = new Request()
|
|
134
|
-
this.
|
|
137
|
+
this.fields = new Fields(this, this.dialog)
|
|
138
|
+
this.filters = new Filters(this, this)
|
|
135
139
|
this.browser = new Browser(this, this._leafletMap)
|
|
136
140
|
this.caption = new Caption(this, this._leafletMap)
|
|
137
141
|
this.importer = new Importer(this)
|
|
@@ -160,10 +164,6 @@ export default class Umap {
|
|
|
160
164
|
) {
|
|
161
165
|
this.properties.slideshow.active = true
|
|
162
166
|
}
|
|
163
|
-
if (this.properties.advancedFilterKey) {
|
|
164
|
-
this.properties.facetKey = this.properties.advancedFilterKey
|
|
165
|
-
delete this.properties.advancedFilterKey
|
|
166
|
-
}
|
|
167
167
|
|
|
168
168
|
// Global storage for retrieving datalayers and features.
|
|
169
169
|
this.datalayers = new DataLayerManager()
|
|
@@ -261,17 +261,6 @@ export default class Umap {
|
|
|
261
261
|
return window.self !== window.top
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
get fields() {
|
|
265
|
-
if (!this.properties.fields) this.properties.fields = []
|
|
266
|
-
return this.properties.fields
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
get fieldKeys() {
|
|
270
|
-
return this.fields
|
|
271
|
-
.map((field) => field.key)
|
|
272
|
-
.concat(...this.datalayers.active().map((dl) => dl.fieldKeys))
|
|
273
|
-
}
|
|
274
|
-
|
|
275
264
|
setPropertiesFromQueryString() {
|
|
276
265
|
const asBoolean = (key) => {
|
|
277
266
|
const value = this.searchParams.get(key)
|
|
@@ -391,6 +380,17 @@ export default class Umap {
|
|
|
391
380
|
}
|
|
392
381
|
}
|
|
393
382
|
|
|
383
|
+
hasFilters() {
|
|
384
|
+
return this.filters.size || this.datalayers.active().some((d) => d.filters.size)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
hasActiveFilters() {
|
|
388
|
+
return (
|
|
389
|
+
this.filters.isActive() ||
|
|
390
|
+
this.datalayers.active().some((d) => d.filters.isActive())
|
|
391
|
+
)
|
|
392
|
+
}
|
|
393
|
+
|
|
394
394
|
getOwnContextMenu(event) {
|
|
395
395
|
const items = []
|
|
396
396
|
if (this.editEnabled) {
|
|
@@ -424,7 +424,7 @@ export default class Umap {
|
|
|
424
424
|
action: () => this.openBrowser('data'),
|
|
425
425
|
}
|
|
426
426
|
)
|
|
427
|
-
if (this.
|
|
427
|
+
if (this.hasFilters()) {
|
|
428
428
|
items.push({
|
|
429
429
|
label: translate('Filter data'),
|
|
430
430
|
action: () => this.openBrowser('filters'),
|
|
@@ -444,7 +444,13 @@ export default class Umap {
|
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
getSharedContextMenu(event) {
|
|
447
|
-
const
|
|
447
|
+
const latlng = `${event.latlng.lat.toFixed(6)},${event.latlng.lng.toFixed(6)}`
|
|
448
|
+
const items = [
|
|
449
|
+
{
|
|
450
|
+
label: latlng,
|
|
451
|
+
action: () => DOMUtils.copyToClipboard(latlng),
|
|
452
|
+
},
|
|
453
|
+
]
|
|
448
454
|
if (this.properties.urls.routing) {
|
|
449
455
|
items.push({
|
|
450
456
|
label: translate('Directions from here'),
|
|
@@ -481,7 +487,7 @@ export default class Umap {
|
|
|
481
487
|
}
|
|
482
488
|
|
|
483
489
|
search() {
|
|
484
|
-
if (this._leafletMap._controls.search) this._leafletMap._controls.search.
|
|
490
|
+
if (this._leafletMap._controls.search) this._leafletMap._controls.search.onClick()
|
|
485
491
|
}
|
|
486
492
|
|
|
487
493
|
hasEditMode() {
|
|
@@ -666,7 +672,7 @@ export default class Umap {
|
|
|
666
672
|
const parent = this._leafletMap.getPane('overlayPane')
|
|
667
673
|
const datalayers = Object.values(this.datalayers)
|
|
668
674
|
.filter((datalayer) => !datalayer._isDeleted)
|
|
669
|
-
.sort((datalayer1, datalayer2) => datalayer1.rank
|
|
675
|
+
.sort((datalayer1, datalayer2) => datalayer1.rank - datalayer2.rank)
|
|
670
676
|
for (const datalayer of datalayers) {
|
|
671
677
|
const child = parent.querySelector(`[data-id="${datalayer.id}"]`)
|
|
672
678
|
parent.appendChild(child)
|
|
@@ -720,7 +726,14 @@ export default class Umap {
|
|
|
720
726
|
return this.properties.name || translate('Untitled map')
|
|
721
727
|
}
|
|
722
728
|
|
|
729
|
+
migrateLegacyProperties(properties) {
|
|
730
|
+
if (migrateLegacyFilters(properties)) {
|
|
731
|
+
this._migrated = true
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
723
735
|
setProperties(newProperties) {
|
|
736
|
+
this.migrateLegacyProperties(newProperties)
|
|
724
737
|
for (const key of Object.keys(SCHEMA)) {
|
|
725
738
|
if (newProperties[key] !== undefined) {
|
|
726
739
|
this.properties[key] = newProperties[key]
|
|
@@ -758,7 +771,7 @@ export default class Umap {
|
|
|
758
771
|
'properties.is_template',
|
|
759
772
|
]
|
|
760
773
|
|
|
761
|
-
DomUtil.createTitle(container, translate('Edit map details'), 'icon-
|
|
774
|
+
DomUtil.createTitle(container, translate('Edit map details'), 'icon-info')
|
|
762
775
|
const builder = new MutatingForm(this, metadataFields, {
|
|
763
776
|
className: 'map-metadata',
|
|
764
777
|
umap: this,
|
|
@@ -868,23 +881,22 @@ export default class Umap {
|
|
|
868
881
|
defaultShapeProperties.appendChild(builder.build())
|
|
869
882
|
}
|
|
870
883
|
|
|
871
|
-
|
|
872
|
-
const
|
|
884
|
+
_editDefaultKeys(container) {
|
|
885
|
+
const shapeOptions = [
|
|
873
886
|
'properties.zoomTo',
|
|
874
887
|
'properties.easing',
|
|
875
888
|
'properties.labelKey',
|
|
876
889
|
'properties.sortKey',
|
|
877
890
|
'properties.filterKey',
|
|
878
|
-
'properties.facetKey',
|
|
879
891
|
'properties.slugKey',
|
|
880
892
|
]
|
|
881
893
|
|
|
882
|
-
const builder = new MutatingForm(this,
|
|
883
|
-
const
|
|
894
|
+
const builder = new MutatingForm(this, shapeOptions, { umap: this })
|
|
895
|
+
const defaultShapeProperties = DomUtil.createFieldset(
|
|
884
896
|
container,
|
|
885
897
|
translate('Default properties')
|
|
886
898
|
)
|
|
887
|
-
|
|
899
|
+
defaultShapeProperties.appendChild(builder.build())
|
|
888
900
|
}
|
|
889
901
|
|
|
890
902
|
_editInteractionsProperties(container) {
|
|
@@ -1159,7 +1171,8 @@ export default class Umap {
|
|
|
1159
1171
|
)
|
|
1160
1172
|
this._editControls(container)
|
|
1161
1173
|
this._editShapeProperties(container)
|
|
1162
|
-
this.
|
|
1174
|
+
this._editDefaultKeys(container)
|
|
1175
|
+
this.fields.edit(container)
|
|
1163
1176
|
this._editInteractionsProperties(container)
|
|
1164
1177
|
this.rules.edit(container)
|
|
1165
1178
|
this._editTilelayer(container)
|
|
@@ -1178,6 +1191,16 @@ export default class Umap {
|
|
|
1178
1191
|
})
|
|
1179
1192
|
}
|
|
1180
1193
|
|
|
1194
|
+
onAnonymousSave(editUrl) {
|
|
1195
|
+
AlertCreation.info(
|
|
1196
|
+
this,
|
|
1197
|
+
translate('Hey, you created a map without an account!'),
|
|
1198
|
+
Number.Infinity,
|
|
1199
|
+
editUrl,
|
|
1200
|
+
this.properties.urls.map_send_edit_link ? this.sendEditLinkEmail.bind(this) : null
|
|
1201
|
+
)
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1181
1204
|
async save() {
|
|
1182
1205
|
const geojson = {
|
|
1183
1206
|
type: 'Feature',
|
|
@@ -1197,11 +1220,10 @@ export default class Umap {
|
|
|
1197
1220
|
if (error) {
|
|
1198
1221
|
return
|
|
1199
1222
|
}
|
|
1200
|
-
//
|
|
1223
|
+
// TODO: map.save may not always be the first call during save process
|
|
1201
1224
|
// since SAVEMANAGER refactor
|
|
1202
1225
|
if (data.login_required) {
|
|
1203
|
-
|
|
1204
|
-
window.open(data.login_required)
|
|
1226
|
+
this.askForLogin().then(() => this.saveAll())
|
|
1205
1227
|
return
|
|
1206
1228
|
}
|
|
1207
1229
|
this.properties.user = data.user
|
|
@@ -1209,17 +1231,9 @@ export default class Umap {
|
|
|
1209
1231
|
this.properties.id = data.id
|
|
1210
1232
|
this.permissions.setProperties(data.permissions)
|
|
1211
1233
|
this.permissions.commit()
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
translate('Your map has been created with an anonymous account!'),
|
|
1216
|
-
Number.Infinity,
|
|
1217
|
-
data.permissions.anonymous_edit_url,
|
|
1218
|
-
this.properties.urls.map_send_edit_link
|
|
1219
|
-
? this.sendEditLinkEmail.bind(this)
|
|
1220
|
-
: null
|
|
1221
|
-
)
|
|
1222
|
-
})
|
|
1234
|
+
const anonymousEditUrl = data.permissions?.anonymous_edit_url
|
|
1235
|
+
if (anonymousEditUrl) {
|
|
1236
|
+
this._leafletMap.once('saved', () => this.onAnonymousSave(anonymousEditUrl))
|
|
1223
1237
|
} else {
|
|
1224
1238
|
this._leafletMap.once('saved', () => {
|
|
1225
1239
|
Alert.success(translate('Congratulations, your map has been created!'))
|
|
@@ -1241,6 +1255,29 @@ export default class Umap {
|
|
|
1241
1255
|
return true
|
|
1242
1256
|
}
|
|
1243
1257
|
|
|
1258
|
+
askForLogin() {
|
|
1259
|
+
const promise = new Promise((resolve) => {
|
|
1260
|
+
const bc = new BroadcastChannel('auth')
|
|
1261
|
+
bc.onmessage = (event) => {
|
|
1262
|
+
if (event.data === 'auth:ok') {
|
|
1263
|
+
bc.postMessage('auth:close')
|
|
1264
|
+
const url = this.urls.get('whoami', { map_id: this.id })
|
|
1265
|
+
this.server.get(url).then(([data]) => {
|
|
1266
|
+
this.properties.user = data.user
|
|
1267
|
+
if (!this.id) {
|
|
1268
|
+
this.properties.permissions.owner = { ...data.user }
|
|
1269
|
+
}
|
|
1270
|
+
this.permissions.pull()
|
|
1271
|
+
this.render(['user', 'properties.permissions'])
|
|
1272
|
+
resolve()
|
|
1273
|
+
})
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
})
|
|
1277
|
+
window.open(this.urls.get('login'))
|
|
1278
|
+
return promise
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1244
1281
|
exportProperties() {
|
|
1245
1282
|
const properties = {}
|
|
1246
1283
|
for (const key of Object.keys(SCHEMA)) {
|
|
@@ -1251,6 +1288,18 @@ export default class Umap {
|
|
|
1251
1288
|
return properties
|
|
1252
1289
|
}
|
|
1253
1290
|
|
|
1291
|
+
renameField(oldName, newName) {
|
|
1292
|
+
for (const datalayer of this.datalayers.active()) {
|
|
1293
|
+
datalayer.renameFeaturesField(oldName, newName)
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
deleteField(name) {
|
|
1298
|
+
for (const datalayer of this.datalayers.active()) {
|
|
1299
|
+
datalayer.deleteFeaturesField(name)
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1254
1303
|
geometry() {
|
|
1255
1304
|
/* Return a GeoJSON geometry Object */
|
|
1256
1305
|
const latlng = this._leafletMap.latLng(
|
|
@@ -1269,6 +1318,51 @@ export default class Umap {
|
|
|
1269
1318
|
this.drop.enable()
|
|
1270
1319
|
this.fire('edit:enabled')
|
|
1271
1320
|
this.initSyncEngine()
|
|
1321
|
+
this.checkForLegacy()
|
|
1322
|
+
this.checkForAnonymous()
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
checkForAnonymous() {
|
|
1326
|
+
if (
|
|
1327
|
+
this.permissions.isAnonymousMap() &&
|
|
1328
|
+
this.permissions.isOwner() &&
|
|
1329
|
+
this.permissions.userIsAuth()
|
|
1330
|
+
) {
|
|
1331
|
+
this.dialog
|
|
1332
|
+
.confirm(
|
|
1333
|
+
translate('This map is anonymous, do you want to attach it to your account?')
|
|
1334
|
+
)
|
|
1335
|
+
.then(() => {
|
|
1336
|
+
this.permissions.attach()
|
|
1337
|
+
})
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
checkForLegacy() {
|
|
1342
|
+
let needSaveAlert = false
|
|
1343
|
+
if (this._migrated) {
|
|
1344
|
+
needSaveAlert = true
|
|
1345
|
+
delete this._migrated
|
|
1346
|
+
// Force user to save
|
|
1347
|
+
this.sync.update('properties.name', this.properties.name, this.properties.name)
|
|
1348
|
+
}
|
|
1349
|
+
for (const datalayer of this.datalayers.active()) {
|
|
1350
|
+
if (!datalayer.isReadOnly() && datalayer._migrated) {
|
|
1351
|
+
datalayer._migrated = false
|
|
1352
|
+
// Force user to resave those datalayers
|
|
1353
|
+
datalayer.sync.update(
|
|
1354
|
+
'properties.name',
|
|
1355
|
+
datalayer.properties.name,
|
|
1356
|
+
datalayer.properties.name
|
|
1357
|
+
)
|
|
1358
|
+
needSaveAlert = true
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
if (needSaveAlert) {
|
|
1362
|
+
Alert.warning(
|
|
1363
|
+
translate('The map has been upgraded to latest version, please save it.')
|
|
1364
|
+
)
|
|
1365
|
+
}
|
|
1272
1366
|
}
|
|
1273
1367
|
|
|
1274
1368
|
disableEdit() {
|
|
@@ -1312,6 +1406,12 @@ export default class Umap {
|
|
|
1312
1406
|
// Propagate will remove the fields it has already
|
|
1313
1407
|
// processed
|
|
1314
1408
|
fields = this.propagate(fields)
|
|
1409
|
+
if (fields.includes('properties.filters')) {
|
|
1410
|
+
this.filters.load()
|
|
1411
|
+
if (this.browser.isOpen()) {
|
|
1412
|
+
this.browser.buildFilters()
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1315
1415
|
|
|
1316
1416
|
const impacts = Utils.getImpactsFromSchema(fields)
|
|
1317
1417
|
for (const impact of impacts) {
|
|
@@ -1353,7 +1453,7 @@ export default class Umap {
|
|
|
1353
1453
|
}
|
|
1354
1454
|
|
|
1355
1455
|
// This method does a targeted update of the UI,
|
|
1356
|
-
// it
|
|
1456
|
+
// it would be merged with `render`` method and the
|
|
1357
1457
|
// SCHEMA at some point
|
|
1358
1458
|
propagate(fields = []) {
|
|
1359
1459
|
const impacts = {
|
|
@@ -1364,7 +1464,7 @@ export default class Umap {
|
|
|
1364
1464
|
},
|
|
1365
1465
|
user: () => {
|
|
1366
1466
|
Utils.eachElement('.umap-user .username', (el) => {
|
|
1367
|
-
if (this.
|
|
1467
|
+
if (this.permissions.userIsAuth()) {
|
|
1368
1468
|
el.textContent = this.properties.user.name
|
|
1369
1469
|
}
|
|
1370
1470
|
})
|
|
@@ -1471,17 +1571,22 @@ export default class Umap {
|
|
|
1471
1571
|
`
|
|
1472
1572
|
const [container, { ul }] = Utils.loadTemplateWithRefs(template)
|
|
1473
1573
|
this.datalayers.reverse().map((datalayer) => {
|
|
1474
|
-
const row = Utils.
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1574
|
+
const [row, { toolbox, formbox }] = Utils.loadTemplateWithRefs(`
|
|
1575
|
+
<li class="orderable with-toolbox ${datalayer.cssId}">
|
|
1576
|
+
<span data-ref=formbox class="datalayer-editable-title truncate"></span>
|
|
1577
|
+
<span data-ref=toolbox>
|
|
1578
|
+
<i class="icon icon-16 icon-drag" title="${translate('Drag to reorder')}"></i>
|
|
1579
|
+
</span>
|
|
1580
|
+
</li>
|
|
1581
|
+
`)
|
|
1582
|
+
datalayer.renderToolbox(toolbox)
|
|
1478
1583
|
const builder = new MutatingForm(
|
|
1479
1584
|
datalayer,
|
|
1480
1585
|
[['properties.name', { handler: 'EditableText' }]],
|
|
1481
1586
|
{ className: 'umap-form-inline' }
|
|
1482
1587
|
)
|
|
1483
1588
|
const form = builder.build()
|
|
1484
|
-
|
|
1589
|
+
formbox.appendChild(form)
|
|
1485
1590
|
row.classList.toggle('off', !datalayer.isVisible())
|
|
1486
1591
|
row.dataset.id = datalayer.id
|
|
1487
1592
|
ul.appendChild(row)
|
|
@@ -1624,6 +1729,8 @@ export default class Umap {
|
|
|
1624
1729
|
const fields = Object.keys(importedData.properties).map(
|
|
1625
1730
|
(field) => `properties.${field}`
|
|
1626
1731
|
)
|
|
1732
|
+
this.fields.pull()
|
|
1733
|
+
this.filters.load()
|
|
1627
1734
|
this.render(fields)
|
|
1628
1735
|
this._leafletMap._setDefaultCenter()
|
|
1629
1736
|
}
|
|
@@ -1637,7 +1744,7 @@ export default class Umap {
|
|
|
1637
1744
|
this.importRaw(rawData)
|
|
1638
1745
|
} catch (e) {
|
|
1639
1746
|
console.error('Error importing data', e)
|
|
1640
|
-
|
|
1747
|
+
Alert.error(
|
|
1641
1748
|
translate('Invalid umap data in {filename}', { filename: file.name })
|
|
1642
1749
|
)
|
|
1643
1750
|
}
|
|
@@ -40,7 +40,7 @@ function _getPropertyName(field) {
|
|
|
40
40
|
* Return an array of unique impacts.
|
|
41
41
|
*
|
|
42
42
|
* @param {fields} list[fields]
|
|
43
|
-
* @param object schema object. If
|
|
43
|
+
* @param object schema object. If omitted, global U.SCHEMA will be used.
|
|
44
44
|
* @returns Array[string]
|
|
45
45
|
*/
|
|
46
46
|
export function getImpactsFromSchema(fields, schema) {
|
|
@@ -400,8 +400,30 @@ export function template(str, data) {
|
|
|
400
400
|
})
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
+
const DATE_REGEX = [
|
|
404
|
+
// Format 1: "YYYY-MM-DD"
|
|
405
|
+
/^(?<year>\d{4})[\-\/](?<month>\d{2})[\-\/](?<day>\d{2})$/,
|
|
406
|
+
// Format2 : "DD-MM-YYYY"
|
|
407
|
+
/^(?<day>0[1-9]|[12][0-9]|3[01])[\-\/](?<month>0[1-9]|1[0-2])[\-\/](?<year>\d{4})/,
|
|
408
|
+
]
|
|
409
|
+
|
|
403
410
|
export function parseNaiveDate(value) {
|
|
404
|
-
|
|
411
|
+
let naive
|
|
412
|
+
if (!value) return undefined
|
|
413
|
+
value = String(value)
|
|
414
|
+
for (const regex of DATE_REGEX) {
|
|
415
|
+
const parsed = value.match(regex)
|
|
416
|
+
if (parsed) {
|
|
417
|
+
const { year, month, day } = parsed.groups
|
|
418
|
+
naive = new Date(year, Number.parseInt(month, 10) - 1, Number.parseInt(day, 10))
|
|
419
|
+
break
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
if (!naive) {
|
|
423
|
+
naive = new Date(value)
|
|
424
|
+
}
|
|
425
|
+
// Number.isNaN will always return false for invalid date
|
|
426
|
+
if (isNaN(naive)) return undefined
|
|
405
427
|
// Let's pretend naive date are UTC, and remove time…
|
|
406
428
|
return new Date(Date.UTC(naive.getFullYear(), naive.getMonth(), naive.getDate()))
|
|
407
429
|
}
|