mirror of
https://github.com/openziti/zrok.git
synced 2025-01-23 14:28:37 +01:00
parent
ceb96b3e4f
commit
40783cdcda
@ -2,10 +2,17 @@ import {useEffect, useState} from "react";
|
|||||||
import {Configuration, MetadataApi} from "./api";
|
import {Configuration, MetadataApi} from "./api";
|
||||||
import buildVisualizerGraph from "./model/visualizer.ts";
|
import buildVisualizerGraph from "./model/visualizer.ts";
|
||||||
import {GraphCanvas} from "reagraph";
|
import {GraphCanvas} from "reagraph";
|
||||||
import {Box} from "@mui/material";
|
import {Box, Button} from "@mui/material";
|
||||||
import NavBar from "./NavBar.tsx";
|
import NavBar from "./NavBar.tsx";
|
||||||
|
import {reagraphTheme} from "./model/theme.ts";
|
||||||
|
import {User} from "./model/user.ts";
|
||||||
|
|
||||||
const ApiConsole = () => {
|
interface ApiConsoleProps {
|
||||||
|
user: User;
|
||||||
|
logout: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ApiConsole = ({ user, logout }: ApiConsoleProps) => {
|
||||||
const [version, setVersion] = useState("no version set");
|
const [version, setVersion] = useState("no version set");
|
||||||
const [nodes, setNodes] = useState([]);
|
const [nodes, setNodes] = useState([]);
|
||||||
const [edges, setEdges] = useState([]);
|
const [edges, setEdges] = useState([]);
|
||||||
@ -26,7 +33,7 @@ const ApiConsole = () => {
|
|||||||
let cfg = new Configuration({
|
let cfg = new Configuration({
|
||||||
headers: {
|
headers: {
|
||||||
// ignorable token, local development environment
|
// ignorable token, local development environment
|
||||||
"X-TOKEN": "8TPUmoBHMdA8"
|
"X-TOKEN": user.token
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let api = new MetadataApi(cfg);
|
let api = new MetadataApi(cfg);
|
||||||
@ -52,8 +59,9 @@ const ApiConsole = () => {
|
|||||||
<NavBar version={version} />
|
<NavBar version={version} />
|
||||||
<Box>
|
<Box>
|
||||||
<div style={{position: "relative", width: "100%", height: "500px"}}>
|
<div style={{position: "relative", width: "100%", height: "500px"}}>
|
||||||
<GraphCanvas nodes={nodes} edges={edges}/>
|
<GraphCanvas nodes={nodes} edges={edges} theme={reagraphTheme} labelFontUrl={"https://fonts.googleapis.com/css?family=Poppins"}/>
|
||||||
</div>
|
</div>
|
||||||
|
<Button onClick={logout}>Log Out</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
42
ui100/src/App.tsx
Normal file
42
ui100/src/App.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import {BrowserRouter, Route, Routes} from "react-router";
|
||||||
|
import ApiConsole from "./ApiConsole.tsx";
|
||||||
|
import Login from "./Login.tsx";
|
||||||
|
import {useEffect, useState} from "react";
|
||||||
|
import {User} from "./model/user.ts";
|
||||||
|
|
||||||
|
const App = () => {
|
||||||
|
const [user, setUser] = useState(null as User);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const checkUser = () => {
|
||||||
|
const user = localStorage.getItem("user");
|
||||||
|
if(user) {
|
||||||
|
console.log(user);
|
||||||
|
setUser(JSON.parse(user));
|
||||||
|
console.log("reloaded user", user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
checkUser();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const login = (user: User) => {
|
||||||
|
setUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
setUser(null);
|
||||||
|
localStorage.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const consoleRoot = user ? <ApiConsole user={user} logout={logout} /> : <Login onLogin={login} />
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BrowserRouter>
|
||||||
|
<Routes>
|
||||||
|
<Route index element={consoleRoot} />
|
||||||
|
</Routes>
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
@ -1,12 +1,37 @@
|
|||||||
import {Box, Button, Container, TextField, Typography} from "@mui/material";
|
import {Box, Button, Container, TextField, Typography} from "@mui/material";
|
||||||
|
import {User} from "./model/user.ts";
|
||||||
|
import {useState} from "react";
|
||||||
|
import {AccountApi} from "./api";
|
||||||
|
|
||||||
|
interface LoginProps {
|
||||||
|
onLogin: (user: User) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Login = ({ onLogin }: LoginProps) => {
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [message, setMessage] = useState("");
|
||||||
|
|
||||||
|
const login = async e => {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log(email, password);
|
||||||
|
|
||||||
|
let api = new AccountApi();
|
||||||
|
api.login({body: {"email": email, "password": password}})
|
||||||
|
.then(d => {
|
||||||
|
onLogin({email: email, token: d.toString()});
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
setMessage("login failed: " + e.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const Login = () => {
|
|
||||||
return (
|
return (
|
||||||
<Typography>
|
<Typography>
|
||||||
<Container maxWidth="xs">
|
<Container maxWidth="xs">
|
||||||
<Box sx={{ marginTop: 8, display: "flex", flexDirection: "column", alignItems: "center"}}>
|
<Box sx={{ marginTop: 8, display: "flex", flexDirection: "column", alignItems: "center"}}>
|
||||||
<h2>welcome to zrok...</h2>
|
<h2>welcome to zrok...</h2>
|
||||||
<Box component="form" noValidate>
|
<Box component="form" noValidate onSubmit={login}>
|
||||||
<TextField
|
<TextField
|
||||||
margin="normal"
|
margin="normal"
|
||||||
required
|
required
|
||||||
@ -16,6 +41,8 @@ const Login = () => {
|
|||||||
name="email"
|
name="email"
|
||||||
autoComplete="email"
|
autoComplete="email"
|
||||||
autoFocus
|
autoFocus
|
||||||
|
value={email}
|
||||||
|
onChange={v => { setMessage(""); setEmail(v.target.value) }}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
margin="normal"
|
margin="normal"
|
||||||
@ -26,10 +53,13 @@ const Login = () => {
|
|||||||
type="password"
|
type="password"
|
||||||
id="password"
|
id="password"
|
||||||
autoComplete="current-password"
|
autoComplete="current-password"
|
||||||
|
value={password}
|
||||||
|
onChange={v => { setMessage(""); setPassword(v.target.value) }}
|
||||||
/>
|
/>
|
||||||
<Button type="submit" fullWidth variant="contained" sx={{ mt: 3, mb: 2 }}>
|
<Button type="submit" fullWidth variant="contained" sx={{ mt: 3, mb: 2 }}>
|
||||||
Log In
|
Log In
|
||||||
</Button>
|
</Button>
|
||||||
|
<Box component="h3">{message}</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -1,21 +1,14 @@
|
|||||||
import "./index.css";
|
import "./index.css";
|
||||||
import {StrictMode} from "react";
|
import {StrictMode} from "react";
|
||||||
import {createRoot} from "react-dom/client";
|
import {createRoot} from "react-dom/client";
|
||||||
import ApiConsole from "./ApiConsole.tsx";
|
|
||||||
import {ThemeProvider} from "@mui/material";
|
import {ThemeProvider} from "@mui/material";
|
||||||
import {theme} from "./model/theme.ts";
|
import {theme} from "./model/theme.ts";
|
||||||
import {BrowserRouter, Route, Routes} from "react-router";
|
import App from "./App.tsx";
|
||||||
import Login from "./Login.tsx";
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')!).render(
|
createRoot(document.getElementById('root')!).render(
|
||||||
<StrictMode>
|
<StrictMode>
|
||||||
<ThemeProvider theme={theme}>
|
<ThemeProvider theme={theme}>
|
||||||
<BrowserRouter>
|
<App />
|
||||||
<Routes>
|
|
||||||
<Route index element={<ApiConsole />} />
|
|
||||||
<Route path="login" element={<Login />} />
|
|
||||||
</Routes>
|
|
||||||
</BrowserRouter>
|
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
</StrictMode>
|
</StrictMode>
|
||||||
);
|
);
|
@ -1,4 +1,5 @@
|
|||||||
import {createTheme} from "@mui/material";
|
import {createTheme} from "@mui/material";
|
||||||
|
import {Theme} from "reagraph";
|
||||||
|
|
||||||
const componentOptions = {
|
const componentOptions = {
|
||||||
MuiCard: {
|
MuiCard: {
|
||||||
@ -45,3 +46,61 @@ export const modalStyle = {
|
|||||||
boxShadow: 24,
|
boxShadow: 24,
|
||||||
p: 4,
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
4
ui100/src/model/user.ts
Normal file
4
ui100/src/model/user.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface User {
|
||||||
|
email: string;
|
||||||
|
token: string;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user