diff --git a/src/components/app.tsx b/src/components/app.tsx index f64653b..95e4a2c 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -4,7 +4,7 @@ import { clsx } from "clsx"; import { useCODAP } from "../hooks/use-codap"; import { useGraph } from "../hooks/use-graph"; import { useGenerator } from "../hooks/use-generator"; -import { Edge, Node } from "../type"; +import { Edge, GraphData, Node } from "../type"; import { Drawing } from "./drawing"; import { Dataset } from "./dataset"; @@ -87,10 +87,12 @@ export const App = () => { const currentSequenceIndex = useRef(0); const animationInterval = useRef(); const { graph, updateGraph, setGraph } = useGraph(); + const [initialGraph, setInitialGraph] = useState(); const { dragging, outputToDataset, viewMode, setViewMode, notifyStateIsDirty, loadState } = useCODAP({ onCODAPDataChanged: updateGraph, getGraph: useCallback(() => graph, [graph]), - setGraph + setGraph, + setInitialGraph }); const { generate } = useGenerator(); const innerOutputRef = useRef(null); @@ -403,15 +405,16 @@ export const App = () => { notifyStateIsDirty(); }; - const handleReset = () => { + const handleReset = useCallback(() => { if (confirm("Are you sure you want to reset?\n\nAny changes you have made will be lost.")) { - setGraph({nodes: [], edges: []}); + setGraph(initialGraph ? {...initialGraph} : {nodes: [], edges: []}); } - }; + }, [initialGraph, setGraph]); const handleReturnToMainMenu = () => { if (confirm("Are you sure you want to go back to the main menu?\n\nAny changes you have made will be lost.")) { setGraph({nodes: [], edges: []}); + setInitialGraph(undefined); setViewMode(undefined); } }; diff --git a/src/components/graph.tsx b/src/components/graph.tsx index 680428b..a518ef3 100644 --- a/src/components/graph.tsx +++ b/src/components/graph.tsx @@ -186,7 +186,7 @@ const nodeLoopPath = (node: D3Node) => { }; const graphSignature = (graph: D3Graph) => { - const nodeSignature = graph.nodes.map(n => `${n.id}/${n.label}/${n.weight}/${n.radius}`); + const nodeSignature = graph.nodes.map(n => `${n.id}/${n.label}/${n.weight}/${n.radius}/${n.x}/${n.y}`); const edgeSignature = graph.edges.map(e => `${e.source.id}/${e.target.id}/${e.weight}`); return `${nodeSignature}::${edgeSignature}`; }; diff --git a/src/hooks/use-codap.ts b/src/hooks/use-codap.ts index e25bb7d..57ca5e9 100644 --- a/src/hooks/use-codap.ts +++ b/src/hooks/use-codap.ts @@ -1,5 +1,5 @@ import { useCallback, useEffect, useState } from "react"; -import { GraphData, Node } from "../type"; +import { Edge, GraphData, Node } from "../type"; import { getValuesForAttribute, // entityInfo, @@ -34,9 +34,10 @@ export type UseCODAPOptions = { onCODAPDataChanged: OnCODAPDataChanged; getGraph: GetGraphCallback; setGraph: React.Dispatch> + setInitialGraph: React.Dispatch> }; -export const useCODAP = ({onCODAPDataChanged, getGraph, setGraph}: UseCODAPOptions) => { +export const useCODAP = ({onCODAPDataChanged, getGraph, setGraph, setInitialGraph}: UseCODAPOptions) => { const [loadState, setLoadState] = useState<"loading"|"loaded">("loading"); const [initialized, setInitialized] = useState(false); const [dragging, setDragging] = useState(false); @@ -89,6 +90,8 @@ export const useCODAP = ({onCODAPDataChanged, getGraph, setGraph}: UseCODAPOptio const {nodes, edges} = values; if (nodes !== undefined && edges !== undefined) { setGraph({nodes, edges}); + // save a copy of the graph + setInitialGraph({nodes: nodes.map((n: Node) => ({...n})), edges: edges.map((e: Edge) => ({...e}))}); } } else { if (values?.attribute) { @@ -97,7 +100,7 @@ export const useCODAP = ({onCODAPDataChanged, getGraph, setGraph}: UseCODAPOptio } } } - }, [setAttribute, handleDataChanged, setGraph]); + }, [setAttribute, handleDataChanged, setGraph, setInitialGraph]); const handleDrop = useCallback(async (iMessage: any) => { let newAttribute: CODAPAttribute;