╒═══╕
│x │
diff --git a/src/browser/modules/Stream/CypherFrame/__snapshots__/CodeView.test.tsx.snap b/src/browser/modules/Stream/CypherFrame/__snapshots__/CodeView.test.tsx.snap
index b0e94bbd504..ae872021f9f 100644
--- a/src/browser/modules/Stream/CypherFrame/__snapshots__/CodeView.test.tsx.snap
+++ b/src/browser/modules/Stream/CypherFrame/__snapshots__/CodeView.test.tsx.snap
@@ -14,7 +14,7 @@ exports[`CodeViews CodeStatusbar displays statusBarMessage 1`] = `
class="sc-jcFjpl cdUBmZ"
>
Started streaming 1 records after 5 ms and completed after 10 ms.
diff --git a/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap b/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap
index 96c747d53b3..0fb029bfe80 100644
--- a/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap
+++ b/src/browser/modules/Stream/__snapshots__/SchemaFrame.test.tsx.snap
@@ -7,16 +7,16 @@ exports[`SchemaFrame renders empty 1`] = `
>
@@ -24,10 +24,10 @@ exports[`SchemaFrame renders empty 1`] = `
None
|
@@ -35,33 +35,33 @@ exports[`SchemaFrame renders empty 1`] = `
@@ -69,24 +69,24 @@ exports[`SchemaFrame renders empty 1`] = `
None
|
|
|
|
|
@@ -121,46 +121,46 @@ exports[`SchemaFrame renders empty for Neo4j >= 4.0 1`] = `
>
@@ -168,62 +168,62 @@ exports[`SchemaFrame renders empty for Neo4j >= 4.0 1`] = `
None
|
|
|
|
|
|
|
@@ -231,24 +231,24 @@ exports[`SchemaFrame renders empty for Neo4j >= 4.0 1`] = `
None
|
|
|
|
|
@@ -283,16 +283,16 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = `
>
@@ -300,10 +300,10 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = `
ON :Movie(released) ONLINE
|
@@ -311,13 +311,13 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = `
@@ -325,10 +325,10 @@ exports[`SchemaFrame renders results for Neo4j < 4.0 1`] = `
ON ( book:Book ) ASSERT book.isbn IS UNIQUE
|
@@ -365,46 +365,46 @@ exports[`SchemaFrame renders results for Neo4j >= 4.2 1`] = `
>
@@ -412,34 +412,34 @@ exports[`SchemaFrame renders results for Neo4j >= 4.2 1`] = `
|
node_label_property
|
|
|
|
[
"released"
]
|
ONLINE
|
@@ -447,33 +447,33 @@ exports[`SchemaFrame renders results for Neo4j >= 4.2 1`] = `
@@ -481,32 +481,32 @@ exports[`SchemaFrame renders results for Neo4j >= 4.2 1`] = `
constraint_550b2518
|
UNIQUE
|
node
|
[
"Movie"
]
|
[
"released"
diff --git a/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.tsx b/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.tsx
index 7a2455e3a66..0dba941a653 100644
--- a/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.tsx
+++ b/src/neo4j-arc/common/components/PropertiesTable/PropertiesTable.tsx
@@ -31,17 +31,31 @@ import {
import { ClipboardCopier } from '../ClipboardCopier'
import { ShowMoreOrAll } from '../ShowMoreOrAll/ShowMoreOrAll'
import { VizItemProperty } from 'neo4j-arc/common'
+import {
+ GraphInteractionCallBack,
+ NODE_PROP_UPDATE
+} from '../../../graph-visualization'
export const ELLIPSIS = '\u2026'
export const WIDE_VIEW_THRESHOLD = 900
export const MAX_LENGTH_NARROW = 150
export const MAX_LENGTH_WIDE = 300
type ExpandableValueProps = {
+ nodeId: string
+ propKey: string
value: string
width: number
type: string
+ onGraphInteraction: GraphInteractionCallBack
}
-function ExpandableValue({ value, width, type }: ExpandableValueProps) {
+function ExpandableValue({
+ nodeId,
+ propKey,
+ value,
+ width,
+ type,
+ onGraphInteraction
+}: ExpandableValueProps) {
const [expanded, setExpanded] = useState(false)
const maxLength =
@@ -56,7 +70,17 @@ function ExpandableValue({ value, width, type }: ExpandableValueProps) {
valueShown += valueIsTrimmed ? ELLIPSIS : ''
return (
- <>
+
+ onGraphInteraction(NODE_PROP_UPDATE, {
+ nodeId: nodeId,
+ propKey: propKey,
+ propVal: e.currentTarget.textContent
+ })
+ }
+ >
{type.startsWith('Array') && '['}
{valueIsTrimmed && (
@@ -65,7 +89,7 @@ function ExpandableValue({ value, width, type }: ExpandableValueProps) {
)}
{type.startsWith('Array') && ']'}
- >
+
)
}
@@ -75,14 +99,23 @@ type PropertiesViewProps = {
totalNumItems: number
moreStep: number
nodeInspectorWidth: number
+ onGraphInteraction?: GraphInteractionCallBack
}
export const PropertiesTable = ({
visibleProperties,
totalNumItems,
onMoreClick,
moreStep,
- nodeInspectorWidth
+ nodeInspectorWidth,
+ onGraphInteraction
}: PropertiesViewProps): JSX.Element => {
+ let id = ''
+ for (let i = 0; i < visibleProperties.length; i++) {
+ if (visibleProperties[i].key == '') {
+ id = visibleProperties[i].value
+ }
+ }
+
return (
<>
@@ -95,9 +128,12 @@ export const PropertiesTable = ({
undefined)}
/>
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx
index 0c8363018f5..02d10efb76b 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/DefaultDetailsPane.tsx
@@ -26,17 +26,20 @@ import { PaneBody, PaneHeader, PaneTitle, PaneWrapper } from './styled'
import { NodeLabel } from './NodeLabel'
import { RelType } from './RelType'
import { GraphStyleModel } from '../../models/GraphStyle'
+import { GraphInteractionCallBack } from '../Graph/GraphEventHandlerModel'
export const DETAILS_PANE_STEP_SIZE = 1000
export type DetailsPaneProps = {
vizItem: NodeItem | RelationshipItem
graphStyle: GraphStyleModel
nodeInspectorWidth: number
+ onGraphInteraction?: GraphInteractionCallBack
}
export function DefaultDetailsPane({
vizItem,
graphStyle,
- nodeInspectorWidth
+ nodeInspectorWidth,
+ onGraphInteraction
}: DetailsPaneProps): JSX.Element {
const [maxPropertiesCount, setMaxPropertiesCount] = useState(
DETAILS_PANE_STEP_SIZE
@@ -76,6 +79,9 @@ export function DefaultDetailsPane({
relType: vizItem.item.type
}}
graphStyle={graphStyle}
+ onGraphInteraction={onGraphInteraction}
+ sourceNodeId={vizItem.item.source.id}
+ targetNodeId={vizItem.item.target.id}
/>
)}
{vizItem.type === 'node' &&
@@ -99,6 +105,7 @@ export function DefaultDetailsPane({
moreStep={DETAILS_PANE_STEP_SIZE}
totalNumItems={allItemProperties.length}
nodeInspectorWidth={nodeInspectorWidth}
+ onGraphInteraction={onGraphInteraction}
/>
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx
index 8b4cbd62969..662d4c6cac3 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/DefaultPanelContent/RelType.tsx
@@ -21,28 +21,54 @@ import React from 'react'
import { GraphStyleModel } from '../../models/GraphStyle'
import { NonClickableRelTypeChip } from './styled'
+import {
+ GraphInteractionCallBack,
+ REL_TYPE_UPDATE
+} from '../Graph/GraphEventHandlerModel'
export type RelTypeProps = {
graphStyle: GraphStyleModel
selectedRelType: { relType: string; propertyKeys: string[]; count?: number }
+ onGraphInteraction?: GraphInteractionCallBack
+ sourceNodeId?: string
+ targetNodeId?: string
+}
+RelType.defaultProps = {
+ onGraphInteraction: () => undefined
}
export function RelType({
selectedRelType,
- graphStyle
+ graphStyle,
+ onGraphInteraction = () => undefined,
+ sourceNodeId,
+ targetNodeId
}: RelTypeProps): JSX.Element {
const styleForRelType = graphStyle.forRelationship({
type: selectedRelType.relType
})
return (
-
+ onGraphInteraction(REL_TYPE_UPDATE, {
+ sourceNodeId: sourceNodeId,
+ targetNodeId: targetNodeId,
+ oldType: selectedRelType.relType,
+ newType: e.currentTarget.textContent
+ })
+ }
>
- {selectedRelType.count !== undefined
- ? `${selectedRelType.relType} (${selectedRelType.count})`
- : `${selectedRelType.relType}`}
-
+
+ {selectedRelType.count !== undefined
+ ? `${selectedRelType.relType} (${selectedRelType.count})`
+ : `${selectedRelType.relType}`}
+
+
)
}
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts
index aa15f6afc54..3ba4a6f935b 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/GraphEventHandlerModel.ts
@@ -31,6 +31,10 @@ import {
import { Visualization } from './visualization/Visualization'
export const NODE_ON_CANVAS_CREATE = 'NODE_ON_CANVAS_CREATE'
+export const NODE_PROP_UPDATE = 'NODE_PROP_UPDATE'
+export const NODE_LABEL_UPDATE = 'NODE_LABEL_UPDATE'
+export const REL_ON_CANVAS_CREATE = 'REL_ON_CANVAS_CREATE'
+export const REL_TYPE_UPDATE = 'REL_TYPE_UPDATE'
export type GraphInteraction =
| 'NODE_EXPAND'
@@ -38,6 +42,10 @@ export type GraphInteraction =
| 'NODE_DISMISSED'
| 'NODE_ON_CANVAS_CREATE'
| typeof NODE_ON_CANVAS_CREATE
+ | typeof NODE_PROP_UPDATE
+ | typeof NODE_LABEL_UPDATE
+ | typeof REL_ON_CANVAS_CREATE
+ | typeof REL_TYPE_UPDATE
export type GraphInteractionCallBack = (
event: GraphInteraction,
@@ -54,6 +62,9 @@ export class GraphEventHandlerModel {
onGraphInteraction: GraphInteractionCallBack
selectedItem: NodeModel | RelationshipModel | null
+ private altCreatedRelSourceNode: any
+ private altCreatedRelTargetNode: any
+
constructor(
graph: GraphModel,
visualization: Visualization,
@@ -72,6 +83,9 @@ export class GraphEventHandlerModel {
this.onGraphInteraction = onGraphInteraction ?? (() => undefined)
this.onGraphModelChange = onGraphModelChange
+
+ this.altCreatedRelSourceNode = null
+ this.altCreatedRelTargetNode = null
}
graphModelChanged(): void {
@@ -239,8 +253,14 @@ export class GraphEventHandlerModel {
new NodeModel(
newId.toString(),
['Undefined'],
- { name: 'New Node' },
- { name: 'string' }
+ {
+ name: 'New Node',
+ description: 'New Node'
+ },
+ {
+ name: 'string',
+ description: 'string'
+ }
)
])
this.visualization.update({ updateNodes: true, updateRelationships: true })
@@ -249,6 +269,7 @@ export class GraphEventHandlerModel {
this.onGraphInteraction(NODE_ON_CANVAS_CREATE, {
id: newId,
name: 'New Node',
+ description: 'New Node',
labels: ['Undefined']
})
}
@@ -263,6 +284,56 @@ export class GraphEventHandlerModel {
})
}
+ nodeAltDown(node: NodeModel): void {
+ if (!node) {
+ return
+ }
+
+ if (
+ this.altCreatedRelSourceNode == null &&
+ this.altCreatedRelTargetNode == null
+ ) {
+ this.altCreatedRelSourceNode = node
+ } else if (
+ this.altCreatedRelSourceNode != null &&
+ this.altCreatedRelTargetNode == null
+ ) {
+ this.altCreatedRelTargetNode = node
+
+ const maxId: number = Math.max(
+ ...this.graph
+ .relationships()
+ .map(relationship => parseInt(relationship.id))
+ )
+ const newId = maxId + 1
+
+ const altCreatedRel: RelationshipModel = new RelationshipModel(
+ newId.toString(),
+ this.altCreatedRelSourceNode,
+ this.altCreatedRelTargetNode,
+ newId.toString(),
+ { name: 'new link' },
+ { name: 'string' }
+ )
+
+ this.graph.addRelationships([altCreatedRel])
+ this.visualization.update({
+ updateNodes: true,
+ updateRelationships: true
+ })
+ this.graphModelChanged()
+
+ this.onGraphInteraction(REL_ON_CANVAS_CREATE, {
+ type: newId,
+ sourceNodeId: this.altCreatedRelSourceNode.id,
+ targetNodeId: this.altCreatedRelTargetNode.id
+ })
+
+ this.altCreatedRelSourceNode = null
+ this.altCreatedRelTargetNode = null
+ }
+ }
+
bindEventHandlers(): void {
this.visualization
.on('nodeMouseOver', this.onNodeMouseOver.bind(this))
@@ -278,6 +349,7 @@ export class GraphEventHandlerModel {
.on('nodeClicked', this.nodeClicked.bind(this))
.on('nodeDblClicked', this.nodeDblClicked.bind(this))
.on('nodeUnlock', this.nodeUnlock.bind(this))
+ .on('nodeAltDown', this.nodeAltDown.bind(this))
this.onItemMouseOut()
}
}
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts
index a65eb8e8f30..ffb28ae3689 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/Graph/visualization/mouseEventHandlers.ts
@@ -66,6 +66,12 @@ export const nodeEventHandlers = (
trigger('nodeMouseOut', node)
}
+ const onNodeMouseDown = (_event: KeyboardEvent, node: NodeModel) => {
+ if (_event.altKey || _event.ctrlKey || _event.metaKey || _event.shiftKey) {
+ trigger('nodeAltDown', node)
+ }
+ }
+
const dragstarted = (event: D3DragEvent) => {
initialDragPosition = [event.x, event.y]
restartedSimulation = false
@@ -115,6 +121,7 @@ export const nodeEventHandlers = (
.on('mouseout', onNodeMouseOut)
.on('click', onNodeClick)
.on('dblclick', onNodeDblClick)
+ .on('mousedown', onNodeMouseDown)
}
export const relationshipEventHandlers = (
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/GraphVisualizer.tsx b/src/neo4j-arc/graph-visualization/GraphVisualizer/GraphVisualizer.tsx
index b67b1360344..87bc6c09ad6 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/GraphVisualizer.tsx
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/GraphVisualizer.tsx
@@ -297,6 +297,7 @@ export class GraphVisualizer extends Component<
}}
DetailsPaneOverride={this.props.DetailsPaneOverride}
OverviewPaneOverride={this.props.OverviewPaneOverride}
+ onGraphInteraction={this.props.onGraphInteraction}
/>
)
diff --git a/src/neo4j-arc/graph-visualization/GraphVisualizer/NodeInspectorPanel.tsx b/src/neo4j-arc/graph-visualization/GraphVisualizer/NodeInspectorPanel.tsx
index 734d813b09e..12d9572c1e7 100644
--- a/src/neo4j-arc/graph-visualization/GraphVisualizer/NodeInspectorPanel.tsx
+++ b/src/neo4j-arc/graph-visualization/GraphVisualizer/NodeInspectorPanel.tsx
@@ -38,6 +38,7 @@ import { Resizable } from 're-resizable'
import { GraphStats } from '../utils/mapper'
import { GraphStyleModel } from '../models/GraphStyle'
import { VizItem } from '../types'
+import { GraphInteractionCallBack } from './Graph/GraphEventHandlerModel'
interface NodeInspectorPanelProps {
expanded: boolean
@@ -51,6 +52,7 @@ interface NodeInspectorPanelProps {
width: number
DetailsPaneOverride?: React.FC
OverviewPaneOverride?: React.FC
+ onGraphInteraction?: GraphInteractionCallBack
}
export const defaultPanelWidth = (): number =>
@@ -68,7 +70,8 @@ export class NodeInspectorPanel extends Component {
toggleExpanded,
width,
DetailsPaneOverride,
- OverviewPaneOverride
+ OverviewPaneOverride,
+ onGraphInteraction
} = this.props
const relevantItems = ['node', 'relationship']
const hoveringNodeOrRelationship =
@@ -120,6 +123,7 @@ export class NodeInspectorPanel extends Component {
vizItem={shownEl}
graphStyle={graphStyle}
nodeInspectorWidth={width}
+ onGraphInteraction={onGraphInteraction}
/>
) : (
+ item: Pick<
+ RelationshipModel,
+ 'id' | 'type' | 'propertyList' | 'source' | 'target'
+ >
}
type CanvasItem = {
diff --git a/src/neo4j-arc/package.json b/src/neo4j-arc/package.json
index 205b8232367..012832938da 100644
--- a/src/neo4j-arc/package.json
+++ b/src/neo4j-arc/package.json
@@ -6,7 +6,7 @@
"license": "GPL-3.0",
"typings": "dist/neo4j-arc.d.ts",
"scripts": {
- "build": "rollup -c --failAfterWarnings",
+ "build": "rollup -c",
"test": "tsc --noEmit",
"prepublishOnly": "npm run test && npm run build"
},
|