tijlleenders / ZinZen

Better together - an app to realize dreams together.
https://ZinZen.me
GNU Affero General Public License v3.0
43 stars 60 forks source link

Move/Paste Goal/Budget in hierarchy #1918

Open tijlleenders opened 5 months ago

tijlleenders commented 5 months ago

Is your feature request related to a problem? Please describe. It's very annoying when you need move Goals/Budgets atound but can't. Especially with a few (layers) of subGoals it's not trivial to just delete/recreate.

Describe the solution you'd like

  1. Add a 'Move' option to the edit modal
  2. When 'Move' is pressed, show a toast 'Navigate to destination place and confirm via +'
  3. When in a different place of the hierarchy, show an extra + option 'Move here'.

Describe alternatives you've considered Not using the 'normal' navigation to go to the destination place. Less intuitive.

Additional context See info in comments before starting this.

tijlleenders commented 1 month ago

So... this seems to be an issue that requires some further breakdown.
After looking at the options in #1934 the conclusion is to keep it simple (latest timestamp wins), so no need for a library.

First we need to agree on the data structure. There are multiple ways of storing a Directed Acyclical Graph (DAG) of Goals:

  1. Each Parent stores all direct Children (one level down)
  2. Each Goal only stores their Parent
  3. Combo of 1 and 2
  4. Separate relationships table(s) for parent-child relation (Graph database style)

We chose 1, for simplicity and speed.
We can quickly go down into the DAG to find the Goal we want, and the path back is stored in memory (navigate back).

Move (or any change) on sharer's side

To implement a move locally, this is a transaction on the database:

  1. Remove child id in old Parent
  2. Add child id in new Parent

Now what happens if we move a Goal that was also shared with someone?
Since we are using CRDTs this is actually quite simple. We share the whole object over the air/wire. This is actually true for any change, not just move. Even in case of a delete (attribute trash=true), so we don´t need a separate Trash collection, just MyGoals and PartnerGoals.

That should be enough on the Sharer's side. Simple eh?
By just sending the Goal, the receiver should have enough info to process any changes.

Move (or any change) on receiver's side

Here's a diagram:
image

@Tushar-4781 @vinaybadgujar102
Do you see any issues with this approach?
I thought it would be necessary to separate the MyGoals and PartnersGoals into three collections each, for hierarchy, core info and sharing info, but actually after discussion with Vinay I realized that this only makes things more complex.

For reference, stored the underlying Mermaid:

flowchart LR
    A[MyGoals] -->|Goal, only strip sharedWith| B(Outbox)
    Z[PartnersGoals] -->|suggestion - not Goal| B(Outbox)
    B --> C{ZinZen router}
    C -->|relId1 device X| D(Inbox device X)
        D -->|notify if change - or handle suggestion|K[X's MyGoals]
        D -->|silent|L[X's PartnersGoals]
    C -->|relId3 Contact A| F(Inbox device Contact A)
        F -->|notify if change - or handle suggestion|Y[A's MyGoals]
        F -->|silent|X[A's PartnersGoals]