feat(sync): sync layer's properties.

This also changes the interface between the synced classes and the sync
engine.

The sync engines only requires two methods now:

- `getSyncMetadata()` which returns all the metadata needed, including
the `engine`.
- `render()` which renders the object, updating the needed parts.
This commit is contained in:
Alexis Métaireau 2024-04-29 18:09:47 +02:00
parent 66105127cb
commit b956101d5d
6 changed files with 29 additions and 25 deletions

View file

@ -41,7 +41,7 @@ export class MapUpdater extends BaseUpdater {
update({ key, value }) {
console.log(key, value)
this.updateObjectValue(this.map, key, value)
this.map.render([key.replace('options.', '')])
this.map.render([key])
}
}
@ -50,8 +50,7 @@ export class DatalayerUpdater extends BaseUpdater {
const datalayer = this.getLayerFromID(metadata.id)
console.log(datalayer, key, value)
this.updateObjectValue(datalayer, key, value)
const property = key.replace('options.', '')
datalayer.render([property])
datalayer.render([key])
}
}

View file

@ -3,6 +3,7 @@ U.FeatureMixin = {
getSyncMetadata: function () {
return {
engine: this.map.sync,
subject: 'feature',
metadata: {
id: this.id,
@ -12,14 +13,9 @@ U.FeatureMixin = {
}
},
getSyncEngine: function () {
// FIXME use a get property / defineProperty
return this.map.sync
},
onCommit: function () {
const { subject, metadata } = this.getSyncMetadata()
this.map.sync.upsert(subject, metadata, {
const { subject, metadata, engine } = this.getSyncMetadata()
engine.upsert(subject, metadata, {
geometry: this.getGeometry(),
})
},
@ -30,14 +26,14 @@ U.FeatureMixin = {
syncUpdatedProperties: function (properties) {
if ('latlng'.includes(properties)) {
const { subject, metadata } = this.getSyncMetadata()
this.map.sync.update(subject, metadata, 'geometry', this.getGeometry())
const { subject, metadata, engine } = this.getSyncMetadata()
engine.update(subject, metadata, 'geometry', this.getGeometry())
}
},
syncDelete: function () {
let { subject, metadata } = this.getSyncMetadata()
this.map.sync.delete(subject, metadata)
let { subject, metadata, engine } = this.getSyncMetadata()
engine.delete(subject, metadata)
},
initialize: function (map, latlng, options, id) {

View file

@ -1186,9 +1186,10 @@ U.FormBuilder = L.FormBuilder.extend({
L.FormBuilder.prototype.setter.call(this, field, value)
this.obj.isDirty = true
if ('render' in this.obj) this.obj.render([field], this)
const syncEngine = this.obj.getSyncEngine()
const { subject, metadata } = this.obj.getSyncMetadata()
syncEngine.update(subject, metadata, field, value)
console.log('setter', field, value)
const { subject, metadata, engine } = this.obj.getSyncMetadata()
console.log('metadata', metadata)
engine.update(subject, metadata, field, value)
},
finish: function () {

View file

@ -266,14 +266,11 @@ U.Map = L.Map.extend({
getSyncMetadata: function () {
return {
engine: this.sync,
subject: 'map',
}
},
getSyncEngine: function () {
return this.sync
},
render: function (fields) {
let impacts = U.Utils.getImpactsFromSchema(fields)

View file

@ -597,6 +597,16 @@ U.DataLayer = L.Evented.extend({
this.on('datachanged', this.map.onDataLayersChanged, this.map)
},
getSyncMetadata: function () {
return {
engine: this.map.sync,
subject: 'datalayer',
metadata: {
id: this.umap_id, // XXX: should we specify it's the layerID here?
},
}
},
render: function (fields, builder) {
let impacts = U.Utils.getImpactsFromSchema(fields)

View file

@ -33,7 +33,7 @@ class JoinMessage(BaseModel):
class Geometry(BaseModel):
type: Literal["Point",]
type: Literal["Point", "Polygon"]
coordinates: list
@ -43,13 +43,15 @@ class GeometryValue(BaseModel):
# FIXME better define the different messages
# to ensure only relying valid ones.
# This would mean having different kind of validation types
# based on the kind and verb.
class OperationMessage(BaseModel):
kind: str = "operation"
verb: str = Literal["upsert", "update", "delete"]
subject: str = Literal["map", "layer", "feature"]
metadata: Optional[dict] = None
key: Optional[str] = None
value: Optional[str | bool | int | GeometryValue]
value: Optional[str | bool | int | GeometryValue] = None
async def join_and_listen(
@ -90,8 +92,7 @@ async def handler(websocket):
signed = TimestampSigner().unsign_object(message.token, max_age=30)
user, map_id, permissions = signed.values()
# We trust the signed info from the server to give access
# If the user can edit the map, let her in
# Check if permissions for this map have been granted by the server
if "edit" in signed["permissions"]:
await join_and_listen(map_id, permissions, user, websocket)