import React, { useState } from 'react'; import useSWR from 'swr'; import LoadingSpinner from '../Common/LoadingSpinner'; import type { User } from '../../../server/entity/User'; import Badge from '../Common/Badge'; import { FormattedDate, defineMessages, useIntl } from 'react-intl'; import Button from '../Common/Button'; import { hasPermission } from '../../../server/lib/permissions'; 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', importfromplex: 'Import Users From Plex', importfromplexerror: 'Something went wrong importing users from Plex', importedfromplex: '{userCount, plural, =0 {No new users} one {# new user} other {# new users}} imported from Plex', username: 'Username', totalrequests: 'Total Requests', usertype: 'User Type', role: 'Role', created: 'Created', lastupdated: 'Last Updated', edit: 'Edit', delete: 'Delete', 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 { addToast } = useToasts(); const { data, error, revalidate } = useSWR('/api/v1/user'); const [isDeleting, setDeleting] = useState(false); const [isImporting, setImporting] = 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 { setDeleting(false); revalidate(); } }; const importFromPlex = async () => { setImporting(true); try { const { data: createdUsers } = await axios.post( '/api/v1/user/import-from-plex' ); addToast( intl.formatMessage(messages.importedfromplex, { userCount: createdUsers.length, }), { autoDismiss: true, appearance: 'success', } ); } catch (e) { addToast(intl.formatMessage(messages.importfromplexerror), { autoDismiss: true, appearance: 'error', }); } finally { revalidate(); setImporting(false); } }; if (!data && !error) { return ; } return ( <> 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={ } > {intl.formatMessage(messages.deleteconfirm)}
{intl.formatMessage(messages.userlist)}
{intl.formatMessage(messages.username)}{intl.formatMessage(messages.totalrequests)}{intl.formatMessage(messages.usertype)}{intl.formatMessage(messages.role)}{intl.formatMessage(messages.created)}{intl.formatMessage(messages.lastupdated)} {data?.map((user) => (
{user.username}
{user.email}
{user.requestCount}
{intl.formatMessage(messages.plexuser)} {hasPermission(Permission.ADMIN, user.permissions) ? intl.formatMessage(messages.admin) : intl.formatMessage(messages.user)} ))}
); }; export default UserList;