[WIP] add page tab and corresponding routes

This commit is contained in:
Sina Blattmann 2023-03-06 08:47:19 +01:00
parent d2e4f93fd1
commit 8369daec24
14 changed files with 168 additions and 74 deletions

View File

@ -1,6 +1,6 @@
import useToken from "./hooks/useToken"; import useToken from "./hooks/useToken";
import Login from "./Login"; import Login from "./Login";
import { BrowserRouter, Route, Routes } from "react-router-dom"; import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
import { Grid } from "@mui/material"; import { Grid } from "@mui/material";
import routes from "./routes.json"; import routes from "./routes.json";
import { IntlProvider } from "react-intl"; import { IntlProvider } from "react-intl";
@ -11,7 +11,7 @@ import LanguageSelect from "./components/LanguageSelect";
import LogoutButton from "./components/LogoutButton"; import LogoutButton from "./components/LogoutButton";
import Installations from "./routes/Installations"; import Installations from "./routes/Installations";
import Users from "./routes/Users"; import Groups from "./routes/Groups";
const App = () => { const App = () => {
const { token, setToken, removeToken } = useToken(); const { token, setToken, removeToken } = useToken();
@ -40,11 +40,15 @@ const App = () => {
<LogoutButton removeToken={removeToken} /> <LogoutButton removeToken={removeToken} />
</Grid> </Grid>
<Routes> <Routes>
<Route
path="*"
element={<Navigate to={routes.installations} replace />}
/>
<Route <Route
path={routes.installations + "*"} path={routes.installations + "*"}
element={<Installations />} element={<Installations />}
/> />
<Route path={routes.tree} element={<Users />} /> <Route path={routes.groups + "*"} element={<Groups />} />
</Routes> </Routes>
</IntlProvider> </IntlProvider>
</BrowserRouter> </BrowserRouter>

View File

@ -1,5 +1,5 @@
import React, { useState } from "react"; import React, { useState } from "react";
import { Alert, Button, CircularProgress } from "@mui/material"; import { Alert, Button, CircularProgress, Grid } from "@mui/material";
import Container from "@mui/material/Container"; import Container from "@mui/material/Container";
import InnovenergyTextfield from "./components/InnovenergyTextfield"; import InnovenergyTextfield from "./components/InnovenergyTextfield";
import { axiosConfigWithoutToken } from "./config/axiosConfig"; import { axiosConfigWithoutToken } from "./config/axiosConfig";
@ -47,11 +47,11 @@ const Login = ({ setToken }: { setToken: any }) => {
handleChange={(e) => setPassword(e.target.value)} handleChange={(e) => setPassword(e.target.value)}
/> />
{error && <Alert severity="error">Incorrect username or password</Alert>} {error && <Alert severity="error">Incorrect username or password</Alert>}
<div> <Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
<Button variant="outlined" onClick={handleSubmit} sx={{ my: 1 }}> <Button variant="outlined" onClick={handleSubmit} sx={{ my: 1 }}>
Login Login
</Button> </Button>
</div> </Grid>
{loading && <CircularProgress />} {loading && <CircularProgress />}
</Container> </Container>
); );

View File

@ -0,0 +1,50 @@
import * as React from "react";
import Tabs from "@mui/material/Tabs";
import Tab from "@mui/material/Tab";
import Box from "@mui/material/Box";
import { Link } from "react-router-dom";
import routes from "../routes.json";
import useRouteMatch from "../hooks/useRouteMatch";
import { useIntl } from "react-intl";
const GroupTabs = () => {
const routeMatch = useRouteMatch([
routes.groups + routes.group + ":id",
routes.groups + routes.users + ":id",
]);
const id = routeMatch?.params?.id;
const intl = useIntl();
return (
<Box sx={{ width: "100%" }}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs
value={routeMatch?.pattern?.path ?? routes.group + ":id"}
aria-label="basic tabs example"
>
<Tab
label={intl.formatMessage({
id: "group",
defaultMessage: "Group",
})}
value={routes.groups + routes.group + ":id"}
component={Link}
to={routes.group + id}
/>
<Tab
label={intl.formatMessage({
id: "users",
defaultMessage: "Users",
})}
value={routes.groups + routes.users + ":id"}
component={Link}
to={routes.users + id}
/>
</Tabs>
</Box>
</Box>
);
};
export default GroupTabs;

View File

@ -5,8 +5,9 @@ import { ReactNode, useEffect, useState } from "react";
import { TreeItem } from "@mui/lab"; import { TreeItem } from "@mui/lab";
import { I_Folder, I_Installation } from "../util/types"; import { I_Folder, I_Installation } from "../util/types";
import axiosConfig from "../config/axiosConfig"; import axiosConfig from "../config/axiosConfig";
const UserList = () => { import { Link } from "react-router-dom";
const [data, setData] = useState<I_Folder[]>(); const GroupTree = () => {
const [data, setData] = useState<(I_Folder | I_Installation)[]>();
useEffect(() => { useEffect(() => {
axiosConfig.get("/GetTree").then((res) => { axiosConfig.get("/GetTree").then((res) => {
@ -14,11 +15,6 @@ const UserList = () => {
}); });
}, []); }, []);
const handleClick = (e: any, nodes: any) => {
console.log(e);
console.log(nodes);
};
const instanceOfFolder = (object: any): object is I_Folder => { const instanceOfFolder = (object: any): object is I_Folder => {
return "children" in object; return "children" in object;
}; };
@ -33,13 +29,18 @@ const UserList = () => {
const renderTree = (data: (I_Folder | I_Installation)[]): ReactNode => { const renderTree = (data: (I_Folder | I_Installation)[]): ReactNode => {
return data.map((element) => { return data.map((element) => {
return ( return (
<TreeItem <Link
key={element.id} to={"/groups/group/" + element.id}
nodeId={element.id.toString()} style={{ textDecoration: "none", color: "black" }}
label={element.name}
> >
{getNodes(element)} <TreeItem
</TreeItem> key={element.id}
nodeId={element.id.toString()}
label={element.name}
>
{getNodes(element)}
</TreeItem>
</Link>
); );
}); });
}; };
@ -49,11 +50,10 @@ const UserList = () => {
defaultCollapseIcon={<ExpandMoreIcon />} defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />} defaultExpandIcon={<ChevronRightIcon />}
sx={{ height: 300, flexGrow: 1, maxWidth: 400 }} sx={{ height: 300, flexGrow: 1, maxWidth: 400 }}
onNodeToggle={handleClick}
> >
{data && renderTree(data)} {data && renderTree(data)}
</TreeView> </TreeView>
); );
}; };
export default UserList; export default GroupTree;

View File

@ -77,7 +77,6 @@ const InstallationList = (props: InstallationListProps) => {
aria-labelledby="nested-list-subheader" aria-labelledby="nested-list-subheader"
> >
{filteredData?.map((installation) => { {filteredData?.map((installation) => {
console.log(routeMatch);
return ( return (
<Fragment key={installation.id}> <Fragment key={installation.id}>
<Link <Link

View File

@ -31,9 +31,7 @@ const InstallationTabs = () => {
id: "installation", id: "installation",
defaultMessage: "Installation", defaultMessage: "Installation",
})} })}
value={ value={routes.installations + routes.installation + ":id"}
routes.installations + routes.installation + ":id"
}
component={Link} component={Link}
to={routes.installation + id} to={routes.installation + id}
/> />

View File

@ -7,7 +7,7 @@ import routes from "../routes.json";
const NavigationButtons = () => { const NavigationButtons = () => {
const routeMatch = useRouteMatch([ const routeMatch = useRouteMatch([
routes.installations + "*", routes.installations + "*",
routes.tree + "*", routes.groups + "*",
]); ]);
return ( return (
@ -27,8 +27,8 @@ const NavigationButtons = () => {
defaultMessage="All installations" defaultMessage="All installations"
/> />
</ToggleButton> </ToggleButton>
<ToggleButton value={routes.tree + "*"} component={Link} to={routes.tree}> <ToggleButton value={routes.groups + "*"} component={Link} to={routes.groups}>
<FormattedMessage id="users" defaultMessage="Users" /> <FormattedMessage id="groups" defaultMessage="Groups" />
</ToggleButton> </ToggleButton>
</ToggleButtonGroup> </ToggleButtonGroup>
); );

View File

@ -14,5 +14,7 @@
"search": "Suche", "search": "Suche",
"users": "Benutzer", "users": "Benutzer",
"logout": "Logout", "logout": "Logout",
"updatedSuccessfully": "Erfolgreich aktualisiert" "updatedSuccessfully": "Erfolgreich aktualisiert",
"groups": "Gruppen",
"group": "Gruppe"
} }

View File

@ -14,5 +14,7 @@
"search": "Search", "search": "Search",
"users": "Users", "users": "Users",
"logout": "Logout", "logout": "Logout",
"updatedSuccessfully": "Updated successfully" "updatedSuccessfully": "Updated successfully",
"groups": "Groups",
"group": "Group"
} }

View File

@ -4,5 +4,6 @@
"users": "users/", "users": "users/",
"log": "log/", "log": "log/",
"installations": "/installations/", "installations": "/installations/",
"tree": "/users/*" "groups": "/groups/",
"group": "group/"
} }

View File

@ -0,0 +1,48 @@
import { Box, CircularProgress, Alert } from "@mui/material";
import { AxiosError } from "axios";
import { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import axiosConfig from "../config/axiosConfig";
import { I_Installation } from "../util/types";
const Group = () => {
const { id } = useParams();
const [values, setValues] = useState<I_Installation>();
const [loading, setLoading] = useState(false);
const [error, setError] = useState<AxiosError>();
useEffect(() => {
setLoading(true);
axiosConfig
.get("/GetFolderById?id=" + id)
.then((res) => {
setValues(res.data);
setLoading(false);
})
.catch((err: AxiosError) => {
setError(err);
setLoading(false);
});
}, [id]);
if (values && values.id && values.id.toString() === id) {
return <Box sx={{ py: 3 }}>{id}</Box>;
} else if (loading) {
return (
<Box
sx={{ width: 1 / 2, justifyContent: "center", display: "flex", mt: 10 }}
>
<CircularProgress sx={{ m: 2 }} />
</Box>
);
} else if (error) {
return (
<Alert severity="error" sx={{ mt: 1 }}>
{error.message}
</Alert>
);
}
return null;
};
export default Group;

View File

@ -0,0 +1,30 @@
import { Grid } from "@mui/material";
import { Container } from "@mui/system";
import { Routes, Route } from "react-router";
import GroupTabs from "../components/GroupTabs";
import NavigationButtons from "../components/NavigationButtons";
import UserTree from "../components/GroupTree";
import routes from "../routes.json";
import Group from "./Group";
const Groups = () => {
return (
<Container maxWidth="xl">
<Grid container spacing={2}>
<Grid item xs={3}>
<NavigationButtons />
<UserTree />
</Grid>
<Grid item xs={9}>
<GroupTabs />
<Routes>
<Route path={routes.group + ":id"} element={<Group />} index />
<Route path={routes.users + ":id"} element={<div>Users</div>} />
</Routes>
</Grid>
</Grid>
</Container>
);
};
export default Groups;

View File

@ -1,4 +1,4 @@
import { Grid, Divider } from "@mui/material"; import { Grid } from "@mui/material";
import { Container } from "@mui/system"; import { Container } from "@mui/system";
import { Routes, Route } from "react-router"; import { Routes, Route } from "react-router";
import InstallationTabs from "../components/InstallationTabs"; import InstallationTabs from "../components/InstallationTabs";
@ -13,22 +13,12 @@ import Sidebar from "../components/Sidebar";
const Installations = () => { const Installations = () => {
return ( return (
<Container maxWidth="xl"> <Container maxWidth="xl">
<Grid container spacing={2}> <Grid container spacing={4}>
<Grid item xs={3}> <Grid item xs={3}>
<NavigationButtons /> <NavigationButtons />
<Sidebar /> <Sidebar />
</Grid> </Grid>
<Grid <Grid item xs={9}>
item
xs={1}
container
direction="row"
justifyContent="center"
alignItems="center"
>
<Divider orientation="vertical" variant="middle" />
</Grid>
<Grid item xs={8}>
<InstallationTabs /> <InstallationTabs />
<Routes> <Routes>
<Route <Route

View File

@ -1,30 +0,0 @@
import { Grid, Divider } from "@mui/material";
import { Container } from "@mui/system";
import NavigationButtons from "../components/NavigationButtons";
import UserTree from "../components/UserTree";
const Users = () => {
return (
<Container maxWidth="xl">
<Grid container spacing={2}>
<Grid item xs={3}>
<NavigationButtons />
<UserTree />
</Grid>
<Grid
item
xs={1}
container
direction="row"
justifyContent="center"
alignItems="center"
>
<Divider orientation="vertical" variant="middle" />
</Grid>
<Grid item xs={8}></Grid>
</Grid>
</Container>
);
};
export default Users;