umap-project 2.8.2__py3-none-any.whl → 2.9.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/asgi.py +12 -7
- umap/context_processors.py +1 -0
- umap/locale/en/LC_MESSAGES/django.po +102 -59
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +105 -61
- umap/management/commands/empty_trash.py +12 -1
- umap/migrations/0026_datalayer_modified_at_datalayer_share_status.py +26 -0
- umap/models.py +23 -3
- umap/settings/base.py +4 -1
- umap/static/umap/base.css +1 -1
- umap/static/umap/content.css +2 -22
- umap/static/umap/css/bar.css +7 -10
- umap/static/umap/css/form.css +28 -29
- umap/static/umap/css/icon.css +8 -2
- umap/static/umap/css/panel.css +2 -1
- umap/static/umap/css/tooltip.css +33 -31
- umap/static/umap/img/16-white.svg +2 -0
- umap/static/umap/img/16.svg +1 -1
- umap/static/umap/img/providers/bitbucket.png +0 -0
- umap/static/umap/img/providers/github.png +0 -0
- umap/static/umap/img/providers/keycloak.png +0 -0
- umap/static/umap/img/providers/openstreetmap-oauth2.png +0 -0
- umap/static/umap/img/providers/twitter-oauth2.png +0 -0
- umap/static/umap/img/source/16-white.svg +3 -1
- umap/static/umap/img/source/16.svg +1 -1
- umap/static/umap/js/components/alerts/alert.js +4 -1
- umap/static/umap/js/modules/browser.js +6 -6
- umap/static/umap/js/modules/caption.js +30 -7
- umap/static/umap/js/modules/data/features.js +21 -24
- umap/static/umap/js/modules/data/layer.js +71 -33
- umap/static/umap/js/modules/form/builder.js +241 -0
- umap/static/umap/js/modules/form/fields.js +1338 -0
- umap/static/umap/js/modules/formatter.js +5 -8
- umap/static/umap/js/modules/help.js +3 -1
- umap/static/umap/js/modules/importer.js +1 -1
- umap/static/umap/js/modules/permissions.js +5 -4
- umap/static/umap/js/modules/rendering/icon.js +5 -1
- umap/static/umap/js/modules/rendering/layers/classified.js +11 -7
- umap/static/umap/js/modules/rendering/layers/cluster.js +11 -1
- umap/static/umap/js/modules/rendering/map.js +0 -2
- umap/static/umap/js/modules/rules.js +2 -1
- umap/static/umap/js/modules/schema.js +5 -6
- umap/static/umap/js/modules/share.js +3 -3
- umap/static/umap/js/modules/sync/engine.js +18 -13
- umap/static/umap/js/modules/sync/updaters.js +8 -0
- umap/static/umap/js/modules/sync/websocket.js +10 -5
- umap/static/umap/js/modules/tableeditor.js +3 -2
- umap/static/umap/js/modules/ui/bar.js +17 -9
- umap/static/umap/js/modules/ui/base.js +7 -24
- umap/static/umap/js/modules/ui/tooltip.js +19 -11
- umap/static/umap/js/modules/umap.js +36 -24
- umap/static/umap/js/modules/utils.js +196 -12
- umap/static/umap/js/umap.controls.js +0 -12
- umap/static/umap/locale/br.js +21 -13
- umap/static/umap/locale/br.json +21 -13
- umap/static/umap/locale/ca.js +12 -4
- umap/static/umap/locale/ca.json +12 -4
- umap/static/umap/locale/cs_CZ.js +10 -4
- umap/static/umap/locale/cs_CZ.json +10 -4
- umap/static/umap/locale/de.js +12 -4
- umap/static/umap/locale/de.json +12 -4
- umap/static/umap/locale/el.js +12 -4
- umap/static/umap/locale/el.json +12 -4
- umap/static/umap/locale/en.js +9 -4
- umap/static/umap/locale/en.json +9 -4
- umap/static/umap/locale/es.js +20 -12
- umap/static/umap/locale/es.json +20 -12
- umap/static/umap/locale/eu.js +12 -4
- umap/static/umap/locale/eu.json +12 -4
- umap/static/umap/locale/fa_IR.js +12 -4
- umap/static/umap/locale/fa_IR.json +12 -4
- umap/static/umap/locale/fr.js +10 -5
- umap/static/umap/locale/fr.json +10 -5
- umap/static/umap/locale/gl.js +353 -345
- umap/static/umap/locale/gl.json +353 -345
- umap/static/umap/locale/hu.js +9 -4
- umap/static/umap/locale/hu.json +9 -4
- umap/static/umap/locale/it.js +100 -92
- umap/static/umap/locale/it.json +100 -92
- umap/static/umap/locale/ms.js +12 -4
- umap/static/umap/locale/ms.json +12 -4
- umap/static/umap/locale/nl.js +12 -4
- umap/static/umap/locale/nl.json +12 -4
- umap/static/umap/locale/pl.js +12 -4
- umap/static/umap/locale/pl.json +12 -4
- umap/static/umap/locale/pt.js +12 -4
- umap/static/umap/locale/pt.json +12 -4
- umap/static/umap/locale/pt_PT.js +12 -4
- umap/static/umap/locale/pt_PT.json +12 -4
- umap/static/umap/locale/th_TH.js +12 -4
- umap/static/umap/locale/th_TH.json +12 -4
- umap/static/umap/locale/zh_TW.js +10 -4
- umap/static/umap/locale/zh_TW.json +10 -4
- umap/static/umap/map.css +12 -8
- umap/static/umap/nav.css +2 -3
- umap/static/umap/unittests/utils.js +14 -0
- umap/static/umap/vars.css +2 -0
- umap/sync/__init__.py +0 -0
- umap/sync/app.py +181 -0
- umap/sync/payloads.py +49 -0
- umap/templates/auth/user_detail.html +4 -0
- umap/templates/auth/user_form.html +9 -6
- umap/templates/auth/user_stars.html +4 -0
- umap/templates/base.html +1 -1
- umap/templates/registration/login.html +2 -5
- umap/templates/umap/about.html +5 -0
- umap/templates/umap/about_summary.html +2 -2
- umap/templates/umap/components/provider.html +8 -0
- umap/templates/umap/js.html +0 -3
- umap/templates/umap/map_detail.html +1 -1
- umap/templates/umap/password_change.html +4 -0
- umap/templates/umap/password_change_done.html +4 -0
- umap/templates/umap/search.html +4 -0
- umap/templates/umap/team_confirm_delete.html +4 -0
- umap/templates/umap/team_detail.html +4 -0
- umap/templates/umap/team_form.html +4 -0
- umap/templates/umap/user_dashboard.html +1 -1
- umap/templates/umap/user_teams.html +4 -0
- umap/tests/base.py +3 -1
- umap/tests/integration/conftest.py +16 -23
- umap/tests/integration/test_basics.py +2 -2
- umap/tests/integration/test_caption.py +1 -0
- umap/tests/integration/test_draw_polygon.py +3 -3
- umap/tests/integration/test_edit_datalayer.py +1 -1
- umap/tests/integration/test_edit_map.py +3 -3
- umap/tests/integration/test_edit_polygon.py +1 -1
- umap/tests/integration/test_import.py +23 -1
- umap/tests/integration/test_optimistic_merge.py +1 -0
- umap/tests/integration/test_picto.py +8 -8
- umap/tests/integration/test_save.py +1 -0
- umap/tests/integration/test_star.py +13 -9
- umap/tests/integration/test_tableeditor.py +1 -0
- umap/tests/integration/test_websocket_sync.py +112 -33
- umap/tests/settings.py +2 -0
- umap/tests/test_datalayer.py +2 -3
- umap/tests/test_datalayer_views.py +20 -1
- umap/tests/test_empty_trash.py +10 -3
- umap/tests/test_map_views.py +11 -0
- umap/utils.py +24 -11
- umap/views.py +37 -6
- {umap_project-2.8.2.dist-info → umap_project-2.9.0b0.dist-info}/METADATA +15 -15
- {umap_project-2.8.2.dist-info → umap_project-2.9.0b0.dist-info}/RECORD +146 -145
- {umap_project-2.8.2.dist-info → umap_project-2.9.0b0.dist-info}/WHEEL +1 -1
- umap/management/commands/run_websocket_server.py +0 -23
- umap/settings/local_s3.py +0 -45
- umap/static/umap/bitbucket.png +0 -0
- umap/static/umap/github.png +0 -0
- umap/static/umap/js/umap.forms.js +0 -1242
- umap/static/umap/keycloak.png +0 -0
- umap/static/umap/openstreetmap.png +0 -0
- umap/static/umap/twitter.png +0 -0
- umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +0 -468
- umap/tests/test_websocket_server.py +0 -22
- umap/websocket_server.py +0 -202
- {umap_project-2.8.2.dist-info → umap_project-2.9.0b0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.8.2.dist-info → umap_project-2.9.0b0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// Uses U.FormBuilder not available as ESM
|
|
2
|
-
|
|
3
1
|
// FIXME: this module should not depend on Leaflet
|
|
4
2
|
import {
|
|
5
3
|
DomUtil,
|
|
@@ -22,6 +20,7 @@ import { Point, LineString, Polygon } from './features.js'
|
|
|
22
20
|
import TableEditor from '../tableeditor.js'
|
|
23
21
|
import { ServerStored } from '../saving.js'
|
|
24
22
|
import * as Schema from '../schema.js'
|
|
23
|
+
import { MutatingForm } from '../form/builder.js'
|
|
25
24
|
|
|
26
25
|
export const LAYER_TYPES = [
|
|
27
26
|
DefaultLayer,
|
|
@@ -250,6 +249,7 @@ export class DataLayer extends ServerStored {
|
|
|
250
249
|
}
|
|
251
250
|
|
|
252
251
|
fromGeoJSON(geojson, sync = true) {
|
|
252
|
+
if (!geojson) return []
|
|
253
253
|
const features = this.addData(geojson, sync)
|
|
254
254
|
this._geojson = geojson
|
|
255
255
|
this.onDataLoaded()
|
|
@@ -283,7 +283,9 @@ export class DataLayer extends ServerStored {
|
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
backupData() {
|
|
286
|
-
|
|
286
|
+
if (this._geojson) {
|
|
287
|
+
this._geojson_bk = Utils.CopyJSON(this._geojson)
|
|
288
|
+
}
|
|
287
289
|
}
|
|
288
290
|
|
|
289
291
|
reindex() {
|
|
@@ -303,21 +305,43 @@ export class DataLayer extends ServerStored {
|
|
|
303
305
|
return this.isRemoteLayer() && Boolean(this.options.remoteData?.dynamic)
|
|
304
306
|
}
|
|
305
307
|
|
|
308
|
+
async getUrl(url, initialUrl) {
|
|
309
|
+
const response = await this._umap.request.get(url)
|
|
310
|
+
return new Promise((resolve) => {
|
|
311
|
+
if (response?.ok) return resolve(response.text())
|
|
312
|
+
Alert.error(
|
|
313
|
+
translate('Cannot load remote data for layer "{layer}" with url "{url}"', {
|
|
314
|
+
layer: this.getName(),
|
|
315
|
+
url: initialUrl || url,
|
|
316
|
+
})
|
|
317
|
+
)
|
|
318
|
+
})
|
|
319
|
+
}
|
|
320
|
+
|
|
306
321
|
async fetchRemoteData(force) {
|
|
307
322
|
if (!this.isRemoteLayer()) return
|
|
308
323
|
if (!this.hasDynamicData() && this.hasDataLoaded() && !force) return
|
|
309
324
|
if (!this.isVisible()) return
|
|
310
|
-
|
|
325
|
+
// Keep non proxied url for later use in Alert.
|
|
326
|
+
const remoteUrl = this._umap.renderUrl(this.options.remoteData.url)
|
|
327
|
+
let url = remoteUrl
|
|
311
328
|
if (this.options.remoteData.proxy) {
|
|
312
329
|
url = this._umap.proxyUrl(url, this.options.remoteData.ttl)
|
|
313
330
|
}
|
|
314
|
-
|
|
315
|
-
if (response?.ok) {
|
|
331
|
+
return await this.getUrl(url, remoteUrl).then((raw) => {
|
|
316
332
|
this.clear()
|
|
317
333
|
return this._umap.formatter
|
|
318
|
-
.parse(
|
|
334
|
+
.parse(raw, this.options.remoteData.format)
|
|
319
335
|
.then((geojson) => this.fromGeoJSON(geojson))
|
|
320
|
-
|
|
336
|
+
.catch((error) => {
|
|
337
|
+
Alert.error(
|
|
338
|
+
translate('Cannot parse remote data for layer "{layer}" with url "{url}"', {
|
|
339
|
+
layer: this.getName(),
|
|
340
|
+
url: remoteUrl,
|
|
341
|
+
})
|
|
342
|
+
)
|
|
343
|
+
})
|
|
344
|
+
})
|
|
321
345
|
}
|
|
322
346
|
|
|
323
347
|
isLoaded() {
|
|
@@ -444,14 +468,14 @@ export class DataLayer extends ServerStored {
|
|
|
444
468
|
// otherwise the layer becomes uneditable.
|
|
445
469
|
return this.makeFeatures(geojson, sync)
|
|
446
470
|
} catch (err) {
|
|
447
|
-
console.
|
|
471
|
+
console.debug('Error with DataLayer', this.id)
|
|
448
472
|
console.error(err)
|
|
449
473
|
return []
|
|
450
474
|
}
|
|
451
475
|
}
|
|
452
476
|
|
|
453
477
|
sortFeatures(collection) {
|
|
454
|
-
const sortKeys = this.
|
|
478
|
+
const sortKeys = this.getOption('sortKey') || U.DEFAULT_LABEL_KEY
|
|
455
479
|
return Utils.sortFeatures(collection, sortKeys, U.lang)
|
|
456
480
|
}
|
|
457
481
|
|
|
@@ -491,7 +515,7 @@ export class DataLayer extends ServerStored {
|
|
|
491
515
|
feature = new Polygon(this._umap, this, geojson, id)
|
|
492
516
|
break
|
|
493
517
|
default:
|
|
494
|
-
console.
|
|
518
|
+
console.debug(geojson)
|
|
495
519
|
Alert.error(
|
|
496
520
|
translate('Skipping unknown geometry.type: {type}', {
|
|
497
521
|
type: geometry.type || 'undefined',
|
|
@@ -513,6 +537,9 @@ export class DataLayer extends ServerStored {
|
|
|
513
537
|
if (data?.length) this.isDirty = true
|
|
514
538
|
return data
|
|
515
539
|
})
|
|
540
|
+
.catch((error) => {
|
|
541
|
+
Alert.error(translate('Import failed: invalid data'))
|
|
542
|
+
})
|
|
516
543
|
}
|
|
517
544
|
|
|
518
545
|
readFile(f) {
|
|
@@ -542,10 +569,9 @@ export class DataLayer extends ServerStored {
|
|
|
542
569
|
|
|
543
570
|
async importFromUrl(uri, type) {
|
|
544
571
|
uri = this._umap.renderUrl(uri)
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
}
|
|
572
|
+
return await this.getUrl(uri).then((raw) => {
|
|
573
|
+
return this.importRaw(raw, type)
|
|
574
|
+
})
|
|
549
575
|
}
|
|
550
576
|
|
|
551
577
|
getColor() {
|
|
@@ -574,9 +600,12 @@ export class DataLayer extends ServerStored {
|
|
|
574
600
|
})
|
|
575
601
|
}
|
|
576
602
|
|
|
577
|
-
|
|
578
|
-
this.isDeleted = true
|
|
603
|
+
del(sync = true) {
|
|
579
604
|
this.erase()
|
|
605
|
+
if (sync) {
|
|
606
|
+
this.isDeleted = true
|
|
607
|
+
this.sync.delete()
|
|
608
|
+
}
|
|
580
609
|
}
|
|
581
610
|
|
|
582
611
|
empty() {
|
|
@@ -656,7 +685,7 @@ export class DataLayer extends ServerStored {
|
|
|
656
685
|
{
|
|
657
686
|
label: translate('Data is browsable'),
|
|
658
687
|
handler: 'Switch',
|
|
659
|
-
helpEntries: 'browsable',
|
|
688
|
+
helpEntries: ['browsable'],
|
|
660
689
|
},
|
|
661
690
|
],
|
|
662
691
|
[
|
|
@@ -668,20 +697,19 @@ export class DataLayer extends ServerStored {
|
|
|
668
697
|
],
|
|
669
698
|
]
|
|
670
699
|
DomUtil.createTitle(container, translate('Layer properties'), 'icon-layers')
|
|
671
|
-
let builder = new
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
},
|
|
700
|
+
let builder = new MutatingForm(this, metadataFields)
|
|
701
|
+
builder.on('set', ({ detail }) => {
|
|
702
|
+
this._umap.onDataLayersChanged()
|
|
703
|
+
if (detail.helper.field === 'options.type') {
|
|
704
|
+
this.edit()
|
|
705
|
+
}
|
|
678
706
|
})
|
|
679
707
|
container.appendChild(builder.build())
|
|
680
708
|
|
|
681
709
|
const layerOptions = this.layer.getEditableOptions()
|
|
682
710
|
|
|
683
711
|
if (layerOptions.length) {
|
|
684
|
-
builder = new
|
|
712
|
+
builder = new MutatingForm(this, layerOptions, {
|
|
685
713
|
id: 'datalayer-layer-properties',
|
|
686
714
|
})
|
|
687
715
|
const layerProperties = DomUtil.createFieldset(
|
|
@@ -704,7 +732,7 @@ export class DataLayer extends ServerStored {
|
|
|
704
732
|
'options.fillOpacity',
|
|
705
733
|
]
|
|
706
734
|
|
|
707
|
-
builder = new
|
|
735
|
+
builder = new MutatingForm(this, shapeOptions, {
|
|
708
736
|
id: 'datalayer-advanced-properties',
|
|
709
737
|
})
|
|
710
738
|
const shapeProperties = DomUtil.createFieldset(
|
|
@@ -719,11 +747,17 @@ export class DataLayer extends ServerStored {
|
|
|
719
747
|
'options.zoomTo',
|
|
720
748
|
'options.fromZoom',
|
|
721
749
|
'options.toZoom',
|
|
750
|
+
'options.sortKey',
|
|
722
751
|
]
|
|
723
752
|
|
|
724
|
-
builder = new
|
|
753
|
+
builder = new MutatingForm(this, optionsFields, {
|
|
725
754
|
id: 'datalayer-advanced-properties',
|
|
726
755
|
})
|
|
756
|
+
builder.on('set', ({ detail }) => {
|
|
757
|
+
if (detail.helper.field === 'options.sortKey') {
|
|
758
|
+
this.reindex()
|
|
759
|
+
}
|
|
760
|
+
})
|
|
727
761
|
const advancedProperties = DomUtil.createFieldset(
|
|
728
762
|
container,
|
|
729
763
|
translate('Advanced properties')
|
|
@@ -740,7 +774,7 @@ export class DataLayer extends ServerStored {
|
|
|
740
774
|
'options.outlinkTarget',
|
|
741
775
|
'options.interactive',
|
|
742
776
|
]
|
|
743
|
-
builder = new
|
|
777
|
+
builder = new MutatingForm(this, popupFields)
|
|
744
778
|
const popupFieldset = DomUtil.createFieldset(
|
|
745
779
|
container,
|
|
746
780
|
translate('Interaction options')
|
|
@@ -796,7 +830,7 @@ export class DataLayer extends ServerStored {
|
|
|
796
830
|
container,
|
|
797
831
|
translate('Remote data')
|
|
798
832
|
)
|
|
799
|
-
builder = new
|
|
833
|
+
builder = new MutatingForm(this, remoteDataFields)
|
|
800
834
|
remoteDataContainer.appendChild(builder.build())
|
|
801
835
|
DomUtil.createButton(
|
|
802
836
|
'button umap-verify',
|
|
@@ -819,7 +853,7 @@ export class DataLayer extends ServerStored {
|
|
|
819
853
|
<i class="icon icon-24 icon-delete"></i>${translate('Delete')}
|
|
820
854
|
</button>`)
|
|
821
855
|
deleteButton.addEventListener('click', () => {
|
|
822
|
-
this.
|
|
856
|
+
this.del()
|
|
823
857
|
this._umap.editPanel.close()
|
|
824
858
|
})
|
|
825
859
|
advancedButtons.appendChild(deleteButton)
|
|
@@ -1147,10 +1181,14 @@ export class DataLayer extends ServerStored {
|
|
|
1147
1181
|
if (this.createdOnServer) {
|
|
1148
1182
|
await this._umap.server.post(this.getDeleteUrl())
|
|
1149
1183
|
}
|
|
1150
|
-
|
|
1184
|
+
this.commitDelete()
|
|
1151
1185
|
return true
|
|
1152
1186
|
}
|
|
1153
1187
|
|
|
1188
|
+
commitDelete() {
|
|
1189
|
+
delete this._umap.datalayers[stamp(this)]
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1154
1192
|
getName() {
|
|
1155
1193
|
return this.options.name || translate('Untitled layer')
|
|
1156
1194
|
}
|
|
@@ -1221,7 +1259,7 @@ export class DataLayer extends ServerStored {
|
|
|
1221
1259
|
this._umap.dialog
|
|
1222
1260
|
.confirm(translate('Are you sure you want to delete this layer?'))
|
|
1223
1261
|
.then(() => {
|
|
1224
|
-
this.
|
|
1262
|
+
this.del()
|
|
1225
1263
|
})
|
|
1226
1264
|
},
|
|
1227
1265
|
this
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import getClass from './fields.js'
|
|
2
|
+
import * as Utils from '../utils.js'
|
|
3
|
+
import { SCHEMA } from '../schema.js'
|
|
4
|
+
import { translate } from '../i18n.js'
|
|
5
|
+
|
|
6
|
+
export class Form extends Utils.WithEvents {
|
|
7
|
+
constructor(obj, fields, properties) {
|
|
8
|
+
super()
|
|
9
|
+
this.setProperties(properties)
|
|
10
|
+
this.defaultProperties = {}
|
|
11
|
+
this.obj = obj
|
|
12
|
+
this.form = Utils.loadTemplate('<form></form>')
|
|
13
|
+
this.setFields(fields)
|
|
14
|
+
if (this.properties.id) {
|
|
15
|
+
this.form.id = this.properties.id
|
|
16
|
+
}
|
|
17
|
+
if (this.properties.className) {
|
|
18
|
+
this.form.classList.add(...this.properties.className.split(' '))
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
setProperties(properties) {
|
|
23
|
+
this.properties = Object.assign({}, this.properties, properties)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
setFields(fields) {
|
|
27
|
+
this.fields = fields || []
|
|
28
|
+
this.helpers = {}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
build() {
|
|
32
|
+
this.form.innerHTML = ''
|
|
33
|
+
for (const definition of this.fields) {
|
|
34
|
+
this.buildField(this.makeField(definition))
|
|
35
|
+
}
|
|
36
|
+
return this.form
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
buildField(field) {
|
|
40
|
+
field.buildTemplate()
|
|
41
|
+
field.build()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
makeField(field) {
|
|
45
|
+
// field can be either a string like "option.name" or a full definition array,
|
|
46
|
+
// like ['properties.tilelayer.tms', {handler: 'CheckBox', helpText: 'TMS format'}]
|
|
47
|
+
let properties
|
|
48
|
+
if (Array.isArray(field)) {
|
|
49
|
+
properties = field[1] || {}
|
|
50
|
+
field = field[0]
|
|
51
|
+
} else {
|
|
52
|
+
properties = this.defaultProperties[this.getName(field)] || {}
|
|
53
|
+
}
|
|
54
|
+
const class_ = getClass(properties.handler || 'Input')
|
|
55
|
+
this.helpers[field] = new class_(this, field, properties)
|
|
56
|
+
return this.helpers[field]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getter(field) {
|
|
60
|
+
const path = field.split('.')
|
|
61
|
+
let value = this.obj
|
|
62
|
+
for (const sub of path) {
|
|
63
|
+
try {
|
|
64
|
+
value = value[sub]
|
|
65
|
+
} catch {
|
|
66
|
+
console.log(field)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return value
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
setter(field, value) {
|
|
73
|
+
const path = field.split('.')
|
|
74
|
+
let obj = this.obj
|
|
75
|
+
let what
|
|
76
|
+
for (let i = 0, l = path.length; i < l; i++) {
|
|
77
|
+
what = path[i]
|
|
78
|
+
if (what === path[l - 1]) {
|
|
79
|
+
if (typeof value === 'undefined') {
|
|
80
|
+
delete obj[what]
|
|
81
|
+
} else {
|
|
82
|
+
obj[what] = value
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
obj = obj[what]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
restoreField(field) {
|
|
91
|
+
const initial = this.helpers[field].initial
|
|
92
|
+
this.setter(field, initial)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
getName(field) {
|
|
96
|
+
const fieldEls = field.split('.')
|
|
97
|
+
return fieldEls[fieldEls.length - 1]
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fetchAll() {
|
|
101
|
+
for (const helper of Object.values(this.helpers)) {
|
|
102
|
+
helper.fetch()
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
syncAll() {
|
|
107
|
+
for (const helper of Object.values(this.helpers)) {
|
|
108
|
+
helper.sync()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
onPostSync(helper) {
|
|
113
|
+
if (this.properties.callback) {
|
|
114
|
+
this.properties.callback(helper)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
finish() {}
|
|
119
|
+
|
|
120
|
+
getTemplate(helper) {
|
|
121
|
+
return `
|
|
122
|
+
<div class="formbox" data-ref=container>
|
|
123
|
+
${helper.getTemplate()}
|
|
124
|
+
<small class="help-text" data-ref=helpText></small>
|
|
125
|
+
</div>`
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export class MutatingForm extends Form {
|
|
130
|
+
constructor(obj, fields, properties) {
|
|
131
|
+
super(obj, fields, properties)
|
|
132
|
+
this._umap = obj._umap || properties.umap
|
|
133
|
+
this.computeDefaultProperties()
|
|
134
|
+
// this.on('finish', this.finish)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
computeDefaultProperties() {
|
|
138
|
+
const customHandlers = {
|
|
139
|
+
sortKey: 'PropertyInput',
|
|
140
|
+
easing: 'Switch',
|
|
141
|
+
facetKey: 'PropertyInput',
|
|
142
|
+
slugKey: 'PropertyInput',
|
|
143
|
+
labelKey: 'PropertyInput',
|
|
144
|
+
}
|
|
145
|
+
for (const [key, schema] of Object.entries(SCHEMA)) {
|
|
146
|
+
if (schema.type === Boolean) {
|
|
147
|
+
if (schema.nullable) schema.handler = 'NullableChoices'
|
|
148
|
+
else schema.handler = 'Switch'
|
|
149
|
+
} else if (schema.type === 'Text') {
|
|
150
|
+
schema.handler = 'Textarea'
|
|
151
|
+
} else if (schema.type === Number) {
|
|
152
|
+
if (schema.step) schema.handler = 'Range'
|
|
153
|
+
else schema.handler = 'IntInput'
|
|
154
|
+
} else if (schema.choices) {
|
|
155
|
+
const text_length = schema.choices.reduce(
|
|
156
|
+
(acc, [_, label]) => acc + label.length,
|
|
157
|
+
0
|
|
158
|
+
)
|
|
159
|
+
// Try to be smart and use MultiChoice only
|
|
160
|
+
// for choices where labels are shorts…
|
|
161
|
+
if (text_length < 40) {
|
|
162
|
+
schema.handler = 'MultiChoice'
|
|
163
|
+
} else {
|
|
164
|
+
schema.handler = 'Select'
|
|
165
|
+
schema.selectOptions = schema.choices
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
switch (key) {
|
|
169
|
+
case 'color':
|
|
170
|
+
case 'fillColor':
|
|
171
|
+
schema.handler = 'ColorPicker'
|
|
172
|
+
break
|
|
173
|
+
case 'iconUrl':
|
|
174
|
+
schema.handler = 'IconUrl'
|
|
175
|
+
break
|
|
176
|
+
case 'licence':
|
|
177
|
+
schema.handler = 'LicenceChooser'
|
|
178
|
+
break
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (customHandlers[key]) {
|
|
183
|
+
schema.handler = customHandlers[key]
|
|
184
|
+
}
|
|
185
|
+
// Input uses this key for its type attribute
|
|
186
|
+
delete schema.type
|
|
187
|
+
this.defaultProperties[key] = schema
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
setter(field, value) {
|
|
192
|
+
super.setter(field, value)
|
|
193
|
+
this.obj.isDirty = true
|
|
194
|
+
if ('render' in this.obj) {
|
|
195
|
+
this.obj.render([field], this)
|
|
196
|
+
}
|
|
197
|
+
if ('sync' in this.obj) {
|
|
198
|
+
this.obj.sync.update(field, value)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
getTemplate(helper) {
|
|
203
|
+
let template
|
|
204
|
+
if (helper.properties.inheritable) {
|
|
205
|
+
const extraClassName = helper.get(true) === undefined ? ' undefined' : ''
|
|
206
|
+
template = `
|
|
207
|
+
<div class="umap-field-${helper.name} formbox inheritable${extraClassName}">
|
|
208
|
+
<div class="header" data-ref=header>
|
|
209
|
+
${helper.getLabelTemplate()}
|
|
210
|
+
<span class="actions show-on-defined" data-ref=actions></span>
|
|
211
|
+
<span class="buttons" data-ref=buttons>
|
|
212
|
+
<button type="button" class="button undefine" data-ref=undefine>${translate('clear')}</button>
|
|
213
|
+
<button type="button" class="button define" data-ref=define>${translate('define')}</button>
|
|
214
|
+
</span>
|
|
215
|
+
</div>
|
|
216
|
+
<div class="show-on-defined" data-ref=container>
|
|
217
|
+
${helper.getTemplate()}
|
|
218
|
+
<small class="help-text" data-ref=helpText></small>
|
|
219
|
+
</div>
|
|
220
|
+
</div>`
|
|
221
|
+
} else {
|
|
222
|
+
template = `
|
|
223
|
+
<div class="formbox umap-field-${helper.name}" data-ref=container>
|
|
224
|
+
${helper.getLabelTemplate()}
|
|
225
|
+
${helper.getTemplate()}
|
|
226
|
+
<small class="help-text" data-ref=helpText></small>
|
|
227
|
+
</div>`
|
|
228
|
+
}
|
|
229
|
+
return template
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
build() {
|
|
233
|
+
super.build()
|
|
234
|
+
this._umap.help.parse(this.form)
|
|
235
|
+
return this.form
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
finish(helper) {
|
|
239
|
+
helper.input?.blur()
|
|
240
|
+
}
|
|
241
|
+
}
|