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