Skip to content

Commit

Permalink
neo4j-arc should be node/rel-ID agnostic (#22)
Browse files Browse the repository at this point in the history
* neo4j-arc should be node/rel-ID agnostic

* Update documentation

* Version bump
  • Loading branch information
QubitPi committed Jun 11, 2024
1 parent 4080c2e commit 0ff9e96
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 34 deletions.
11 changes: 5 additions & 6 deletions docs/modules/ROOT/pages/neo4j-arc/graph-interactions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ click on canvas. We will follow the steps above by first defining the event hand
this.visualization.update({ updateNodes: true, updateRelationships: true })
this.graphModelChanged()
this.onGraphInteraction(NODE_ON_CANVAS_CREATE, { id: newNodeId, name: 'New Node', labels: ['Undefined'] })
this.onGraphInteraction(NODE_ON_CANVAS_CREATE, { name: 'New Node', labels: ['Undefined'] })
}
----

Expand Down Expand Up @@ -99,22 +99,21 @@ As we've mentioned earlier, we would like to persist this new node to database.
if (event == NODE_ON_CANVAS_CREATE) {
if (properties == null) {
throw new Error(
'A property map with id, name, and labels keys are required'
'A property map with name, and labels keys are required'
)
}
const id = properties['id']
const name = properties['name']
const variableName = `node${id}`
const variableName = `node`
const labels = (properties['labels'] as string[]).map(label => `\`${label}\``).join(':')
const query = `CREATE (${variableName}:${labels} { id: ${id}, name: "${name}" });`
const query = `CREATE (${variableName}:${labels} { name: "${name}" });`
this.props.bus.self(
CYPHER_REQUEST,
{
query,
params: { labels, id, name },
params: { labels, name },
queryType: NEO4J_BROWSER_USER_ACTION_QUERY
},
(response: any) => {
Expand Down
30 changes: 24 additions & 6 deletions docs/modules/ROOT/pages/neo4j-arc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,32 @@ export default function MyGraphComponent(): JSX.Element {

The Neo4J Browser is logically composed of 2 parts:

1. A slightly coupled graphing module
2. A user-interface that combines the graph rendering (supported by the graphing module), database, and user
. 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

The graphing 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.

[WARNING]
====
Expand Down
22 changes: 21 additions & 1 deletion docs/modules/ROOT/pages/operations/on-canvas-operations.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,27 @@

*Double clicking the white area* on canvas will automatically generate a new node with

1. an auto-incremented ID, i.e. (the max ID of nodes on canvas) + 1
1. a transient ID prefixed with "transient-" followed by a random string. For example "transient-rxnnzr6t4x"

[NOTE]
====

The reason that the ID being transient is due to the fact that this ID won't be persisted into database. Refreshing
the browser will replace this transient ID with a database-generated ID (in the form of a number, such as 65).

Normally, neo4j-browser feeds into neo4j-arc, which is the graphing module of neo4j-browser, with a set of
fully-hydrated set of nodes and relationships. This results in the design in neo4j-arc which is: to render a node or
relationship, the ID of it must be provided (i.e. a required argument to node/rel constructor).

Generating a new node by double-clicking, however, is an operation manged by neo4j-arc, which by design is not
responsible for generating and managing node/relationship ID's. But to implement the "realtime editing" effect, the
new node/rel ID has to be genreated at the beginning.

To resolve the conflict between original neo4j-browser design and on-canvas operation, any node/rel generated
"on-canvas" will have this transient ID.

====

2. a label of "Undefined"
3. the node caption of "New Node"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,25 +400,24 @@ LIMIT ${maxNewNeighbours}`
if (event == NODE_ON_CANVAS_CREATE) {
if (properties == null) {
throw new Error(
'A property map with id, name, and labels keys are required'
'A property map with name, and labels keys are required'
)
}

const id = properties['id']
const name = properties['name']
const description = properties['description']
const variableName = `node${id}`
const variableName = `node`
const labels = (properties['labels'] as string[])
.map(label => `\`${label}\``)
.join(':')

const query = `CREATE (${variableName}:${labels} { id: ${id}, name: "${name}", description: "${description}" });`
const query = `CREATE (${variableName}:${labels} { name: "${name}", description: "${description}" });`

this.props.bus.self(
CYPHER_REQUEST,
{
query,
params: { labels, id, name, description },
params: { labels, name, description },
queryType: NEO4J_BROWSER_USER_ACTION_QUERY
},
(response: any) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,14 +244,12 @@ export class GraphEventHandlerModel {
}

onCanvasDblClicked(): void {
const maxId: number = Math.max(
...this.graph.nodes().map(node => parseInt(node.id))
)
const newId = maxId + 1
const transientId: string =
'transient-' + Math.random().toString(36).slice(2)

this.graph.addNodes([
new NodeModel(
newId.toString(),
transientId,
['Undefined'],
{
name: 'New Node',
Expand All @@ -267,7 +265,6 @@ export class GraphEventHandlerModel {
this.graphModelChanged()

this.onGraphInteraction(NODE_ON_CANVAS_CREATE, {
id: newId,
name: 'New Node',
description: 'New Node',
labels: ['Undefined']
Expand Down Expand Up @@ -300,18 +297,14 @@ export class GraphEventHandlerModel {
) {
this.altCreatedRelTargetNode = node

const maxId: number = Math.max(
...this.graph
.relationships()
.map(relationship => parseInt(relationship.id))
)
const newId = maxId + 1
const transientId: string =
'transient-' + Math.random().toString(36).slice(2)

const altCreatedRel: RelationshipModel = new RelationshipModel(
newId.toString(),
transientId,
this.altCreatedRelSourceNode,
this.altCreatedRelTargetNode,
newId.toString(),
transientId,
{ name: 'new link' },
{ name: 'string' }
)
Expand All @@ -324,7 +317,7 @@ export class GraphEventHandlerModel {
this.graphModelChanged()

this.onGraphInteraction(REL_ON_CANVAS_CREATE, {
type: newId,
type: transientId,
sourceNodeId: this.altCreatedRelSourceNode.id,
targetNodeId: this.altCreatedRelTargetNode.id
})
Expand Down
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.53",
"version": "0.0.54",
"main": "dist/neo4j-arc.js",
"author": "Neo4j Inc.",
"license": "GPL-3.0",
Expand Down

0 comments on commit 0ff9e96

Please sign in to comment.