diff --git a/docs/modules/ROOT/images/cql/graph-model-relationships.cql b/docs/modules/ROOT/images/cql/graph-model-relationships.cql new file mode 100644 index 00000000000..ff478aaf959 --- /dev/null +++ b/docs/modules/ROOT/images/cql/graph-model-relationships.cql @@ -0,0 +1,274 @@ +CREATE (id:`State` { + name: "id" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "id" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (labels:`State` { + name: "labels" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "labels" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (propertyList:`State` { + name: "propertyList" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "propertyList" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (propertyMap:`State` { + name: "propertyMap" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "propertyMap" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (isNode:`FixedState` { + name: "isNode" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "isNode" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (isRelationship:`FixedState` { + name: "isRelationship" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "isRelationship" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (radius:`VisualState` { + name: "radius" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "radius" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (caption:`VisualState` { + name: "caption" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "caption" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (selected:`VisualState` { + name: "selected" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "selected" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (expanded:`VisualState` { + name: "expanded" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "expanded" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (minified:`VisualState` { + name: "minified" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "minified" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (contextMenu:`VisualState` { + name: "contextMenu" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "contextMenu" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (x:`VisualState` { + name: "x" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "x" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (y:`VisualState` { + name: "y" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "y" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (fx:`VisualState` { + name: "fixed x" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "fixed x" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (fx:`VisualState` { + name: "fixed y" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "fixed y" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (hoverFixed:`VisualState` { + name: "hoverFixed" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "hoverFixed" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (initialPositionCalculated:`VisualState` { + name: "initialPositionCalculated" +}); +MATCH (source), (target) +WHERE source.name = "NodeModel" AND target.name = "initialPositionCalculated" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + + + + + + + + + + + + + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "id" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "propertyList" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "propertyMap" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "NodeModel" +CREATE (source)-[r:`source`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "NodeModel" +CREATE (source)-[r:`target`]->(target) RETURN type(r); + +CREATE (type:`State` { + name: "type" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "type" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "isNode" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "isRelationship" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (naturalAngle:`VisualState` { + name: "naturalAngle" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "naturalAngle" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "caption" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (captionLength:`VisualState` { + name: "captionLength" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "captionLength" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (captionHeight:`VisualState` { + name: "captionHeight" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "captionHeight" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "RelationshipCaptionLayout" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (shortCaption:`VisualState` { + name: "shortCaption" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "shortCaption" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (shortCaptionLength:`VisualState` { + name: "shortCaptionLength" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "shortCaptionLength" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "selected" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (centreDistance:`VisualState` { + name: "centreDistance" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "centreDistance" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +CREATE (arrow:`VisualState` { + name: "arrow" +}); +MATCH (source), (target) +WHERE source.name = "RelationshipModel" AND target.name = "arrow" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "arrow" AND target.name = "ArcArrow" +CREATE (source)-[r:`sub-type`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "arrow" AND target.name = "LoopArrow" +CREATE (source)-[r:`sub-type`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "arrow" AND target.name = "StraightArrow" +CREATE (source)-[r:`sub-type`]->(target) RETURN type(r); + + + + + + + + + + +MATCH (source), (target) +WHERE source.name = "GraphModel" AND target.name = "NodeModel" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "GraphModel" AND target.name = "RelationshipModel" +CREATE (source)-[r:`state`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "GraphModel" AND target.name = "NodeModel" +CREATE (source)-[r:`expandedNodeMap`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "GraphModel" AND target.name = "NodeModel" +CREATE (source)-[r:`nodeMap`]->(target) RETURN type(r); + +MATCH (source), (target) +WHERE source.name = "GraphModel" AND target.name = "RelationshipModel" +CREATE (source)-[r:`relationshipMap`]->(target) RETURN type(r); diff --git a/docs/modules/ROOT/images/cql/types.cql b/docs/modules/ROOT/images/cql/types.cql new file mode 100644 index 00000000000..df36d814973 --- /dev/null +++ b/docs/modules/ROOT/images/cql/types.cql @@ -0,0 +1,26 @@ +MATCH (n) DETACH DELETE n; + +CREATE (NodeModel:`Type` { + name: "NodeModel" +}); +CREATE (RelationshipModel:`Type` { + name: "RelationshipModel" +}); +CREATE (GraphModel:`Type` { + name: "GraphModel" +}); + +CREATE (RelationshipCaptionLayout:`Type` { + name: "RelationshipCaptionLayout" +}); + +CREATE (StraightArrow:`Type` { + name: "StraightArrow" +}); + +CREATE (LoopArrow:`Type` { + name: "LoopArrow" +}); +CREATE (ArcArrow:`Type` { + name: "ArcArrow" +}); \ No newline at end of file diff --git a/docs/modules/ROOT/images/internals-graph-model.png b/docs/modules/ROOT/images/internals-graph-model.png new file mode 100644 index 00000000000..0ddcf00a80e Binary files /dev/null and b/docs/modules/ROOT/images/internals-graph-model.png differ diff --git a/docs/modules/ROOT/pages/internals/graph-modelling.adoc b/docs/modules/ROOT/pages/internals/graph-modelling.adoc index c33e93509a8..bdcafedd842 100644 --- a/docs/modules/ROOT/pages/internals/graph-modelling.adoc +++ b/docs/modules/ROOT/pages/internals/graph-modelling.adoc @@ -12,28 +12,25 @@ Neo4J Browser first defines 3 of its own language-independent models: The node and relationship are implemented as TypeScript classes. +image:internals-graph-model.png[width=300] == Node Modeling https://github.com/QubitPi/neo4j-browser/blob/master/src/neo4j-arc/graph-visualization/models/Node.ts[NodeModel] models a node/vertex in a graph. It also encapsulates styling information, such as node radius and caption text. The styling -fields of this node are all "effectively uninitialized" and will be determined later +fields of this node are all "effectively uninitialized" and will be computed later. -To initialize a node, the following information is needed +The orange nodes shown above have to be initialized through constructor. -- An unique identifier of this node. This is also the surrogate key of that node in database -- labels The name of the group under which all nodes with the same label are counted together and displayed - as a single node type on UI. The name is a bit of misleading. In Neo4J browser, a `label` is NOT the text displayed on - a node but rather the "type" of that node. This is used to distinguish the different types of node displayed on UI -- A mapping containig all node properties where the key is the propery name and value is the - property value -- propertyTypes An object that maps the property name to the data type (in string) of the propery value +Note that the "labels" are sort of mis-leading. They are actually the name of the *group* under which all nodes with the +same label are counted together and displayed as a single node type on UI (specirically on inspection panel). In Neo4J +browser, a `label` is NOT the text displayed on a node but rather the "type" of that node. == Link Modeling A link is modeled as a https://github.com/QubitPi/neo4j-browser/blob/master/src/neo4j-arc/graph-visualization/models/Relationship.ts[Relationship] -in Neo4J Broswer. +in Neo4J Broswer. == Graph Modeling diff --git a/docs/modules/ROOT/pages/operations/browser-rbac-count.adoc b/docs/modules/ROOT/pages/operations/browser-rbac-count.adoc index 1fedeae2034..d83ca37864d 100644 --- a/docs/modules/ROOT/pages/operations/browser-rbac-count.adoc +++ b/docs/modules/ROOT/pages/operations/browser-rbac-count.adoc @@ -2,7 +2,7 @@ = Node and relationship counts with role-based access control Normally Neo4j Browser can look up node and relationship counts quickly, as they are cached in the database. -However, if role-based access control is configured (see link:https://neo4j.com/docs/operations-manual/current/authentication-authorization/access-control/[Operations Manual -> Fine-grained access control^] for more information), Neo4j counts the nodes and relationships the current user has access to on-demand, which is computationally expensive and thus potentially time-consuming. -If Neo4j Browser detects that the counts are slow, it automatically stops polling counts and instead show a button for manual refresh. +However, if role-based access control is configured (see link:https://neo4j.com/docs/operations-manual/current/authentication-authorization/access-control/[Operations Manual -> Fine-grained access control^] for more information), Neo4j counts the nodes and relationships the current user has access to on-demand, which is computationally expensive and thus potentially time-consuming. +If Neo4j Browser detects that the counts are slow, it automatically stops polling counts and instead show a button for manual refresh. image:rbac-count.png[width=300] \ No newline at end of file