diff --git a/package.json b/package.json
index 6a3b1b1..454bcc5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-policy-topology",
- "version": "0.1.5",
+ "version": "0.1.6",
"type": "module",
"main": "src/main.js",
"module": "src/main.js",
diff --git a/src/App.js b/src/App.js
index d65e32b..afe893c 100644
--- a/src/App.js
+++ b/src/App.js
@@ -1,10 +1,7 @@
-import React, { useState, useEffect, useCallback } from 'react';
+import React, { useState, useEffect } from 'react';
import PolicyTopology from './PolicyTopology.js';
import PickResource from './PickResource.js';
-import ResetPolicyTopology from './ResetPolicyTopology.js';
-import DotStringEditor from './DotStringEditor.js';
-import graphlib from 'graphlib';
-import * as dot from 'graphlib-dot';
+import * as dot from 'graphlib-dot'; // still needed for parsing dotString
import './App.css';
function App() {
@@ -125,67 +122,14 @@ function App() {
setGraph(g);
}, [dotString]);
- const handleNodeSelection = useCallback((nodeId) => {
- if (!graph) return;
-
- if (nodeId === null) {
- setDotString(initialDotString);
- return;
- }
-
- const filteredGraph = new graphlib.Graph();
- const nodesToInclude = new Set();
-
- const addPredecessors = (node) => {
- if (!nodesToInclude.has(node)) {
- nodesToInclude.add(node);
- const predecessors = graph.predecessors(node) || [];
- predecessors.forEach(addPredecessors);
- }
- };
-
- const addSuccessors = (node) => {
- const successors = graph.successors(node) || [];
- successors.forEach(successor => {
- nodesToInclude.add(successor);
- });
- };
-
- addPredecessors(nodeId);
- addSuccessors(nodeId);
-
- nodesToInclude.forEach(node => {
- filteredGraph.setNode(node, graph.node(node));
- });
-
- graph.edges().forEach(edge => {
- if (nodesToInclude.has(edge.v) && nodesToInclude.has(edge.w)) {
- filteredGraph.setEdge(edge.v, edge.w, graph.edge(edge.v, edge.w));
- }
- });
-
- const filteredDotString = dot.write(filteredGraph);
- setDotString(filteredDotString);
- }, [graph, initialDotString]);
-
- const resetGraph = () => {
- setDotString(initialDotString);
- };
-
- const handleDotStringChange = (newDotString) => {
- setDotString(newDotString);
- };
-
return (
Policy Topology Example
-
-
+
);
diff --git a/src/PolicyTopology.js b/src/PolicyTopology.js
index 0430091..1d663b7 100644
--- a/src/PolicyTopology.js
+++ b/src/PolicyTopology.js
@@ -1,13 +1,66 @@
-import React, { useEffect, useRef } from 'react';
+import React, { useEffect, useRef, useState, useCallback } from 'react';
import * as d3 from 'd3';
import { graphviz } from 'd3-graphviz'; // eslint-disable-line no-unused-vars
+import { Button } from '@patternfly/react-core';
+import graphlib from 'graphlib';
+import * as dot from 'graphlib-dot';
import './PolicyTopology.css';
-const PolicyTopology = ({ dotString, onNodeClick }) => {
+const PolicyTopology = ({ initialDotString }) => {
const containerRef = useRef(null);
+ const [dotString, setDotString] = useState(initialDotString); // State for the dot string
+ const [graph, setGraph] = useState(null);
+ // Parse the DOT string into a graph object
useEffect(() => {
- if (containerRef.current && dotString) {
+ if (dotString) {
+ const g = dot.read(dotString);
+ setGraph(g);
+ }
+ }, [dotString]);
+
+ // Function to handle node selection and update the graph
+ const handleNodeSelection = useCallback((nodeId) => {
+ if (!graph) return;
+
+ const filteredGraph = new graphlib.Graph();
+ const nodesToInclude = new Set();
+
+ const addPredecessors = (node) => {
+ if (!nodesToInclude.has(node)) {
+ nodesToInclude.add(node);
+ const predecessors = graph.predecessors(node) || [];
+ predecessors.forEach(addPredecessors);
+ }
+ };
+
+ const addSuccessors = (node) => {
+ const successors = graph.successors(node) || [];
+ successors.forEach(successor => {
+ nodesToInclude.add(successor);
+ });
+ };
+
+ addPredecessors(nodeId);
+ addSuccessors(nodeId);
+
+ nodesToInclude.forEach(node => {
+ filteredGraph.setNode(node, graph.node(node));
+ });
+
+ graph.edges().forEach(edge => {
+ if (nodesToInclude.has(edge.v) && nodesToInclude.has(edge.w)) {
+ filteredGraph.setEdge(edge.v, edge.w, graph.edge(edge.v, edge.w));
+ }
+ });
+
+ const filteredDotString = dot.write(filteredGraph);
+ setDotString(filteredDotString); // Update the dotString state
+ }, [graph]);
+
+ // Render the graph when the component mounts or the dotString changes
+ useEffect(() => {
+ if (containerRef.current && graph) {
const renderGraph = () => {
d3.select(containerRef.current).graphviz()
.zoom(false)
@@ -19,7 +72,7 @@ const PolicyTopology = ({ dotString, onNodeClick }) => {
node.addEventListener('click', (event) => {
const nodeElement = event.target.closest('g.node');
const nodeId = nodeElement.querySelector('title').textContent;
- onNodeClick(nodeId);
+ handleNodeSelection(nodeId);
});
});
});
@@ -27,9 +80,21 @@ const PolicyTopology = ({ dotString, onNodeClick }) => {
renderGraph();
}
- }, [dotString, onNodeClick]);
+ }, [graph, dotString, handleNodeSelection]);
+
+ // Function to reset the graph to its initial state
+ const resetGraph = useCallback(() => {
+ setDotString(initialDotString); // Reset the dotString state
+ }, [initialDotString]);
- return ;
+ return (
+
+ );
};
export default PolicyTopology;