Commit graph

2658 commits

Author SHA1 Message Date
2ca27c3c20
test(sync): Ensure map properties are synced
This tests that the name of the map, and that zoom-control visibility is
properly synced over websockets.
2024-05-15 14:47:55 +02:00
550a43c6d1
test(sync): ensure polygon drag-n-drop is synced 2024-05-15 14:31:53 +02:00
98c3849165
test(sync): Ensure polygons and their edits can be synced 2024-05-15 12:25:02 +02:00
4c6e0a86d5
test(sync): Marker drag-n-drop and delete are synced 2024-05-15 12:25:02 +02:00
2c9b8230ab
tests(sync): Test that marker sync works properly
This commit handles the start and stop of the websocket server during
the tests, using the xprocess library
2024-05-15 12:25:01 +02:00
fff2235c3d
chore(tests): Rename "collaboration" tests to "optimistic merge"
As "collaboration" can be mistaken between "websocket" and
"server-merge". This naming makes it explicit.
2024-05-15 12:25:01 +02:00
c0212eeb93
chore(sync): Add message-dispatcher unit tests 2024-05-15 12:25:01 +02:00
6618f38b17
feat(sync): Add JS unittests for updateObjectValue, and refactor.
The new implementation uses `reduce`, in the hopes of producing a more
readable version than old-style loops and reassignment of object values.
2024-05-15 12:25:01 +02:00
d95d8d4cba
feat(sync): add tests for the websocket token view 2024-05-15 12:25:01 +02:00
991add938c
refactor(sync): Remove unnecessary complexity
Because we're relying on the `geoJSONToFeatures` method, we don't need
anymore updaters, the default ones (map, datalayer, feature) are enough.

It also makes the codebase compatible with our eslint configuration.
2024-05-15 12:25:00 +02:00
124b7278da
chore(sync) make the test pass 2024-05-15 12:25:00 +02:00
b85ee4011e
chore(docker) remove ws.py for now 2024-05-15 12:25:00 +02:00
90e85f1465
fix(sync) only send datalayer options 2024-05-15 12:25:00 +02:00
190c3535fe
fix(sync): do not call getSyncMetadata if it doesn't exist
This can arise when the form isn't bound to a "syncable" object. We
might want to provide an utility to check an object is *syncable*, or a
specific form to not attempt to sync objects which don't need it.
2024-05-15 12:24:59 +02:00
47070d148f
feat(sync): Allow the sync of datalayer creation 2024-05-15 12:24:59 +02:00
178eb2ac1c
fix(sync): allow features geometries to be synced
By defining the `geometry` property in the schema.
2024-05-15 12:24:59 +02:00
61d8ccbdaf
chore(docker): run the websocket server as a separate command 2024-05-15 12:24:59 +02:00
57355eb4c5
chore(sync): remove useless dependencies from ws.py 2024-05-15 12:24:58 +02:00
81554d1e2e
feat(settings): allow reading socket-related settings from ENV variables 2024-05-15 12:24:58 +02:00
cbdcfba720
fix(sync): intialize the sync engine before entering edit mode.
Otherwise `this.sync` is not defined.
2024-05-15 12:24:58 +02:00
1f0782665b
feat(sync): handle syncing of map limitbounds. 2024-05-15 12:24:58 +02:00
a491a7c837
feat(sync): Avoid syncing remote datalayers' features
They will be synced on their own, and we dont want them to be present
twice on the map.
2024-05-15 12:24:58 +02:00
1d2cf981d1
fix(sync): Initialize tilelayerand remoteData earlier.
It makes it possible to set these values on a remote peer.
2024-05-15 12:24:57 +02:00
1aad9013f5
fix(sync): Allow overlays to sync
`this.options.overlay` is now set during `map.initialize()`, which makes
it possible to be set by incoming websocket operations.
2024-05-15 12:24:57 +02:00
bfd7613d68
chore(sync): Ensure properties can be updated before doing it.
When receiving a message, this checks the given properties belong to
the "subject" before applying the message.
2024-05-15 12:24:57 +02:00
1c1dd4af82
chore(schema): Add a belongsTo field in the schema.
The goal is to use this as a security measure, to check that the
updated properties belong the the "subject" when receiving sync
operations.
2024-05-15 12:24:57 +02:00
0bddba24fd
fix(sync): Allow cloning of features
Removing the `id` from the feature when cloning makes it generate a new
one. Without this change, the cloned feature keep the already existing
`id`, and during sync, the original object is lost (replaced by the
clone).

Nobody wants to be replaced by a clone.
2024-05-15 12:24:57 +02:00
5a32a3d0ca
feat(sync): Sync only when the edition of a feature is over.
It's less spectacular than sending the position as it changes, but takes
less bandwidth and seems good enough.
2024-05-15 12:24:56 +02:00
99e24d9b41
fix(sync): Import the data when syncing GeoJSON objects.
Prior to these changes, the data wasn't transmitted over WebSocket, and
even if present it wasn't taken into account.
2024-05-15 12:24:56 +02:00
23d1c3bda9
fix(sync): Keep features IDs for Polygons and Lines
It wasn't passed previously, so objects where duplicated.
2024-05-15 12:24:56 +02:00
f964bfff0f
feat(sync): Only sync when on edit mode
The is done to save server resources, for accessed maps which
aren't currently being edited.
2024-05-15 12:24:56 +02:00
346391b311
chore(sync): Move the sync flag in the options
The goal being for it to be hidden for now.

- Add a `is_owner` method on the map and use it in the view
- Remove duplicated line in `global.js`
- Rename `Datalayer` to `DataLayer` everywhere
- Move the sync flag in the map options (next to slideshow)
2024-05-15 12:24:55 +02:00
33108a9ae0
feat(sync): Add WebSocket specific settings
`WEBSOCKET_ENABLED`, `WEBSOCKET_HOST`, `WEBSOCKET_PORT` and
`WEBSOCKET_URI` have been added.

They are being transmitted to the client via the `map.options`.
When `WEBSOCKET_ENABLED` is set to `False`, the client doesn't have
the ability to be synced.
2024-05-15 12:24:55 +02:00
c4db041494
feat(sync): Add a enableSync option.
This changes how the syncEngine works. At the moment, it's always
instanciated, even if no syncing is configured. It just does nothing.

This is to avoid doing `if (engine) engine.update()` calls everywhere
we use it.

You now need to `start()` and `stop()` it.
2024-05-15 12:24:55 +02:00
1ed47848b4
feat(sync): initialize datalayers internal objects in the constructor.
Otherwise, an event can come from the websocket, trying to update an
`undefined` property.
2024-05-15 12:24:55 +02:00
2bd96d2517
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.
2024-05-15 12:24:54 +02:00
8a4c50d379
feat(sync): Sync features over websockets
Added a new `geometryToFeature` method in `umap.layer.js` which can
update a given geometry if needed.

A new `id` property can also be passed to the features on creation, to
make it possible to have the same features `id` on different peers.
2024-05-15 12:24:54 +02:00
cd09cacf19
feat(sync): sync map properties over websocket
All keystrokes are currently sent, which is not ideal because it will
use a lot of bandwidth.
2024-05-15 12:24:54 +02:00
4474f06ed4
feat(sync): sync features and map properties
Synced objects now expose different methods, such as:
- `getSyncEngine` which returns the location of the sync object.
- `getMetadata` which returns the associated metadata with the object.

Hooks have been added when features are created or changed, so the
changes can be synced with other peers.
2024-05-15 12:24:53 +02:00
4de4907ff4
feat(websockets): Authenticate with signed tokens.
Authentication is now done using a signed token provided by the Django
server, sent by the JS client and checked by the WebSocket server.

The token contains a `permissions` key that's checked to ensure the user
has access to the map "room", where events will be shared by the peers.
2024-05-15 12:24:53 +02:00
6122b2b6dd
feat(websockets): First SyncEngine appearance
A new SyncEngine module has been added to the JavaScript code. It aims
to sync the local changes with remote ones. This first implementation
relies on a websocket connection.
2024-05-15 12:24:51 +02:00
d11451a4d4
feat(WebSockets): Features a WebSocket server.
There is one "room" per map, and the server relays messages to all the
other connected peers.

Messages are checked for compliance with what's allowed as a security
measure. They should also be checked in the clients to avoid potential
attack vectors.
2024-05-15 12:24:18 +02:00
fd9817082a
doc: update cookie-related comment 2024-05-15 12:24:17 +02:00
b10b1ed88a
WIP 2024-05-15 12:24:17 +02:00
d2e3148375
feat(settings): Expose settings as a dict.
This makes it possible to use them in standalone scripts, when using
`django.settings.configure(**settings_dict)`.
2024-05-15 12:24:17 +02:00
David Larlet
44b8433216
Merge pull request #1810 from umap-project/docs-more
docs: Tutorials review and improvements
2024-05-14 13:06:47 -04:00
Yohan Boniface
a1084e0c7b
Merge pull request #1816 from umap-project/dependabot/pip/pytest-playwright-0.5.0
chore: bump pytest-playwright from 0.4.4 to 0.5.0
2024-05-14 18:45:58 +02:00
Yohan Boniface
754c895dde
Merge pull request #1821 from umap-project/caption-module
fix: display all layers in caption
2024-05-14 18:30:31 +02:00
Yohan Boniface
303e5f78e8
Merge pull request #1819 from umap-project/dependabot/pip/django-5.0.6
chore: bump django from 5.0.5 to 5.0.6
2024-05-14 17:36:39 +02:00
Yohan Boniface
9e2a29002a Apply suggestions from code review
Co-authored-by: David Larlet <3556+davidbgk@users.noreply.github.com>
2024-05-14 17:35:33 +02:00