umap-project 2.3.0__py3-none-any.whl → 2.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.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/locale/en/LC_MESSAGES/django.po +81 -31
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +117 -66
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +83 -78
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +129 -123
- umap/management/commands/run_websocket_server.py +23 -0
- umap/models.py +6 -1
- umap/settings/base.py +11 -3
- umap/static/umap/base.css +68 -186
- umap/static/umap/content.css +3 -2
- umap/static/umap/css/dialog.css +18 -0
- umap/static/umap/css/icon.css +8 -0
- umap/static/umap/css/importers.css +51 -0
- umap/static/umap/css/panel.css +18 -57
- umap/static/umap/css/tooltip.css +59 -0
- umap/static/umap/css/window.css +35 -0
- umap/static/umap/img/16-white.svg +1 -3
- umap/static/umap/img/alert-icon-error.svg +8 -0
- umap/static/umap/img/alert-icon-info.svg +4 -0
- umap/static/umap/img/alert-icon-success.svg +3 -0
- umap/static/umap/img/icon-external-link.svg +3 -0
- umap/static/umap/img/importers/communesfr.svg +5 -0
- umap/static/umap/img/importers/datasets.svg +13 -0
- umap/static/umap/img/importers/geodatamine.svg +10 -0
- umap/static/umap/img/importers/overpass.svg +7 -0
- umap/static/umap/img/importers/random.svg +18 -0
- umap/static/umap/img/importers/random1.svg +4 -0
- umap/static/umap/img/importers/random2.svg +4 -0
- umap/static/umap/img/source/16-white.svg +2 -4
- umap/static/umap/js/components/alerts/alert.css +160 -0
- umap/static/umap/js/components/alerts/alert.js +169 -0
- umap/static/umap/js/components/base.js +54 -0
- umap/static/umap/js/modules/autocomplete.js +347 -0
- umap/static/umap/js/modules/browser.js +14 -21
- umap/static/umap/js/modules/caption.js +119 -0
- umap/static/umap/js/modules/global.js +37 -11
- umap/static/umap/js/modules/help.js +255 -0
- umap/static/umap/js/modules/importer.js +308 -0
- umap/static/umap/js/modules/importers/communesfr.js +44 -0
- umap/static/umap/js/modules/importers/datasets.js +42 -0
- umap/static/umap/js/modules/importers/geodatamine.js +95 -0
- umap/static/umap/js/modules/importers/overpass.js +84 -0
- umap/static/umap/js/modules/request.js +12 -14
- umap/static/umap/js/modules/rules.js +241 -0
- umap/static/umap/js/modules/schema.js +63 -14
- umap/static/umap/js/modules/sync/engine.js +93 -0
- umap/static/umap/js/modules/sync/updaters.js +109 -0
- umap/static/umap/js/modules/sync/websocket.js +25 -0
- umap/static/umap/js/modules/ui/dialog.js +52 -0
- umap/static/umap/js/modules/{panel.js → ui/panel.js} +37 -20
- umap/static/umap/js/modules/ui/tooltip.js +116 -0
- umap/static/umap/js/modules/utils.js +25 -18
- umap/static/umap/js/umap.controls.js +37 -112
- umap/static/umap/js/umap.core.js +1 -327
- umap/static/umap/js/umap.features.js +77 -29
- umap/static/umap/js/umap.forms.js +17 -19
- umap/static/umap/js/umap.js +265 -228
- umap/static/umap/js/umap.layer.js +154 -76
- umap/static/umap/js/umap.permissions.js +5 -9
- umap/static/umap/js/umap.popup.js +2 -1
- umap/static/umap/js/umap.tableeditor.js +8 -8
- umap/static/umap/locale/am_ET.js +51 -16
- umap/static/umap/locale/am_ET.json +51 -16
- umap/static/umap/locale/ar.js +51 -16
- umap/static/umap/locale/ar.json +51 -16
- umap/static/umap/locale/ast.js +51 -16
- umap/static/umap/locale/ast.json +51 -16
- umap/static/umap/locale/bg.js +51 -16
- umap/static/umap/locale/bg.json +51 -16
- umap/static/umap/locale/br.js +55 -20
- umap/static/umap/locale/br.json +55 -20
- umap/static/umap/locale/ca.js +51 -16
- umap/static/umap/locale/ca.json +51 -16
- umap/static/umap/locale/cs_CZ.js +93 -58
- umap/static/umap/locale/cs_CZ.json +93 -58
- umap/static/umap/locale/da.js +51 -16
- umap/static/umap/locale/da.json +51 -16
- umap/static/umap/locale/de.js +56 -21
- umap/static/umap/locale/de.json +56 -21
- umap/static/umap/locale/el.js +51 -16
- umap/static/umap/locale/el.json +51 -16
- umap/static/umap/locale/en.js +52 -16
- umap/static/umap/locale/en.json +52 -16
- umap/static/umap/locale/en_US.json +51 -16
- umap/static/umap/locale/es.js +51 -16
- umap/static/umap/locale/es.json +51 -16
- umap/static/umap/locale/et.js +51 -16
- umap/static/umap/locale/et.json +51 -16
- umap/static/umap/locale/eu.js +51 -16
- umap/static/umap/locale/eu.json +51 -16
- umap/static/umap/locale/fa_IR.js +51 -16
- umap/static/umap/locale/fa_IR.json +51 -16
- umap/static/umap/locale/fi.js +51 -16
- umap/static/umap/locale/fi.json +51 -16
- umap/static/umap/locale/fr.js +61 -25
- umap/static/umap/locale/fr.json +61 -25
- umap/static/umap/locale/gl.js +51 -16
- umap/static/umap/locale/gl.json +51 -16
- umap/static/umap/locale/he.js +51 -16
- umap/static/umap/locale/he.json +51 -16
- umap/static/umap/locale/hr.js +51 -16
- umap/static/umap/locale/hr.json +51 -16
- umap/static/umap/locale/hu.js +51 -16
- umap/static/umap/locale/hu.json +51 -16
- umap/static/umap/locale/id.js +51 -16
- umap/static/umap/locale/id.json +51 -16
- umap/static/umap/locale/is.js +51 -16
- umap/static/umap/locale/is.json +51 -16
- umap/static/umap/locale/it.js +51 -16
- umap/static/umap/locale/it.json +51 -16
- umap/static/umap/locale/ja.js +51 -16
- umap/static/umap/locale/ja.json +51 -16
- umap/static/umap/locale/ko.js +51 -16
- umap/static/umap/locale/ko.json +51 -16
- umap/static/umap/locale/lt.js +51 -16
- umap/static/umap/locale/lt.json +51 -16
- umap/static/umap/locale/ms.js +51 -16
- umap/static/umap/locale/ms.json +51 -16
- umap/static/umap/locale/nl.js +51 -16
- umap/static/umap/locale/nl.json +51 -16
- umap/static/umap/locale/no.js +51 -16
- umap/static/umap/locale/no.json +51 -16
- umap/static/umap/locale/pl.js +93 -58
- umap/static/umap/locale/pl.json +93 -58
- umap/static/umap/locale/pl_PL.json +51 -16
- umap/static/umap/locale/pt.js +215 -180
- umap/static/umap/locale/pt.json +215 -180
- umap/static/umap/locale/pt_BR.js +51 -16
- umap/static/umap/locale/pt_BR.json +51 -16
- umap/static/umap/locale/pt_PT.js +51 -16
- umap/static/umap/locale/pt_PT.json +51 -16
- umap/static/umap/locale/ro.js +51 -16
- umap/static/umap/locale/ro.json +51 -16
- umap/static/umap/locale/ru.js +51 -16
- umap/static/umap/locale/ru.json +51 -16
- umap/static/umap/locale/si.js +51 -16
- umap/static/umap/locale/si.json +51 -16
- umap/static/umap/locale/sk_SK.js +51 -16
- umap/static/umap/locale/sk_SK.json +51 -16
- umap/static/umap/locale/sl.js +51 -16
- umap/static/umap/locale/sl.json +51 -16
- umap/static/umap/locale/sr.js +51 -16
- umap/static/umap/locale/sr.json +51 -16
- umap/static/umap/locale/sv.js +51 -16
- umap/static/umap/locale/sv.json +51 -16
- umap/static/umap/locale/th_TH.js +51 -16
- umap/static/umap/locale/th_TH.json +51 -16
- umap/static/umap/locale/tr.js +51 -16
- umap/static/umap/locale/tr.json +51 -16
- umap/static/umap/locale/uk_UA.js +51 -16
- umap/static/umap/locale/uk_UA.json +51 -16
- umap/static/umap/locale/vi.js +51 -16
- umap/static/umap/locale/vi.json +51 -16
- umap/static/umap/locale/vi_VN.json +51 -16
- umap/static/umap/locale/zh.js +51 -16
- umap/static/umap/locale/zh.json +51 -16
- umap/static/umap/locale/zh_CN.json +51 -16
- umap/static/umap/locale/zh_TW.Big5.json +51 -16
- umap/static/umap/locale/zh_TW.js +51 -16
- umap/static/umap/locale/zh_TW.json +51 -16
- umap/static/umap/map.css +40 -53
- umap/static/umap/unittests/sync.js +105 -0
- umap/static/umap/unittests/utils.js +78 -36
- umap/static/umap/vars.css +19 -1
- umap/static/umap/vendors/dompurify/purify.es.js +50 -15
- umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
- umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +2 -2
- umap/templates/umap/components/alerts/alert.html +89 -0
- umap/templates/umap/content.html +4 -3
- umap/templates/umap/css.html +4 -0
- umap/templates/umap/home.html +3 -0
- umap/templates/umap/js.html +0 -3
- umap/templates/umap/map_init.html +2 -8
- umap/templates/umap/messages.html +9 -11
- umap/templates/umap/search.html +3 -0
- umap/tests/base.py +3 -0
- umap/tests/integration/conftest.py +30 -0
- umap/tests/integration/test_anonymous_owned_map.py +8 -13
- umap/tests/integration/test_browser.py +81 -6
- umap/tests/integration/test_caption.py +27 -0
- umap/tests/integration/test_conditional_rules.py +201 -0
- umap/tests/integration/test_dashboard.py +1 -1
- umap/tests/integration/test_datalayer.py +2 -3
- umap/tests/integration/test_edit_datalayer.py +32 -3
- umap/tests/integration/test_edit_map.py +1 -1
- umap/tests/integration/test_facets_browser.py +7 -4
- umap/tests/integration/test_import.py +185 -49
- umap/tests/integration/test_map.py +31 -17
- umap/tests/integration/{test_collaborative_editing.py → test_optimistic_merge.py} +7 -7
- umap/tests/integration/test_owned_map.py +1 -1
- umap/tests/integration/test_picto.py +2 -2
- umap/tests/integration/test_statics.py +1 -1
- umap/tests/integration/test_view_marker.py +19 -2
- umap/tests/integration/test_websocket_sync.py +283 -0
- umap/tests/settings.py +5 -0
- umap/tests/test_datalayer_views.py +0 -1
- umap/tests/test_views.py +53 -0
- umap/urls.py +5 -0
- umap/views.py +40 -11
- umap/websocket_server.py +92 -0
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/METADATA +13 -11
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/RECORD +208 -172
- umap/static/umap/js/umap.autocomplete.js +0 -341
- umap/static/umap/js/umap.importer.js +0 -187
- umap/static/umap/js/umap.ui.js +0 -190
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/WHEEL +0 -0
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
const EVENT_PREFIX = 'umap'
|
|
2
|
+
|
|
3
|
+
export class uMapElement extends HTMLElement {
|
|
4
|
+
static emit(type, detail = {}) {
|
|
5
|
+
const event = new CustomEvent(`${EVENT_PREFIX}:${type}`, {
|
|
6
|
+
bubbles: true,
|
|
7
|
+
cancelable: true,
|
|
8
|
+
detail: detail,
|
|
9
|
+
})
|
|
10
|
+
return document.dispatchEvent(event)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Retrieves a clone of the content template either using the `template`
|
|
15
|
+
* attribute or an id mathing the name of the component:
|
|
16
|
+
*
|
|
17
|
+
* `umap-alert` component => `umap-alert-template` template id lookup.
|
|
18
|
+
*/
|
|
19
|
+
get template() {
|
|
20
|
+
return document
|
|
21
|
+
.getElementById(this.getAttribute('template') || `${this.localName}-template`)
|
|
22
|
+
.content.cloneNode(true)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
constructor() {
|
|
26
|
+
super()
|
|
27
|
+
this.append(this.template)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Special method which allows to easily listen to events
|
|
32
|
+
* and have automated event to component method binding.
|
|
33
|
+
*
|
|
34
|
+
* For instance listening to `alert` will then call `onAlert`.
|
|
35
|
+
*/
|
|
36
|
+
handleEvent(event) {
|
|
37
|
+
event.preventDefault()
|
|
38
|
+
// From `umap:alert` to `alert`.
|
|
39
|
+
const eventName = event.type.replace(`${EVENT_PREFIX}:`, '')
|
|
40
|
+
// From `alert` event type to `onAlert` call against that class.
|
|
41
|
+
this[`on${eventName.charAt(0).toUpperCase() + eventName.slice(1)}`](event)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
listen(eventName) {
|
|
45
|
+
// Using `this` as a listener will call `handleEvent` under the hood.
|
|
46
|
+
document.addEventListener(`${EVENT_PREFIX}:${eventName}`, this)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function register(klass, name) {
|
|
51
|
+
if ('customElements' in globalThis && !customElements.get(name)) {
|
|
52
|
+
customElements.define(name, klass)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DomUtil,
|
|
3
|
+
DomEvent,
|
|
4
|
+
setOptions,
|
|
5
|
+
Util,
|
|
6
|
+
} from '../../vendors/leaflet/leaflet-src.esm.js'
|
|
7
|
+
import { translate } from './i18n.js'
|
|
8
|
+
import { Request, ServerRequest } from './request.js'
|
|
9
|
+
|
|
10
|
+
export class BaseAutocomplete {
|
|
11
|
+
constructor(el, options) {
|
|
12
|
+
this.el = el
|
|
13
|
+
this.options = {
|
|
14
|
+
placeholder: translate('Start typing...'),
|
|
15
|
+
emptyMessage: translate('No result'),
|
|
16
|
+
allowFree: true,
|
|
17
|
+
minChar: 2,
|
|
18
|
+
maxResults: 5,
|
|
19
|
+
}
|
|
20
|
+
this.cache = ''
|
|
21
|
+
this.results = []
|
|
22
|
+
this._current = null
|
|
23
|
+
setOptions(this, options)
|
|
24
|
+
this.createInput()
|
|
25
|
+
this.createContainer()
|
|
26
|
+
this.selectedContainer = this.initSelectedContainer()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get current() {
|
|
30
|
+
return this._current
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
set current(index) {
|
|
34
|
+
if (typeof index === 'object') {
|
|
35
|
+
index = this.resultToIndex(index)
|
|
36
|
+
}
|
|
37
|
+
this._current = index
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
createInput() {
|
|
41
|
+
this.input = DomUtil.element({
|
|
42
|
+
tagName: 'input',
|
|
43
|
+
type: 'text',
|
|
44
|
+
parent: this.el,
|
|
45
|
+
placeholder: this.options.placeholder,
|
|
46
|
+
autocomplete: 'off',
|
|
47
|
+
className: this.options.className,
|
|
48
|
+
})
|
|
49
|
+
DomEvent.on(this.input, 'keydown', this.onKeyDown, this)
|
|
50
|
+
DomEvent.on(this.input, 'keyup', this.onKeyUp, this)
|
|
51
|
+
DomEvent.on(this.input, 'blur', this.onBlur, this)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
createContainer() {
|
|
55
|
+
this.container = DomUtil.element({
|
|
56
|
+
tagName: 'ul',
|
|
57
|
+
parent: document.body,
|
|
58
|
+
className: 'umap-autocomplete',
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
resizeContainer() {
|
|
63
|
+
const l = this.getLeft(this.input)
|
|
64
|
+
const t = this.getTop(this.input) + this.input.offsetHeight
|
|
65
|
+
this.container.style.left = `${l}px`
|
|
66
|
+
this.container.style.top = `${t}px`
|
|
67
|
+
const width = this.options.width ? this.options.width : this.input.offsetWidth - 2
|
|
68
|
+
this.container.style.width = `${width}px`
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
onKeyDown(e) {
|
|
72
|
+
switch (e.key) {
|
|
73
|
+
case 'Tab':
|
|
74
|
+
if (this.current !== null) this.setChoice()
|
|
75
|
+
DomEvent.stop(e)
|
|
76
|
+
break
|
|
77
|
+
case 'Enter':
|
|
78
|
+
DomEvent.stop(e)
|
|
79
|
+
this.setChoice()
|
|
80
|
+
break
|
|
81
|
+
case 'Escape':
|
|
82
|
+
DomEvent.stop(e)
|
|
83
|
+
this.hide()
|
|
84
|
+
break
|
|
85
|
+
case 'ArrowDown':
|
|
86
|
+
if (this.results.length > 0) {
|
|
87
|
+
if (this.current !== null && this.current < this.results.length - 1) {
|
|
88
|
+
// what if one result?
|
|
89
|
+
this.current++
|
|
90
|
+
this.highlight()
|
|
91
|
+
} else if (this.current === null) {
|
|
92
|
+
this.current = 0
|
|
93
|
+
this.highlight()
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
break
|
|
97
|
+
case 'ArrowUp':
|
|
98
|
+
if (this.current !== null) {
|
|
99
|
+
DomEvent.stop(e)
|
|
100
|
+
}
|
|
101
|
+
if (this.results.length > 0) {
|
|
102
|
+
if (this.current > 0) {
|
|
103
|
+
this.current--
|
|
104
|
+
this.highlight()
|
|
105
|
+
} else if (this.current === 0) {
|
|
106
|
+
this.current = null
|
|
107
|
+
this.highlight()
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
break
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
onKeyUp(e) {
|
|
115
|
+
const special = [
|
|
116
|
+
'Tab',
|
|
117
|
+
'Enter',
|
|
118
|
+
'ArrowLeft',
|
|
119
|
+
'ArrowRight',
|
|
120
|
+
'ArrowDown',
|
|
121
|
+
'ArrowUp',
|
|
122
|
+
'Meta',
|
|
123
|
+
'Shift',
|
|
124
|
+
'Alt',
|
|
125
|
+
'Control',
|
|
126
|
+
]
|
|
127
|
+
if (!special.includes(e.key)) {
|
|
128
|
+
this.search()
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
onBlur() {
|
|
133
|
+
setTimeout(() => this.hide(), 100)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
clear() {
|
|
137
|
+
this.results = []
|
|
138
|
+
this.current = null
|
|
139
|
+
this.cache = ''
|
|
140
|
+
this.container.innerHTML = ''
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
hide() {
|
|
144
|
+
this.clear()
|
|
145
|
+
this.container.style.display = 'none'
|
|
146
|
+
this.input.value = ''
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
setChoice(choice) {
|
|
150
|
+
choice = choice || this.results[this.current]
|
|
151
|
+
if (choice) {
|
|
152
|
+
this.input.value = choice.item.label
|
|
153
|
+
this.options.on_select(choice)
|
|
154
|
+
this.displaySelected(choice)
|
|
155
|
+
this.hide()
|
|
156
|
+
if (this.options.callback) {
|
|
157
|
+
this.options.callback.bind(this)(choice)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
createResult(item) {
|
|
163
|
+
const el = DomUtil.element({
|
|
164
|
+
tagName: 'li',
|
|
165
|
+
parent: this.container,
|
|
166
|
+
textContent: item.label,
|
|
167
|
+
})
|
|
168
|
+
const result = {
|
|
169
|
+
item: item,
|
|
170
|
+
el: el,
|
|
171
|
+
}
|
|
172
|
+
DomEvent.on(el, 'mouseover', () => {
|
|
173
|
+
this.current = result
|
|
174
|
+
this.highlight()
|
|
175
|
+
})
|
|
176
|
+
DomEvent.on(el, 'mousedown', () => this.setChoice())
|
|
177
|
+
return result
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
resultToIndex(result) {
|
|
181
|
+
return this.results.findIndex((item) => item.item.value === result.item.value)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
handleResults(data) {
|
|
185
|
+
this.clear()
|
|
186
|
+
this.container.style.display = 'block'
|
|
187
|
+
this.resizeContainer()
|
|
188
|
+
data.forEach((item) => {
|
|
189
|
+
this.results.push(this.createResult(item))
|
|
190
|
+
})
|
|
191
|
+
this.current = 0
|
|
192
|
+
this.highlight()
|
|
193
|
+
//TODO manage no results
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
highlight() {
|
|
197
|
+
this.results.forEach((result, index) => {
|
|
198
|
+
if (index === this.current) DomUtil.addClass(result.el, 'on')
|
|
199
|
+
else DomUtil.removeClass(result.el, 'on')
|
|
200
|
+
})
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
getLeft(el) {
|
|
204
|
+
let tmp = el.offsetLeft
|
|
205
|
+
el = el.offsetParent
|
|
206
|
+
while (el) {
|
|
207
|
+
tmp += el.offsetLeft
|
|
208
|
+
el = el.offsetParent
|
|
209
|
+
}
|
|
210
|
+
return tmp
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
getTop(el) {
|
|
214
|
+
let tmp = el.offsetTop
|
|
215
|
+
el = el.offsetParent
|
|
216
|
+
while (el) {
|
|
217
|
+
tmp += el.offsetTop
|
|
218
|
+
el = el.offsetParent
|
|
219
|
+
}
|
|
220
|
+
return tmp
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export class BaseAjax extends BaseAutocomplete {
|
|
225
|
+
constructor(el, options) {
|
|
226
|
+
super(el, options)
|
|
227
|
+
this.setUrl()
|
|
228
|
+
this.initRequest()
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
setUrl() {
|
|
232
|
+
this.url = this.options?.url
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
initRequest() {
|
|
236
|
+
this.request = new Request()
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
optionToResult(option) {
|
|
240
|
+
return {
|
|
241
|
+
value: option.value,
|
|
242
|
+
label: option.innerHTML,
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async search() {
|
|
247
|
+
let val = this.input.value
|
|
248
|
+
if (val.length < this.options.minChar) {
|
|
249
|
+
this.clear()
|
|
250
|
+
return
|
|
251
|
+
}
|
|
252
|
+
if (val === this.cache) return
|
|
253
|
+
else this.cache = val
|
|
254
|
+
val = val.toLowerCase()
|
|
255
|
+
const url = Util.template(this.url, { q: encodeURIComponent(val) })
|
|
256
|
+
this.handleResults(await this._search(url))
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
async _search(url) {
|
|
260
|
+
const response = await this.request.get(url)
|
|
261
|
+
if (response && response.ok) {
|
|
262
|
+
return await response.json()
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
class BaseServerAjax extends BaseAjax {
|
|
268
|
+
setUrl() {
|
|
269
|
+
this.url = '/agnocomplete/AutocompleteUser/?q={q}'
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
initRequest() {
|
|
273
|
+
this.server = new ServerRequest()
|
|
274
|
+
}
|
|
275
|
+
async _search(url) {
|
|
276
|
+
const [{ data }, response] = await this.server.get(url)
|
|
277
|
+
return data
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export const SingleMixin = (Base) =>
|
|
282
|
+
class extends Base {
|
|
283
|
+
initSelectedContainer() {
|
|
284
|
+
return DomUtil.after(
|
|
285
|
+
this.input,
|
|
286
|
+
DomUtil.element({ tagName: 'div', className: 'umap-singleresult' })
|
|
287
|
+
)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
displaySelected(result) {
|
|
291
|
+
const result_el = DomUtil.element({
|
|
292
|
+
tagName: 'div',
|
|
293
|
+
parent: this.selectedContainer,
|
|
294
|
+
})
|
|
295
|
+
result_el.textContent = result.item.label
|
|
296
|
+
const close = DomUtil.element({
|
|
297
|
+
tagName: 'span',
|
|
298
|
+
parent: result_el,
|
|
299
|
+
className: 'close',
|
|
300
|
+
textContent: '×',
|
|
301
|
+
})
|
|
302
|
+
this.input.style.display = 'none'
|
|
303
|
+
DomEvent.on(
|
|
304
|
+
close,
|
|
305
|
+
'click',
|
|
306
|
+
function () {
|
|
307
|
+
this.selectedContainer.innerHTML = ''
|
|
308
|
+
this.input.style.display = 'block'
|
|
309
|
+
},
|
|
310
|
+
this
|
|
311
|
+
)
|
|
312
|
+
this.hide()
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export const MultipleMixin = (Base) =>
|
|
317
|
+
class extends Base {
|
|
318
|
+
initSelectedContainer() {
|
|
319
|
+
return DomUtil.after(
|
|
320
|
+
this.input,
|
|
321
|
+
DomUtil.element({ tagName: 'ul', className: 'umap-multiresult' })
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
displaySelected(result) {
|
|
326
|
+
const result_el = DomUtil.element({
|
|
327
|
+
tagName: 'li',
|
|
328
|
+
parent: this.selectedContainer,
|
|
329
|
+
})
|
|
330
|
+
result_el.textContent = result.item.label
|
|
331
|
+
const close = DomUtil.element({
|
|
332
|
+
tagName: 'span',
|
|
333
|
+
parent: result_el,
|
|
334
|
+
className: 'close',
|
|
335
|
+
textContent: '×',
|
|
336
|
+
})
|
|
337
|
+
DomEvent.on(close, 'click', () => {
|
|
338
|
+
this.selectedContainer.removeChild(result_el)
|
|
339
|
+
this.options.on_unselect(result)
|
|
340
|
+
})
|
|
341
|
+
this.hide()
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
export class AjaxAutocompleteMultiple extends MultipleMixin(BaseServerAjax) {}
|
|
346
|
+
|
|
347
|
+
export class AjaxAutocomplete extends SingleMixin(BaseServerAjax) {}
|
|
@@ -9,18 +9,7 @@ export default class Browser {
|
|
|
9
9
|
filter: '',
|
|
10
10
|
inBbox: false,
|
|
11
11
|
}
|
|
12
|
-
this.
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
set mode(value) {
|
|
16
|
-
// Store the mode so we can respect it when we redraw
|
|
17
|
-
if (['data', 'filters'].includes(value)) this.map.panel.mode = 'expanded'
|
|
18
|
-
else if (value === 'layers') this.map.panel.mode = 'condensed'
|
|
19
|
-
this._mode = value
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get mode() {
|
|
23
|
-
return this._mode
|
|
12
|
+
this.mode = 'layers'
|
|
24
13
|
}
|
|
25
14
|
|
|
26
15
|
addFeature(feature, parent) {
|
|
@@ -73,7 +62,7 @@ export default class Browser {
|
|
|
73
62
|
|
|
74
63
|
addDataLayer(datalayer, parent) {
|
|
75
64
|
let className = `datalayer ${datalayer.getHidableClass()}`
|
|
76
|
-
if (this.
|
|
65
|
+
if (this.mode !== 'layers') className += ' show-list'
|
|
77
66
|
const container = DomUtil.create('div', className, parent),
|
|
78
67
|
headline = DomUtil.create('h5', '', container)
|
|
79
68
|
container.id = this.datalayerId(datalayer)
|
|
@@ -87,7 +76,7 @@ export default class Browser {
|
|
|
87
76
|
const parent = DomUtil.get(this.datalayerId(datalayer))
|
|
88
77
|
// Panel is not open
|
|
89
78
|
if (!parent) return
|
|
90
|
-
|
|
79
|
+
parent.classList.toggle('off', !datalayer.isVisible())
|
|
91
80
|
const container = parent.querySelector('ul')
|
|
92
81
|
const headline = parent.querySelector('h5')
|
|
93
82
|
const toggleList = () => parent.classList.toggle('show-list')
|
|
@@ -154,14 +143,12 @@ export default class Browser {
|
|
|
154
143
|
open(mode) {
|
|
155
144
|
// Force only if mode is known, otherwise keep current mode.
|
|
156
145
|
if (mode) this.mode = mode
|
|
157
|
-
// Get once but use it for each feature later
|
|
158
|
-
this.filterKeys = this.map.getFilterKeys()
|
|
159
146
|
const container = DomUtil.create('div')
|
|
160
147
|
// HOTFIX. Remove when this is released:
|
|
161
148
|
// https://github.com/Leaflet/Leaflet/pull/9052
|
|
162
149
|
DomEvent.disableClickPropagation(container)
|
|
163
150
|
|
|
164
|
-
DomUtil.createTitle(container, translate('
|
|
151
|
+
DomUtil.createTitle(container, translate('Data browser'), 'icon-layers')
|
|
165
152
|
const formContainer = DomUtil.createFieldset(container, L._('Filters'), {
|
|
166
153
|
on: this.mode === 'filters',
|
|
167
154
|
className: 'filters',
|
|
@@ -201,7 +188,11 @@ export default class Browser {
|
|
|
201
188
|
if (filtersBuilder) filtersBuilder.form.reset()
|
|
202
189
|
})
|
|
203
190
|
DomUtil.createIcon(reset, 'icon-restore')
|
|
204
|
-
DomUtil.element({
|
|
191
|
+
DomUtil.element({
|
|
192
|
+
tagName: 'span',
|
|
193
|
+
parent: reset,
|
|
194
|
+
textContent: translate('Reset all'),
|
|
195
|
+
})
|
|
205
196
|
|
|
206
197
|
this.map.panel.open({
|
|
207
198
|
content: container,
|
|
@@ -212,9 +203,11 @@ export default class Browser {
|
|
|
212
203
|
}
|
|
213
204
|
|
|
214
205
|
static backButton(map) {
|
|
215
|
-
const button = DomUtil.
|
|
216
|
-
|
|
217
|
-
|
|
206
|
+
const button = DomUtil.createButtonIcon(
|
|
207
|
+
DomUtil.create('li', '', undefined),
|
|
208
|
+
'icon-back',
|
|
209
|
+
translate('Back to browser')
|
|
210
|
+
)
|
|
218
211
|
// Fixme: remove me when this is merged and released
|
|
219
212
|
// https://github.com/Leaflet/Leaflet/pull/9052
|
|
220
213
|
DomEvent.disableClickPropagation(button)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
|
|
2
|
+
import { translate } from './i18n.js'
|
|
3
|
+
import * as Utils from './utils.js'
|
|
4
|
+
|
|
5
|
+
export default class Caption {
|
|
6
|
+
constructor(map) {
|
|
7
|
+
this.map = map
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
isOpen() {
|
|
11
|
+
return Boolean(document.querySelector('.on .umap-caption'))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
refresh() {
|
|
15
|
+
if (!this.isOpen()) return
|
|
16
|
+
this.open()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
open() {
|
|
20
|
+
const container = DomUtil.create('div', 'umap-caption')
|
|
21
|
+
const hgroup = DomUtil.element({tagName: 'hgroup', parent: container})
|
|
22
|
+
DomUtil.createTitle(hgroup, this.map.options.name, 'icon-caption icon-block')
|
|
23
|
+
this.map.permissions.addOwnerLink('h4', hgroup)
|
|
24
|
+
if (this.map.options.description) {
|
|
25
|
+
const description = DomUtil.element({
|
|
26
|
+
tagName: 'div',
|
|
27
|
+
className: 'umap-map-description text',
|
|
28
|
+
safeHTML: Utils.toHTML(this.map.options.description),
|
|
29
|
+
parent: container,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
const datalayerContainer = DomUtil.create('div', 'datalayer-container', container)
|
|
33
|
+
this.map.eachDataLayerReverse((datalayer) =>
|
|
34
|
+
this.addDataLayer(datalayer, datalayerContainer)
|
|
35
|
+
)
|
|
36
|
+
const creditsContainer = DomUtil.create('div', 'credits-container', container)
|
|
37
|
+
this.addCredits(creditsContainer)
|
|
38
|
+
this.map.panel.open({ content: container })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
addDataLayer(datalayer, container) {
|
|
42
|
+
if (!datalayer.options.inCaption) return
|
|
43
|
+
const p = DomUtil.create('p', 'datalayer-legend', container),
|
|
44
|
+
legend = DomUtil.create('span', '', p),
|
|
45
|
+
headline = DomUtil.create('strong', '', p)
|
|
46
|
+
datalayer.onceLoaded(() => {
|
|
47
|
+
datalayer.renderLegend(legend)
|
|
48
|
+
if (datalayer.options.description) {
|
|
49
|
+
DomUtil.element({
|
|
50
|
+
tagName: 'span',
|
|
51
|
+
parent: p,
|
|
52
|
+
safeHTML: Utils.toHTML(datalayer.options.description),
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
datalayer.renderToolbox(headline)
|
|
57
|
+
DomUtil.add('span', '', headline, `${datalayer.options.name} `)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
addCredits(container) {
|
|
61
|
+
const credits = DomUtil.createFieldset(container, translate('Credits'))
|
|
62
|
+
let title = DomUtil.add('h5', '', credits, translate('User content credits'))
|
|
63
|
+
if (this.map.options.shortCredit || this.map.options.longCredit) {
|
|
64
|
+
DomUtil.element({
|
|
65
|
+
tagName: 'p',
|
|
66
|
+
parent: credits,
|
|
67
|
+
safeHTML: Utils.toHTML(
|
|
68
|
+
this.map.options.longCredit || this.map.options.shortCredit
|
|
69
|
+
),
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
if (this.map.options.licence) {
|
|
73
|
+
const licence = DomUtil.add(
|
|
74
|
+
'p',
|
|
75
|
+
'',
|
|
76
|
+
credits,
|
|
77
|
+
`${translate('Map user content has been published under licence')} `
|
|
78
|
+
)
|
|
79
|
+
DomUtil.createLink(
|
|
80
|
+
'',
|
|
81
|
+
licence,
|
|
82
|
+
this.map.options.licence.name,
|
|
83
|
+
this.map.options.licence.url
|
|
84
|
+
)
|
|
85
|
+
} else {
|
|
86
|
+
DomUtil.add('p', '', credits, translate('No licence has been set'))
|
|
87
|
+
}
|
|
88
|
+
title = DomUtil.create('h5', '', credits)
|
|
89
|
+
title.textContent = translate('Map background credits')
|
|
90
|
+
const tilelayerCredit = DomUtil.create('p', '', credits)
|
|
91
|
+
DomUtil.element({
|
|
92
|
+
tagName: 'strong',
|
|
93
|
+
parent: tilelayerCredit,
|
|
94
|
+
textContent: `${this.map.selected_tilelayer.options.name} `,
|
|
95
|
+
})
|
|
96
|
+
DomUtil.element({
|
|
97
|
+
tagName: 'span',
|
|
98
|
+
parent: tilelayerCredit,
|
|
99
|
+
safeHTML: this.map.selected_tilelayer.getAttribution(),
|
|
100
|
+
})
|
|
101
|
+
const urls = {
|
|
102
|
+
leaflet: 'http://leafletjs.com',
|
|
103
|
+
django: 'https://www.djangoproject.com',
|
|
104
|
+
umap: 'https://umap-project.org/',
|
|
105
|
+
changelog: 'https://docs.umap-project.org/en/master/changelog/',
|
|
106
|
+
version: this.map.options.umap_version,
|
|
107
|
+
}
|
|
108
|
+
const creditHTML = translate(
|
|
109
|
+
`
|
|
110
|
+
Powered by <a href="{leaflet}">Leaflet</a> and
|
|
111
|
+
<a href="{django}">Django</a>,
|
|
112
|
+
glued by <a href="{umap}">uMap project</a>
|
|
113
|
+
(version <a href="{changelog}">{version}</a>).
|
|
114
|
+
`,
|
|
115
|
+
urls
|
|
116
|
+
)
|
|
117
|
+
DomUtil.element({ tagName: 'p', innerHTML: creditHTML, parent: credits })
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -1,28 +1,54 @@
|
|
|
1
1
|
import URLs from './urls.js'
|
|
2
2
|
import Browser from './browser.js'
|
|
3
3
|
import Facets from './facets.js'
|
|
4
|
-
import
|
|
4
|
+
import Caption from './caption.js'
|
|
5
|
+
import { Panel, EditPanel, FullPanel } from './ui/panel.js'
|
|
6
|
+
import Dialog from './ui/dialog.js'
|
|
7
|
+
import Tooltip from './ui/tooltip.js'
|
|
8
|
+
import Rules from './rules.js'
|
|
5
9
|
import * as Utils from './utils.js'
|
|
6
10
|
import { SCHEMA } from './schema.js'
|
|
7
11
|
import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js'
|
|
12
|
+
import { AjaxAutocomplete, AjaxAutocompleteMultiple } from './autocomplete.js'
|
|
8
13
|
import Orderable from './orderable.js'
|
|
14
|
+
import Importer from './importer.js'
|
|
15
|
+
import Help from './help.js'
|
|
16
|
+
import { SyncEngine } from './sync/engine.js'
|
|
17
|
+
import {
|
|
18
|
+
uMapAlert as Alert,
|
|
19
|
+
uMapAlertCreation as AlertCreation,
|
|
20
|
+
uMapAlertConflict as AlertConflict,
|
|
21
|
+
} from '../components/alerts/alert.js'
|
|
9
22
|
|
|
10
23
|
// Import modules and export them to the global scope.
|
|
11
24
|
// For the not yet module-compatible JS out there.
|
|
12
25
|
|
|
26
|
+
// By alphabetic order
|
|
13
27
|
window.U = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
NOKError,
|
|
28
|
+
Alert,
|
|
29
|
+
AlertCreation,
|
|
30
|
+
AlertConflict,
|
|
31
|
+
AjaxAutocomplete,
|
|
32
|
+
AjaxAutocompleteMultiple,
|
|
20
33
|
Browser,
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
Caption,
|
|
35
|
+
Dialog,
|
|
23
36
|
EditPanel,
|
|
37
|
+
Facets,
|
|
24
38
|
FullPanel,
|
|
25
|
-
|
|
26
|
-
|
|
39
|
+
Help,
|
|
40
|
+
HTTPError,
|
|
41
|
+
Importer,
|
|
42
|
+
NOKError,
|
|
27
43
|
Orderable,
|
|
44
|
+
Panel,
|
|
45
|
+
Request,
|
|
46
|
+
RequestError,
|
|
47
|
+
Rules,
|
|
48
|
+
SCHEMA,
|
|
49
|
+
ServerRequest,
|
|
50
|
+
SyncEngine,
|
|
51
|
+
Tooltip,
|
|
52
|
+
URLs,
|
|
53
|
+
Utils,
|
|
28
54
|
}
|