Start syncing layers

This commit is contained in:
Alexis Métaireau 2024-02-19 10:30:18 +01:00
parent 88c0dac6d3
commit 07b1e237cd
5 changed files with 123 additions and 46 deletions

View file

@ -1,5 +1,5 @@
import { WebSocketTransport } from "./websocket.js" import { WebSocketTransport } from "./websocket.js"
import { MapUpdater, MarkerUpdater, PolygonUpdater, PolylineUpdater } from "./updaters.js" import { MapUpdater, MarkerUpdater, PolygonUpdater, PolylineUpdater, DatalayerUpdater } from "./updaters.js"
export class SyncEngine { export class SyncEngine {
constructor(map) { constructor(map) {
@ -21,6 +21,7 @@ export class MessagesDispatcher {
marker: new MarkerUpdater(this.map), marker: new MarkerUpdater(this.map),
polyline: new PolylineUpdater(this.map), polyline: new PolylineUpdater(this.map),
polygon: new PolygonUpdater(this.map), polygon: new PolygonUpdater(this.map),
datalayer: new DatalayerUpdater(this.map),
} }
} }
@ -34,6 +35,7 @@ export class MessagesDispatcher {
return updater return updater
} }
case 'map': case 'map':
case 'datalayer':
return this.updaters[subject] return this.updaters[subject]
default: default:
throw new Error(`Unknown updater ${subject}, ${metadata}`) throw new Error(`Unknown updater ${subject}, ${metadata}`)

View file

@ -4,6 +4,10 @@
*/ */
class BaseUpdater { class BaseUpdater {
constructor(map) {
this.map = map
}
updateObjectValue(obj, key, value) { updateObjectValue(obj, key, value) {
// XXX refactor so it's cleaner // XXX refactor so it's cleaner
let path = key.split('.') let path = key.split('.')
@ -22,6 +26,12 @@ class BaseUpdater {
} }
} }
getLayerFromID(layerId) {
if (layerId)
return this.map.getDataLayerByUmapId(layerId)
return this.map.defaultEditDataLayer()
}
applyMessage(message) { applyMessage(message) {
let { verb } = message let { verb } = message
return this[verb](message) return this[verb](message)
@ -29,10 +39,6 @@ class BaseUpdater {
} }
export class MapUpdater extends BaseUpdater { export class MapUpdater extends BaseUpdater {
constructor(map) {
super()
this.map = map
}
update({ key, value }) { update({ key, value }) {
console.log(key, value) console.log(key, value)
@ -41,6 +47,16 @@ export class MapUpdater extends BaseUpdater {
} }
} }
export class DatalayerUpdater extends BaseUpdater {
update({ key, metadata, value }) {
const datalayer = this.getLayerFromID(metadata.id)
console.log(datalayer, key, value)
this.updateObjectValue(datalayer, key, value)
datalayer.renderProperties([key])
}
}
/** /**
* This is an abstract base class * This is an abstract base class
* And needs to be subclassed to be used. * And needs to be subclassed to be used.
@ -51,17 +67,6 @@ export class MapUpdater extends BaseUpdater {
**/ **/
class FeatureUpdater extends BaseUpdater { class FeatureUpdater extends BaseUpdater {
constructor(map) {
super()
this.map = map
}
getLayerFromID(layerId) {
if (layerId)
return this.map.getDataLayerByUmapId(layerId)
return this.map.defaultEditDataLayer()
}
getFeatureFromMetadata({ id, layerId }) { getFeatureFromMetadata({ id, layerId }) {
const datalayer = this.getLayerFromID(layerId) const datalayer = this.getLayerFromID(layerId)
return datalayer.getFeatureById(id) return datalayer.getFeatureById(id)

View file

@ -12,17 +12,33 @@ L.U.DataRendererMixin = {
/** /**
* Rerender the interface for the properties passed as an argument. * Rerender the interface for the properties passed as an argument.
* *
* @param list updatedProperties : properties that have been updated. * @param list properties : properties that have been updated.
*/ */
renderProperties: function (updatedProperties) { renderProperties: function (properties, builder) {
let renderers = new Set() let renderers = new Set()
for (const prop of updatedProperties) { for (const prop of properties) {
const propRenderers = this.propertiesRenderers[prop] const propRenderers = this.propertiesRenderers[prop]
if (propRenderers) { if (propRenderers) {
for (const renderer of propRenderers) renderers.add(renderer) for (const renderer of propRenderers) {
renderers.add(renderer)
} }
} }
for (const renderer of renderers) this[renderer]() }
// If no renderer has been found, use the default one.
const hasDefault = Object.keys(this.propertiesRenderers).includes('default')
const defaultRenderers = this.propertiesRenderers['default']
if (hasDefault && renderers.size == 0) {
for (const renderer of defaultRenderers) {
renderers.add(renderer)
}
}
for (const renderer of renderers) {
this[renderer](properties, builder)
}
}, },
} }

View file

@ -1276,7 +1276,7 @@ L.U.FormBuilder = L.FormBuilder.extend({
// in the map definition // in the map definition
// Remove the "options" prefix for now // Remove the "options" prefix for now
field = field.replace('options.', '') field = field.replace('options.', '')
this.obj.renderProperties([field]) this.obj.renderProperties([field], this)
}, },
finish: function () { finish: function () {

View file

@ -513,6 +513,78 @@ L.U.DataLayer = L.Evented.extend({
editMode: 'advanced', editMode: 'advanced',
}, },
propertiesRenderers: {
'name': ['updateDatalayersControl'],
'description': ['updateDatalayersControl'],
'type': ['resetLayer', 'updateDatalayersControl'],
'displayOnLoad': ['updateDatalayersControl'],
'browsable': ['updateDatalayersControl'],
'inCaption': ['updateDatalayersControl'],
// Shape options
'color': ['redrawCallback'],
'iconClass': ['redrawCallback'],
'iconUrl': ['redrawCallback'],
'iconOpacity': ['redrawCallback'],
'opacity': ['redrawCallback'],
'stroke': ['redrawCallback'],
'weight': ['redrawCallback'],
'fill': ['redrawCallback'],
'fillColor': ['redrawCallback'],
'fillOpacity': ['redrawCallback'],
// Options fields
'smoothFactor': ['redrawCallback'],
'dashArray': ['redrawCallback'],
'zoomTo': ['redrawCallback'],
'fromZoom': ['redrawCallback'],
'toZoom': ['redrawCallback'],
'labelKey': ['redrawCallback'],
// Popup fields
'popupShape': ['redrawCallback'],
'popupTemplate': ['redrawCallback'],
'popupContentTemplate': ['redrawCallback'],
'showLabel': ['redrawCallback'],
'labelDirection': ['redrawCallback'],
'labelInteractive': ['redrawCallback'],
'outlinkTarget': ['redrawCallback'],
'interactive': ['redrawCallback'],
// Remote Data fields
'remoteData.url': ['fetchRemoteData'],
'remoteData.format': ['fetchRemoteData'],
'fromZoom': ['fetchRemoteData'],
'toZoom': ['fetchRemoteData'],
'remoteData.dynamic': ['fetchRemoteData'],
'remoteData.licence': ['fetchRemoteData'],
'remoteData.proxy': ['fetchRemoteData'],
'remoteData.ttl': ['fetchRemoteData'],
'default': ['redrawCallback']
},
updateDataLayersControl() {
this.map.updateDatalayersControl()
},
redrawCallback: function (properties, builder) {
this.hide()
for (let property of properties) {
this.layer.onEdit(property, builder)
}
this.show()
},
getSyncEngine: function () {
return this.map.syncEngine
},
getSyncSubject: function () {
return "datalayer"
},
initialize: function (map, data) { initialize: function (map, data) {
this.map = map this.map = map
this._index = Array() this._index = Array()
@ -1197,31 +1269,13 @@ L.U.DataLayer = L.Evented.extend({
], ],
] ]
const title = L.DomUtil.add('h3', '', container, L._('Layer properties')) const title = L.DomUtil.add('h3', '', container, L._('Layer properties'))
let builder = new L.U.FormBuilder(this, metadataFields, { let builder = new L.U.FormBuilder(this, metadataFields)
callback: function (e) {
this.map.updateDatalayersControl()
if (e.helper.field === 'options.type') {
this.resetLayer()
this.edit()
}
},
})
container.appendChild(builder.build()) container.appendChild(builder.build())
const redrawCallback = function (e) {
const field = e.helper.field,
builder = e.helper.builder
this.hide()
this.layer.onEdit(field, builder)
this.show()
}
const layerOptions = this.layer.getEditableOptions() const layerOptions = this.layer.getEditableOptions()
if (layerOptions.length) { if (layerOptions.length) {
builder = new L.U.FormBuilder(this, layerOptions, { builder = new L.U.FormBuilder(this, layerOptions, {
id: 'datalayer-layer-properties', id: 'datalayer-layer-properties'
callback: redrawCallback,
}) })
const layerProperties = L.DomUtil.createFieldset( const layerProperties = L.DomUtil.createFieldset(
container, container,
@ -1244,8 +1298,7 @@ L.U.DataLayer = L.Evented.extend({
] ]
builder = new L.U.FormBuilder(this, shapeOptions, { builder = new L.U.FormBuilder(this, shapeOptions, {
id: 'datalayer-advanced-properties', id: 'datalayer-advanced-properties'
callback: redrawCallback,
}) })
const shapeProperties = L.DomUtil.createFieldset(container, L._('Shape properties')) const shapeProperties = L.DomUtil.createFieldset(container, L._('Shape properties'))
shapeProperties.appendChild(builder.build()) shapeProperties.appendChild(builder.build())
@ -1261,7 +1314,6 @@ L.U.DataLayer = L.Evented.extend({
builder = new L.U.FormBuilder(this, optionsFields, { builder = new L.U.FormBuilder(this, optionsFields, {
id: 'datalayer-advanced-properties', id: 'datalayer-advanced-properties',
callback: redrawCallback,
}) })
const advancedProperties = L.DomUtil.createFieldset( const advancedProperties = L.DomUtil.createFieldset(
container, container,
@ -1279,7 +1331,7 @@ L.U.DataLayer = L.Evented.extend({
'options.outlinkTarget', 'options.outlinkTarget',
'options.interactive', 'options.interactive',
] ]
builder = new L.U.FormBuilder(this, popupFields, { callback: redrawCallback }) builder = new L.U.FormBuilder(this, popupFields)
const popupFieldset = L.DomUtil.createFieldset( const popupFieldset = L.DomUtil.createFieldset(
container, container,
L._('Interaction options') L._('Interaction options')
@ -1644,6 +1696,8 @@ L.U.DataLayer = L.Evented.extend({
}, },
}) })
L.U.DataLayer.include(L.U.DataRendererMixin)
L.TileLayer.include({ L.TileLayer.include({
toJSON: function () { toJSON: function () {
return { return {