Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete modal - create a shared delete modal, use for all deletions #312

Merged
merged 10 commits into from
Mar 9, 2021
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
# ide config
.idea/

# vim swap
.*.sw[po]

# dependencies
node_modules

Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
src/index.html
*.json
.*.sw[po]
50 changes: 50 additions & 0 deletions src/components/delete-modal/delete-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as React from 'react';
import { Button, Modal, Spinner } from '@patternfly/react-core';

interface IProps {
cancelAction: () => void;
children?: any;
deleteAction: () => void;
isDisabled?: boolean;
title: string;
spinner?: boolean;
}

export class DeleteModal extends React.Component<IProps> {
render() {
const {
cancelAction,
children,
deleteAction,
isDisabled,
title,
spinner,
} = this.props;

return (
<Modal
actions={[
<Button
key='delete'
onClick={deleteAction}
variant='danger'
isDisabled={isDisabled}
>
Delete
{spinner && <Spinner size='sm'></Spinner>}
</Button>,
<Button key='cancel' onClick={cancelAction} variant='link'>
Cancel
</Button>,
]}
isOpen={true}
onClose={cancelAction}
title={title}
titleIconVariant='warning'
variant='small'
>
{children}
</Modal>
);
}
}
52 changes: 52 additions & 0 deletions src/containers/group-management/delete-group-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import { List, ListItem, Spinner } from '@patternfly/react-core';
import { DeleteModal } from '../../components/delete-modal/delete-modal';
import { UserType } from '../../api';

interface IProps {
count?: number;
cancelAction: () => void;
deleteAction: () => void;
name: string;
users?: UserType[];
}

export class DeleteGroupModal extends React.Component<IProps> {
render() {
const { cancelAction, count, deleteAction, name, users } = this.props;

return (
<DeleteModal
cancelAction={cancelAction}
deleteAction={deleteAction}
title='Delete group?'
>
<b>{name}</b> will be permanently deleted.
<p>&nbsp;</p>
<div>
{users && count > 10 && (
<p>Deleting this group will affect {count} users.</p>
)}
{users && count > 0 && count <= 10 && (
<>
<p>These users will lose access to the group content:</p>
<List>
{users.map(u => (
<ListItem key={u.username}>
<b>{u.username}</b>
</ListItem>
))}
</List>
</>
)}
{users && !count && <p>No users will be affected.</p>}
{!users && (
<p>
Checking for affected users... <Spinner size='sm' />
</p>
)}
</div>
</DeleteModal>
);
}
}
133 changes: 112 additions & 21 deletions src/containers/group-management/group-detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,18 @@ import { Constants } from '../../constants';
import * as moment from 'moment';
import { InsightsUserType } from '../../api/response-types/user';
import { AppContext } from '../../loaders/app-context';
import { DeleteGroupModal } from './delete-group-modal';
import { DeleteModal } from '../../components/delete-modal/delete-modal';

interface IState {
group: any;
params: { id: string; tab: string; page?: number; page_size?: number };
params: {
id: string;
page?: number;
page_size?: number;
sort?: string;
tab: string;
};
users: UserType[];
allUsers: UserType[];
itemCount: number;
Expand All @@ -52,6 +60,8 @@ interface IState {
options: { id: number; name: string }[];
selected: { id: number; name: string }[];
editPermissions: boolean;
showDeleteModal: boolean;
showUserRemoveModal: UserType | null;
permissions: string[];
originalPermissions: { id: number; name: string }[];
loading: boolean;
Expand All @@ -70,30 +80,25 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
'page_size',
]);

if (!params['page_size']) {
params['page_size'] = 10;
}

if (!params['tab']) {
params['tab'] = 'permissions';
}

this.state = {
group: null,
users: null,
allUsers: null,
params: {
id: id,
tab: params['tab'],
page: 0,
page_size: params['page_size'],
page_size: params['page_size'] || 10,
sort: params['sort'] || 'username',
tab: params['tab'] || 'permissions',
},
itemCount: 0,
alerts: [],
addModalVisible: false,
options: undefined,
selected: [],
editPermissions: false,
showDeleteModal: false,
showUserRemoveModal: null,
permissions: [],
originalPermissions: [],
loading: false,
Expand All @@ -117,7 +122,15 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
}

render() {
const { group, params, alerts, addModalVisible, loading } = this.state;
const {
addModalVisible,
alerts,
group,
loading,
params,
showDeleteModal,
showUserRemoveModal,
} = this.state;
const { user } = this.context;

const tabs = ['Permissions'];
Expand All @@ -139,6 +152,8 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
closeAlert={i => this.closeAlert(i)}
></AlertList>
{addModalVisible ? this.renderAddModal() : null}
{showDeleteModal ? this.renderGroupDeleteModal() : null}
{showUserRemoveModal ? this.renderUserRemoveModal() : null}
<BaseHeader
title={
this.state.editPermissions && this.state.params.tab == 'permissions'
Expand Down Expand Up @@ -241,11 +256,21 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
Cancel
</Button>
</ToolbarItem>
) : !!user && user.model_permissions.change_group ? (
) : !!user ? (
<ToolbarItem>
<Button onClick={() => this.setState({ editPermissions: true })}>
Edit
</Button>
{user.model_permissions.change_group ? (
<Button onClick={() => this.setState({ editPermissions: true })}>
Edit
</Button>
) : null}{' '}
{user.model_permissions.delete_group ? (
<Button
onClick={() => this.setState({ showDeleteModal: true })}
variant='secondary'
>
Delete
</Button>
) : null}
</ToolbarItem>
) : null;
}
Expand Down Expand Up @@ -420,6 +445,69 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
);
}

private renderGroupDeleteModal() {
const { group, users, itemCount } = this.state;

const deleteAction = () => {
GroupAPI.delete(group.id)
.then(() => {
this.setState({
showDeleteModal: false,
alerts: [
...this.state.alerts,
{
variant: 'success',
title: null,
description: 'Successfully deleted group.',
},
],
});
this.props.history.push(Paths.groupList);
})
.catch(() =>
this.setState({
alerts: [
...this.state.alerts,
{
variant: 'danger',
title: null,
description: 'Error deleting group.',
},
],
}),
);
};

if (!users) {
this.queryUsers();
}

return (
<DeleteGroupModal
count={itemCount}
cancelAction={() => this.setState({ showDeleteModal: false })}
deleteAction={deleteAction}
name={group.name}
users={users}
/>
);
}

private renderUserRemoveModal() {
const group = this.state.group;
const user = this.state.showUserRemoveModal as UserType;

return (
<DeleteModal
cancelAction={() => this.setState({ showUserRemoveModal: null })}
deleteAction={() => this.deleteUser(user)}
title='Remove user from group?'
>
<b>{user.username}</b> will be removed from <b>{group.name}</b>.
</DeleteModal>
);
}

private addUserToGroup(selectedUsers, group) {
const allPromises = [];
selectedUsers.forEach(user => {
Expand Down Expand Up @@ -453,9 +541,7 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
const noData =
itemCount === 0 &&
!filterIsSet(params, ['username', 'first_name', 'last_name', 'email']);
if (!params['sort']) {
params['sort'] = 'username';
}

if (noData) {
return (
<EmptyStateNoData
Expand All @@ -472,6 +558,7 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
/>
);
}

return (
<Section className='body'>
<div className='toolbar'>
Expand Down Expand Up @@ -618,7 +705,7 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
items={[
<DropdownItem
key='delete'
onClick={() => this.deleteUser(user)}
onClick={() => this.setState({ showUserRemoveModal: user })}
>
Remove
</DropdownItem>,
Expand All @@ -629,23 +716,26 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
</tr>
);
}

private queryUsers() {
UserAPI.list({
...this.state.params,
...{ groups__name: this.state.group.name },
}).then(result =>
this.setState({
users: result.data.data,
itemCount: result.data.data.length,
itemCount: result.data.meta.count,
addModalVisible: false,
loading: false,
}),
);
}

private deleteUser(user) {
user.groups = user.groups.filter(group => {
return group.id != this.state.params.id;
});

UserAPI.update(user.id, user)
.then(() => {
this.setState({
Expand All @@ -657,6 +747,7 @@ class GroupDetail extends React.Component<RouteComponentProps, IState> {
description: 'Successfully removed a user from a group.',
},
],
showUserRemoveModal: null,
});
this.queryUsers();
})
Expand Down
Loading