From 66ba8b0c2e65e61856552b0a63bc6f3d1860df55 Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Wed, 29 Apr 2026 13:03:05 -0700 Subject: [PATCH 01/11] Remove drag feature from nodes --- packages/core/entity/Graph/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/entity/Graph/index.ts b/packages/core/entity/Graph/index.ts index 44952da33..e89369721 100644 --- a/packages/core/entity/Graph/index.ts +++ b/packages/core/entity/Graph/index.ts @@ -9,7 +9,7 @@ import FileService, { FmsFileAnnotation } from "../../services/FileService"; const FILE_NODE_WIDTH = 110; const FILE_NODE_HEIGHT = 125; const METADATA_NODE_WIDTH = 180; -const METADATA_NODE_HEIGHT = 45; +const METADATA_NODE_HEIGHT = 90; const ROW_SPACING = Math.max(FILE_NODE_HEIGHT, METADATA_NODE_HEIGHT) + 25; const COLUMN_SPACING = Math.max(FILE_NODE_WIDTH, METADATA_NODE_WIDTH) + 25; @@ -138,6 +138,7 @@ function createFileNode(file: FileDetail, isSelected = false): FileNode { file, isSelected, }, + draggable: false, // Placeholder values: Overwritten in this.nodes() position: { x: 0, y: 0 }, width: FILE_NODE_WIDTH, @@ -603,6 +604,7 @@ export default class Graph { file: undefined, isSelected: false, }, + draggable: false, width: METADATA_NODE_WIDTH, height: METADATA_NODE_HEIGHT, // Placeholder values: Overwritten in this.nodes() From e89180fad49a21f3f7919b91b10da48f2a5f6c43 Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Fri, 8 May 2026 14:22:15 -0700 Subject: [PATCH 02/11] Add view controls --- packages/core/components/NetworkGraph/index.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/core/components/NetworkGraph/index.tsx b/packages/core/components/NetworkGraph/index.tsx index 42967bd03..cd75f1072 100644 --- a/packages/core/components/NetworkGraph/index.tsx +++ b/packages/core/components/NetworkGraph/index.tsx @@ -1,5 +1,5 @@ import { SpinnerSize } from "@fluentui/react"; -import { Edge, ReactFlow, EdgeTypes, useNodesState, useEdgesState } from "@xyflow/react"; +import { Edge, ReactFlow, EdgeTypes, useNodesState, useEdgesState, Controls } from "@xyflow/react"; import "@xyflow/react/dist/style.css"; import classNames from "classnames"; import React from "react"; @@ -72,9 +72,10 @@ export default function NetworkGraph(props: NetworkGraphProps) { onlyRenderVisibleElements className={styles.graph} edgesFocusable={false} + nodesDraggable={false} nodesConnectable={false} nodesFocusable={false} - elementsSelectable={false} + elementsSelectable={true} edgesReconnectable={false} colorMode="dark" nodes={nodes} @@ -84,7 +85,9 @@ export default function NetworkGraph(props: NetworkGraphProps) { proOptions={{ hideAttribution: true }} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange} - /> + > + + ); } From ecd64960e87c8889826c07d8c1dd2b422324c973 Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Fri, 8 May 2026 17:29:30 -0700 Subject: [PATCH 03/11] Add refresh button to provenance graph --- .../NetworkGraph/NetworkGraph.module.css | 18 +++ .../core/components/NetworkGraph/index.tsx | 103 ++++++++++++------ packages/core/entity/Graph/index.ts | 9 +- 3 files changed, 93 insertions(+), 37 deletions(-) diff --git a/packages/core/components/NetworkGraph/NetworkGraph.module.css b/packages/core/components/NetworkGraph/NetworkGraph.module.css index fc6dc87cd..1fefe70c6 100644 --- a/packages/core/components/NetworkGraph/NetworkGraph.module.css +++ b/packages/core/components/NetworkGraph/NetworkGraph.module.css @@ -10,6 +10,24 @@ stroke: var(--primary-text-color); } +.refresh-button { + width: unset; + color: var(--primary-text-color); + border: none; + position: absolute; + z-index: 100; + right: 0; + margin: 10px; +} + +.refresh-button:hover { + color: var(--highlight-text-color); +} + +.refresh-button i { + padding-right: 8px; +} + .simple-container { display: flex; } diff --git a/packages/core/components/NetworkGraph/index.tsx b/packages/core/components/NetworkGraph/index.tsx index cd75f1072..2ef6211bf 100644 --- a/packages/core/components/NetworkGraph/index.tsx +++ b/packages/core/components/NetworkGraph/index.tsx @@ -1,9 +1,18 @@ -import { SpinnerSize } from "@fluentui/react"; -import { Edge, ReactFlow, EdgeTypes, useNodesState, useEdgesState, Controls } from "@xyflow/react"; +import { DefaultButton, Icon, SpinnerSize } from "@fluentui/react"; +import { + Edge, + ReactFlow, + EdgeTypes, + useNodesState, + useEdgesState, + Controls, + useReactFlow, + ReactFlowProvider, +} from "@xyflow/react"; import "@xyflow/react/dist/style.css"; import classNames from "classnames"; import React from "react"; -import { useSelector } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import DefaultEdge from "./Edges/DefaultEdge"; import FileNode from "./Nodes/FileNode"; @@ -19,6 +28,7 @@ import { import { interaction, selection } from "../../state"; import styles from "./NetworkGraph.module.css"; +import buttonStyles from "../Buttons/TertiaryButton.module.css"; interface NetworkGraphProps { className?: string; @@ -37,20 +47,11 @@ const NODE_TYPES = { * Component for rendering a graph at the given origin */ export default function NetworkGraph(props: NetworkGraphProps) { + const dispatch = useDispatch(); const graph = useSelector(interaction.selectors.getGraph); const isLoading = useSelector(interaction.selectors.isGraphLoading); const refreshKey = useSelector(interaction.selectors.getGraphRefreshKey); const provenanceSource = useSelector(selection.selectors.getSelectedSourceProvenance); - const [edges, setEdges, onEdgesChange] = useEdgesState>([]); - const [nodes, setNodes, onNodesChange] = useNodesState([]); - - // Unfortunately we have to have some notion of state at a high level for control from the components - // and at the dagre level for when the user does a drag action causing this duplication of efforts - React.useEffect(() => { - setEdges(graph.edges); - setNodes(graph.nodes); - }, [graph, setEdges, setNodes, refreshKey]); - // The option to open this graph shouldn't even appear when a // source isn't available so this shouldn't ever happen if (!provenanceSource) { @@ -65,29 +66,61 @@ export default function NetworkGraph(props: NetworkGraphProps) { ); } + function Flow() { + const [edges, setEdges, onEdgesChange] = useEdgesState>([]); + const [nodes, setNodes, onNodesChange] = useNodesState([]); + // Unfortunately we have to have some notion of state at a high level for control from the components + // and at the dagre level for when the user does a drag action causing this duplication of efforts + React.useEffect(() => { + setEdges(graph.edges); + setNodes(graph.nodes); + }, [graph, setEdges, setNodes, refreshKey]); + const { fitView } = useReactFlow(); + const onClickReset = () => { + graph.resetLayout(); // return to default layout if any + fitView(); // reset zoom + dispatch(interaction.actions.refreshGraph()); + }; + return ( + <> + + + Reset view + + + + + + ); + } + return ( -
- - - +
+ + +
); } diff --git a/packages/core/entity/Graph/index.ts b/packages/core/entity/Graph/index.ts index e89369721..cc5a910f5 100644 --- a/packages/core/entity/Graph/index.ts +++ b/packages/core/entity/Graph/index.ts @@ -138,7 +138,6 @@ function createFileNode(file: FileDetail, isSelected = false): FileNode { file, isSelected, }, - draggable: false, // Placeholder values: Overwritten in this.nodes() position: { x: 0, y: 0 }, width: FILE_NODE_WIDTH, @@ -331,6 +330,13 @@ export default class Graph { .setDefaultEdgeLabel(() => ({})); } + /** + * Reset the layout of the graph to its default (tree view) + */ + public resetLayout() { + dagre.layout(this.graph); + } + /** * Position nodes within graph according to edge connections and * height/width of individual nodes @@ -604,7 +610,6 @@ export default class Graph { file: undefined, isSelected: false, }, - draggable: false, width: METADATA_NODE_WIDTH, height: METADATA_NODE_HEIGHT, // Placeholder values: Overwritten in this.nodes() From 9c54013f7c212dbf71cc437dd3aaae4524fdcd53 Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Mon, 18 May 2026 00:57:40 -0700 Subject: [PATCH 04/11] Make details panel match original --- .../core/components/FileDetails/index.tsx | 110 ++++++++---------- 1 file changed, 48 insertions(+), 62 deletions(-) diff --git a/packages/core/components/FileDetails/index.tsx b/packages/core/components/FileDetails/index.tsx index 3e7086f3a..4b82c96f9 100644 --- a/packages/core/components/FileDetails/index.tsx +++ b/packages/core/components/FileDetails/index.tsx @@ -105,51 +105,41 @@ export default function FileDetails(props: Props) {
{props.fileDetails && ( <> - {!props.onClose ? ( -
-
- -
- {/* spacing component */} -
-
- - - - -
+
+
+
- ) : ( -
-

Metadata

-
+
+ + + + + {props.onClose && ( + + )}
- )} -

- {props.fileDetails?.name} -

+
+

{props.fileDetails?.name}

- {!props.onClose && ( -
-

Metadata

- {hasProvenanceSource && ( - - dispatch( - interaction.actions.setOriginForProvenance( - props.fileDetails - ) +
+

Metadata

+ {hasProvenanceSource && ( + + dispatch( + interaction.actions.setOriginForProvenance( + props.fileDetails ) - } - > - View provenance - - )} -
- )} + ) + } + > + View provenance +
+ )} +
Date: Mon, 18 May 2026 09:31:21 -0700 Subject: [PATCH 05/11] Wrap the reactflow component --- .../core/components/NetworkGraph/index.tsx | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/core/components/NetworkGraph/index.tsx b/packages/core/components/NetworkGraph/index.tsx index 2ef6211bf..f891d75a5 100644 --- a/packages/core/components/NetworkGraph/index.tsx +++ b/packages/core/components/NetworkGraph/index.tsx @@ -47,10 +47,7 @@ const NODE_TYPES = { * Component for rendering a graph at the given origin */ export default function NetworkGraph(props: NetworkGraphProps) { - const dispatch = useDispatch(); - const graph = useSelector(interaction.selectors.getGraph); const isLoading = useSelector(interaction.selectors.isGraphLoading); - const refreshKey = useSelector(interaction.selectors.getGraphRefreshKey); const provenanceSource = useSelector(selection.selectors.getSelectedSourceProvenance); // The option to open this graph shouldn't even appear when a // source isn't available so this shouldn't ever happen @@ -66,14 +63,25 @@ export default function NetworkGraph(props: NetworkGraphProps) { ); } - function Flow() { + // The ReactFlow component can only access state (useReactFlow) if it's the child of a ReactFlowProvider + // See https://reactflow.dev/learn/troubleshooting/common-errors#001 + function ReactFlowComponent() { + const dispatch = useDispatch(); const [edges, setEdges, onEdgesChange] = useEdgesState>([]); const [nodes, setNodes, onNodesChange] = useNodesState([]); + const graph = useSelector(interaction.selectors.getGraph); + const refreshKey = useSelector(interaction.selectors.getGraphRefreshKey); // Unfortunately we have to have some notion of state at a high level for control from the components // and at the dagre level for when the user does a drag action causing this duplication of efforts React.useEffect(() => { - setEdges(graph.edges); - setNodes(graph.nodes); + let cancel = false; + if (!cancel) { + setEdges(graph.edges); + setNodes(graph.nodes); + } + return function cleanup() { + cancel = true; + }; }, [graph, setEdges, setNodes, refreshKey]); const { fitView } = useReactFlow(); const onClickReset = () => { @@ -116,10 +124,11 @@ export default function NetworkGraph(props: NetworkGraphProps) { ); } + // The wrapped ReactFlow component return (
- +
); From 3acd566aed4548662cce882dadbc6ef9d97bff3e Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Mon, 18 May 2026 12:49:10 -0700 Subject: [PATCH 06/11] Update selected file styling --- .../core/components/NetworkGraph/Nodes/FileNode.module.css | 5 ++++- .../components/NetworkGraph/Nodes/MetadataNode.module.css | 2 +- packages/core/styles/global.css | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/core/components/NetworkGraph/Nodes/FileNode.module.css b/packages/core/components/NetworkGraph/Nodes/FileNode.module.css index fac34cffa..d00f11c5e 100644 --- a/packages/core/components/NetworkGraph/Nodes/FileNode.module.css +++ b/packages/core/components/NetworkGraph/Nodes/FileNode.module.css @@ -6,7 +6,7 @@ .file-node { height: unset; background-color: var(--primary-dark); - border: 1px solid var(--primary-text-color); + border: 1px solid var(--border-secondary-color); color: var(--primary-text-color); padding: 10px; border-radius: 5px; @@ -27,7 +27,10 @@ } .current-file { + background-color: var(--aqua); border-color: var(--highlight-background-color); + color: var(--highlight-text-color); + font-weight: 600; } .handle { diff --git a/packages/core/components/NetworkGraph/Nodes/MetadataNode.module.css b/packages/core/components/NetworkGraph/Nodes/MetadataNode.module.css index 26427b714..dcd259b23 100644 --- a/packages/core/components/NetworkGraph/Nodes/MetadataNode.module.css +++ b/packages/core/components/NetworkGraph/Nodes/MetadataNode.module.css @@ -5,7 +5,7 @@ .node { background-color: var(--primary-dark); - border: 1px solid var(--primary-text-color); + border: 1px solid var(--border-secondary-color); border-radius: 5px; color: var(--primary-text-color); display: flex; diff --git a/packages/core/styles/global.css b/packages/core/styles/global.css index 7757e22db..76a503e39 100644 --- a/packages/core/styles/global.css +++ b/packages/core/styles/global.css @@ -55,6 +55,7 @@ body { --secondary-dark: #1c1c1c; --accent-dark: #3d3d3d; --medium-grey: #575859; + --med-light-grey: #999; --light-grey: #BFBFBF; --white: #ffffff; --red: #c23030; @@ -70,6 +71,7 @@ body { --highlight-hover-background-color: var(--bright-aqua); --highlight-hover-text-color: var(--white); --border-color: var(--medium-grey); + --border-secondary-color: var(--med-light-grey); --error-background-color: var(--red); --error-text-color: var(--white); --aqua-secondary-hover: rgba(13, 187, 206, 0.18); From a1706ef398fd520ff1d2d66de67d90c9a9c0888b Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Mon, 18 May 2026 12:56:49 -0700 Subject: [PATCH 07/11] Temporarily hide provenance button in graph mode --- packages/core/components/FileDetails/index.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/components/FileDetails/index.tsx b/packages/core/components/FileDetails/index.tsx index 4b82c96f9..85ae5a120 100644 --- a/packages/core/components/FileDetails/index.tsx +++ b/packages/core/components/FileDetails/index.tsx @@ -190,7 +190,8 @@ export default function FileDetails(props: Props) {

Metadata

- {hasProvenanceSource && ( + {/* To do: un-hide the provenance source button while in graph mode, should redraw graph */} + {hasProvenanceSource && !props.onClose && ( dispatch( From b03188ac973c8c7e53ff989046f016c1fcf7c258 Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Mon, 18 May 2026 16:49:51 -0700 Subject: [PATCH 08/11] Change provenance phrasing --- packages/core/components/RelationshipDiagram/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/components/RelationshipDiagram/index.tsx b/packages/core/components/RelationshipDiagram/index.tsx index b059826f1..e1cb0b535 100644 --- a/packages/core/components/RelationshipDiagram/index.tsx +++ b/packages/core/components/RelationshipDiagram/index.tsx @@ -30,7 +30,7 @@ export default function RelationshipDiagram({ className, origin }: Props) { onClick={() => dispatch(interaction.actions.setOriginForProvenance(undefined))} title="Close provenance relationship diagram" /> -

Provenance for {origin?.name}

+

Relationship diagram for {origin?.name}

From 7256b21f1197144305b6659ed15088c75da42ec8 Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Thu, 28 May 2026 10:10:33 -0700 Subject: [PATCH 09/11] Move ReactFlowProvider out of NetworkGraph --- .../core/components/NetworkGraph/index.tsx | 119 ++++++++---------- .../components/RelationshipDiagram/index.tsx | 7 +- 2 files changed, 60 insertions(+), 66 deletions(-) diff --git a/packages/core/components/NetworkGraph/index.tsx b/packages/core/components/NetworkGraph/index.tsx index f891d75a5..1ab7594bc 100644 --- a/packages/core/components/NetworkGraph/index.tsx +++ b/packages/core/components/NetworkGraph/index.tsx @@ -7,7 +7,6 @@ import { useEdgesState, Controls, useReactFlow, - ReactFlowProvider, } from "@xyflow/react"; import "@xyflow/react/dist/style.css"; import classNames from "classnames"; @@ -47,8 +46,28 @@ const NODE_TYPES = { * Component for rendering a graph at the given origin */ export default function NetworkGraph(props: NetworkGraphProps) { + const dispatch = useDispatch(); + const graph = useSelector(interaction.selectors.getGraph); const isLoading = useSelector(interaction.selectors.isGraphLoading); + const refreshKey = useSelector(interaction.selectors.getGraphRefreshKey); const provenanceSource = useSelector(selection.selectors.getSelectedSourceProvenance); + const [edges, setEdges, onEdgesChange] = useEdgesState>([]); + const [nodes, setNodes, onNodesChange] = useNodesState([]); + const { fitView } = useReactFlow(); + + // Unfortunately we have to have some notion of state at a high level for control from the components + // and at the dagre level for when the user does a drag action causing this duplication of efforts + React.useEffect(() => { + let cancel = false; + if (!cancel) { + setEdges(graph.edges); + setNodes(graph.nodes); + } + return function cleanup() { + cancel = true; + }; + }, [graph, setEdges, setNodes, refreshKey]); + // The option to open this graph shouldn't even appear when a // source isn't available so this shouldn't ever happen if (!provenanceSource) { @@ -63,73 +82,43 @@ export default function NetworkGraph(props: NetworkGraphProps) { ); } - // The ReactFlow component can only access state (useReactFlow) if it's the child of a ReactFlowProvider - // See https://reactflow.dev/learn/troubleshooting/common-errors#001 - function ReactFlowComponent() { - const dispatch = useDispatch(); - const [edges, setEdges, onEdgesChange] = useEdgesState>([]); - const [nodes, setNodes, onNodesChange] = useNodesState([]); - const graph = useSelector(interaction.selectors.getGraph); - const refreshKey = useSelector(interaction.selectors.getGraphRefreshKey); - // Unfortunately we have to have some notion of state at a high level for control from the components - // and at the dagre level for when the user does a drag action causing this duplication of efforts - React.useEffect(() => { - let cancel = false; - if (!cancel) { - setEdges(graph.edges); - setNodes(graph.nodes); - } - return function cleanup() { - cancel = true; - }; - }, [graph, setEdges, setNodes, refreshKey]); - const { fitView } = useReactFlow(); - const onClickReset = () => { - graph.resetLayout(); // return to default layout if any - fitView(); // reset zoom - dispatch(interaction.actions.refreshGraph()); - }; - return ( - <> - - - Reset view - - - - - - ); - } + const onClickReset = () => { + graph.resetLayout(); // return to default layout if any + fitView(); // reset zoom + dispatch(interaction.actions.refreshGraph()); + }; - // The wrapped ReactFlow component return (
- - - + + + Reset view + + + +
); } diff --git a/packages/core/components/RelationshipDiagram/index.tsx b/packages/core/components/RelationshipDiagram/index.tsx index e1cb0b535..4d3e21eed 100644 --- a/packages/core/components/RelationshipDiagram/index.tsx +++ b/packages/core/components/RelationshipDiagram/index.tsx @@ -1,3 +1,4 @@ +import { ReactFlowProvider } from "@xyflow/react"; import classNames from "classnames"; import * as React from "react"; import { useDispatch } from "react-redux"; @@ -32,7 +33,11 @@ export default function RelationshipDiagram({ className, origin }: Props) { />

Relationship diagram for {origin?.name}

- + {/* The ReactFlow component can only access state (useReactFlow) if it's the child of a ReactFlowProvider + See https://reactflow.dev/learn/troubleshooting/common-errors#001 */} + + +
); } From b2f2fec6f9ae1439317d631790e16b155073a36e Mon Sep 17 00:00:00 2001 From: Anya Wallace Date: Thu, 28 May 2026 10:28:34 -0700 Subject: [PATCH 10/11] Use tertiary button for reset --- .../core/components/Buttons/TertiaryButton.tsx | 2 ++ .../NetworkGraph/NetworkGraph.module.css | 17 ++++++++++++----- packages/core/components/NetworkGraph/index.tsx | 17 ++++++++--------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/core/components/Buttons/TertiaryButton.tsx b/packages/core/components/Buttons/TertiaryButton.tsx index 8cda15839..8bc437c27 100644 --- a/packages/core/components/Buttons/TertiaryButton.tsx +++ b/packages/core/components/Buttons/TertiaryButton.tsx @@ -16,6 +16,7 @@ interface Props { menuItems?: IContextualMenuItem[]; onClick?: () => void; invertColor?: boolean; + text?: string; title: string; } @@ -37,6 +38,7 @@ export default function TertiaryButton(props: Props) { menuDirection={props.menuDirection} menuItems={props.menuItems} onClick={props.onClick} + text={props.text} title={props.title} /> ); diff --git a/packages/core/components/NetworkGraph/NetworkGraph.module.css b/packages/core/components/NetworkGraph/NetworkGraph.module.css index 1fefe70c6..0b111a8dc 100644 --- a/packages/core/components/NetworkGraph/NetworkGraph.module.css +++ b/packages/core/components/NetworkGraph/NetworkGraph.module.css @@ -10,7 +10,7 @@ stroke: var(--primary-text-color); } -.refresh-button { +.reset-button { width: unset; color: var(--primary-text-color); border: none; @@ -20,12 +20,19 @@ margin: 10px; } -.refresh-button:hover { - color: var(--highlight-text-color); +.reset-button i { + font-weight: 400; + padding-right: 8px; } -.refresh-button i { - padding-right: 8px; +/* Use sentence case */ +.reset-button span { + font-weight: 400; + text-transform: lowercase; +} + +.reset-button span:first-letter { + text-transform: uppercase; } .simple-container { diff --git a/packages/core/components/NetworkGraph/index.tsx b/packages/core/components/NetworkGraph/index.tsx index 1ab7594bc..088d4af71 100644 --- a/packages/core/components/NetworkGraph/index.tsx +++ b/packages/core/components/NetworkGraph/index.tsx @@ -1,4 +1,4 @@ -import { DefaultButton, Icon, SpinnerSize } from "@fluentui/react"; +import { SpinnerSize } from "@fluentui/react"; import { Edge, ReactFlow, @@ -16,6 +16,7 @@ import { useDispatch, useSelector } from "react-redux"; import DefaultEdge from "./Edges/DefaultEdge"; import FileNode from "./Nodes/FileNode"; import MetadataNode from "./Nodes/MetadataNode"; +import { TertiaryButton } from "../Buttons"; import LoadingIcon from "../Icons/LoadingIcon"; import { AnnotationEdge, @@ -27,7 +28,6 @@ import { import { interaction, selection } from "../../state"; import styles from "./NetworkGraph.module.css"; -import buttonStyles from "../Buttons/TertiaryButton.module.css"; interface NetworkGraphProps { className?: string; @@ -89,15 +89,14 @@ export default function NetworkGraph(props: NetworkGraphProps) { }; return ( -
- + - - Reset view - + /> Date: Thu, 28 May 2026 11:05:20 -0700 Subject: [PATCH 11/11] Keep ReactFlowProvider in NetworkGraph component --- packages/core/components/NetworkGraph/index.tsx | 13 ++++++++++++- .../core/components/RelationshipDiagram/index.tsx | 7 +------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/core/components/NetworkGraph/index.tsx b/packages/core/components/NetworkGraph/index.tsx index 088d4af71..117297c73 100644 --- a/packages/core/components/NetworkGraph/index.tsx +++ b/packages/core/components/NetworkGraph/index.tsx @@ -7,6 +7,7 @@ import { useEdgesState, Controls, useReactFlow, + ReactFlowProvider, } from "@xyflow/react"; import "@xyflow/react/dist/style.css"; import classNames from "classnames"; @@ -45,7 +46,7 @@ const NODE_TYPES = { /** * Component for rendering a graph at the given origin */ -export default function NetworkGraph(props: NetworkGraphProps) { +function NetworkGraph(props: NetworkGraphProps) { const dispatch = useDispatch(); const graph = useSelector(interaction.selectors.getGraph); const isLoading = useSelector(interaction.selectors.isGraphLoading); @@ -121,3 +122,13 @@ export default function NetworkGraph(props: NetworkGraphProps) {
); } + +// The ReactFlow component can only access state (useReactFlow) if it's the child of a ReactFlowProvider +// See https://reactflow.dev/learn/troubleshooting/common-errors#001 +export default function WrappedNetworkGraph(props: NetworkGraphProps) { + return ( + + + + ); +} diff --git a/packages/core/components/RelationshipDiagram/index.tsx b/packages/core/components/RelationshipDiagram/index.tsx index 4d3e21eed..e1cb0b535 100644 --- a/packages/core/components/RelationshipDiagram/index.tsx +++ b/packages/core/components/RelationshipDiagram/index.tsx @@ -1,4 +1,3 @@ -import { ReactFlowProvider } from "@xyflow/react"; import classNames from "classnames"; import * as React from "react"; import { useDispatch } from "react-redux"; @@ -33,11 +32,7 @@ export default function RelationshipDiagram({ className, origin }: Props) { />

Relationship diagram for {origin?.name}

- {/* The ReactFlow component can only access state (useReactFlow) if it's the child of a ReactFlowProvider - See https://reactflow.dev/learn/troubleshooting/common-errors#001 */} - - - + ); }