Click on nodes to explore their connections and use the slider to change the tightness of arrangement inside the open combos.
This story shows a fictional IT infrastructure, showing the network connections between physical devices and highlighting security risks.
Combos can be created when you load data by defining the combine prop in your initial state.
See also
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import pickBy from "lodash/pickBy";
import values from "lodash/values";
import { Chart } from "regraph";
import data from "./data";
import { style } from "@ci/theme/rg/js/storyStyles";
import "@fortawesome/fontawesome-free/css/fontawesome.css";
import "@fortawesome/fontawesome-free/css/solid.css";
const initialTightness = 3;
function ComboTightness(props) {
const { items } = props;
const [state, setState] = useState({
animate: false,
closedCombos: {},
tightness: initialTightness,
combine: {
shape: "rectangle",
level: 2,
properties: ["ip", "network"],
tightness: initialTightness,
},
layout: {
name: "sequential",
linkShape: "curved",
top: "_combonode_Central Server\n181.13.51.159",
},
});
const getGlyph = (value) => {
if (
values(items).some((item) => {
const { data: d } = item;
return d && (d.network === value || d.ip === value) && d.alert;
})
) {
return [
{
...style.selectMain,
border: { color: style.colors.red3 },
label: { text: "!", color: "#fff" },
position: "ne",
size: 1.1,
},
];
}
return null;
};
const buildComboLabels = ({ location, locIp, ip, isNetwork, nodes }) => {
const numDevices = Object.keys(nodes).length;
const networkLabels = [
{
backgroundColor: style.colors.teal0,
minWidth: "stretch",
minHeight: 40,
position: { vertical: "top", horizontal: "left" },
},
{
text: location,
position: { vertical: "top", horizontal: "left" },
fontSize: 20,
bold: true,
minHeight: 40,
padding: { left: 10 },
backgroundColor: style.colors.transparent,
},
{
text: locIp,
position: { vertical: "top", horizontal: "center" },
minHeight: 40,
fontSize: 20,
margin: "0 10",
fontFamily: "monospace",
backgroundColor: style.colors.transparent,
},
{
text: `Devices: ${numDevices}`,
position: { vertical: "top", horizontal: "right" },
minHeight: 40,
bold: true,
fontSize: 20,
margin: { right: 10 },
backgroundColor: style.colors.transparent,
},
];
const nonNetworkLabels = [
{
backgroundColor: style.colors.teal0,
minWidth: "stretch",
minHeight: 40,
position: { vertical: "top", horizontal: "left" },
},
{
text: ip,
fontFamily: "monospace",
position: { vertical: "top", horizontal: "center" },
minHeight: 40,
fontSize: 20,
backgroundColor: style.colors.transparent,
},
];
return isNetwork ? networkLabels : nonNetworkLabels;
};
const buildClosedComboLabels = ({ location, locIp, ip, isNetwork }) => {
const networkLabels = [
{
text: location,
position: "s",
bold: true,
},
{
text: locIp,
fontFamily: "monospace",
},
];
const nonNetworkLabels = [
{
position: "s",
text: ip,
fontFamily: "monospace",
},
];
return isNetwork ? networkLabels : nonNetworkLabels;
};
const combineNodesHandler = ({ setStyle, combo, id, nodes }) => {
const { ip, network } = combo;
const { closedCombos } = state;
const isNetwork = !ip;
const [location, locIp] = isNetwork ? network.split("\n") : [];
setStyle({
open: !closedCombos[id],
color: style.combo.color,
border: isNetwork ? {} : { lineStyle: "dashed", width: 4 },
fontIcon: {
text: "fas fa-sitemap",
color: style.primary1.color,
},
arrange: {
name: "grid",
tightness: isNetwork ? 5 : state.tightness,
},
label: buildComboLabels({ location, locIp, ip, isNetwork, nodes }),
closedStyle: {
color: style.colors.charcoal,
label: buildClosedComboLabels({ location, locIp, ip, isNetwork }),
shape: "box",
glyphs: getGlyph(ip || network),
},
});
};
const combineLinksHandler = ({ setStyle, links }) => {
const contents = pickBy(links, (link) => link.data.alert);
setStyle({
label: {},
flow: false,
width: 3,
glyphs: [],
contents,
});
};
const doubleClickHandler = ({ id, itemType }) => {
// if it is a combo, toggle its open state
if (itemType === "combo") {
setState((current) => {
return {
...current,
animate: true,
combine: { ...current.combine },
closedCombos: { ...current.closedCombos, [id]: !current.closedCombos[id] },
};
});
}
};
const setTightness = (e) => {
setState((current) => ({
...current,
animate: false,
tightness: parseFloat(e.target.value),
}));
};
const layout = () => {
setState((current) => ({
...current,
combine: {
...current.combine,
tightness: current.tightness,
},
layout: { ...current.layout },
}));
};
return (
<div className="story">
<div className="options">
<span style={{ paddingLeft: 20, paddingRight: 20 }}>Nested combo tightness</span>
<input
type="range"
tabIndex="0"
style={{ width: 200 }}
min={0}
max={10}
step={1}
value={state.tightness}
onInput={setTightness}
onChange={layout}
/>
<span style={{ paddingLeft: 20 }}>{state.tightness}</span>
</div>
<div className="chart-wrapper">
<Chart
items={items(state.combine.shape)}
combine={state.combine}
layout={state.layout}
options={{
selection: {
color: style.colors.teal0,
labelColor: "#000",
},
iconFontFamily: "Font Awesome 5 Free",
imageAlignment: {
"fas fa-sitemap": { dy: -8, size: 0.75 },
"fas fa-print": { size: 0.8 },
"fas fa-laptop": { size: 0.75 },
"fas fa-phone": { size: 0.8 },
"fas fa-server": { size: 0.8 },
},
}}
animation={{ animate: state.animate, time: 800 }}
onCombineNodes={combineNodesHandler}
onCombineLinks={combineLinksHandler}
onDoubleClick={doubleClickHandler}
/>
</div>
</div>
);
}
const FontReadyChart = React.lazy(() =>
document.fonts.load("900 24px 'Font Awesome 5 Free'").then(() => ({
default: () => <ComboTightness items={data} />,
}))
);
export function Demo() {
return (
<React.Suspense fallback="">
<FontReadyChart />
</React.Suspense>
);
}
const root = createRoot(document.getElementById("regraph"));
root.render(<Demo />); import has from "lodash/has";
import mapValues from "lodash/mapValues";
import merge from "lodash/merge";
import { style } from "@ci/theme/rg/js/storyStyles";
function styleItem(item, shape) {
const isCircle = shape === "circle";
const glyphs = {};
const hasAlert = item.data && item.data.alert;
const isNode = !has(item, "id1");
if (!isNode) {
if (hasAlert) {
glyphs.glyphs = [
{
...style.selectMain,
border: { color: style.colors.red3 },
label: { ...style.secondaryLabel2, text: "!" },
size: 1.5,
},
];
}
return {
...item,
...glyphs,
color: hasAlert ? style.secondary1.color : style.link.color,
width: 4,
};
}
if (hasAlert) {
glyphs.glyphs = [
{
...style.selectMain,
border: { color: style.colors.red3 },
label: { ...style.secondaryLabel2, text: "!" },
position: "ne",
size: 1.1,
},
];
}
return merge(
item,
{
size: 1.3,
shape: isCircle ? "circle" : { width: 130, height: 80 },
color: style.colors.charcoal,
border: { color: null },
label: [
{
...item.label[0],
fontFamily: "Font Awesome 5 Free",
backgroundColor: "rgba(0, 0, 0, 0)",
color: style.colors.teal1,
fontSize: 42,
position: {
vertical: isCircle ? "middle" : 15,
},
},
{
...item.label[1],
backgroundColor: "rgba(0, 0, 0, 0)",
color: isCircle ? "black" : "white",
fontSize: 15,
position: isCircle ? "s" : { vertical: 55 },
},
],
},
glyphs
);
}
function data(shape) {
const items = {
"140.211.152.43::192.168.247.240": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.247.240" }],
data: { type: "win", network: "Cambridge\n140.211.152.43", ip: "192.168.247.0" },
},
"140.211.152.43::192.168.16.232": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.16.232" }],
data: { type: "win", network: "Cambridge\n140.211.152.43", ip: "192.168.16.0" },
},
"140.211.152.43::192.168.16.194": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.16.194" }],
data: { type: "win", network: "Cambridge\n140.211.152.43", ip: "192.168.16.0" },
},
"140.211.152.43::192.168.16.209": {
label: [{ fontIcon: { text: "fas fa-phone" } }, { text: "192.168.16.209" }],
data: { type: "win", network: "Cambridge\n140.211.152.43", ip: "192.168.16.0" },
},
"140.211.152.43::192.168.247.168": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.247.168" }],
data: { type: "win", network: "Cambridge\n140.211.152.43", ip: "192.168.247.0" },
},
"140.211.152.43::192.168.247.162": {
label: [{ fontIcon: { text: "fas fa-print" } }, { text: "192.168.247.162" }],
data: { type: "printer", network: "Cambridge\n140.211.152.43", ip: "192.168.247.0" },
},
"140.211.152.43::192.168.247.242": {
label: [{ fontIcon: { text: "fas fa-phone" } }, { text: "192.168.247.242" }],
data: { type: "win", network: "Cambridge\n140.211.152.43", ip: "192.168.247.0" },
},
"56.35.38.237::192.168.51.101": {
label: [{ fontIcon: { text: "fas fa-print" } }, { text: "192.168.51.101" }],
data: { type: "printer", network: "London\n56.35.38.237", ip: "192.168.51.0" },
},
"56.35.38.237::192.168.51.158": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.51.158" }],
data: { type: "mac", network: "London\n56.35.38.237", ip: "192.168.51.0" },
},
"56.35.38.237::192.168.51.108": {
label: [{ fontIcon: { text: "fas fa-print" } }, { text: "192.168.51.108" }],
data: { type: "printer", network: "London\n56.35.38.237", ip: "192.168.51.0" },
},
"56.35.38.237::192.168.131.80": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.131.80" }],
data: { type: "mac", network: "London\n56.35.38.237", ip: "192.168.131.0" },
},
"56.35.38.237::192.168.131.57": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.131.57" }],
data: { type: "mac", network: "London\n56.35.38.237", ip: "192.168.131.0" },
},
"56.35.38.237::192.168.131.11": {
label: [{ fontIcon: { text: "fas fa-print" } }, { text: "192.168.131.11" }],
data: { type: "printer", network: "London\n56.35.38.237", ip: "192.168.131.0" },
},
"56.35.38.237::192.168.51.194": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.51.194" }],
data: {
type: "mac",
network: "London\n56.35.38.237",
ip: "192.168.51.0",
alert: "Blacklisted application",
},
},
"56.35.38.237::192.168.131.120": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.131.120" }],
data: { type: "mac", network: "London\n56.35.38.237", ip: "192.168.131.0" },
},
"56.35.38.237::192.168.131.151": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "192.168.131.151" }],
data: { type: "mac", network: "London\n56.35.38.237", ip: "192.168.131.0" },
},
"56.35.38.237::192.168.131.167": {
label: [{ fontIcon: { text: "fas fa-print" } }, { text: "192.168.131.167" }],
data: { type: "printer", network: "London\n56.35.38.237", ip: "192.168.131.0" },
},
"134.58.218.94::10.0.71.179": {
label: [{ fontIcon: { text: "fas fa-print" } }, { text: "10.0.71.179" }],
data: { type: "printer", network: "Paris\n134.58.218.94", ip: "10.0.71.0" },
},
"134.58.218.94::10.0.203.8": {
label: [{ fontIcon: { text: "fas fa-print" } }, { text: "10.0.203.8" }],
data: { type: "printer", network: "Paris\n134.58.218.94", ip: "10.0.203.0" },
},
"134.58.218.94::10.0.203.56": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "10.0.203.56" }],
data: { type: "win", network: "Paris\n134.58.218.94", ip: "10.0.203.0" },
},
"134.58.218.94::10.0.71.224": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "10.0.71.224" }],
data: { type: "win", network: "Paris\n134.58.218.94", ip: "10.0.71.0" },
},
"134.58.218.94::10.0.203.249": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "10.0.203.249" }],
data: { type: "win", network: "Paris\n134.58.218.94", ip: "10.0.203.0" },
},
"134.58.218.94::10.0.203.101": {
label: [{ fontIcon: { text: "fas fa-phone" } }, { text: "10.0.203.101" }],
data: { type: "phone", network: "Paris\n134.58.218.94", ip: "10.0.203.0" },
},
"134.58.218.94::10.0.71.134": {
label: [{ fontIcon: { text: "fas fa-laptop" } }, { text: "10.0.71.134" }],
data: { type: "win", network: "Paris\n134.58.218.94", ip: "10.0.71.0" },
},
"181.13.51.159::192.168.235.94": {
label: [{ fontIcon: { text: "fas fa-server" } }, { text: "192.168.235.94" }],
data: { type: "server", network: "Central Server\n181.13.51.159", ip: "192.168.235.0" },
},
"181.13.51.159::192.168.235.235": {
label: [{ fontIcon: { text: "fas fa-server" } }, { text: "192.168.235.235" }],
data: { type: "server", network: "Central Server\n181.13.51.159", ip: "192.168.235.0" },
},
"181.13.51.159::192.168.235.111": {
label: [{ fontIcon: { text: "fas fa-server" } }, { text: "192.168.235.111" }],
data: { type: "server", network: "Central Server\n181.13.51.159", ip: "192.168.235.0" },
},
"181.13.51.159::192.168.223.223": {
label: [{ fontIcon: { text: "fas fa-server" } }, { text: "192.168.223.223" }],
data: { type: "server", network: "Central Server\n181.13.51.159", ip: "192.168.223.0" },
},
"181.13.51.159::192.168.223.34": {
label: [{ fontIcon: { text: "fas fa-server" } }, { text: "192.168.223.34" }],
data: { type: "server", network: "Central Server\n181.13.51.159", ip: "192.168.223.0" },
},
"181.13.51.159::192.168.223.76": {
label: [{ fontIcon: { text: "fas fa-server" } }, { text: "192.168.223.76" }],
data: { type: "server", network: "Central Server\n181.13.51.159", ip: "192.168.223.0" },
},
"181.13.51.159::192.168.235.34": {
label: [{ fontIcon: { text: "fas fa-server" } }, { text: "192.168.235.34" }],
data: { type: "server", network: "Central Server\n181.13.51.159", ip: "192.168.235.0" },
},
"140.211.152.43::192.168.16.209-140.211.152.43::192.168.247.242": {
flow: { velocity: 3 },
id1: "140.211.152.43::192.168.16.209",
id2: "140.211.152.43::192.168.247.242",
data: { port1: 8080, port2: 80 },
},
"140.211.152.43::192.168.16.209-140.211.152.43::192.168.16.194": {
flow: { velocity: 1 },
id1: "140.211.152.43::192.168.16.194",
id2: "140.211.152.43::192.168.16.209",
data: { port1: 8080, port2: 80 },
},
"140.211.152.43::192.168.247.240-140.211.152.43::192.168.247.162": {
flow: { velocity: 2 },
id1: "140.211.152.43::192.168.247.240",
id2: "140.211.152.43::192.168.247.162",
data: { port1: 443, port2: 443 },
},
"140.211.152.43::192.168.247.168-140.211.152.43::192.168.16.194": {
flow: { velocity: 1 },
id1: "140.211.152.43::192.168.247.168",
id2: "140.211.152.43::192.168.16.194",
data: { port1: 80, port2: 8080 },
},
"140.211.152.43::192.168.247.162-140.211.152.43::192.168.247.168": {
flow: { velocity: -1 },
id1: "140.211.152.43::192.168.247.162",
id2: "140.211.152.43::192.168.247.168",
data: { port1: 8080, port2: 80 },
},
"140.211.152.43::192.168.247.242-140.211.152.43::192.168.247.162": {
flow: { velocity: -1 },
id1: "140.211.152.43::192.168.247.242",
id2: "140.211.152.43::192.168.247.162",
data: { port1: 20, port2: 8080 },
},
"56.35.38.237::192.168.51.101-56.35.38.237::192.168.131.167": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.51.101",
id2: "56.35.38.237::192.168.131.167",
data: { port1: 80, port2: 20 },
},
"56.35.38.237::192.168.51.101-56.35.38.237::192.168.51.194": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.51.101",
id2: "56.35.38.237::192.168.51.194",
data: { port1: 443, port2: 8080 },
},
"56.35.38.237::192.168.51.158-56.35.38.237::192.168.131.80": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.51.158",
id2: "56.35.38.237::192.168.131.80",
data: { port1: 80, port2: 20 },
},
"56.35.38.237::192.168.51.108-56.35.38.237::192.168.131.80": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.51.108",
id2: "56.35.38.237::192.168.131.80",
data: { port1: 8080, port2: 20 },
},
"56.35.38.237::192.168.51.108-56.35.38.237::192.168.51.108": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.51.108",
id2: "56.35.38.237::192.168.51.108",
data: { port1: 22, port2: 80 },
},
"56.35.38.237::192.168.131.80-56.35.38.237::192.168.131.120": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.80",
id2: "56.35.38.237::192.168.131.120",
data: { port1: 20, port2: 20 },
},
"56.35.38.237::192.168.131.80-56.35.38.237::192.168.131.167": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.80",
id2: "56.35.38.237::192.168.131.167",
data: { port1: 22, port2: 443 },
},
"56.35.38.237::192.168.131.80-56.35.38.237::192.168.51.158": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.80",
id2: "56.35.38.237::192.168.51.158",
data: { port1: 443, port2: 443 },
},
"56.35.38.237::192.168.131.57-56.35.38.237::192.168.51.158": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.57",
id2: "56.35.38.237::192.168.51.158",
data: { port1: 443, port2: 80 },
},
"56.35.38.237::192.168.131.57-56.35.38.237::192.168.51.101": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.57",
id2: "56.35.38.237::192.168.51.101",
data: { port1: 22, port2: 20 },
},
"56.35.38.237::192.168.131.11-56.35.38.237::192.168.131.80": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.11",
id2: "56.35.38.237::192.168.131.80",
data: { port1: 20, port2: 8080 },
},
"56.35.38.237::192.168.131.11-56.35.38.237::192.168.131.151": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.11",
id2: "56.35.38.237::192.168.131.151",
data: { port1: 20, port2: 443 },
},
"56.35.38.237::192.168.131.11-56.35.38.237::192.168.131.167": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.131.11",
id2: "56.35.38.237::192.168.131.167",
data: { port1: 8080, port2: 443 },
},
"56.35.38.237::192.168.51.194-56.35.38.237::192.168.51.158": {
flow: { velocity: -3 },
id1: "56.35.38.237::192.168.51.194",
id2: "56.35.38.237::192.168.51.158",
data: { port1: 443, port2: 20 },
},
"56.35.38.237::192.168.51.194-56.35.38.237::192.168.131.80": {
flow: { velocity: 3 },
id1: "56.35.38.237::192.168.51.194",
id2: "56.35.38.237::192.168.131.80",
data: { port1: 8080, port2: 80 },
},
"56.35.38.237::192.168.131.151-56.35.38.237::192.168.131.11": {
flow: { velocity: 3 },
id1: "56.35.38.237::192.168.131.151",
id2: "56.35.38.237::192.168.131.11",
data: { port1: 443, port2: 20 },
},
"56.35.38.237::192.168.131.151-56.35.38.237::192.168.51.194": {
flow: { velocity: 3 },
id1: "56.35.38.237::192.168.131.151",
id2: "56.35.38.237::192.168.51.194",
data: { port1: 443, port2: 443 },
},
"56.35.38.237::192.168.131.151-56.35.38.237::192.168.131.80": {
flow: { velocity: 3 },
id1: "56.35.38.237::192.168.131.151",
id2: "56.35.38.237::192.168.131.80",
data: { port1: 22, port2: 20 },
},
"56.35.38.237::192.168.131.167-56.35.38.237::192.168.51.194": {
flow: { velocity: 3 },
id1: "56.35.38.237::192.168.131.57",
id2: "56.35.38.237::192.168.131.167",
data: { port1: 20, port2: 20 },
},
"56.35.38.237::192.168.131.167-56.35.38.237::192.168.131.151": {
flow: { velocity: 3 },
id1: "56.35.38.237::192.168.131.167",
id2: "56.35.38.237::192.168.131.151",
data: { port1: 22, port2: 20 },
},
"56.35.38.237::192.168.131.167-56.35.38.237::192.168.131.11": {
flow: { velocity: 3 },
id1: "56.35.38.237::192.168.131.167",
id2: "56.35.38.237::192.168.131.11",
data: { port1: 8080, port2: 443 },
},
"10.0.203.56-134.58.218.94::10.0.203.8": {
flow: { velocity: 1 },
id1: "134.58.218.94::10.0.203.56",
id2: "134.58.218.94::10.0.203.8",
data: { port1: 21, port2: 24 },
},
"10.0.203.249-134.58.218.94::10.0.203.8": {
flow: { velocity: 1 },
id1: "134.58.218.94::10.0.203.249",
id2: "134.58.218.94::10.0.203.8",
data: { port1: 22, port2: 18 },
},
"134.58.218.94::10.0.71.179-134.58.218.94::10.0.203.101": {
flow: { velocity: 3 },
id1: "134.58.218.94::10.0.71.179",
id2: "134.58.218.94::10.0.203.101",
data: { port1: 22, port2: 80 },
},
"134.58.218.94::10.0.71.179-134.58.218.94::10.0.203.56": {
flow: { velocity: 3 },
id1: "134.58.218.94::10.0.71.179",
id2: "134.58.218.94::10.0.203.56",
data: { port1: 443, port2: 22 },
},
"134.58.218.94::10.0.71.179-134.58.218.94::10.0.203.249": {
flow: { velocity: 3 },
id1: "134.58.218.94::10.0.71.179",
id2: "134.58.218.94::10.0.203.249",
data: { port1: 8080, port2: 22 },
},
"134.58.218.94::10.0.203.56-134.58.218.94::10.0.203.101": {
flow: { velocity: 2 },
id1: "134.58.218.94::10.0.203.56",
id2: "134.58.218.94::10.0.203.101",
data: { port1: 80, port2: 22 },
},
"134.58.218.94::10.0.71.224-134.58.218.94::10.0.71.134": {
flow: { velocity: 2 },
id1: "134.58.218.94::10.0.71.224",
id2: "134.58.218.94::10.0.71.134",
data: { port1: 20, port2: 443 },
},
"134.58.218.94::10.0.203.101-134.58.218.94::10.0.71.224": {
flow: { velocity: -1 },
id1: "134.58.218.94::10.0.203.101",
id2: "134.58.218.94::10.0.71.224",
data: { port1: 8080, port2: 80 },
},
"134.58.218.94::10.0.203.101-134.58.218.94::10.0.71.179": {
flow: { velocity: -1 },
id1: "134.58.218.94::10.0.203.101",
id2: "134.58.218.94::10.0.71.179",
data: { port1: 443, port2: 80 },
},
"181.13.51.159::192.168.235.94-56.35.38.237::192.168.131.57": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.94",
id2: "56.35.38.237::192.168.131.57",
data: { port1: 80, port2: 20, crossNetwork: true },
},
"181.13.51.159::192.168.235.94-140.211.152.43::192.168.247.240": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.94",
id2: "140.211.152.43::192.168.247.240",
data: { port1: 443, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.235.235-56.35.38.237::192.168.51.158": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.235",
id2: "56.35.38.237::192.168.51.158",
data: { port1: 8080, port2: 22, crossNetwork: true },
},
"181.13.51.159::192.168.235.235-56.35.38.237::192.168.131.167": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.235",
id2: "56.35.38.237::192.168.131.167",
data: { port1: 20, port2: 443, crossNetwork: true },
},
"181.13.51.159::192.168.235.235-140.211.152.43::192.168.247.240": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.235",
id2: "140.211.152.43::192.168.247.240",
data: { port1: 443, port2: 443, crossNetwork: true },
},
"181.13.51.159::192.168.223.76-134.58.218.94::10.0.71.134": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.223.76",
id2: "134.58.218.94::10.0.71.134",
data: { port1: 443, port2: 443, crossNetwork: true },
},
"181.13.51.159::192.168.235.111-140.211.152.43::192.168.247.162": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.111",
id2: "140.211.152.43::192.168.247.162",
data: { port1: 443, port2: 22, crossNetwork: true },
},
"181.13.51.159::192.168.235.111-56.35.38.237::192.168.131.167": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.111",
id2: "56.35.38.237::192.168.131.167",
data: { port1: 8080, port2: 20, crossNetwork: true },
},
"181.13.51.159::192.168.235.111-56.35.38.237::192.168.51.108": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.111",
id2: "56.35.38.237::192.168.51.108",
data: { port1: 22, port2: 22, crossNetwork: true },
},
"181.13.51.159::192.168.235.111-134.58.218.94::10.0.71.134": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.111",
id2: "134.58.218.94::10.0.71.134",
data: { port1: 20, port2: 80, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-140.211.152.43::192.168.16.194": {
flow: { velocity: 5 },
id1: "181.13.51.159::192.168.235.34",
id2: "140.211.152.43::192.168.16.194",
data: { port1: 80, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-134.58.218.94::10.0.71.224": {
flow: { velocity: -5 },
id1: "181.13.51.159::192.168.235.34",
id2: "134.58.218.94::10.0.71.224",
data: { port1: 8080, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-56.35.38.237::192.168.131.120": {
flow: { velocity: -5 },
id1: "181.13.51.159::192.168.235.34",
id2: "56.35.38.237::192.168.131.120",
data: { port1: 22, port2: 22, crossNetwork: true },
},
"181.13.51.159::192.168.223.223-134.58.218.94::10.0.71.224": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.223.223",
id2: "134.58.218.94::10.0.71.224",
data: { port1: 22, port2: 20, crossNetwork: true },
},
"181.13.51.159::192.168.223.223-56.35.38.237::192.168.51.194": {
flow: { velocity: -2 },
id1: "181.13.51.159::192.168.223.223",
id2: "56.35.38.237::192.168.51.194",
data: { port1: 443, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.223.34-56.35.38.237::192.168.131.167": {
flow: { velocity: -2 },
id1: "181.13.51.159::192.168.223.34",
id2: "56.35.38.237::192.168.131.167",
data: { port1: 22, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.223.34-140.211.152.43::192.168.16.232": {
flow: { velocity: -2 },
id1: "181.13.51.159::192.168.223.34",
id2: "140.211.152.43::192.168.16.232",
data: { port1: 80, port2: 22, crossNetwork: true },
},
"181.13.51.159::192.168.223.34-134.58.218.94::10.0.203.56": {
flow: { velocity: -2 },
id1: "181.13.51.159::192.168.223.34",
id2: "134.58.218.94::10.0.203.56",
data: { port1: 20, port2: 443, crossNetwork: true },
},
"181.13.51.159::192.168.223.34-56.35.38.237::192.168.51.158": {
flow: { velocity: -2 },
id1: "181.13.51.159::192.168.223.34",
id2: "56.35.38.237::192.168.51.158",
data: { port1: 443, port2: 80, crossNetwork: true },
},
"181.13.51.159::192.168.223.34-134.58.218.94::10.0.203.249": {
flow: { velocity: -2 },
id1: "181.13.51.159::192.168.223.34",
id2: "134.58.218.94::10.0.203.249",
data: { port1: 80, port2: 443, crossNetwork: true },
},
"181.13.51.159::192.168.235.294-134.58.218.94::10.0.71.134": {
flow: { velocity: 6 },
id1: "181.13.51.159::192.168.235.94",
id2: "134.58.218.94::10.0.71.134",
data: { port1: 8080, port2: 443, crossNetwork: true },
},
"181.13.51.159::192.168.223.76-56.35.38.237::192.168.51.101": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.223.76",
id2: "56.35.38.237::192.168.51.101",
data: { port1: 443, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.223.76-56.35.38.237::192.168.51.158": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.223.76",
id2: "56.35.38.237::192.168.51.158",
data: { port1: 80, port2: 80, crossNetwork: true },
},
"181.13.51.159::192.168.223.76-134.58.218.94::10.0.203.56": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.223.76",
id2: "134.58.218.94::10.0.203.56",
data: { port1: 22, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.223.223-140.211.152.43::192.168.16.194": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.223.223",
id2: "140.211.152.43::192.168.16.194",
data: { port1: 80, port2: 20, crossNetwork: true },
},
"181.13.51.159::192.168.223.223-140.211.152.43::192.168.247.240": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.223.223",
id2: "140.211.152.43::192.168.247.240",
data: { port1: 80, port2: 20, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-134.58.218.94::10.0.71.179": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.34",
id2: "134.58.218.94::10.0.71.179",
data: { port1: 20, port2: 22, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-56.35.38.237::192.168.51.101": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.34",
id2: "56.35.38.237::192.168.51.101",
data: { port1: 8080, port2: 8080, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-56.35.38.237::192.168.51.158": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.34",
id2: "56.35.38.237::192.168.51.158",
data: { port1: 22, port2: 80, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-140.211.152.43::192.168.16.232": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.34",
id2: "140.211.152.43::192.168.16.232",
data: { port1: 80, port2: 20, crossNetwork: true },
},
"181.13.51.159::192.168.235.34-56.35.38.237::192.168.131.11": {
flow: { velocity: 2 },
id1: "181.13.51.159::192.168.235.34",
id2: "56.35.38.237::192.168.131.11",
data: { port1: 20, port2: 443, crossNetwork: true },
},
"140.211.152.43::192.168.16.194-134.58.218.94::10.0.71.134": {
flow: { velocity: 2 },
id1: "140.211.152.43::192.168.16.194",
id2: "134.58.218.94::10.0.71.134",
data: { port1: 443, port2: 22, crossNetwork: true, alert: "Unencrypted data" },
},
};
return mapValues(items, (item, key) => {
return styleItem(item, shape);
});
}
export default data; <!doctype html>
<html>
<body>
<div id="regraph" style="height: 100vh"></div>
<script type="module" src="./code.jsx"></script>
</body>
</html>