Skip to content

Commit

Permalink
react-flow; lint; layouting (#799)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelquigley committed Dec 4, 2024
1 parent 96eb246 commit 334637b
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 1,060 deletions.
1,115 changes: 165 additions & 950 deletions ui100/package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions ui100/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
"@emotion/styled": "^11.13.5",
"@mui/icons-material": "^6.1.8",
"@mui/material": "^6.1.8",
"@xyflow/react": "^12.3.5",
"d3-hierarchy": "^3.1.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router": "^7.0.1",
"reagraph": "^4.21.0"
"react-router": "^7.0.1"
},
"devDependencies": {
"@eslint/js": "^9.13.0",
Expand Down
21 changes: 7 additions & 14 deletions ui100/src/ApiConsole.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import {useEffect, useState} from "react";
import {Configuration, MetadataApi} from "./api";
import buildVisualizerGraph from "./model/visualizer.ts";
import {GraphCanvas} from "reagraph";
import {Box, Button} from "@mui/material";
import buildVisualizerGraph, {VisualOverview} from "./model/visualizer.ts";
import {Box} from "@mui/material";
import NavBar from "./NavBar.tsx";
import {reagraphTheme} from "./model/theme.ts";
import {User} from "./model/user.ts";
import Visualizer from "./Visualizer.tsx";

interface ApiConsoleProps {
user: User;
Expand All @@ -14,8 +13,7 @@ interface ApiConsoleProps {

const ApiConsole = ({ user, logout }: ApiConsoleProps) => {
const [version, setVersion] = useState("no version set");
const [nodes, setNodes] = useState([]);
const [edges, setEdges] = useState([]);
const [overview, setOverview] = useState(new VisualOverview());

useEffect(() => {
let api = new MetadataApi();
Expand All @@ -32,16 +30,13 @@ const ApiConsole = ({ user, logout }: ApiConsoleProps) => {
let interval = setInterval(() => {
let cfg = new Configuration({
headers: {
// ignorable token, local development environment
"X-TOKEN": user.token
}
});
let api = new MetadataApi(cfg);
api.overview()
.then(d => {
let graph = buildVisualizerGraph(d);
setNodes(graph.nodes);
setEdges(graph.edges);
setOverview(buildVisualizerGraph(d));
})
.catch(e => {
console.log(e);
Expand All @@ -54,11 +49,9 @@ const ApiConsole = ({ user, logout }: ApiConsoleProps) => {

return (
<div>
<NavBar logout={logout} version={version} />
<NavBar logout={logout} />
<Box>
<div style={{position: "relative", width: "100%", height: "500px"}}>
<GraphCanvas nodes={nodes} edges={edges} theme={reagraphTheme} />
</div>
<Visualizer overview={overview} />
</Box>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion ui100/src/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {User} from "./model/user.ts";
import {useEffect, useState} from "react";
import {AccountApi, MetadataApi} from "./api";
import {Link} from "react-router";
import zroket from "../public/zrok-1.0.0-rocket.svg";
import zroket from "./assets/zrok-1.0.0-rocket-purple.svg";

interface LoginProps {
onLogin: (user: User) => void;
Expand Down
4 changes: 2 additions & 2 deletions ui100/src/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {AppBar, Box, Button, Grid2, IconButton, Toolbar, Typography} from "@mui/material";
import MenuIcon from "@mui/icons-material/Menu";
import LogoutIcon from "@mui/icons-material/Logout";
import zroket from "../public/zrok-1.0.0-rocket-white.svg";
import zroket from "./assets/zrok-1.0.0-rocket-white.svg";

interface NavBarProps {
logout: () => void;
Expand All @@ -15,7 +15,7 @@ const NavBar = ({ logout }: NavBarProps) => {
<IconButton size="large" edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }}>
<MenuIcon />
</IconButton>
<Typography variant="h6" sx={{ flexGrow: 1 }} display={{ xs: "none", sm: "none", md: "block" }}>
<Typography variant="h6" sx={{ flexGrow: 1 }}>
<Grid2 container sx={{ flexGrow: 1 }}>
<Grid2 display="flex" justifyContent="left">
<img src={zroket} height="30" />
Expand Down
66 changes: 66 additions & 0 deletions ui100/src/Visualizer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import "@xyflow/react/dist/style.css";
import "./react-flow.css";
import {Background, Controls, ReactFlow, ReactFlowProvider, useEdgesState, useNodesState} from "@xyflow/react";
import {VisualOverview} from "./model/visualizer.ts";
import {useEffect} from "react";
import {stratify, tree} from "d3-hierarchy";

interface VisualizerProps {
overview: VisualOverview;
}

const Visualizer = ({ overview }: VisualizerProps) => {
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);

const layout = (nodes, edges): VisualOverview => {
if(!nodes) {
return { nodes: [], edges: [] };
}
let g = tree();
if(nodes.length === 0) return { nodes, edges };
// const { width, height } = document.querySelector(`[data-id="$nodes[0].id"]`).getBoundingClientRect();
const width = 100;
const height = 40;
const hierarchy = stratify()
.id((node) => node.id)
.parentId((node) => edges.find((edge) => edge.target === node.id)?.source);
const root = hierarchy(nodes);
const layout = g.nodeSize([width * 2, height * 2])(root);
return {
nodes: layout
.descendants()
.map((node) => ({ ...node.data, position: { x: node.x, y: node.y }})),
edges,
}
}

useEffect(() => {
let layouted = layout(overview.nodes, overview.edges);
setNodes(layouted.nodes);
setEdges(layouted.edges);
}, [overview]);

return (
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
fitView
>
<Background/>
<Controls />
</ReactFlow>
);
}

export default ({ overview }: VisualizerProps) => {
return (
<div style={{ height: "400px" }}>
<ReactFlowProvider>
<Visualizer overview={overview}/>
</ReactFlowProvider>
</div>
);
}
50 changes: 50 additions & 0 deletions ui100/src/assets/zrok-1.0.0-rocket-purple.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
23 changes: 2 additions & 21 deletions ui100/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,18 @@ code {

a {
font-weight: 500;
color: #646cff;
color: #241775;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
color: #9bf316;
}

h1 {
font-size: 3.2em;
line-height: 1.1;
}

button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}

#root {
max-width: 1280px;
margin: 0 auto;
Expand Down
59 changes: 0 additions & 59 deletions ui100/src/model/theme.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {createTheme} from "@mui/material";
import {Theme} from "reagraph";

const componentOptions = {
MuiCard: {
Expand Down Expand Up @@ -45,62 +44,4 @@ export const modalStyle = {
bgcolor: 'background.paper',
boxShadow: 24,
p: 4,
};

export const reagraphTheme: Theme = {
canvas: {
background: '#fff',
fog: '#fff'
},
node: {
fill: '#241775',
activeFill: '#9bf316',
opacity: 1,
selectedOpacity: 1,
inactiveOpacity: 0.2,
label: {
color: '#241775',
stroke: '#fff',
activeColor: '#9bf316'
},
subLabel: {
color: '#241775',
stroke: '#eee',
activeColor: '#9bf316'
}
},
lasso: {
border: '1px solid #55aaff',
background: 'rgba(75, 160, 255, 0.1)'
},
ring: {
fill: '#D8E6EA',
activeFill: '#1DE9AC'
},
edge: {
fill: '#D8E6EA',
activeFill: '#1DE9AC',
opacity: 1,
selectedOpacity: 1,
inactiveOpacity: 0.1,
label: {
stroke: '#fff',
color: '#2A6475',
activeColor: '#1DE9AC'
}
},
arrow: {
fill: '#D8E6EA',
activeFill: '#1DE9AC'
},
cluster: {
stroke: '#D8E6EA',
opacity: 1,
selectedOpacity: 1,
inactiveOpacity: 0.1,
label: {
stroke: '#fff',
color: '#2A6475'
}
}
};
38 changes: 27 additions & 11 deletions ui100/src/model/visualizer.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,34 @@
import {Overview} from "../api";
import {Edge, Node} from "@xyflow/react";

export class VisualOverview {
nodes: Node[];
edges: Edge[];
}

const buildVisualizerGraph = (overview: Overview): VisualOverview => {
let out = new VisualOverview();
out.nodes = [
{ id: "1", position: { x: 0, y: 0 }, data: { label: "[email protected]" } }
];
out.edges = [];

const buildVisualizerGraph = (overview: Overview) => {
let nodes = [
{ id: "1", label: "[email protected]" }
]
let edges = [];
overview.environments?.forEach((env, i) => {
nodes.push({ id: (i+2).toString(), label: env.environment?.description! });
edges.push({ source: (i+2).toString(), target: "1", id: (i+2)+"-1" });
out.nodes.push({
id: (i+2).toString(),
position: { x: 0, y: 0 },
data: { label: env.environment?.description! },
});
out.edges.push({
id: "e" + (i+2) + "-1",
source: "1",
target: (i+2).toString()
});
})
return {
nodes: nodes,
edges: edges,
}

console.log(out);

return out;
}

export default buildVisualizerGraph;
8 changes: 8 additions & 0 deletions ui100/src/react-flow.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.react-flow__node {
font-family: "Poppins", sans-serif;
color: #241775;
border: 1px solid #241775;
}
.react-flow__attribution {
display: none;
}

0 comments on commit 334637b

Please sign in to comment.