Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Bug report) Relation map crashes when there is an unpaired relation definition #3055

Closed
eliandoran opened this issue Aug 11, 2022 · 3 comments

Comments

@eliandoran
Copy link
Collaborator

Trilium Version

0.54.2

What operating system are you using?

Other Linux

What is your setup?

Local (no sync)

Operating System Version

Linux workstation 5.10.135 #1-NixOS SMP Wed Aug 3 10:00:52 UTC 2022 x86_64 GNU/Linux

Description

Steps to reproduce:

  1. Create a new note (call it "Big Note").
  2. Inside “Big Note”, create four more sub-notes:
    1. Parent
    2. Child 1
    3. Child 2
    4. Child 3
  3. In “Big Note”, go to “Owned attributes” and “Add new relation definition”:
    1. Name: contains
    2. Promoted: checked
    3. Multiplicity: multi value
    4. Inverse relation: containedIn
    5. Inheritable: checked
    6. Should be: #relation:contains(inheritable)="promoted,multi,inverse=containedIn" 
  4. Go to “Parent”:
    1. In “Promoted attributes”, go to “contains” and add “Child 1”.
    2. Add a new “contains” attribute and select “Child 2”.
    3. End result in “Owned attributes” should be: ~contains=Child 1 ~contains=Child2 ~contains=Child3
  5. Go to “Big note”, “Basic Properties” and select Note type “Relation map”.
    1. Add “Child 1”, “Child 2” and “Child 3" to the map via drag-and-drop from the sidebar.
    2. Add “Parent”.

The diagram gets half-rendered:

image

The console reveals this stack trace:

Uncaught (in promise) TypeError: this.labelText is undefined
    update http://localhost:8080/#root/rUeOmSxulfQZ-bekV line 2 > injectedScript:1
    a http://localhost:8080/#root/rUeOmSxulfQZ-bekV line 2 > injectedScript:1
    setLabel http://localhost:8080/#root/rUeOmSxulfQZ-bekV line 2 > injectedScript:1
    a http://localhost:8080/#root/rUeOmSxulfQZ-bekV line 2 > injectedScript:1
    loadNotesAndRelations http://localhost:8080/app/widgets/type_widgets/relation_map.js:287
localhost:8080:1:167560
@eliandoran
Copy link
Collaborator Author

Turns out the explaination is quite simple:

Previously, we defined a single relation definition, having an inverse relation.

The documentation says:

Relation definition allows you to specify such "inverse relation" - for the relation you just define you specify which is the inverse relation. Note that in the second example we should have two relation definitions - one for isParentOf which defines isChildOf as inverse relation and then second relation definition for isChildOf which defines isParentOf as inverse relation.

The problem is we didn't add the corresponding inverse relation.

With just #relation:contains(inheritable)="promoted,multi,inverse=containedIn", the map fails to render.

Adding the full declaration:

#relation:contains(inheritable)="promoted,multi,inverse=containedIn"
#relation:containedIn(inheritable)="promoted,multi,inverse=contains" 

And then relation map will render like a charm.

Nevertheless, even if the user somehow ends up with a inverse relation with no corresponding relation, the relation map should not crash.

@eliandoran
Copy link
Collaborator Author

eliandoran commented Aug 11, 2022

My attempts at a possible solution:

Change the client to add a fake inverse relation:

diff --git a/src/public/app/widgets/type_widgets/relation_map.js b/src/public/app/widgets/type_widgets/relation_map.js
index 615b9d06..2eeb0ed3 100644
--- a/src/public/app/widgets/type_widgets/relation_map.js
+++ b/src/public/app/widgets/type_widgets/relation_map.js
@@ -250,6 +250,7 @@ export default class RelationMapTypeWidget extends TypeWidget {
             if (match) {
                 match.type = relation.type = relation.name === data.inverseRelations[relation.name] ? 'biDirectional' : 'inverse';
                 relation.render = false; // don't render second relation
+                data.inverseRelations[match.name] = relation.name;
             } else {
                 relation.type = 'uniDirectional';
                 relation.render = true;

or, change the server to add a fake inverse relation:

diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js
index ccd6dec0..bb493530 100644
--- a/src/routes/api/notes.js
+++ b/src/routes/api/notes.js
@@ -181,6 +181,7 @@ function getRelationMap(req) {
 
             if (def.inverseRelation) {
                 resp.inverseRelations[relationDefinition.getDefinedName()] = def.inverseRelation;
+                resp.inverseRelations[def.inverseRelation] = relationDefinition.getDefinedName();
             }
         }
     }

Both of these result in a working diagram:

image

@eliandoran eliandoran changed the title (Bug report) (Bug report) Relation map crashes when there is an unpaired relation definition Aug 11, 2022
@eliandoran
Copy link
Collaborator Author

eliandoran commented Aug 11, 2022

Here are my notes more detailed notes regarding this issue: Relation map crashes when there is an unpaired relation definition.zip

Please note that this does not contain the notes that have this issue. Interestingly enough, attempting to export and then importing the notes into a clean environment will not reproduce the issue. It has to be done manually as per the steps above.

@zadam zadam closed this as completed in ddb57e3 Aug 14, 2022
zadam added a commit that referenced this issue Aug 14, 2022
Fix relation map crash on missing inverse pair (fixes #3055)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant