mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Wired suspend user action on user detail modal in adminX
refs https://github.com/TryGhost/Team/issues/3351 - wires Suspend/Un-suspend user action on user detail modal - adds running state for task buttons in modal - adds api to delete and suspend/un-suspend users
This commit is contained in:
parent
2b0a6bc454
commit
c2371b4841
3 changed files with 74 additions and 29 deletions
|
@ -1,39 +1,49 @@
|
|||
import Modal from './Modal';
|
||||
import NiceModal from '@ebay/nice-modal-react';
|
||||
import React from 'react';
|
||||
import NiceModal, {useModal} from '@ebay/nice-modal-react';
|
||||
import React, {useState} from 'react';
|
||||
|
||||
export interface ConfirmationModalProps {
|
||||
title?: string;
|
||||
prompt?: React.ReactNode;
|
||||
cancelLabel?: string;
|
||||
okLabel?: string;
|
||||
okRunningLabel?: string;
|
||||
okColor?: string;
|
||||
onCancel?: () => void;
|
||||
onOk?: () => void;
|
||||
onOk?: (modal?: {
|
||||
remove: () => void;
|
||||
}) => void;
|
||||
customFooter?: React.ReactNode;
|
||||
}
|
||||
|
||||
const ConfirmationModal: React.FC<ConfirmationModalProps> = ({
|
||||
title = 'Are you sure?',
|
||||
title = 'Are you sure?',
|
||||
prompt,
|
||||
cancelLabel = 'Cancel',
|
||||
okLabel = 'OK',
|
||||
cancelLabel = 'Cancel',
|
||||
okLabel = 'OK',
|
||||
okRunningLabel = '...',
|
||||
okColor = 'black',
|
||||
onCancel,
|
||||
onOk,
|
||||
onCancel,
|
||||
onOk,
|
||||
customFooter
|
||||
}) => {
|
||||
const modal = useModal();
|
||||
const [taskState, setTaskState] = useState<'running' | ''>('');
|
||||
return (
|
||||
<Modal
|
||||
<Modal
|
||||
backDrop={false}
|
||||
cancelLabel={cancelLabel}
|
||||
customFooter={customFooter}
|
||||
okColor={okColor}
|
||||
okLabel={okLabel}
|
||||
okLabel={taskState === 'running' ? okRunningLabel : okLabel}
|
||||
size={540}
|
||||
title={title}
|
||||
onCancel={onCancel}
|
||||
onOk={onOk}
|
||||
onOk={async () => {
|
||||
setTaskState('running');
|
||||
await onOk?.(modal);
|
||||
setTaskState('');
|
||||
}}
|
||||
>
|
||||
<div className='py-4'>
|
||||
{prompt}
|
||||
|
|
|
@ -416,23 +416,38 @@ const confirmDelete = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const confirmSuspend = () => {
|
||||
NiceModal.show(ConfirmationModal, {
|
||||
title: 'Are you sure you want to suspend this user?',
|
||||
prompt: (
|
||||
<>
|
||||
<strong>WARNING:</strong> This user will no longer be able to log in but their posts will be kept.
|
||||
</>
|
||||
),
|
||||
okLabel: 'Suspend',
|
||||
okColor: 'red'
|
||||
});
|
||||
};
|
||||
|
||||
const UserDetailModal:React.FC<UserDetailModalProps> = ({user, updateUser}) => {
|
||||
const {api} = useContext(ServicesContext);
|
||||
const [userData, setUserData] = useState(user);
|
||||
const [saveState, setSaveState] = useState('');
|
||||
|
||||
const confirmSuspend = (_user: User) => {
|
||||
let warningText = 'This user will no longer be able to log in but their posts will be kept.';
|
||||
if (_user.status === 'inactive') {
|
||||
warningText = 'This user will be able to log in again and will have the same permissions they had previously.';
|
||||
}
|
||||
NiceModal.show(ConfirmationModal, {
|
||||
title: 'Are you sure you want to suspend this user?',
|
||||
prompt: (
|
||||
<>
|
||||
<strong>WARNING:</strong> {warningText}
|
||||
</>
|
||||
),
|
||||
okLabel: _user.status === 'inactive' ? 'Un-suspend' : 'Suspend',
|
||||
okRunningLabel: _user.status === 'inactive' ? 'Un-suspending...' : 'Suspending...',
|
||||
okColor: 'red',
|
||||
onOk: async (modal) => {
|
||||
await api.users.edit({
|
||||
..._user,
|
||||
status: _user.status === 'inactive' ? 'active' : 'inactive'
|
||||
});
|
||||
modal?.remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let suspendUserLabel = user?.status === 'inactive' ? 'Un-suspend user' : 'Suspend user';
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
id: 'make-owner',
|
||||
|
@ -442,12 +457,16 @@ const UserDetailModal:React.FC<UserDetailModalProps> = ({user, updateUser}) => {
|
|||
{
|
||||
id: 'delete-user',
|
||||
label: 'Delete user',
|
||||
onClick: confirmDelete
|
||||
onClick: () => {
|
||||
confirmDelete();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'suspend-user',
|
||||
label: 'Suspend user',
|
||||
onClick: confirmSuspend
|
||||
label: suspendUserLabel,
|
||||
onClick: () => {
|
||||
confirmSuspend(user);
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 'view-user-activity',
|
||||
|
@ -471,6 +490,8 @@ const UserDetailModal:React.FC<UserDetailModalProps> = ({user, updateUser}) => {
|
|||
|
||||
const fileUploadButtonClasses = 'absolute right-[104px] bottom-12 bg-[rgba(0,0,0,0.75)] rounded text-sm text-white flex items-center justify-center px-3 h-8 opacity-80 hover:opacity-100 transition cursor-pointer font-medium z-10';
|
||||
|
||||
const suspendedText = user.status === 'inactive' ? ' (Suspended)' : '';
|
||||
|
||||
return (
|
||||
<Modal
|
||||
okColor='green'
|
||||
|
@ -522,11 +543,11 @@ const UserDetailModal:React.FC<UserDetailModalProps> = ({user, updateUser}) => {
|
|||
<Icon color='white' name='user-add' size='lg' />
|
||||
</ImageUpload>
|
||||
<div>
|
||||
<Heading styles='text-white'>{user.name}</Heading>
|
||||
<Heading styles='text-white'>{user.name}{suspendedText}</Heading>
|
||||
<span className='text-md font-semibold text-white'>Administrator</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-10 grid grid-cols-2 gap-x-12 gap-y-20 pb-10'>
|
||||
<Basic setUserData={setUserData} user={userData} />
|
||||
<Details setUserData={setUserData} user={userData} />
|
||||
|
|
|
@ -22,6 +22,12 @@ export interface UsersResponseType {
|
|||
users: User[];
|
||||
}
|
||||
|
||||
export interface DeleteUserResponse {
|
||||
meta: {
|
||||
filename: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface RolesResponseType {
|
||||
meta?: Meta;
|
||||
roles: UserRole[];
|
||||
|
@ -90,6 +96,7 @@ interface API {
|
|||
browse: () => Promise<UsersResponseType>;
|
||||
currentUser: () => Promise<User>;
|
||||
edit: (editedUser: User) => Promise<UsersResponseType>;
|
||||
delete: (userId: string) => Promise<DeleteUserResponse>;
|
||||
updatePassword: (options: UpdatePasswordOptions) => Promise<PasswordUpdateResponseType>;
|
||||
};
|
||||
roles: {
|
||||
|
@ -205,6 +212,13 @@ function setupGhostApi({ghostVersion}: GhostApiOptions): API {
|
|||
});
|
||||
const data: PasswordUpdateResponseType = await response.json();
|
||||
return data;
|
||||
},
|
||||
delete: async (userId: string) => {
|
||||
const response = await fetcher(`/users/${userId}/`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
const data: DeleteUserResponse = await response.json();
|
||||
return data;
|
||||
}
|
||||
},
|
||||
roles: {
|
||||
|
|
Loading…
Add table
Reference in a new issue