Fix a few small bugs, revert Detail Component
This commit is contained in:
parent
156eee6c9c
commit
30c9752f9a
|
@ -7,7 +7,6 @@ import { IntlProvider } from "react-intl";
|
|||
import { useState } from "react";
|
||||
import en from "./lang/en.json";
|
||||
import de from "./lang/de.json";
|
||||
import Installations from "./components/Installations/Installations";
|
||||
import LanguageSelect from "./components/Layout/LanguageSelect";
|
||||
import LogoutButton from "./components/Layout/LogoutButton";
|
||||
import Users from "./components/Users/Users";
|
||||
|
@ -36,7 +35,7 @@ const App = () => {
|
|||
locale={language}
|
||||
defaultLocale="EN"
|
||||
>
|
||||
<Container maxWidth="xl" sx={{ margin: 2 }}>
|
||||
<Container maxWidth="xl" sx={{ marginTop: 2 }}>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={3}>
|
||||
<NavigationButtons />
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React, { useState } from "react";
|
||||
import { Alert, Button, CircularProgress, Grid } from "@mui/material";
|
||||
import { Alert, CircularProgress, Grid } from "@mui/material";
|
||||
import Container from "@mui/material/Container";
|
||||
import { axiosConfigWithoutToken } from "./config/axiosConfig";
|
||||
import InnovenergyTextfield from "./components/Layout/InnovenergyTextfield";
|
||||
import InnovenergyButton from "./components/Layout/InnovenergyButton";
|
||||
|
||||
const loginUser = async (username: string, password: string) => {
|
||||
return axiosConfigWithoutToken.post("/Login", null, {
|
||||
|
@ -67,9 +68,9 @@ const Login = ({ setToken, setLanguage }: I_LoginProps) => {
|
|||
/>
|
||||
{error && <Alert severity="error">Incorrect username or password</Alert>}
|
||||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||
<Button variant="outlined" onClick={handleSubmit} sx={{ my: 1 }}>
|
||||
<InnovenergyButton onClick={handleSubmit} sx={{ my: 1 }}>
|
||||
Login
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
</Grid>
|
||||
{loading && <CircularProgress />}
|
||||
</Container>
|
||||
|
|
|
@ -11,26 +11,26 @@ import axiosConfig from "../../config/axiosConfig";
|
|||
import { I_User, UserWithInheritedAccess } from "../../util/user.util";
|
||||
import { GroupContext } from "./GroupContextProvider";
|
||||
|
||||
interface UserContextProviderProps {
|
||||
interface UsersContextProviderProps {
|
||||
directAccessUsers: I_User[];
|
||||
setDirectAccessUsers: (value: I_User[]) => void;
|
||||
inheritedAccessUsers: UserWithInheritedAccess[];
|
||||
setInheritedAccessUsers: (value: UserWithInheritedAccess[]) => void;
|
||||
availableUsers: I_User[];
|
||||
setAvailableUsers: (value: I_User[]) => void;
|
||||
getAvailableUsers: () => I_User[];
|
||||
getAvailableUsersForResource: () => I_User[];
|
||||
fetchUsersWithInheritedAccessForResource: () => Promise<void>;
|
||||
fetchUsersWithDirectAccessForResource: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const UserContext = createContext<UserContextProviderProps>({
|
||||
export const UsersContext = createContext<UsersContextProviderProps>({
|
||||
directAccessUsers: [],
|
||||
setDirectAccessUsers: () => {},
|
||||
inheritedAccessUsers: [],
|
||||
setInheritedAccessUsers: () => {},
|
||||
availableUsers: [],
|
||||
setAvailableUsers: () => {},
|
||||
getAvailableUsers: () => {
|
||||
getAvailableUsersForResource: () => {
|
||||
return [];
|
||||
},
|
||||
fetchUsersWithInheritedAccessForResource: () => {
|
||||
|
@ -41,7 +41,7 @@ export const UserContext = createContext<UserContextProviderProps>({
|
|||
},
|
||||
});
|
||||
|
||||
const UserContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
const UsersContextProvider = ({ children }: { children: ReactNode }) => {
|
||||
const [directAccessUsers, setDirectAccessUsers] = useState<I_User[]>([]);
|
||||
const [inheritedAccessUsers, setInheritedAccessUsers] = useState<
|
||||
UserWithInheritedAccess[]
|
||||
|
@ -88,7 +88,7 @@ const UserContextProvider = ({ children }: { children: ReactNode }) => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<UserContext.Provider
|
||||
<UsersContext.Provider
|
||||
value={{
|
||||
directAccessUsers,
|
||||
setDirectAccessUsers,
|
||||
|
@ -96,14 +96,14 @@ const UserContextProvider = ({ children }: { children: ReactNode }) => {
|
|||
setInheritedAccessUsers,
|
||||
availableUsers,
|
||||
setAvailableUsers,
|
||||
getAvailableUsers: getAvailableUsersForResource,
|
||||
getAvailableUsersForResource,
|
||||
fetchUsersWithInheritedAccessForResource,
|
||||
fetchUsersWithDirectAccessForResource,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</UserContext.Provider>
|
||||
</UsersContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserContextProvider;
|
||||
export default UsersContextProvider;
|
|
@ -1,5 +1,5 @@
|
|||
import { Grid } from "@mui/material";
|
||||
import UserContextProvider from "../../Context/UserContextProvider";
|
||||
import UsersContextProvider from "../../Context/UsersContextProvider";
|
||||
import AvailableUserDialog from "./AvailableUserDialog";
|
||||
import InnovenergyList from "./InnovenergyList";
|
||||
import UsersWithDirectAccess from "./UsersWithDirectAccess";
|
||||
|
@ -7,7 +7,7 @@ import UsersWithInheritedAccess from "./UsersWithInheritedAccess";
|
|||
|
||||
const AccessManagement = () => {
|
||||
return (
|
||||
<UserContextProvider>
|
||||
<UsersContextProvider>
|
||||
<Grid container sx={{ mt: 1 }}>
|
||||
<Grid item xs={6}>
|
||||
<AvailableUserDialog />
|
||||
|
@ -17,7 +17,7 @@ const AccessManagement = () => {
|
|||
</InnovenergyList>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserContextProvider>
|
||||
</UsersContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import {
|
||||
Autocomplete,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
|
@ -13,7 +12,8 @@ import { useParams } from "react-router-dom";
|
|||
import axiosConfig from "../../../config/axiosConfig";
|
||||
import { I_User } from "../../../util/user.util";
|
||||
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||
import { UserContext } from "../../Context/UserContextProvider";
|
||||
import { UsersContext } from "../../Context/UsersContextProvider";
|
||||
import InnovenergyButton from "../../Layout/InnovenergyButton";
|
||||
|
||||
const AvailableUserDialog = () => {
|
||||
const [selectedUsers, setSelectedUsers] = useState<I_User[]>([]);
|
||||
|
@ -22,10 +22,10 @@ const AvailableUserDialog = () => {
|
|||
const { currentType } = useContext(GroupContext);
|
||||
const { id } = useParams();
|
||||
const {
|
||||
getAvailableUsers,
|
||||
getAvailableUsersForResource,
|
||||
fetchUsersWithDirectAccessForResource,
|
||||
fetchUsersWithInheritedAccessForResource,
|
||||
} = useContext(UserContext);
|
||||
} = useContext(UsersContext);
|
||||
|
||||
const handleGrant = () => {
|
||||
selectedUsers.forEach((user) => {
|
||||
|
@ -63,7 +63,7 @@ const AvailableUserDialog = () => {
|
|||
sx={{ width: "500px" }}
|
||||
multiple
|
||||
id="tags-standard"
|
||||
options={getAvailableUsers()}
|
||||
options={getAvailableUsersForResource()}
|
||||
getOptionLabel={(option) => option.name}
|
||||
renderInput={(params) => (
|
||||
<TextField
|
||||
|
@ -77,19 +77,18 @@ const AvailableUserDialog = () => {
|
|||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
variant="outlined"
|
||||
<InnovenergyButton
|
||||
type="submit"
|
||||
sx={{ height: 40, ml: 2 }}
|
||||
onClick={handleGrant}
|
||||
>
|
||||
<FormattedMessage id="grantAccess" defaultMessage="Grant access" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
<Button variant="outlined" type="submit" onClick={() => setOpen(true)}>
|
||||
<InnovenergyButton type="submit" onClick={() => setOpen(true)}>
|
||||
<FormattedMessage id="grantAccess" defaultMessage="Grant access" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -10,13 +10,13 @@ import { Fragment, useContext, useEffect } from "react";
|
|||
import axiosConfig from "../../../config/axiosConfig";
|
||||
import PersonRemoveIcon from "@mui/icons-material/PersonRemove";
|
||||
import PersonIcon from "@mui/icons-material/Person";
|
||||
import { UserContext } from "../../Context/UserContextProvider";
|
||||
import { UsersContext } from "../../Context/UsersContextProvider";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||
|
||||
const UsersWithDirectAccess = () => {
|
||||
const { fetchUsersWithDirectAccessForResource, directAccessUsers } =
|
||||
useContext(UserContext);
|
||||
useContext(UsersContext);
|
||||
const { currentType } = useContext(GroupContext);
|
||||
const { id } = useParams();
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ import {
|
|||
} from "../../../util/user.util";
|
||||
import routes from "../../../routes.json";
|
||||
import PersonIcon from "@mui/icons-material/Person";
|
||||
import { UserContext } from "../../Context/UserContextProvider";
|
||||
import { UsersContext } from "../../Context/UsersContextProvider";
|
||||
|
||||
const UsersWithInheritedAccess = () => {
|
||||
const { fetchUsersWithInheritedAccessForResource, inheritedAccessUsers } =
|
||||
useContext(UserContext);
|
||||
useContext(UsersContext);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUsersWithInheritedAccessForResource();
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { Button, Dialog, DialogContent, DialogTitle } from "@mui/material";
|
||||
import { Dialog, DialogContent, DialogTitle, IconButton } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { I_Folder } from "../../util/types";
|
||||
import FolderForm from "./FolderForm";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||
|
||||
interface AddNewDialogProps {
|
||||
values: I_Folder;
|
||||
|
@ -13,17 +15,22 @@ const AddNewDialog = (props: AddNewDialogProps) => {
|
|||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleSubmit = (data: I_Folder, childData: Partial<I_Folder>) => {
|
||||
return axiosConfig.post("/CreateFolder", {
|
||||
return axiosConfig
|
||||
.post("/CreateFolder", {
|
||||
...childData,
|
||||
parentId: data.id,
|
||||
})
|
||||
.then((res) => {
|
||||
setOpen(false);
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button variant="outlined" sx={{ ml: 2 }} onClick={() => setOpen(true)}>
|
||||
<InnovenergyButton sx={{ ml: 2 }} onClick={() => setOpen(true)}>
|
||||
<FormattedMessage id="addNewChild" defaultMessage="Add new child" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
<Dialog
|
||||
onClose={() => setOpen(false)}
|
||||
aria-labelledby="customized-dialog-title"
|
||||
|
@ -33,8 +40,25 @@ const AddNewDialog = (props: AddNewDialogProps) => {
|
|||
maxHeight: 500,
|
||||
}}
|
||||
scroll="paper"
|
||||
fullWidth
|
||||
maxWidth="sm"
|
||||
>
|
||||
<DialogTitle>Create new folder</DialogTitle>
|
||||
<DialogTitle>
|
||||
Create new folder
|
||||
<IconButton
|
||||
edge="start"
|
||||
color="inherit"
|
||||
onClick={() => setOpen(false)}
|
||||
aria-label="close"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
right: 8,
|
||||
top: 8,
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<FolderForm values={props.values} handleSubmit={handleSubmit} />
|
||||
</DialogContent>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Button, CircularProgress, Grid } from "@mui/material";
|
||||
import { CircularProgress, Grid } from "@mui/material";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { useFormik } from "formik";
|
||||
import { ReactNode, useContext, useState } from "react";
|
||||
|
@ -6,6 +6,7 @@ import { FormattedMessage, useIntl } from "react-intl";
|
|||
import { I_Folder } from "../../util/types";
|
||||
import { GroupContext } from "../Context/GroupContextProvider";
|
||||
import InnovenergySnackbar from "../InnovenergySnackbar";
|
||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||
import InnovenergyTextfield from "../Layout/InnovenergyTextfield";
|
||||
|
||||
interface I_CustomerFormProps {
|
||||
|
@ -28,8 +29,9 @@ const FolderForm = (props: I_CustomerFormProps) => {
|
|||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
name: values.name,
|
||||
information: values.information,
|
||||
name: additionalButtons && additionalButtons.length ? values.name : "",
|
||||
information:
|
||||
additionalButtons && additionalButtons.length ? values.information : "",
|
||||
},
|
||||
onSubmit: (formikValues) => {
|
||||
setLoading(true);
|
||||
|
@ -73,9 +75,9 @@ const FolderForm = (props: I_CustomerFormProps) => {
|
|||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||
{loading && <CircularProgress />}
|
||||
{additionalButtons && additionalButtons.map((button) => button)}
|
||||
<Button variant="outlined" type="submit" sx={{ ml: 2 }}>
|
||||
<InnovenergyButton type="submit" sx={{ ml: 2 }}>
|
||||
<FormattedMessage id="submit" defaultMessage="Submit" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
</Grid>
|
||||
<InnovenergySnackbar
|
||||
error={error}
|
||||
|
|
|
@ -9,15 +9,17 @@ import { AntTabs, StyledTab } from "../../util/installation.util";
|
|||
|
||||
const GroupTabs = () => {
|
||||
const routeMatch = useRouteMatch([
|
||||
routes.groups + routes.folder + ":id",
|
||||
routes.groups + routes.manageAccess + ":id",
|
||||
routes.groups + routes.installation + ":id",
|
||||
routes.installations + routes.tree + routes.folder + ":id",
|
||||
routes.installations + routes.tree + routes.manageAccess + ":id",
|
||||
routes.installations + routes.tree + routes.installation + ":id",
|
||||
]);
|
||||
|
||||
const id = routeMatch?.params?.id;
|
||||
const intl = useIntl();
|
||||
const { currentType } = useContext(GroupContext);
|
||||
|
||||
console.log(routeMatch);
|
||||
|
||||
if (id) {
|
||||
return (
|
||||
<Box sx={{ width: "100%" }}>
|
||||
|
@ -32,7 +34,9 @@ const GroupTabs = () => {
|
|||
id: "folder",
|
||||
defaultMessage: "Folder",
|
||||
})}
|
||||
value={routes.groups + routes.folder + ":id"}
|
||||
value={
|
||||
routes.installations + routes.tree + routes.folder + ":id"
|
||||
}
|
||||
component={Link}
|
||||
to={routes.folder + id}
|
||||
/>
|
||||
|
@ -42,7 +46,12 @@ const GroupTabs = () => {
|
|||
id: "installation",
|
||||
defaultMessage: "Installation",
|
||||
})}
|
||||
value={routes.groups + routes.installation + ":id"}
|
||||
value={
|
||||
routes.installations +
|
||||
routes.tree +
|
||||
routes.installation +
|
||||
":id"
|
||||
}
|
||||
component={Link}
|
||||
to={routes.installation + id}
|
||||
/>
|
||||
|
@ -53,7 +62,9 @@ const GroupTabs = () => {
|
|||
id: "manageAccess",
|
||||
defaultMessage: "Manage access",
|
||||
})}
|
||||
value={routes.groups + routes.manageAccess + ":id"}
|
||||
value={
|
||||
routes.installations + routes.tree + routes.manageAccess + ":id"
|
||||
}
|
||||
component={Link}
|
||||
to={routes.manageAccess + id}
|
||||
/>
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
import { Grid } from "@mui/material";
|
||||
import { Container } from "@mui/system";
|
||||
import { Routes, Route } from "react-router";
|
||||
import routes from "../../routes.json";
|
||||
import Folder from "./Folder";
|
||||
import GroupTabs from "./GroupTabs";
|
||||
import GroupContextProvider from "../Context/GroupContextProvider";
|
||||
import GroupTree from "./Tree/GroupTree";
|
||||
import NavigationButtons from "../Layout/NavigationButtons";
|
||||
import AccessManagement from "./AccessManagement/AccessManagement";
|
||||
import { I_Installation } from "../../util/types";
|
||||
import InstallationForm from "../Installations/InstallationForm";
|
||||
import Detail from "../Layout/Detail";
|
||||
import Installation from "../Installations/Installation";
|
||||
|
||||
const Groups = () => {
|
||||
return (
|
||||
|
@ -29,12 +25,7 @@ const Groups = () => {
|
|||
/>
|
||||
<Route
|
||||
path={routes.installation + ":id"}
|
||||
element={
|
||||
<Detail<I_Installation>
|
||||
route="/GetInstallationById?id="
|
||||
formComponent={InstallationForm}
|
||||
/>
|
||||
}
|
||||
element={<Installation hasMoveButton />}
|
||||
/>
|
||||
</Routes>
|
||||
</Grid>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Button, Grid, InputLabel } from "@mui/material";
|
||||
import { Grid, InputLabel } from "@mui/material";
|
||||
import { useContext, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useParams } from "react-router-dom";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { GroupContext } from "../Context/GroupContextProvider";
|
||||
import MoveTree from "./Tree/MoveTree";
|
||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||
|
||||
interface LocationFormProps {
|
||||
parentId: number;
|
||||
|
@ -39,13 +39,9 @@ const LocationForm = (props: LocationFormProps) => {
|
|||
</Grid>
|
||||
<Grid item xs={9} display="inline"></Grid>
|
||||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
sx={{ height: 40, ml: 2 }}
|
||||
onClick={handleMove}
|
||||
>
|
||||
<InnovenergyButton sx={{ height: 40, ml: 2 }} onClick={handleMove}>
|
||||
<FormattedMessage id="move" defaultMessage="Move" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
|
|
@ -19,14 +19,6 @@ const GroupTree = () => {
|
|||
fetchData();
|
||||
}, [fetchData]);
|
||||
|
||||
/* useEffect(() => {
|
||||
if (id) {
|
||||
setSelected(
|
||||
currentType === "Folder" ? "Folder" + id : "Installation" + id
|
||||
);
|
||||
}
|
||||
}, [id, currentType]); */
|
||||
|
||||
const getNodes = (element: I_Folder | I_Installation): null | ReactNode => {
|
||||
if (instanceOfFolder(element)) {
|
||||
return element.children ? renderTree(element.children) : null;
|
||||
|
@ -55,6 +47,9 @@ const GroupTree = () => {
|
|||
nodeId={element.type + element.id}
|
||||
label={element.name}
|
||||
onClick={() => setCurrentType(element.type)}
|
||||
sx={{
|
||||
".MuiTreeItem-content": { paddingY: "12px" },
|
||||
}}
|
||||
>
|
||||
{getNodes(element)}
|
||||
</TreeItem>
|
||||
|
@ -75,7 +70,12 @@ const GroupTree = () => {
|
|||
aria-label="rich object"
|
||||
defaultCollapseIcon={<ExpandMoreIcon />}
|
||||
defaultExpandIcon={<ChevronRightIcon />}
|
||||
sx={{ height: 300, flexGrow: 1, maxWidth: 400 }}
|
||||
sx={{
|
||||
height: 480,
|
||||
flexGrow: 1,
|
||||
overflow: "auto",
|
||||
".MuiTreeView-root": { overflowX: "hidden" },
|
||||
}}
|
||||
expanded={openNodes}
|
||||
onNodeToggle={(e, ids) => {
|
||||
setOpenNodes(ids);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Button, DialogActions, Dialog, DialogTitle } from "@mui/material";
|
||||
import { DialogActions, Dialog, DialogTitle } from "@mui/material";
|
||||
import DialogContent from "@mui/material/DialogContent";
|
||||
import { useContext, useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
@ -6,6 +6,7 @@ import { useParams } from "react-router-dom";
|
|||
import axiosConfig from "../../../config/axiosConfig";
|
||||
import { I_Folder } from "../../../util/types";
|
||||
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||
import InnovenergyButton from "../../Layout/InnovenergyButton";
|
||||
import MoveTree from "./MoveTree";
|
||||
|
||||
interface MoveDialogProps {
|
||||
|
@ -37,9 +38,9 @@ const MoveDialog = (props: MoveDialogProps) => {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<Button variant="outlined" onClick={() => setOpen(true)}>
|
||||
<InnovenergyButton onClick={() => setOpen(true)} sx={{ mr: 1 }}>
|
||||
<FormattedMessage id="move" defaultMessage="Move" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
<Dialog
|
||||
onClose={() => setOpen(false)}
|
||||
aria-labelledby="customized-dialog-title"
|
||||
|
@ -58,9 +59,7 @@ const MoveDialog = (props: MoveDialogProps) => {
|
|||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button autoFocus onClick={handleMove}>
|
||||
Move
|
||||
</Button>
|
||||
<InnovenergyButton onClick={handleMove}>Move</InnovenergyButton>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
import { Alert, Box, CircularProgress } from "@mui/material";
|
||||
import { AxiosError } from "axios";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { I_Installation } from "../../util/types";
|
||||
import InstallationForm from "./InstallationForm";
|
||||
|
||||
interface I_InstallationProps {
|
||||
hasMoveButton?: boolean;
|
||||
}
|
||||
const Installation = (props: I_InstallationProps) => {
|
||||
const { id } = useParams();
|
||||
const [values, setValues] = useState<I_Installation>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<AxiosError>();
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
axiosConfig
|
||||
.get("/GetInstallationById?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 }}>
|
||||
<InstallationForm
|
||||
values={values}
|
||||
id={id}
|
||||
hasMoveButton={props.hasMoveButton}
|
||||
/>
|
||||
</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 Installation;
|
|
@ -1,21 +1,25 @@
|
|||
import { Alert, Button, Grid, Snackbar } from "@mui/material";
|
||||
import { Alert, Grid, Snackbar } from "@mui/material";
|
||||
import { useFormik } from "formik";
|
||||
import { useState } from "react";
|
||||
import { useContext, useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { I_Installation } from "../../util/types";
|
||||
import { InstallationContext } from "../Context/InstallationContextProvider";
|
||||
import MoveDialog from "../Groups/Tree/MoveDialog";
|
||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||
import InnovenergyTextfield from "../Layout/InnovenergyTextfield";
|
||||
|
||||
interface I_InstallationFormProps {
|
||||
values: I_Installation;
|
||||
id: string | undefined;
|
||||
hasMoveButton?: boolean;
|
||||
}
|
||||
const InstallationForm = (props: I_InstallationFormProps) => {
|
||||
const { values, id } = props;
|
||||
const { values, id, hasMoveButton } = props;
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const intl = useIntl();
|
||||
const { fetchData } = useContext(InstallationContext);
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
|
@ -33,6 +37,7 @@ const InstallationForm = (props: I_InstallationFormProps) => {
|
|||
})
|
||||
.then(() => {
|
||||
setOpen(true);
|
||||
fetchData();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
@ -94,10 +99,10 @@ const InstallationForm = (props: I_InstallationFormProps) => {
|
|||
handleChange={formik.handleChange}
|
||||
/>
|
||||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||
<MoveDialog values={values} />
|
||||
<Button variant="outlined" type="submit">
|
||||
{hasMoveButton && <MoveDialog values={values} />}
|
||||
<InnovenergyButton type="submit">
|
||||
<FormattedMessage id="applyChanges" defaultMessage="Apply changes" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
</Grid>
|
||||
<Snackbar
|
||||
open={open}
|
||||
|
|
|
@ -41,9 +41,9 @@ const InstallationList = (props: InstallationListProps) => {
|
|||
const filteredData = filterData(props.searchQuery, data);
|
||||
|
||||
const routeMatch = useRouteMatch([
|
||||
routes.installations + routes.installation + ":id",
|
||||
routes.installations + routes.alarms + ":id",
|
||||
routes.installations + routes.log + ":id",
|
||||
routes.installations + routes.list + routes.installation + ":id",
|
||||
routes.installations + routes.list + routes.alarms + ":id",
|
||||
routes.installations + routes.list + routes.log + ":id",
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -95,7 +95,6 @@ const InstallationList = (props: InstallationListProps) => {
|
|||
</List>
|
||||
);
|
||||
} else if (error) {
|
||||
console.log(error);
|
||||
return (
|
||||
<Alert severity="error" sx={{ mt: 1 }}>
|
||||
{error.message}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
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, Routes } from "react-router-dom";
|
||||
import { Link } from "react-router-dom";
|
||||
import routes from "../../routes.json";
|
||||
import useRouteMatch from "../../hooks/useRouteMatch";
|
||||
import { useIntl } from "react-intl";
|
||||
import { styled } from "@mui/material";
|
||||
import { AntTabs, StyledTab } from "../../util/installation.util";
|
||||
|
||||
const InstallationTabs = () => {
|
||||
|
@ -25,7 +22,7 @@ const InstallationTabs = () => {
|
|||
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
|
||||
<AntTabs
|
||||
value={routeMatch?.pattern?.path ?? routes.installation + ":id"}
|
||||
aria-label="basic tabs example"
|
||||
aria-label="installation tabs"
|
||||
>
|
||||
<StyledTab
|
||||
label={intl.formatMessage({
|
||||
|
|
|
@ -1,35 +1,27 @@
|
|||
import { Grid } from "@mui/material";
|
||||
import { Container } from "@mui/system";
|
||||
import { Routes, Route } from "react-router";
|
||||
import NavigationButtons from "../Layout/NavigationButtons";
|
||||
import Sidebar from "../Layout/Sidebar";
|
||||
import Alarms from "./Alarms";
|
||||
import InstallationTabs from "./InstallationTabs";
|
||||
import Log from "./Log";
|
||||
import routes from "../../routes.json";
|
||||
import InstallationContextProvider from "../Context/InstallationContextProvider";
|
||||
import Detail from "../Layout/Detail";
|
||||
import { I_Installation } from "../../util/types";
|
||||
import InstallationForm from "./InstallationForm";
|
||||
import SearchSidebar from "../Layout/Search";
|
||||
import InstallationList from "./InstallationList";
|
||||
import Installation from "./Installation";
|
||||
|
||||
const Installations = () => {
|
||||
return (
|
||||
<InstallationContextProvider>
|
||||
<Grid container spacing={2}>
|
||||
<Grid item xs={3}>
|
||||
<Sidebar />
|
||||
<SearchSidebar listComponent={InstallationList} />
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<InstallationTabs />
|
||||
<Routes>
|
||||
<Route
|
||||
path={routes.installation + ":id"}
|
||||
element={
|
||||
<Detail<I_Installation>
|
||||
route="/GetInstallationById?id="
|
||||
formComponent={InstallationForm}
|
||||
/>
|
||||
}
|
||||
element={<Installation />}
|
||||
index
|
||||
/>
|
||||
<Route path={routes.alarms + ":id"} element={<Alarms />} />
|
||||
|
|
|
@ -149,7 +149,6 @@ const Log = () => {
|
|||
return previous;
|
||||
}, {});
|
||||
|
||||
console.log(flattenObject(foo.Devices[0]));
|
||||
return <div>log</div>;
|
||||
};
|
||||
|
||||
|
|
|
@ -6,14 +6,16 @@ import axiosConfig from "../../config/axiosConfig";
|
|||
export interface I_FormProps<T> {
|
||||
values: T;
|
||||
id: string;
|
||||
hasMoveButton?: boolean;
|
||||
}
|
||||
interface I_DetailProps<T> {
|
||||
formComponent: FC<I_FormProps<T>>;
|
||||
route: string;
|
||||
hasMoveButton?: boolean;
|
||||
}
|
||||
const Detail = <T extends { id: number }>(props: I_DetailProps<T>) => {
|
||||
const { id } = useParams();
|
||||
const { formComponent: FormComponent, route } = props;
|
||||
const { formComponent: FormComponent, route, hasMoveButton } = props;
|
||||
const [values, setValues] = useState<T>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<AxiosError>();
|
||||
|
@ -33,7 +35,9 @@ const Detail = <T extends { id: number }>(props: I_DetailProps<T>) => {
|
|||
}, [id, route]);
|
||||
|
||||
if (values && values.id && values.id.toString() === id) {
|
||||
return <FormComponent values={values} id={id} />;
|
||||
return (
|
||||
<FormComponent values={values} id={id} hasMoveButton={hasMoveButton} />
|
||||
);
|
||||
} else if (loading) {
|
||||
return (
|
||||
<Box
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import { Button, SxProps, Theme } from "@mui/material";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
interface I_InnovenergyButtonProps {
|
||||
children?: ReactNode;
|
||||
type?: "button" | "submit" | "reset" | undefined;
|
||||
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
sx?: SxProps<Theme> | undefined;
|
||||
}
|
||||
|
||||
const InnovenergyButton = (props: I_InnovenergyButtonProps) => {
|
||||
return (
|
||||
<Button
|
||||
variant="contained"
|
||||
type={props.type}
|
||||
onClick={props.onClick}
|
||||
sx={props.sx}
|
||||
>
|
||||
{props.children}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default InnovenergyButton;
|
|
@ -1,7 +1,7 @@
|
|||
import { Button } from "@mui/material";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import InnovenergyButton from "./InnovenergyButton";
|
||||
|
||||
interface LogoutButtonProps {
|
||||
removeToken: () => void;
|
||||
|
@ -10,8 +10,7 @@ const LogoutButton = (props: LogoutButtonProps) => {
|
|||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="outlined"
|
||||
<InnovenergyButton
|
||||
onClick={() => {
|
||||
axiosConfig.post("/Logout").then(() => {
|
||||
navigate("/");
|
||||
|
@ -21,7 +20,7 @@ const LogoutButton = (props: LogoutButtonProps) => {
|
|||
sx={{ mx: 1 }}
|
||||
>
|
||||
<FormattedMessage id="logout" defaultMessage="Logout" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import useRouteMatch from "../../hooks/useRouteMatch";
|
|||
import routes from "../../routes.json";
|
||||
import ListIcon from "@mui/icons-material/List";
|
||||
import AccountTreeIcon from "@mui/icons-material/AccountTree";
|
||||
import { AntTabs, StyledTab } from "../../util/installation.util";
|
||||
import { ToggleButtonGroup, ToggleButton } from "@mui/material";
|
||||
|
||||
const ModeButtons = () => {
|
||||
const routeMatch = useRouteMatch([
|
||||
|
@ -13,7 +13,7 @@ const ModeButtons = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<AntTabs
|
||||
{/* <AntTabs
|
||||
value={routeMatch?.pattern?.path ?? routes.installation + ":id"}
|
||||
aria-label="basic tabs example"
|
||||
>
|
||||
|
@ -29,8 +29,8 @@ const ModeButtons = () => {
|
|||
component={Link}
|
||||
to={routes.tree}
|
||||
/>
|
||||
</AntTabs>
|
||||
{/* <ToggleButtonGroup
|
||||
</AntTabs> */}
|
||||
<ToggleButtonGroup
|
||||
color="primary"
|
||||
value={routeMatch?.pattern?.path}
|
||||
exclusive
|
||||
|
@ -51,7 +51,7 @@ const ModeButtons = () => {
|
|||
>
|
||||
<AccountTreeIcon />
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup> */}
|
||||
</ToggleButtonGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { ToggleButton, ToggleButtonGroup } from "@mui/material";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { Link } from "react-router-dom";
|
||||
import useRouteMatch from "../../hooks/useRouteMatch";
|
||||
import routes from "../../routes.json";
|
||||
import { AntTabs, StyledTab } from "../../util/installation.util";
|
||||
|
||||
const NavigationButtons = () => {
|
||||
const routeMatch = useRouteMatch([
|
||||
|
@ -11,7 +11,8 @@ const NavigationButtons = () => {
|
|||
]);
|
||||
|
||||
return (
|
||||
<ToggleButtonGroup
|
||||
<>
|
||||
{/* <ToggleButtonGroup
|
||||
color="primary"
|
||||
value={routeMatch?.pattern?.path}
|
||||
exclusive
|
||||
|
@ -32,7 +33,30 @@ const NavigationButtons = () => {
|
|||
>
|
||||
<FormattedMessage id="users" defaultMessage="Users" />
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
</ToggleButtonGroup> */}
|
||||
<AntTabs
|
||||
value={routeMatch?.pattern?.path}
|
||||
aria-label="basic tabs example"
|
||||
>
|
||||
<StyledTab
|
||||
value={routes.installations + "*"}
|
||||
component={Link}
|
||||
to={routes.installations + routes.list}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id="installations"
|
||||
defaultMessage="Installations"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<StyledTab
|
||||
value={routes.users + "*"}
|
||||
component={Link}
|
||||
to={routes.users}
|
||||
label={<FormattedMessage id="users" defaultMessage="Users" />}
|
||||
/>
|
||||
</AntTabs>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import { TextField } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { FC, useState } from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
import InstallationList from "../Installations/InstallationList";
|
||||
|
||||
const Sidebar = () => {
|
||||
interface SearchSidebarProps {
|
||||
listComponent: FC<{ searchQuery: string }>;
|
||||
}
|
||||
const SearchSidebar = (props: SearchSidebarProps) => {
|
||||
const { listComponent: ListComponent } = props;
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const intl = useIntl();
|
||||
|
||||
|
@ -20,10 +23,9 @@ const Sidebar = () => {
|
|||
value={searchQuery}
|
||||
onChange={(e) => setSearchQuery(e.target.value)}
|
||||
/>
|
||||
|
||||
<InstallationList searchQuery={searchQuery} />
|
||||
<ListComponent searchQuery={searchQuery} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
export default SearchSidebar;
|
|
@ -0,0 +1,61 @@
|
|||
import { Dialog, DialogTitle, IconButton, DialogContent } from "@mui/material";
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { I_User } from "../../util/user.util";
|
||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import UserForm from "./UserForm";
|
||||
|
||||
const AddUser = () => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleSubmit = (data: Partial<I_User>) => {
|
||||
return axiosConfig.post("/CreateUser", data).then((res) => {
|
||||
setOpen(false);
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<InnovenergyButton sx={{ my: 1 }} onClick={() => setOpen(true)}>
|
||||
<FormattedMessage id="addNewChild" defaultMessage="Add user" />
|
||||
</InnovenergyButton>
|
||||
<Dialog
|
||||
onClose={() => setOpen(false)}
|
||||
aria-labelledby="customized-dialog-title"
|
||||
open={open}
|
||||
sx={{
|
||||
".MuiDialogContent-root": { overflowX: "hidden" },
|
||||
maxHeight: 500,
|
||||
}}
|
||||
scroll="paper"
|
||||
fullWidth
|
||||
maxWidth="sm"
|
||||
>
|
||||
<DialogTitle>
|
||||
Create new user
|
||||
<IconButton
|
||||
edge="start"
|
||||
color="inherit"
|
||||
onClick={() => setOpen(false)}
|
||||
aria-label="close"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
right: 8,
|
||||
top: 8,
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<UserForm handleSubmit={handleSubmit} />
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddUser;
|
|
@ -0,0 +1,59 @@
|
|||
import { Box, CircularProgress, Alert } from "@mui/material";
|
||||
import { AxiosError } from "axios";
|
||||
import { useState, useEffect, FC } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { I_User } from "../../util/user.util";
|
||||
import UserForm from "./UserForm";
|
||||
|
||||
interface I_DetailProps<T> {
|
||||
hasMoveButton?: boolean;
|
||||
}
|
||||
const Detail = <T extends { id: number }>(props: I_DetailProps<T>) => {
|
||||
const { id } = useParams();
|
||||
const [values, setValues] = useState<I_User>();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<AxiosError>();
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
axiosConfig
|
||||
.get("/GetUserById?id=" + id)
|
||||
.then((res) => {
|
||||
setValues(res.data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
setError(err);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [id]);
|
||||
|
||||
const handleUpdate = (formikValues: Partial<I_User>) => {
|
||||
return axiosConfig.put("/UpdateUser", {
|
||||
...formikValues,
|
||||
id: id,
|
||||
});
|
||||
};
|
||||
|
||||
if (values && values.id && values.id.toString() === id) {
|
||||
return <UserForm values={values} handleSubmit={handleUpdate} />;
|
||||
} 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 Detail;
|
|
@ -1,33 +1,29 @@
|
|||
import { Alert, Button, Grid, Snackbar } from "@mui/material";
|
||||
import { Alert, Grid, Snackbar } from "@mui/material";
|
||||
import { AxiosResponse } from "axios";
|
||||
import { useFormik } from "formik";
|
||||
import { useState } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
import axiosConfig from "../../config/axiosConfig";
|
||||
import { I_User } from "../../util/user.util";
|
||||
import InnovenergyButton from "../Layout/InnovenergyButton";
|
||||
import InnovenergyTextfield from "../Layout/InnovenergyTextfield";
|
||||
|
||||
interface I_UserFormProps {
|
||||
values: I_User;
|
||||
id: string;
|
||||
handleSubmit: (formikValues: Partial<I_User>) => Promise<AxiosResponse>;
|
||||
values?: I_User;
|
||||
}
|
||||
const UserForm = (props: I_UserFormProps) => {
|
||||
const { values, id } = props;
|
||||
const { values, handleSubmit } = props;
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const intl = useIntl();
|
||||
|
||||
const formik = useFormik({
|
||||
initialValues: {
|
||||
email: values.email,
|
||||
information: values.information,
|
||||
email: values ? values.email : "",
|
||||
information: values ? values.information : "",
|
||||
},
|
||||
onSubmit: (formikValues) => {
|
||||
axiosConfig
|
||||
.put("/UpdateUser", {
|
||||
...formikValues,
|
||||
id: id,
|
||||
})
|
||||
.then(() => {
|
||||
handleSubmit(formikValues).then(() => {
|
||||
setOpen(true);
|
||||
});
|
||||
},
|
||||
|
@ -60,9 +56,9 @@ const UserForm = (props: I_UserFormProps) => {
|
|||
handleChange={formik.handleChange}
|
||||
/>
|
||||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||
<Button variant="outlined" type="submit">
|
||||
<InnovenergyButton type="submit">
|
||||
<FormattedMessage id="applyChanges" defaultMessage="Apply changes" />
|
||||
</Button>
|
||||
</InnovenergyButton>
|
||||
</Grid>
|
||||
<Snackbar
|
||||
open={open}
|
||||
|
|
|
@ -6,8 +6,8 @@ import { Link } from "react-router-dom";
|
|||
import useRouteMatch from "../../hooks/useRouteMatch";
|
||||
import routes from "../../routes.json";
|
||||
import { Fragment, useContext } from "react";
|
||||
import { I_Installation } from "../../util/types";
|
||||
import { UserContext } from "../Context/UserContextProvider";
|
||||
import { UsersContext } from "../Context/UsersContextProvider";
|
||||
import { I_User } from "../../util/user.util";
|
||||
|
||||
const getPathWithoutId = (path?: string) => {
|
||||
if (path) {
|
||||
|
@ -17,26 +17,26 @@ const getPathWithoutId = (path?: string) => {
|
|||
return routes.user;
|
||||
};
|
||||
|
||||
const filterData = (
|
||||
searchQuery: string,
|
||||
data: I_Installation[] | undefined
|
||||
) => {
|
||||
const filterData = (searchQuery: string, data: I_User[] | undefined) => {
|
||||
if (data) {
|
||||
return data.filter(
|
||||
(installation) =>
|
||||
installation.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
installation.location.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
return data.filter((installation) =>
|
||||
installation.name.toLowerCase().includes(searchQuery.toLowerCase())
|
||||
);
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
const UserList = () => {
|
||||
const { availableUsers } = useContext(UserContext);
|
||||
interface UserListProps {
|
||||
searchQuery: string;
|
||||
}
|
||||
|
||||
const UserList = (props: UserListProps) => {
|
||||
const { availableUsers } = useContext(UsersContext);
|
||||
const filteredData = filterData(props.searchQuery, availableUsers);
|
||||
|
||||
const routeMatch = useRouteMatch([routes.users + routes.user + ":id"]);
|
||||
|
||||
if (availableUsers && availableUsers.length) {
|
||||
if (filteredData && filteredData.length) {
|
||||
return (
|
||||
<List
|
||||
sx={{
|
||||
|
@ -51,7 +51,7 @@ const UserList = () => {
|
|||
component="nav"
|
||||
aria-labelledby="nested-list-subheader"
|
||||
>
|
||||
{availableUsers.map((user) => {
|
||||
{filteredData.map((user) => {
|
||||
return (
|
||||
<Fragment key={user.id}>
|
||||
<Link
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
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";
|
||||
import { AntTabs, StyledTab } from "../../util/installation.util";
|
||||
|
||||
const UserTabs = () => {
|
||||
const routeMatch = useRouteMatch([routes.users + routes.user + ":id"]);
|
||||
|
@ -17,11 +16,11 @@ const UserTabs = () => {
|
|||
return (
|
||||
<Box sx={{ width: "100%" }}>
|
||||
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
|
||||
<Tabs
|
||||
<AntTabs
|
||||
value={routeMatch?.pattern?.path ?? routes.user + ":id"}
|
||||
aria-label="basic tabs example"
|
||||
aria-label="user tabs"
|
||||
>
|
||||
<Tab
|
||||
<StyledTab
|
||||
label={intl.formatMessage({
|
||||
id: "user",
|
||||
defaultMessage: "User",
|
||||
|
@ -30,7 +29,7 @@ const UserTabs = () => {
|
|||
component={Link}
|
||||
to={routes.user + id}
|
||||
/>
|
||||
</Tabs>
|
||||
</AntTabs>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
|
|
@ -1,38 +1,29 @@
|
|||
import { Grid } from "@mui/material";
|
||||
import { Container } from "@mui/system";
|
||||
import { Routes, Route } from "react-router";
|
||||
import routes from "../../routes.json";
|
||||
import { I_User } from "../../util/user.util";
|
||||
import UserContextProvider from "../Context/UserContextProvider";
|
||||
import Detail from "../Layout/Detail";
|
||||
import UserForm from "./UserForm";
|
||||
import UsersContextProvider from "../Context/UsersContextProvider";
|
||||
import SearchSidebar from "../Layout/Search";
|
||||
import AddUser from "./AddUser";
|
||||
import User from "./User";
|
||||
import UserList from "./UserList";
|
||||
import UserTabs from "./UserTabs";
|
||||
|
||||
const Users = () => {
|
||||
return (
|
||||
<UserContextProvider>
|
||||
<Grid container spacing={2}>
|
||||
<UsersContextProvider>
|
||||
<Grid container>
|
||||
<Grid item xs={3}>
|
||||
<UserList />
|
||||
<AddUser />
|
||||
<SearchSidebar listComponent={UserList} />
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<UserTabs />
|
||||
<Routes>
|
||||
<Route
|
||||
path={routes.user + ":id"}
|
||||
element={
|
||||
<Detail<I_User>
|
||||
route="/GetUserById?id="
|
||||
formComponent={UserForm}
|
||||
/>
|
||||
}
|
||||
index
|
||||
/>
|
||||
<Route path={routes.user + ":id"} element={<User />} />
|
||||
</Routes>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserContextProvider>
|
||||
</UsersContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,6 @@
|
|||
"updatedSuccessfully": "Updated successfully",
|
||||
"groups": "Groups",
|
||||
"group": "Group",
|
||||
"folder": "folder",
|
||||
"folder": "Folder",
|
||||
"updateFolderErrorMessage": "Couldn't update folder, an error occured"
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ export const StyledTab = styled((props: any) => (
|
|||
fontWeight: theme.typography.fontWeightRegular,
|
||||
fontSize: theme.typography.pxToRem(15),
|
||||
marginRight: theme.spacing(1),
|
||||
color: "#0d6efd",
|
||||
background: "0 0",
|
||||
border: "1px solid transparent",
|
||||
borderTopLeftRadius: "0.25rem",
|
||||
|
@ -19,7 +18,7 @@ export const StyledTab = styled((props: any) => (
|
|||
color: "#495057",
|
||||
backgroundColor: "#fff",
|
||||
borderColor: "#dee2e6 #dee2e6 #fff",
|
||||
marginBottom: "-2px",
|
||||
marginBottom: "-3px",
|
||||
},
|
||||
"&.Mui-focusVisible": {
|
||||
backgroundColor: "rgba(100, 95, 228, 0.32)",
|
||||
|
@ -28,7 +27,6 @@ export const StyledTab = styled((props: any) => (
|
|||
|
||||
export const AntTabs = styled(Tabs)({
|
||||
borderBottom: "1px solid #dee2e6",
|
||||
|
||||
overflow: "visible!important",
|
||||
"& div.MuiTabs-scroller": {
|
||||
overflow: "visible!important",
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// TODO add if required or not
|
||||
export interface I_Installation {
|
||||
type: string;
|
||||
title: string;
|
||||
status: number;
|
||||
detail: string;
|
||||
instance: string;
|
||||
title?: string;
|
||||
status?: number;
|
||||
detail?: string;
|
||||
instance?: string;
|
||||
location: string;
|
||||
region: string;
|
||||
country: string;
|
||||
|
@ -16,6 +16,7 @@ export interface I_Installation {
|
|||
name: string;
|
||||
information: string;
|
||||
parentId: number;
|
||||
s3Url: string;
|
||||
}
|
||||
|
||||
export interface I_Folder {
|
||||
|
|
Loading…
Reference in New Issue