ls1intum / Apollon

UML Modeling Editor written in React
https://apollon-library.readthedocs.io
MIT License
61 stars 21 forks source link

Initial support for tracking / applying patches #318

Closed loreanvictor closed 8 months ago

loreanvictor commented 8 months ago

Checklist

Motivation and Context

This is a follow-up to this PR, merging some of the functionality introduced in that PR. The remainder of that

API Users of ApollonEditor can get notified when the diagram state changes, but they can't get notified of exactly what has changed. In the same vein, they can change the diagram whole-sale, but they can't apply patches to partially modify the diagram (without changing it all).

These limitations can be particularly problematic in contexts such as realtime collaboration, as with the current APIs clients can sync the diagram whole-sale, which is error-prone and taxing on bandwidth.

Description

This PR adds the following methods to ApollonEditor class:

subscribeToModelChangePatches(callback: (patch: Patch) => void): void
unsubscribeFromModelChangePatches(callback: (patch: Patch) => void): void 
importPatch(patch: Patch): void

Additionally, it adds the following components, all contained in main/services/patcher package:

class Patcher<T>

Keeps track of some given object, notifying subscribers of patches when some change happens, and applying incoming patches to the object.

function createPatcherReducer<T>(patcher: Patcher<T>, options)

Creates a Redux reducer to allow applying patches via action dispatch on the store.

function createPatcherMiddleware<T>(patcher: Patcher<T>, options)

Creates a Redux middleware to intercept changes to the state using the patcher.

function* PatchLayouter()

A redux saga to correct layouts after applying a patch.

The format of the patch objects is according to JSONPatch spec.

Steps for Testing

  1. Clone Apollon_standalone and switch to this PR,
  2. Create /diagrams folder,
  3. Link local Apollon,
  4. Run Apollon_standalone and test realtime collaboration.

Test Coverage

File Branch Line
main/apollon-editor.ts 79.16% 82.85%
main/components/store/model-store.tsx 100% 100%
main/scenes/application.tsx 100% 100%
services/patcher 86.66% 97.32%
services/patcher/compare.ts 100% 100%
services/patcher/index.ts 100% 100%
services/patcher/patcher-middleware.ts 57.14% 94.73%
services/patcher/patcher-reducer.ts 100% 100%
services/patcher/patcher-repository.ts 100% 100%
services/patcher/patcher-saga.ts 75% 90.9%
services/patcher/patcher.ts 100% 100%

Screenshots

The changes do not modify the UI, but they would look like the following (for example, testing via Apollon_standalone):

ezgif com-video-to-gif-2

matthiaslehnertum commented 8 months ago

@loreanvictor Could you run prettier on the files? The build step seems to complain about that 🤔

matthiaslehnertum commented 8 months ago

The code itself looks fine, I think the implementation is done nicely! If you could just have a look at the prettier issue and the few things codacy complains about the PR would be good to go! :)

loreanvictor commented 8 months ago

The code itself looks fine, I think the implementation is done nicely! If you could just have a look at the prettier issue and the few things codacy complains about the PR would be good to go! :)

Thanks, I did fix styling issues with prettier and codacy, and added docs both for external APIs and the patcher service itself.

matthiaslehnertum commented 8 months ago

With these adaptions in place, the change looks good to me 👍