component model refactoring (#221)

This commit is contained in:
Michael Quigley 2024-10-21 16:49:16 -04:00
parent b40e69227c
commit ba34f472bb
No known key found for this signature in database
GPG Key ID: 9B60314A9DD20A62
8 changed files with 246 additions and 203 deletions

View File

@ -5,38 +5,31 @@ import {useEffect, useState} from "react";
import {AgentApi, ApiClient} from "./api/src/index.js";
import buildOverview from "./model/overview.js";
import NavBar from "./NavBar.jsx";
import {Box, Button, MenuItem, Modal, TextField} from "@mui/material";
import {useFormik} from "formik";
import NewShareModal from "./NewShareModal.jsx";
import NewAccessModal from "./NewAccessModal.jsx";
import {accessHandler, releaseAccess, releaseShare, shareHandler} from "./model/handler.js";
const AgentUi = () => {
const [version, setVersion] = useState("");
const [overview, setOverview] = useState(new Map());
const [newShare, setNewShare] = useState(false);
const [newAccess, setNewAccess] = useState(false);
let api = new AgentApi(new ApiClient(window.location.protocol+'//'+window.location.host));
const [newShare, setNewShare] = useState(false);
const openNewShare = () => {
setNewShare(true);
}
const closeNewShare = () => {
setNewShare(false);
}
const [newAccess, setNewAccess] = useState(false);
const openNewAccess = () => {
setNewAccess(true);
}
const closeNewAccess = () => {
setNewAccess(false);
}
const modalStyle = {
position: 'absolute',
top: '25%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 600,
bgcolor: 'background.paper',
boxShadow: 24,
p: 4,
};
let api = new AgentApi(new ApiClient(window.location.protocol+'//'+window.location.host));
useEffect(() => {
let mounted = true;
@ -49,6 +42,11 @@ const AgentUi = () => {
useEffect(() => {
let mounted = true;
api.agentStatus((err, data) => {
if(mounted) {
setOverview(buildOverview(data));
}
});
let interval = setInterval(() => {
api.agentStatus((err, data) => {
if(mounted) {
@ -62,18 +60,6 @@ const AgentUi = () => {
}
});
const releaseShare = (opts) => {
api.agentReleaseShare(opts, (err, data) => {
console.log(data);
});
}
const releaseAccess = (opts) => {
api.agentReleaseAccess(opts, (err, data) => {
console.log(data);
});
}
const router = createBrowserRouter([
{
path: "/",
@ -92,138 +78,12 @@ const AgentUi = () => {
}
]);
const shareHandler = (values) => {
switch(values.shareMode) {
case "public":
api.agentSharePublic({
target: values.target,
backendMode: values.backendMode,
}, (err, data) => {
closeNewShare();
});
break;
case "private":
api.agentSharePrivate({
target: values.target,
backendMode: values.backendMode,
}, (err, data) => {
closeNewShare();
});
break;
}
}
const accessHandler = (values) => {
api.agentAccessPrivate({
token: values.token,
bindAddress: values.bindAddress,
}, (err, data) => {
closeNewAccess();
});
}
const newShareForm = useFormik({
initialValues: {
shareMode: "public",
backendMode: "proxy",
target: "",
},
onSubmit: shareHandler,
});
const newAccessForm = useFormik({
initialValues: {
token: "",
bindAddress: "",
},
onSubmit: accessHandler,
})
return (
<>
<NavBar version={version} shareClick={openNewShare} accessClick={openNewAccess} />
<RouterProvider router={router} />
<Modal
open={newShare}
onClose={closeNewShare}
>
<Box sx={{ ...modalStyle }}>
<h2>Share...</h2>
<form onSubmit={newShareForm.handleSubmit}>
<TextField
fullWidth
select
id="shareMode"
name="shareMode"
label="Share Mode"
value={newShareForm.values.shareMode}
onChange={newShareForm.handleChange}
onBlur={newShareForm.handleBlur}
sx={{ mt: 2 }}
>
<MenuItem value="public">public</MenuItem>
<MenuItem value="private">private</MenuItem>
</TextField>
<TextField
fullWidth select
id="backendMode"
name="backendMode"
label="Backend Mode"
value={newShareForm.values.backendMode}
onChange={newShareForm.handleChange}
onBlur={newShareForm.handleBlur}
sx={{ mt: 2 }}
>
<MenuItem value="proxy">proxy</MenuItem>
<MenuItem value="web">web</MenuItem>
</TextField>
<TextField
fullWidth
id="target"
name="target"
label="Target"
value={newShareForm.values.target}
onChange={newShareForm.handleChange}
onBlur={newShareForm.handleBlur}
sx={{ mt: 2 }}
/>
<Button color="primary" variant="contained" type="submit" sx={{ mt: 2 }}>Create Share</Button>
</form>
</Box>
</Modal>
<Modal
open={newAccess}
onClose={closeNewAccess}
>
<Box sx={{...modalStyle}}>
<h2>Access...</h2>
<form onSubmit={newAccessForm.handleSubmit}>
<TextField
fullWidth
id="token"
name="token"
label="Share Token"
value={newAccessForm.values.token}
onChange={newAccessForm.handleChange}
onBlur={newAccessForm.handleBlur}
sx={{ mt: 2 }}
/>
<TextField
fullWidth
id="bindAddress"
name="bindAddress"
label="Bind Address"
value={newAccessForm.values.bindAddress}
onChange={newAccessForm.handleChange}
onBlur={newAccessForm.handleBlur}
sx={{ mt: 2 }}
/>
<Button color="primary" variant="contained" type="submit" sx={{ mt: 2 }}>Create Access</Button>
</form>
</Box>
</Modal>
<NewShareModal show={newShare} close={closeNewShare} handler={shareHandler} />
<NewAccessModal show={newAccess} close={closeNewAccess} handler={accessHandler} />
</>
);
}

View File

@ -0,0 +1,52 @@
import {Box, Button, Modal, TextField} from "@mui/material";
import {useFormik} from "formik";
import {modalStyle} from "./model/theme.js";
const NewAccessModal = (props) => {
const newAccessForm = useFormik({
initialValues: {
token: "",
bindAddress: "",
},
onSubmit: (v) => {
props.handler(v);
props.close();
},
});
return (
<Modal
open={props.show}
onClose={props.close}
>
<Box sx={{ ...modalStyle }}>
<h2>Access...</h2>
<form onSubmit={newAccessForm.handleSubmit}>
<TextField
fullWidth
id="token"
name="token"
label="Share Token"
value={newAccessForm.values.token}
onChange={newAccessForm.handleChange}
onBlur={newAccessForm.handleBlur}
sx={{ mt: 2 }}
/>
<TextField
fullWidth
id="bindAddress"
name="bindAddress"
label="Bind Address"
value={newAccessForm.values.bindAddress}
onChange={newAccessForm.handleChange}
onBlur={newAccessForm.handleBlur}
sx={{ mt: 2 }}
/>
<Button color="primary" variant="contained" type="submit" sx={{ mt: 2 }}>Create Access</Button>
</form>
</Box>
</Modal>
);
}
export default NewAccessModal;

View File

@ -0,0 +1,70 @@
import {Box, Button, MenuItem, Modal, TextField} from "@mui/material";
import {useFormik} from "formik";
import {modalStyle} from "./model/theme.js";
const NewShareModal = (props) => {
const newShareForm = useFormik({
initialValues: {
shareMode: "public",
backendMode: "proxy",
target: "",
},
onSubmit: (v) => {
props.handler(v);
props.close();
},
});
return (
<Modal
open={props.show}
onClose={props.close}
>
<Box sx={{ ...modalStyle }}>
<h2>Share...</h2>
<form onSubmit={newShareForm.handleSubmit}>
<TextField
fullWidth
select
id="shareMode"
name="shareMode"
label="Share Mode"
value={newShareForm.values.shareMode}
onChange={newShareForm.handleChange}
onBlur={newShareForm.handleBlur}
sx={{ mt: 2 }}
>
<MenuItem value="public">public</MenuItem>
<MenuItem value="private">private</MenuItem>
</TextField>
<TextField
fullWidth select
id="backendMode"
name="backendMode"
label="Backend Mode"
value={newShareForm.values.backendMode}
onChange={newShareForm.handleChange}
onBlur={newShareForm.handleBlur}
sx={{ mt: 2 }}
>
<MenuItem value="proxy">proxy</MenuItem>
<MenuItem value="web">web</MenuItem>
</TextField>
<TextField
fullWidth
id="target"
name="target"
label="Target"
value={newShareForm.values.target}
onChange={newShareForm.handleChange}
onBlur={newShareForm.handleBlur}
sx={{ mt: 2 }}
/>
<Button color="primary" variant="contained" type="submit" sx={{ mt: 2 }}>Create Share</Button>
</form>
</Box>
</Modal>
)
}
export default NewShareModal;

View File

@ -11,11 +11,11 @@ const Overview = (props) => {
props.overview.forEach((row) => {
switch(row.type) {
case "share":
cards.push(<ShareCard key={row.v.token} releaseShare={props.releaseShare} share={row.v} />);
cards.push(<ShareCard releaseShare={props.releaseShare} share={row.v} />);
break;
case "access":
cards.push(<AccessCard key={row.v.frontendToken} releaseAccess={props.releaseAccess} access={row.v} />);
cards.push(<AccessCard releaseAccess={props.releaseAccess} access={row.v} />);
break;
}
});

View File

@ -3,40 +3,7 @@ import {StrictMode} from "react";
import {createRoot} from "react-dom/client";
import AgentUi from "./AgentUi.jsx";
import {createTheme, ThemeProvider} from "@mui/material";
export const themeOptions = {
components: {
MuiCard: {
styleOverrides: {
root: ({theme}) => theme.unstable_sx({
mt: 5,
p: 2.5,
pt: 3.25,
borderRadius: 2,
}),
}
},
MuiAppBar: {
styleOverrides: {
root : ({theme}) => theme.unstable_sx({
borderRadius: 2,
}),
}
}
},
palette: {
mode: 'light',
primary: {
main: '#241775',
},
secondary: {
main: '#9bf316',
},
},
typography: {
fontFamily: 'Poppins',
}
};
import {themeOptions} from "./model/theme.js";
createRoot(document.getElementById('root')).render(
<StrictMode>
@ -44,4 +11,4 @@ createRoot(document.getElementById('root')).render(
<AgentUi />
</ThemeProvider>
</StrictMode>,
)
);

View File

@ -0,0 +1,46 @@
import {AgentApi, ApiClient} from "../api/src/index.js";
let api = new AgentApi(new ApiClient(window.location.protocol+'//'+window.location.host));
export const shareHandler = (values) => {
switch(values.shareMode) {
case "public":
api.agentSharePublic({
target: values.target,
backendMode: values.backendMode,
}, (err, data) => {
console.log(err, data);
});
break;
case "private":
api.agentSharePrivate({
target: values.target,
backendMode: values.backendMode,
}, (err, data) => {
console.log(err, data);
});
break;
}
}
export const accessHandler = (values) => {
api.agentAccessPrivate({
token: values.token,
bindAddress: values.bindAddress,
}, (err, data) => {
console.log(err, data);
});
}
export const releaseShare = (opts) => {
api.agentReleaseShare(opts, (err, data) => {
console.log(data);
});
}
export const releaseAccess = (opts) => {
api.agentReleaseAccess(opts, (err, data) => {
console.log(data);
});
}

View File

@ -1,17 +1,19 @@
const buildOverview = (status) => {
let overview = new Map();
status.accesses.map(acc => {
overview.set(acc.frontendToken, {
type: "access",
v: acc
if(status) {
status.accesses.map(acc => {
overview.set(acc.frontendToken, {
type: "access",
v: acc
});
});
});
status.shares.map(shr => {
overview.set(shr.token, {
type: "share",
v: shr
})
});
status.shares.map(shr => {
overview.set(shr.token, {
type: "share",
v: shr
})
});
}
return overview;
}

View File

@ -0,0 +1,46 @@
const componentOptions = {
MuiCard: {
styleOverrides: {
root: ({theme}) => theme.unstable_sx({
mt: 5,
p: 2.5,
pt: 3.25,
borderRadius: 2,
}),
}
},
MuiAppBar: {
styleOverrides: {
root : ({theme}) => theme.unstable_sx({
borderRadius: 2,
}),
}
}
}
export const themeOptions = {
components: componentOptions,
palette: {
mode: 'light',
primary: {
main: '#241775',
},
secondary: {
main: '#9bf316',
},
},
typography: {
fontFamily: 'Poppins',
}
};
export const modalStyle = {
position: 'absolute',
top: '25%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 600,
bgcolor: 'background.paper',
boxShadow: 24,
p: 4,
};