diff --git a/apps/web-graphpolaris/src/components/querybuilder/querybuilder.tsx b/apps/web-graphpolaris/src/components/querybuilder/querybuilder.tsx index 8e42ebf76a9a22c79a1d8444af3bd3df6eaaca39..031156107f3709f0bec2aab77877bd82ff7bc69b 100644 --- a/apps/web-graphpolaris/src/components/querybuilder/querybuilder.tsx +++ b/apps/web-graphpolaris/src/components/querybuilder/querybuilder.tsx @@ -1,4 +1,8 @@ -import { createReactFlowElements } from '@graphpolaris/querybuilder/usecases'; +import { + createReactFlowElements, + DragAttributePill, + DragAttributesAlong, +} from '@graphpolaris/querybuilder/usecases'; import { setQuerybuilderNodes, useAppDispatch, @@ -15,6 +19,7 @@ import ReactFlow, { FlowElement, Background, Node, + isNode, } from 'react-flow-renderer'; import styles from './querybuilder.module.scss'; import ConnectionLine from './customFlowLines/connection'; @@ -46,20 +51,27 @@ const QueryBuilder = (props: {}) => { event: React.MouseEvent<Element, MouseEvent>, node: Node<any> ) => { - const attr = nodes.getNodeAttributes(node.id); - const dx = node.position.x - attr.x; - const dy = node.position.y - attr.y; + const pNode = elements.find((e) => e.id == node.id); + if (!(pNode && isNode(pNode))) return; - nodes.forEachInNeighbor(node.id, (nb) => { - if (nodes.getNodeAttribute(nb, 'type') == 'attribute') { - nodes.updateNodeAttribute(nb, 'x', (x) => x + dx); - nodes.updateNodeAttribute(nb, 'y', (y) => y + dy); - } - }); + const dx = node.position.x - pNode.position.x; + const dy = node.position.y - pNode.position.y; nodes.setNodeAttribute(node.id, 'x', node.position.x); nodes.setNodeAttribute(node.id, 'y', node.position.y); + switch (nodes.getNodeAttribute(node.id, 'type')) { + case 'attribute': + DragAttributePill(node.id, nodes, dx, dy); + break; + case 'entity': + DragAttributesAlong(node.id, nodes, dx, dy); + break; + case 'relation': + DragAttributesAlong(node.id, nodes, dx, dy); + break; + } + dispatch(setQuerybuilderNodes(nodes.export())); }; diff --git a/libs/querybuilder/usecases/src/index.ts b/libs/querybuilder/usecases/src/index.ts index 587b11ec5597a24573db73767f21dec89f2cd273..b842820297da6b18305f33d1973de734199743d4 100644 --- a/libs/querybuilder/usecases/src/index.ts +++ b/libs/querybuilder/usecases/src/index.ts @@ -1,4 +1,6 @@ export * from './lib/attribute/getAttributeBoolOperators'; export * from './lib/attribute/checkInput'; export * from './lib/createReactFlowElements'; -export * from './lib/connPointsOnPills'; +export * from './lib/pillHandles'; +export * from './lib/dragging/dragAttribute'; +export * from './lib/dragging/dragAttributesAlong'; diff --git a/libs/querybuilder/usecases/src/lib/createReactFlowElements.ts b/libs/querybuilder/usecases/src/lib/createReactFlowElements.ts index 76b9e83c44ed94e8918fa6651410a5e22aaa6480..1757b3291ae18ef4d91b2adb8411fa28ce0ca269 100644 --- a/libs/querybuilder/usecases/src/lib/createReactFlowElements.ts +++ b/libs/querybuilder/usecases/src/lib/createReactFlowElements.ts @@ -12,7 +12,6 @@ export function createReactFlowElements(graph: Graph): Elements<Node | Edge> { switch (attributes.type) { case 'entity': data = { - name: attributes.name, isConnected: graph .neighbors(node) .some((nb) => graph.getNodeAttribute(nb, 'type') == 'relation'), @@ -20,7 +19,6 @@ export function createReactFlowElements(graph: Graph): Elements<Node | Edge> { break; case 'relation': data = { - name: attributes.name, isFromEntityConnected: graph .inNeighbors(node) .some((nb) => graph.getNodeAttribute(nb, 'type') == 'entity'), @@ -38,7 +36,6 @@ export function createReactFlowElements(graph: Graph): Elements<Node | Edge> { if (ERNeighbors.length > 0) attributeOfA = graph.getNodeAttribute(ERNeighbors[0], 'type'); data = { - name: attributes.name, datatype: attributes.datatype, operator: attributes.operator, attributeOfA: attributeOfA, @@ -46,6 +43,8 @@ export function createReactFlowElements(graph: Graph): Elements<Node | Edge> { break; } } + // Each pill should have a name and type + data = { ...data, name: attributes.name }; const RFNode: Node = { id: node, diff --git a/libs/querybuilder/usecases/src/lib/dragging/dragAttribute.ts b/libs/querybuilder/usecases/src/lib/dragging/dragAttribute.ts new file mode 100644 index 0000000000000000000000000000000000000000..332ca29cd3283c97d3876b9ca176068d97815e3e --- /dev/null +++ b/libs/querybuilder/usecases/src/lib/dragging/dragAttribute.ts @@ -0,0 +1,12 @@ +import Graph from 'graphology'; + +export function DragAttributePill( + id: string, + nodes: Graph, + dx: number, + dy: number +) { + // if the attribute is still connected to an entity or relation pill, disconnect + const es = nodes.outEdges(id); + es.forEach((e) => nodes.dropEdge(e)); +} diff --git a/libs/querybuilder/usecases/src/lib/dragging/dragAttributesAlong.ts b/libs/querybuilder/usecases/src/lib/dragging/dragAttributesAlong.ts new file mode 100644 index 0000000000000000000000000000000000000000..56697ab3f9cd125629c309c9df699419365a4a49 --- /dev/null +++ b/libs/querybuilder/usecases/src/lib/dragging/dragAttributesAlong.ts @@ -0,0 +1,27 @@ +import Graph from 'graphology'; + +/** + * Changes the position of connected attributes. + * @param id The id of the node which could have attributes connected to it (entity or relation) + * @param nodes The graphology query builder object + * @param dx The change in x + * @param dy The change in y + * @returns True if any attribute positions were changed + */ +export function DragAttributesAlong( + id: string, + nodes: Graph, + dx: number, + dy: number +): boolean { + let didChangeAttributes = false; + nodes.forEachInNeighbor(id, (nb) => { + if (nodes.getNodeAttribute(nb, 'type') == 'attribute') { + nodes.updateNodeAttribute(nb, 'x', (x) => x + dx); + nodes.updateNodeAttribute(nb, 'y', (y) => y + dy); + didChangeAttributes = true; + } + }); + + return didChangeAttributes; +} diff --git a/libs/querybuilder/usecases/src/lib/connPointsOnPills.ts b/libs/querybuilder/usecases/src/lib/pillHandles.ts similarity index 100% rename from libs/querybuilder/usecases/src/lib/connPointsOnPills.ts rename to libs/querybuilder/usecases/src/lib/pillHandles.ts