Groups UI revision (#1959)

Co-authored-by: Prakash Senthil Vel <23444145+prakashsvmx@users.noreply.github.com>
This commit is contained in:
jinapurapu
2022-05-06 11:48:04 -07:00
committed by GitHub
parent 3854372f4d
commit 22390a6781
4 changed files with 102 additions and 31 deletions

View File

@@ -739,7 +739,6 @@ const TableWrapper = ({
)}
{hasOptions && (
<Column
headerRenderer={() => <Fragment>Options</Fragment>}
dataKey={idField}
width={optionsWidth}
headerClassName="optionsAlignment"

View File

@@ -24,45 +24,51 @@ import useApi from "../Common/Hooks/useApi";
import { ConfirmDeleteIcon } from "../../../icons";
interface IDeleteGroup {
selectedGroup: string;
selectedGroups: string[];
deleteOpen: boolean;
closeDeleteModalAndRefresh: any;
setErrorSnackMessage: typeof setErrorSnackMessage;
}
const DeleteGroup = ({
selectedGroup,
selectedGroups,
deleteOpen,
closeDeleteModalAndRefresh,
setErrorSnackMessage,
}: IDeleteGroup) => {
const onDelSuccess = () => closeDeleteModalAndRefresh(true);
const onDelError = (err: ErrorResponseHandler) => setErrorSnackMessage(err);
const onDelError = (err: ErrorResponseHandler) => {
setErrorSnackMessage(err);
closeDeleteModalAndRefresh(true);
}
const onClose = () => closeDeleteModalAndRefresh(false);
const [deleteLoading, invokeDeleteApi] = useApi(onDelSuccess, onDelError);
if (!selectedGroup) {
if (!selectedGroups) {
return null;
}
const onDeleteGroup = () => {
invokeDeleteApi("DELETE", `/api/v1/group?name=${encodeURI(selectedGroup)}`);
};
const onDeleteGroups = () => {
for (let group of selectedGroups){
invokeDeleteApi("DELETE", `/api/v1/group?name=${encodeURI(group)}`);
}
};
const renderGroups = selectedGroups.map((group) => <div key={group}><b>{group}</b></div>);
return (
<ConfirmDialog
title={`Delete Group`}
title={`Delete Group${selectedGroups.length >1 ? "s": ""}`}
confirmText={"Delete"}
isOpen={deleteOpen}
titleIcon={<ConfirmDeleteIcon />}
isLoading={deleteLoading}
onConfirm={onDeleteGroup}
onConfirm={onDeleteGroups}
onClose={onClose}
confirmationContent={
<DialogContentText>
Are you sure you want to delete group
<br />
<b>{selectedGroup}</b>?
Are you sure you want to delete the following {selectedGroups.length} group{selectedGroups.length >1 ? "s?": "?"}
{renderGroups}
</DialogContentText>
}
/>

View File

@@ -20,8 +20,8 @@ import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import Grid from "@mui/material/Grid";
import { LinearProgress } from "@mui/material";
import { AddIcon, GroupsIcon, UsersIcon } from "../../../icons";
import { LinearProgress, Box } from "@mui/material";
import { AddIcon, GroupsIcon, UsersIcon, DeleteIcon, IAMPoliciesIcon } from "../../../icons";
import { setErrorSnackMessage } from "../../../actions";
import { GroupsList } from "./types";
import { stringSort } from "../../../utils/sortFunctions";
@@ -79,12 +79,12 @@ const styles = (theme: Theme) =>
});
const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
const [selectedGroup, setSelectedGroup] = useState<any>(null);
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
const [loading, isLoading] = useState<boolean>(false);
const [records, setRecords] = useState<any[]>([]);
const [filter, setFilter] = useState<string>("");
const [policyOpen, setPolicyOpen] = useState<boolean>(false);
const [checkedGroups, setCheckedGroups] = useState<string[]>([]);
useEffect(() => {
isLoading(true);
@@ -106,6 +106,24 @@ const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
IAM_SCOPES.ADMIN_GET_GROUP,
]);
const selectionChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const { target: { value = "", checked = false } = {} } = e;
let elements: string[] = [...checkedGroups]; // We clone the checkedUsers array
if (checked) {
// If the user has checked this field we need to push this to checkedUsersList
elements.push(value);
} else {
// User has unchecked this field, we need to remove it from the list
elements = elements.filter((element) => element !== value);
}
setCheckedGroups(elements);
return elements;
};
useEffect(() => {
if (loading) {
if (displayGroups) {
@@ -134,7 +152,7 @@ const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
const closeDeleteModalAndRefresh = (refresh: boolean) => {
setDeleteOpen(false);
setCheckedGroups([]);
if (refresh) {
isLoading(true);
}
@@ -148,10 +166,6 @@ const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
history.push(`${IAM_PAGES.GROUPS}/${group}`);
};
const deleteAction = (group: any) => {
setDeleteOpen(true);
setSelectedGroup(group);
};
const tableActions = [
{
@@ -160,25 +174,26 @@ const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
disableButtonFunction: () => !getGroup,
},
{
type: "delete",
onClick: deleteAction,
disableButtonFunction: () => !deleteGroup,
type: "edit",
onClick: viewAction,
disableButtonFunction: () => !getGroup,
},
];
return (
<React.Fragment>
{deleteOpen && (
<DeleteGroup
deleteOpen={deleteOpen}
selectedGroup={selectedGroup}
selectedGroups={checkedGroups}
closeDeleteModalAndRefresh={closeDeleteModalAndRefresh}
/>
)}
{setPolicyOpen && (
{policyOpen && (
<SetPolicy
open={policyOpen}
selectedGroup={selectedGroup}
selectedGroup={checkedGroups[0]}
selectedUser={null}
closeModalAndRefresh={() => {
setPolicyOpen(false);
@@ -189,19 +204,67 @@ const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
<PageLayout>
<Grid item xs={12} className={classes.actionsTray}>
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[IAM_SCOPES.ADMIN_LIST_GROUPS]}
errorProps={{ disabled: true }}
>
>
<SearchBox
placeholder={"Search Groups"}
onChange={setFilter}
overrideClass={classes.searchField}
value={filter}
/>
</SecureComponent>
</SecureComponent>
<Box
sx={{
display: "flex",
}}
>
{" "}
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[
IAM_SCOPES.ADMIN_ATTACH_USER_OR_GROUP_POLICY
]}
matchAll
errorProps={{ disabled: true }}
>
<RBIconButton
tooltip={"Select Policy"}
onClick={() => {
setPolicyOpen(true);
}}
text={"Assign Policy"}
icon={<IAMPoliciesIcon />}
color="primary"
disabled={checkedGroups.length !== 1}
variant={"outlined"}
/>
</SecureComponent>
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[
IAM_SCOPES.ADMIN_REMOVE_USER_FROM_GROUP
]}
matchAll
errorProps={{ disabled: true }}
>
<RBIconButton
tooltip={"Delete Selected"}
onClick={() => {
setDeleteOpen(true);
}}
text={"Delete Selected"}
icon={<DeleteIcon />}
color="secondary"
disabled={checkedGroups.length === 0}
variant={"outlined"}
/>
</SecureComponent>
<SecureComponent
resource={CONSOLE_UI_RESOURCE}
scopes={[
@@ -222,6 +285,7 @@ const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
}}
/>
</SecureComponent>
</Box>
</Grid>
{loading && <LinearProgress />}
{!loading && (
@@ -238,6 +302,8 @@ const Groups = ({ classes, setErrorSnackMessage, history }: IGroupsProps) => {
itemActions={tableActions}
columns={[{ label: "Name", elementKey: "" }]}
isLoading={loading}
selectedItems={checkedGroups}
onSelect={deleteGroup ? selectionChanged : undefined}
records={filteredRecords}
entityName="Groups"
idField=""

View File

@@ -378,7 +378,7 @@ const GroupsDetails = ({ classes }: IGroupDetailsProps) => {
{deleteOpen && (
<DeleteGroup
deleteOpen={deleteOpen}
selectedGroup={groupName}
selectedGroups={[groupName]}
closeDeleteModalAndRefresh={(isDelSuccess: boolean) => {
setDeleteOpen(false);
if (isDelSuccess) {