mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat(frontend): added user deletion to the user list
also includes small updates to the api to prevent administrators from being deleted, as well as migrations to cascade deletions to requests the users made fixes #348
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import useSWR from 'swr';
|
||||
import LoadingSpinner from '../Common/LoadingSpinner';
|
||||
import type { User } from '../../../server/entity/User';
|
||||
@@ -10,6 +10,11 @@ import { Permission } from '../../hooks/useUser';
|
||||
import { useRouter } from 'next/router';
|
||||
import Header from '../Common/Header';
|
||||
import Table from '../Common/Table';
|
||||
import Transition from '../Transition';
|
||||
import Modal from '../Common/Modal';
|
||||
import axios from 'axios';
|
||||
import { useToasts } from 'react-toast-notifications';
|
||||
import globalMessages from '../../i18n/globalMessages';
|
||||
|
||||
const messages = defineMessages({
|
||||
userlist: 'User List',
|
||||
@@ -24,12 +29,46 @@ const messages = defineMessages({
|
||||
admin: 'Admin',
|
||||
user: 'User',
|
||||
plexuser: 'Plex User',
|
||||
deleteuser: 'Delete User',
|
||||
userdeleted: 'User deleted',
|
||||
userdeleteerror: 'Something went wrong deleting the user',
|
||||
deleteconfirm:
|
||||
'Are you sure you want to delete this user? All existing request data from this user will be removed.',
|
||||
});
|
||||
|
||||
const UserList: React.FC = () => {
|
||||
const intl = useIntl();
|
||||
const router = useRouter();
|
||||
const { data, error } = useSWR<User[]>('/api/v1/user');
|
||||
const { addToast } = useToasts();
|
||||
const { data, error, revalidate } = useSWR<User[]>('/api/v1/user');
|
||||
const [isDeleting, setDeleting] = useState(false);
|
||||
const [deleteModal, setDeleteModal] = useState<{
|
||||
isOpen: boolean;
|
||||
user?: User;
|
||||
}>({
|
||||
isOpen: false,
|
||||
});
|
||||
|
||||
const deleteUser = async () => {
|
||||
setDeleting(true);
|
||||
|
||||
try {
|
||||
await axios.delete(`/api/v1/user/${deleteModal.user?.id}`);
|
||||
|
||||
addToast(intl.formatMessage(messages.userdeleted), {
|
||||
autoDismiss: true,
|
||||
appearance: 'success',
|
||||
});
|
||||
setDeleteModal({ isOpen: false });
|
||||
} catch (e) {
|
||||
addToast(intl.formatMessage(messages.userdeleteerror), {
|
||||
autoDismiss: true,
|
||||
appearance: 'error',
|
||||
});
|
||||
} finally {
|
||||
revalidate();
|
||||
}
|
||||
};
|
||||
|
||||
if (!data && !error) {
|
||||
return <LoadingSpinner />;
|
||||
@@ -37,6 +76,46 @@ const UserList: React.FC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Transition
|
||||
enter="opacity-0 transition duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="opacity-100 transition duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
show={deleteModal.isOpen}
|
||||
>
|
||||
<Modal
|
||||
onOk={() => deleteUser()}
|
||||
okText={
|
||||
isDeleting
|
||||
? intl.formatMessage(globalMessages.deleting)
|
||||
: intl.formatMessage(globalMessages.delete)
|
||||
}
|
||||
okDisabled={isDeleting}
|
||||
okButtonType="danger"
|
||||
onCancel={() => setDeleteModal({ isOpen: false })}
|
||||
title={intl.formatMessage(messages.deleteuser)}
|
||||
iconSvg={
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
||||
/>
|
||||
</svg>
|
||||
}
|
||||
>
|
||||
{intl.formatMessage(messages.deleteconfirm)}
|
||||
</Modal>
|
||||
</Transition>
|
||||
<Header extraMargin={4}>{intl.formatMessage(messages.userlist)}</Header>
|
||||
<Table>
|
||||
<thead>
|
||||
@@ -104,7 +183,11 @@ const UserList: React.FC = () => {
|
||||
>
|
||||
{intl.formatMessage(messages.edit)}
|
||||
</Button>
|
||||
<Button buttonType="danger">
|
||||
<Button
|
||||
buttonType="danger"
|
||||
disabled={hasPermission(Permission.ADMIN, user.permissions)}
|
||||
onClick={() => setDeleteModal({ isOpen: true, user })}
|
||||
>
|
||||
{intl.formatMessage(messages.delete)}
|
||||
</Button>
|
||||
</Table.TD>
|
||||
|
Reference in New Issue
Block a user