[WIP] add dialog for choosing where to move folder or installation, work on access rights page
This commit is contained in:
parent
05dc389eaf
commit
78b9d22fbd
|
@ -5,7 +5,6 @@ import { useParams } from "react-router-dom";
|
||||||
import axiosConfig from "../../config/axiosConfig";
|
import axiosConfig from "../../config/axiosConfig";
|
||||||
import { I_Installation } from "../../util/types";
|
import { I_Installation } from "../../util/types";
|
||||||
import FolderForm from "./FolderForm";
|
import FolderForm from "./FolderForm";
|
||||||
import LocationForm from "./LocationForm";
|
|
||||||
|
|
||||||
const Folder = () => {
|
const Folder = () => {
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
@ -32,7 +31,6 @@ const Folder = () => {
|
||||||
<>
|
<>
|
||||||
<Box sx={{ py: 3 }}>
|
<Box sx={{ py: 3 }}>
|
||||||
<FolderForm values={values} id={id} />
|
<FolderForm values={values} id={id} />
|
||||||
<LocationForm parentId={values.parentId} />
|
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@ 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 InnovenergyTextfield from "../Layout/InnovenergyTextfield";
|
import InnovenergyTextfield from "../Layout/InnovenergyTextfield";
|
||||||
|
import MoveDialog from "./Tree/MoveDialog";
|
||||||
|
|
||||||
interface I_CustomerFormProps {
|
interface I_CustomerFormProps {
|
||||||
values: I_Folder;
|
values: I_Folder;
|
||||||
|
@ -78,7 +79,8 @@ 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 />}
|
||||||
<Button variant="outlined" type="submit" sx={{ height: 40, ml: 2 }}>
|
<MoveDialog values={values} />
|
||||||
|
<Button variant="outlined" type="submit" sx={{ ml: 2 }}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="applyChanges"
|
id="applyChanges"
|
||||||
defaultMessage="Apply changes"
|
defaultMessage="Apply changes"
|
||||||
|
|
|
@ -37,12 +37,7 @@ const LocationForm = (props: LocationFormProps) => {
|
||||||
<FormattedMessage id="location" defaultMessage="Location" />
|
<FormattedMessage id="location" defaultMessage="Location" />
|
||||||
</InputLabel>
|
</InputLabel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={9} display="inline">
|
<Grid item xs={9} display="inline"></Grid>
|
||||||
<MoveTree
|
|
||||||
setSelectedParentId={setSelectedParentId}
|
|
||||||
parentId={selectedParentId}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
<Grid container justifyContent="flex-end" sx={{ pt: 1 }}>
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { Button, DialogActions, Dialog, DialogTitle } from "@mui/material";
|
||||||
|
import DialogContent from "@mui/material/DialogContent";
|
||||||
|
import { useContext, useState } from "react";
|
||||||
|
import { FormattedMessage } from "react-intl";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import axiosConfig from "../../../config/axiosConfig";
|
||||||
|
import { I_Folder } from "../../../util/types";
|
||||||
|
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||||
|
import MoveTree from "./MoveTree";
|
||||||
|
|
||||||
|
interface MoveDialogProps {
|
||||||
|
values: I_Folder;
|
||||||
|
}
|
||||||
|
const MoveDialog = (props: MoveDialogProps) => {
|
||||||
|
const { values } = props;
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [selectedParentId, setSelectedParentId] = useState<number>(
|
||||||
|
values.parentId
|
||||||
|
);
|
||||||
|
const { fetchData, currentType } = useContext(GroupContext);
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
const handleMove = () => {
|
||||||
|
const route =
|
||||||
|
currentType === "Folder" ? "/MoveFolder" : "/MoveInstallation";
|
||||||
|
const paramsProp = currentType === "Folder" ? "folderId" : "installationId";
|
||||||
|
axiosConfig
|
||||||
|
.put(route, null, {
|
||||||
|
params: { [paramsProp]: id, parentId: selectedParentId },
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
setOpen(false);
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Button variant="outlined" onClick={() => setOpen(true)}>
|
||||||
|
<FormattedMessage id="move" defaultMessage="Move" />
|
||||||
|
</Button>
|
||||||
|
<Dialog
|
||||||
|
onClose={() => setOpen(false)}
|
||||||
|
aria-labelledby="customized-dialog-title"
|
||||||
|
open={open}
|
||||||
|
sx={{
|
||||||
|
".MuiDialogContent-root": { overflowX: "hidden" },
|
||||||
|
maxHeight: 500,
|
||||||
|
}}
|
||||||
|
scroll="paper"
|
||||||
|
>
|
||||||
|
<DialogTitle>Move to</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<MoveTree
|
||||||
|
parentId={selectedParentId}
|
||||||
|
setSelectedParentId={setSelectedParentId}
|
||||||
|
/>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleMove}>
|
||||||
|
Move
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MoveDialog;
|
|
@ -45,7 +45,6 @@ const MoveTree = (props: MoveTreeProps) => {
|
||||||
defaultCollapseIcon={<ExpandMoreIcon />}
|
defaultCollapseIcon={<ExpandMoreIcon />}
|
||||||
defaultExpandIcon={<ChevronRightIcon />}
|
defaultExpandIcon={<ChevronRightIcon />}
|
||||||
sx={{
|
sx={{
|
||||||
height: 200,
|
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
width: 400,
|
width: 400,
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
import {
|
import { Autocomplete, Button, Grid, TextField } from "@mui/material";
|
||||||
Autocomplete,
|
|
||||||
Button,
|
|
||||||
CircularProgress,
|
|
||||||
Grid,
|
|
||||||
TextField,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { useContext, useEffect, useState } from "react";
|
import { useContext, useEffect, 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";
|
||||||
|
@ -12,10 +6,6 @@ import axiosConfig from "../../../config/axiosConfig";
|
||||||
import { User } from "../../../util/user.util";
|
import { User } from "../../../util/user.util";
|
||||||
import { GroupContext } from "../../Context/GroupContextProvider";
|
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||||
|
|
||||||
interface AutoCompleteOption {
|
|
||||||
label: string;
|
|
||||||
id: number;
|
|
||||||
}
|
|
||||||
const AvailableUserList = () => {
|
const AvailableUserList = () => {
|
||||||
const [users, setUsers] = useState<User[]>([]);
|
const [users, setUsers] = useState<User[]>([]);
|
||||||
const [selectedUsers, setSelectedUsers] = useState<User[]>([]);
|
const [selectedUsers, setSelectedUsers] = useState<User[]>([]);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Grid } from "@mui/material";
|
import { Grid } from "@mui/material";
|
||||||
import AvailableUserList from "./AvailableUserList";
|
import AvailableUserList from "./AvailableUserList";
|
||||||
|
import InnovenergyList from "./UserList";
|
||||||
import UsersWithDirectAccess from "./UsersWithDirectAccess";
|
import UsersWithDirectAccess from "./UsersWithDirectAccess";
|
||||||
import UsersWithInheritedAccess from "./UsersWithInheritedAccess";
|
import UsersWithInheritedAccess from "./UsersWithInheritedAccess";
|
||||||
|
|
||||||
|
@ -8,8 +9,12 @@ const Users = () => {
|
||||||
<>
|
<>
|
||||||
<AvailableUserList />
|
<AvailableUserList />
|
||||||
<Grid container sx={{ mt: 1 }}>
|
<Grid container sx={{ mt: 1 }}>
|
||||||
<UsersWithInheritedAccess />
|
<Grid item xs={6}>
|
||||||
<UsersWithDirectAccess />
|
<InnovenergyList>
|
||||||
|
<UsersWithDirectAccess />
|
||||||
|
<UsersWithInheritedAccess />
|
||||||
|
</InnovenergyList>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import {
|
import {
|
||||||
Grid,
|
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Divider,
|
Divider,
|
||||||
IconButton,
|
IconButton,
|
||||||
Avatar,
|
Avatar,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { Fragment, useCallback, useContext, useEffect, useState } from "react";
|
import { Fragment, useCallback, useContext, useEffect, useState } from "react";
|
||||||
import axiosConfig from "../../../config/axiosConfig";
|
import axiosConfig from "../../../config/axiosConfig";
|
||||||
|
@ -14,9 +12,7 @@ import { User } from "../../../util/user.util";
|
||||||
import PersonRemoveIcon from "@mui/icons-material/PersonRemove";
|
import PersonRemoveIcon from "@mui/icons-material/PersonRemove";
|
||||||
import { GroupContext } from "../../Context/GroupContextProvider";
|
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import InnovenergyList from "./UserList";
|
|
||||||
import PersonIcon from "@mui/icons-material/Person";
|
import PersonIcon from "@mui/icons-material/Person";
|
||||||
import { FormattedMessage } from "react-intl";
|
|
||||||
|
|
||||||
const UsersWithDirectAccess = () => {
|
const UsersWithDirectAccess = () => {
|
||||||
const [users, setUsers] = useState<User[]>();
|
const [users, setUsers] = useState<User[]>();
|
||||||
|
@ -26,12 +22,7 @@ const UsersWithDirectAccess = () => {
|
||||||
|
|
||||||
const fetchUsers = useCallback(async () => {
|
const fetchUsers = useCallback(async () => {
|
||||||
axiosConfig
|
axiosConfig
|
||||||
.get(
|
.get("/GetUsersWithDirectAccessTo" + currentType, { params: { id } })
|
||||||
currentType === "Folder"
|
|
||||||
? "/GetUsersWithDirectAccessToFolder"
|
|
||||||
: "/GetUsersWithDirectAccessToInstallation",
|
|
||||||
{ params: { id } }
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setUsers(res.data);
|
setUsers(res.data);
|
||||||
});
|
});
|
||||||
|
@ -39,17 +30,15 @@ const UsersWithDirectAccess = () => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
}, [currentType, fetchUsers, id]);
|
}, [fetchUsers]);
|
||||||
|
|
||||||
const handleIconClick = (userId: number) => {
|
const handleIconClick = (userId: number) => {
|
||||||
const folderId = id ? parseInt(id) : "";
|
const folderId = id ? parseInt(id) : "";
|
||||||
axiosConfig
|
axiosConfig
|
||||||
.post(
|
.post("/RevokeUserAccessTo" + currentType, {
|
||||||
currentType === "Folder"
|
userId: userId,
|
||||||
? "/RevokeUserAccessToFolder"
|
folderId: folderId,
|
||||||
: "/RevokeUserAccessToInstallation",
|
})
|
||||||
{ userId: userId, folderId: folderId }
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
fetchUsers();
|
fetchUsers();
|
||||||
});
|
});
|
||||||
|
@ -57,40 +46,32 @@ const UsersWithDirectAccess = () => {
|
||||||
|
|
||||||
if (users && users.length) {
|
if (users && users.length) {
|
||||||
return (
|
return (
|
||||||
<Grid item xs={6}>
|
<>
|
||||||
<Typography variant="overline" gutterBottom>
|
{users.map((user) => {
|
||||||
<FormattedMessage
|
return (
|
||||||
id="usersWithDirectAccess"
|
<Fragment key={user.id}>
|
||||||
defaultMessage="Users with direct access"
|
<ListItem
|
||||||
/>
|
secondaryAction={
|
||||||
</Typography>
|
<IconButton
|
||||||
<InnovenergyList>
|
onClick={() => handleIconClick(user.id)}
|
||||||
{users.map((user) => {
|
edge="end"
|
||||||
return (
|
>
|
||||||
<Fragment key={user.id}>
|
<PersonRemoveIcon id={user.id.toString()} />
|
||||||
<ListItem
|
</IconButton>
|
||||||
secondaryAction={
|
}
|
||||||
<IconButton
|
>
|
||||||
onClick={() => handleIconClick(user.id)}
|
<ListItemAvatar>
|
||||||
edge="end"
|
<Avatar>
|
||||||
>
|
<PersonIcon />
|
||||||
<PersonRemoveIcon id={user.id.toString()} />
|
</Avatar>
|
||||||
</IconButton>
|
</ListItemAvatar>
|
||||||
}
|
<ListItemText primary={user.name} />
|
||||||
>
|
</ListItem>
|
||||||
<ListItemAvatar>
|
<Divider />
|
||||||
<Avatar>
|
</Fragment>
|
||||||
<PersonIcon />
|
);
|
||||||
</Avatar>
|
})}
|
||||||
</ListItemAvatar>
|
</>
|
||||||
<ListItemText primary={user.name} />
|
|
||||||
</ListItem>
|
|
||||||
<Divider />
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</InnovenergyList>
|
|
||||||
</Grid>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
import {
|
import {
|
||||||
Grid,
|
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Divider,
|
Divider,
|
||||||
ListItemAvatar,
|
ListItemAvatar,
|
||||||
Avatar,
|
Avatar,
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import { Fragment, useContext, useEffect, useState } from "react";
|
import { Fragment, useCallback, useContext, useEffect, useState } from "react";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useParams } from "react-router-dom";
|
||||||
import axiosConfig from "../../../config/axiosConfig";
|
import axiosConfig from "../../../config/axiosConfig";
|
||||||
import { UserWithInheritedAccess } from "../../../util/user.util";
|
import {
|
||||||
|
filterDuplicateUsers,
|
||||||
|
UserWithInheritedAccess,
|
||||||
|
} from "../../../util/user.util";
|
||||||
import { GroupContext } from "../../Context/GroupContextProvider";
|
import { GroupContext } from "../../Context/GroupContextProvider";
|
||||||
import routes from "../../../routes.json";
|
import routes from "../../../routes.json";
|
||||||
import InnovenergyList from "./UserList";
|
|
||||||
import PersonIcon from "@mui/icons-material/Person";
|
import PersonIcon from "@mui/icons-material/Person";
|
||||||
import { FormattedMessage } from "react-intl";
|
|
||||||
|
|
||||||
const UsersWithInheritedAccess = () => {
|
const UsersWithInheritedAccess = () => {
|
||||||
const [users, setUsers] = useState<UserWithInheritedAccess[]>();
|
const [users, setUsers] = useState<UserWithInheritedAccess[]>();
|
||||||
|
@ -23,78 +22,49 @@ const UsersWithInheritedAccess = () => {
|
||||||
const { currentType } = useContext(GroupContext);
|
const { currentType } = useContext(GroupContext);
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
|
|
||||||
useEffect(() => {
|
const fetchUsers = useCallback(async () => {
|
||||||
axiosConfig
|
axiosConfig
|
||||||
.get(
|
.get("/GetUsersWithInheritedAccessTo" + currentType, { params: { id } })
|
||||||
currentType === "Folder"
|
|
||||||
? "/GetUsersWithInheritedAccessToFolder"
|
|
||||||
: "/GetUsersWithInheritedAccessToInstallation",
|
|
||||||
{ params: { id } }
|
|
||||||
)
|
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setUsers(res.data);
|
setUsers(res.data);
|
||||||
});
|
});
|
||||||
}, [currentType, id]);
|
}, [currentType, id]);
|
||||||
|
|
||||||
const filterDuplicateUsers = (data: any[]) => {
|
useEffect(() => {
|
||||||
return data.reduce(
|
fetchUsers();
|
||||||
(prev: UserWithInheritedAccess[], curr: UserWithInheritedAccess) => {
|
}, [fetchUsers]);
|
||||||
const foundUser = prev.find(({ user }) => user.id === curr.user.id);
|
|
||||||
if (foundUser) {
|
|
||||||
const prevIds = foundUser.user.folderIds
|
|
||||||
? foundUser.user.folderIds
|
|
||||||
: [];
|
|
||||||
foundUser.user.folderIds = [...prevIds, curr.user.parentId];
|
|
||||||
return prev;
|
|
||||||
}
|
|
||||||
curr.user.folderIds = [curr.user.parentId];
|
|
||||||
prev.push(curr);
|
|
||||||
return prev;
|
|
||||||
},
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
if (users && users.length) {
|
if (users && users.length) {
|
||||||
return (
|
return (
|
||||||
<Grid item xs={6}>
|
<>
|
||||||
<Typography variant="overline" gutterBottom>
|
{filterDuplicateUsers(users).map(
|
||||||
<FormattedMessage
|
({ user, folderName }: UserWithInheritedAccess) => {
|
||||||
id="usersWithInheritedAccess"
|
return (
|
||||||
defaultMessage="Users with inherited access"
|
<Fragment key={user.id}>
|
||||||
/>
|
<ListItem>
|
||||||
</Typography>
|
<ListItemAvatar>
|
||||||
<InnovenergyList>
|
<Avatar>
|
||||||
{filterDuplicateUsers(users).map(
|
<PersonIcon />
|
||||||
({ user, folderName }: UserWithInheritedAccess) => {
|
</Avatar>
|
||||||
return (
|
</ListItemAvatar>
|
||||||
<Fragment key={user.id}>
|
<ListItemText
|
||||||
<ListItem>
|
primary={user.name}
|
||||||
<ListItemAvatar>
|
secondary={
|
||||||
<Avatar>
|
<>
|
||||||
<PersonIcon />
|
Inherited access from{" "}
|
||||||
</Avatar>
|
<Link to={routes.groups + routes.users + user.parentId}>
|
||||||
</ListItemAvatar>
|
{folderName}
|
||||||
<ListItemText
|
</Link>
|
||||||
primary={user.name}
|
</>
|
||||||
secondary={
|
}
|
||||||
<>
|
/>
|
||||||
Inherited access from{" "}
|
</ListItem>
|
||||||
<Link
|
<Divider />
|
||||||
to={routes.groups + routes.users + user.parentId}
|
</Fragment>
|
||||||
>
|
);
|
||||||
{folderName}
|
}
|
||||||
</Link>
|
)}
|
||||||
</>
|
</>
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItem>
|
|
||||||
<Divider />
|
|
||||||
</Fragment>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</InnovenergyList>
|
|
||||||
</Grid>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -16,3 +16,22 @@ export interface UserWithInheritedAccess {
|
||||||
folderName: string;
|
folderName: string;
|
||||||
user: User;
|
user: User;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const filterDuplicateUsers = (data: any[]) => {
|
||||||
|
return data.reduce(
|
||||||
|
(prev: UserWithInheritedAccess[], curr: UserWithInheritedAccess) => {
|
||||||
|
const foundUser = prev.find(({ user }) => user.id === curr.user.id);
|
||||||
|
if (foundUser) {
|
||||||
|
const prevIds = foundUser.user.folderIds
|
||||||
|
? foundUser.user.folderIds
|
||||||
|
: [];
|
||||||
|
foundUser.user.folderIds = [...prevIds, curr.user.parentId];
|
||||||
|
return prev;
|
||||||
|
}
|
||||||
|
curr.user.folderIds = [curr.user.parentId];
|
||||||
|
prev.push(curr);
|
||||||
|
return prev;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in New Issue