Skip to content

Commit

Permalink
Improvements & Bugfixes (#32)
Browse files Browse the repository at this point in the history
* Update Graph.tsx

* Add more stuff
  • Loading branch information
tubarao312 authored Jan 16, 2024
1 parent 38d169a commit 536c60f
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 74 deletions.
35 changes: 32 additions & 3 deletions src/components/Graph/Graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ReactFlow, {
useOnSelectionChange,
Panel,
useUpdateNodeInternals,
Controls,
} from "reactflow";
import "reactflow/dist/style.css";
import { Transition } from "@headlessui/react";
Expand Down Expand Up @@ -160,11 +161,33 @@ const GraphProvided: FC<GraphProvidedProps> = ({

// Regularly update the node internals to make sure edges are consistent
const updateNodeInternals = useUpdateNodeInternals();
const prevNodeWidths = useRef<Map<string, number | null | undefined>>(
new Map(),
);
useEffect(() => {
nodes.forEach((node) => {
updateNodeInternals(node.id);
if (prevNodeWidths.current.get(node.id) !== node.width) {
prevNodeWidths.current.set(node.id, node.width);
updateNodeInternals(node.id);
}
});
}, [nodes.length]);
}, [nodes]);

// For the first 3 seconds after mounting, we want to updateNodeInternals for all nodes every 100ms
const [firstUpdate, setFirstUpdate] = useState<boolean>(true);
useEffect(() => {
if (firstUpdate) {
const interval = setInterval(() => {
nodes.forEach((node) => {
updateNodeInternals(node.id);
});
}, 100);
setTimeout(() => {
clearInterval(interval);
setFirstUpdate(false);
}, 10000);
}
}, [firstUpdate]);

// Record Optimization -------------------------------------------------------

Expand Down Expand Up @@ -479,13 +502,19 @@ const GraphProvided: FC<GraphProvidedProps> = ({
selectionMode={SelectionMode.Partial}
zoomOnDoubleClick={true}
className="h-full w-full"
maxZoom={1.5}
minZoom={0.25}
>
<img
className="-z-10 m-auto w-full scale-150 animate-pulse opacity-40"
aria-hidden="true"
src="https://tailwindui.com/img/[email protected]"
/>

<Controls
position="top-right"
showFitView={false}
showInteractive={false}
/>
<Background />
<Panel position="top-left">
<Legend />
Expand Down
107 changes: 70 additions & 37 deletions src/components/Graph/Legend/Legend.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,79 @@
import { FC } from "react";
import { InformationCircleIcon } from "@heroicons/react/16/solid";

import "./LegendPath.css";

const RightTip: FC = () => {
return (
<span className="flex flex-row items-center gap-x-1.5">
<svg className="h-5" viewBox="0 0 50 20">
<path
d={`M5,10 H45`}
fill="none"
className="animated-dotted-line animate-pulse stroke-blue-400"
strokeWidth={7}
/>
<path
d={`M5,10 H45`}
fill="none"
className="animate-pulse stroke-blue-400 opacity-50"
strokeWidth={7}
strokeLinecap="round"
/>
</svg>
<h3 className="text-xs font-semibold text-blue-700"> Right </h3>
</span>
);
};

const LeftTip: FC = () => {
return (
<span className="flex flex-row items-center gap-x-1.5">
<svg className="h-5" viewBox="0 0 50 20">
<path
d={`M5,10 H45`}
fill="none"
className="animated-dotted-line-reverse animate-pulse stroke-orange-400"
strokeWidth={7}
/>
<path
d={`M5,10 H45`}
fill="none"
className="animate-pulse stroke-orange-400 opacity-50"
strokeWidth={7}
strokeLinecap="round"
/>
</svg>
<h3 className="text-xs font-semibold text-orange-700">Left</h3>
</span>
);
};

const RiskTip: FC = () => {
return (
<span className="flex flex-row items-center gap-x-1.5">
<h1 className="flex h-9 w-9 items-center justify-center rounded-md bg-red-50 text-center text-sm font-medium text-red-700 ring-1 ring-inset ring-red-600/10">
8.2
</h1>
<h3 className="text-xs font-semibold text-red-700"> Risk </h3>
</span>
);
};

const Legend: FC = () => {
return (
<div className="flex h-fit w-32 flex-col gap-y-3 bg-white/10 p-3 backdrop-blur-sm">
<span className="flex flex-row items-center gap-x-1.5">
<svg className="h-5" viewBox="0 0 50 20">
<path
d={`M5,10 H45`}
fill="none"
className="animated-dotted-line animate-pulse stroke-blue-400"
strokeWidth={7}
/>
<path
d={`M5,10 H45`}
fill="none"
className="animate-pulse stroke-blue-400 opacity-50"
strokeWidth={7}
strokeLinecap="round"
/>
</svg>
<h3 className="text-sm font-semibold text-blue-700"> Right </h3>
</span>
<span className="flex flex-row items-center gap-x-1.5">
<svg className="h-5" viewBox="0 0 50 20">
<path
d={`M5,10 H45`}
fill="none"
className="animated-dotted-line-reverse animate-pulse stroke-orange-400"
strokeWidth={7}
/>
<path
d={`M5,10 H45`}
fill="none"
className="animate-pulse stroke-orange-400 opacity-50"
strokeWidth={7}
strokeLinecap="round"
/>
</svg>
<h3 className="text-sm font-semibold text-orange-700">Left</h3>
</span>
<div className="flex h-fit w-32 flex-col items-center gap-y-3 divide-y divide-gray-300 bg-white/10 p-3 backdrop-blur-sm">
<h2 className="flex flex-row items-center gap-x-1 text-xs font-semibold tracking-wide text-gray-600">
<InformationCircleIcon className="h-5 w-5 text-gray-400" />
LEGEND
</h2>
<div className="flex flex-col gap-y-3 pt-3">
<RightTip />
<LeftTip />
</div>
<div className="flex flex-col gap-y-3 pt-3">
<RiskTip />
</div>
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
.animated-dotted-line {
stroke-dasharray: 15, 15;
stroke-dashoffset: 30;
/* animation: dash 0.6s linear infinite; */
animation: dash 0.6s linear infinite;
stroke-linecap: round; /* Add this line */
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ const CustomEdgePath = ({
strokeWidth={strokeWidth}
markerEnd={`url(#${triangleMarkerID})`}
opacity={opacity}
style={{
transition: "stroke-width 1s ease-in-out",
}}
/>
<path
id={id}
Expand All @@ -100,6 +103,9 @@ const CustomEdgePath = ({
: "stroke-orange-400",
)}
strokeWidth={strokeWidth * 1.1}
style={{
transition: "stroke-width 1s ease-in-out",
}}
opacity={opacity * 0.8}
/>
{isClickable && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
createTransfershipEdge,
TransfershipEdgeStates,
} from "../../../edges/TransfershipEdge";
import { Transition } from "@headlessui/react";

/** Context data for the AddressNode */

Expand Down Expand Up @@ -146,39 +147,47 @@ const AddressNode: FC<AddressNodeProps> = ({ data: { address } }) => {
isConnectable={false}
/>

<span
className={clsx(
"flex flex-row items-center gap-x-2 rounded-lg bg-white px-4 py-5 transition-all duration-150 hover:bg-gray-50",
focusedAddressData?.address === address
? "shadow-2xl shadow-blue-300 ring-4 ring-blue-400"
: "shadow-md ring-1 ring-gray-300",
)}
onClick={() => {
if (analysisData) {
setFocusedAddressData(analysisData);
}
}}
<Transition
appear={true}
show={true}
enter="transition-all duration-250"
enterFrom="opacity-0 scale-50"
enterTo="opacity-100 scale-100"
>
{/* Address Risk inside a badge */}
<RiskIndicator
risk={analysisData?.risk}
isLoading={isLoadingAddressData}
/>

{/* Address information */}
<div className="flex flex-col gap-y-0.5">
<h1 className="flex flex-row font-mono font-semibold tracking-tight text-gray-800">
{`${address.slice(0, 5)}...${address.slice(-5)}`}
{analysisData && analysisData.labels.length > 0 && (
<EntityLogo
entity={analysisData!.labels[0]}
className="ml-2 h-7 w-7 rounded-full"
/>
)}
</h1>
{analysisData && <LabelList labels={analysisData!.labels} />}
</div>
</span>
<span
className={clsx(
"flex flex-row items-center gap-x-2 rounded-lg bg-white px-4 py-5 transition-all duration-150 hover:bg-gray-50",
focusedAddressData?.address === address
? "shadow-2xl shadow-blue-300 ring-4 ring-blue-400"
: "shadow-md ring-1 ring-gray-300",
)}
onClick={() => {
if (analysisData) {
setFocusedAddressData(analysisData);
}
}}
>
{/* Address Risk inside a badge */}
<RiskIndicator
risk={analysisData?.risk}
isLoading={isLoadingAddressData}
/>

{/* Address information */}
<div className="flex flex-col gap-y-0.5">
<h1 className="flex flex-row font-mono font-semibold tracking-tight text-gray-800">
{`${address.slice(0, 5)}...${address.slice(-5)}`}
{analysisData && analysisData.labels.length > 0 && (
<EntityLogo
entity={analysisData!.labels[0]}
className="ml-2 h-7 w-7 rounded-full"
/>
)}
</h1>
{analysisData && <LabelList labels={analysisData!.labels} />}
</div>
</span>
</Transition>
</AnalysisContext.Provider>
);
};
Expand Down
1 change: 0 additions & 1 deletion src/components/Graph/graph_calculations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ export function calculateLayoutedElements(
Dagre.layout(dagreGraph);

const newNodes: Node[] = [...nodes];

dagreGraph.nodes().forEach((nodeId) => {
const node = newNodes.find((n) => n.id === nodeId);
if (node) {
Expand Down

0 comments on commit 536c60f

Please sign in to comment.