Skip to content

Commit

Permalink
Add documentation explaining Suber (v.s. Redux) (#25)
Browse files Browse the repository at this point in the history
* Add documentation explaining Suber (v.s Redux)

* version bump

* Self-review

* Self-review
  • Loading branch information
QubitPi authored Nov 22, 2023
1 parent d97e8d0 commit 89e8dca
Show file tree
Hide file tree
Showing 7 changed files with 12,802 additions and 13,203 deletions.
181 changes: 101 additions & 80 deletions docs/modules/ROOT/images/neo4j-browser.drawio

Large diffs are not rendered by default.

Binary file modified docs/modules/ROOT/images/neo4j-browser.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
81 changes: 81 additions & 0 deletions docs/modules/ROOT/images/redux-vs-suber.drawio
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<mxfile host="app.diagrams.net" modified="2023-11-22T08:50:41.601Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36" etag="4f750IJMlx4wg1Adnw_5" version="22.1.3" type="device">
<diagram name="Page-1" id="yI2_bbRLoR0CGLotLe0P">
<mxGraphModel dx="1481" dy="821" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=3;" edge="1" parent="1" source="XDQ285Tv6tWhBn1Cl0IR-1" target="XDQ285Tv6tWhBn1Cl0IR-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-1" value="&lt;font face=&quot;Ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;Redux&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#7248B6;fontColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="360" y="320" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-2" value="&lt;font face=&quot;ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;&lt;font color=&quot;#00aa00&quot;&gt;&lt;b&gt;Shared&lt;/b&gt;&lt;/font&gt; States&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="345" y="280" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;strokeWidth=3;" edge="1" parent="1" source="XDQ285Tv6tWhBn1Cl0IR-3" target="XDQ285Tv6tWhBn1Cl0IR-1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-3" value="&lt;font face=&quot;Ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;Component A&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#5FD3F2;fontColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="80" y="320" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-5" value="&lt;font face=&quot;Ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;Component B&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#5FD3F2;fontColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="640" y="320" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-8" value="&lt;font face=&quot;ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;dispatch(S)&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="210" y="310" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-9" value="&lt;font face=&quot;ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;selector(S)&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="490" y="310" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-10" value="&lt;font face=&quot;ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;update state S&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="70" y="240" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-11" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;curved=1;strokeWidth=3;" edge="1" parent="1" source="XDQ285Tv6tWhBn1Cl0IR-3" target="XDQ285Tv6tWhBn1Cl0IR-3">
<mxGeometry relative="1" as="geometry">
<Array as="points">
<mxPoint x="110" y="280" />
<mxPoint x="170" y="280" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-13" value="&lt;font face=&quot;Ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;Suber&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#000000;fontColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="365" y="500" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-14" value="&lt;font face=&quot;ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;&lt;font color=&quot;#00aa00&quot;&gt;&lt;b&gt;No&lt;/b&gt;&lt;/font&gt; States&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="355" y="460" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-16" value="&lt;font face=&quot;Ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;Component A&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#5FD3F2;fontColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="85" y="500" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-17" value="&lt;font face=&quot;Ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;Component B&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=none;fillColor=#5FD3F2;fontColor=#FFFFFF;" vertex="1" parent="1">
<mxGeometry x="645" y="500" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-23" value="" style="shape=flexArrow;endArrow=classic;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;strokeWidth=3;width=23.47826086956522;endSize=10.304347826086957;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="XDQ285Tv6tWhBn1Cl0IR-16" target="XDQ285Tv6tWhBn1Cl0IR-17">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="410" y="440" as="sourcePoint" />
<mxPoint x="460" y="390" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-30" value="&lt;font face=&quot;ubuntu&quot; style=&quot;font-size: 20px;&quot;&gt;bus&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="210" y="514" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-32" value="" style="endArrow=none;dashed=1;html=1;rounded=0;strokeWidth=3;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="340" y="640" as="sourcePoint" />
<mxPoint x="340" y="200" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-33" value="" style="endArrow=none;dashed=1;html=1;rounded=0;strokeWidth=3;" edge="1" parent="1">
<mxGeometry width="50" height="50" relative="1" as="geometry">
<mxPoint x="500" y="640" as="sourcePoint" />
<mxPoint x="500" y="200" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="XDQ285Tv6tWhBn1Cl0IR-34" value="&lt;font face=&quot;ubuntu&quot;&gt;&lt;span style=&quot;font-size: 20px;&quot;&gt;&lt;b style=&quot;&quot;&gt;Components&lt;br&gt;Decoupling&lt;br&gt;&lt;/b&gt;&lt;/span&gt;&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="345" y="200" width="150" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
Binary file added docs/modules/ROOT/images/redux-vs-suber.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
54 changes: 33 additions & 21 deletions docs/modules/ROOT/pages/neo4j-arc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -102,31 +102,27 @@ export default function MyGraphComponent(): JSX.Element {
The Neo4J Browser is logically composed of 2 parts:

. The neo4j-arc, which is the current part we are discussing

.. The neo4j-arc is based on D3 and implements its own layout, coloring, and link drawing. For example, the calculation
of arrow, i.e. links, between nodes uses some
https://github.com/QubitPi/neo4j-browser/blob/master/src/neo4j-arc/graph-visualization/utils/ArcArrow.ts[very complicated math]
along with very prelimiary MDN standard basic shap specification.
.. IMPORTANT
====
Although we see `<id>` property for every node or relationship in the node inspection panel of Neo4J Browser, those
ID's are NOT generated by neo4j-arc, but https://stackoverflow.com/a/67702695[instead by Neo4J database]

Note: the displayed `<id>` is the value of NodeMode.id
====

CAUTION
====

neo4j-arc does not generate or manage node/rel ID. Any xref:operations/on-canvas-operations.adoc[on-canvas operation]
generates nodes/rel with *transient ID* only. Any node/rel ID that is to be persisted needs to be generated and
managed by external logics, such as database auto-ID or library user

====

. A user-interface that combines the graph rendering (supported by the graphing module), database, and user
interaction together

[IMPORTANT]
====
Although we see `<id>` property for every node or relationship in the node inspection panel of Neo4J Browser, those
ID's are NOT generated by neo4j-arc, but https://stackoverflow.com/a/67702695[instead by Neo4J database]
Note: the displayed `<id>` is the value of NodeMode.id
====

[CAUTION]
====
neo4j-arc does not generate or manage node/rel ID. Any xref:operations/on-canvas-operations.adoc[on-canvas operation]
generates nodes/rel with *transient ID* only. Any node/rel ID that is to be persisted needs to be generated and
managed by external logics, such as database auto-ID or library user
====

[WARNING]
====
Expand All @@ -145,9 +141,7 @@ image:neo4j-browser.png[width=900]
+
--
** Redux
** Suber: The reason suber is used is sharing states between Neo4J database data and React components is not supported
by Redux. As its doc (https://github.com/oskarhane/suber#in-combination-with-redux) points out, Redux is for two-way
communications between components. Suber is for one-way comm. between component and DB.
** Sube (discussed below)
** Apollo GraphQL Client
** Drag & Drop Plugin
--
Expand All @@ -167,3 +161,21 @@ The initialization assumes provider pattern around regular App component:
----

* Neo4J Browser styling is implemented via https://styled-components.com/[styled-components] and is initialized in App.tsx

=== What is Suber?

Looking at suber-related code (`bus`), we feel that it is very similar to Redux. It's true that both Suber and Redux are
designed to *decouple React components*.

Redux decouples components via "state", which makes it great for shared application state handling. Essentially, if one
component A depends on component B via a state S; when S is updated in B, A gets re-rendered accordingly. Redux is our
choice in this case

But what if component A depends on B via a prop that is not a state? For example, if component B is a database client
and component A is a user registration form, then there is no concept of state S between A and B, because between A and
B is just a one-time username/password message. Application state that is not shared should not go into Redux, it should
go directly into the component that needs it.

This is where https://github.com/oskarhane/suber[suber] comes in.

image:redux-vs-suber.png[width=900]
2 changes: 1 addition & 1 deletion src/neo4j-arc/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "neo4j-devtools-arc",
"version": "0.0.56",
"version": "0.0.57",
"main": "dist/neo4j-arc.js",
"author": "Neo4j Inc.",
"license": "GPL-3.0",
Expand Down
Loading

0 comments on commit 89e8dca

Please sign in to comment.