[WIP] add page tab and corresponding routes
This commit is contained in:
parent
d2e4f93fd1
commit
8369daec24
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
||||||
|
|
|
@ -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}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
"users": "users/",
|
"users": "users/",
|
||||||
"log": "log/",
|
"log": "log/",
|
||||||
"installations": "/installations/",
|
"installations": "/installations/",
|
||||||
"tree": "/users/*"
|
"groups": "/groups/",
|
||||||
|
"group": "group/"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
|
Loading…
Reference in New Issue