-
Notifications
You must be signed in to change notification settings - Fork 21
Add delete user functionality to system-admin app / fix checkpoint screener #1363
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
Changes from all commits
64eed3e
85c2285
b8a59da
37a0370
b82e610
d7c673b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| @import '@libs/ui/styles/includes'; | ||
|
|
||
| .container { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: $sp-4; | ||
| } | ||
|
|
||
| .description { | ||
| white-space: pre-line; | ||
| } | ||
|
|
||
| .actions { | ||
| display: flex; | ||
| justify-content: flex-end; | ||
| gap: $sp-3; | ||
| margin-top: $sp-4; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| import { ChangeEvent, FC, useCallback, useEffect, useState } from 'react' | ||
| import classNames from 'classnames' | ||
|
|
||
| import { BaseModal, Button, InputText } from '~/libs/ui' | ||
|
|
||
| import { UserInfo } from '../../models' | ||
|
|
||
| import styles from './DialogDeleteUser.module.scss' | ||
|
|
||
| interface Props { | ||
| className?: string | ||
| open: boolean | ||
| setOpen: (isOpen: boolean) => void | ||
| userInfo: UserInfo | ||
| isLoading?: boolean | ||
| onDelete: (ticketUrl: string) => void | ||
| } | ||
|
|
||
| export const DialogDeleteUser: FC<Props> = (props: Props) => { | ||
| const [ticketUrl, setTicketUrl] = useState('') | ||
| const [error, setError] = useState('') | ||
|
|
||
| useEffect(() => { | ||
| if (props.open) { | ||
| setTicketUrl('') | ||
| setError('') | ||
| } | ||
| }, [props.open]) | ||
|
|
||
| const handleClose = useCallback(() => { | ||
| if (!props.isLoading) { | ||
| props.setOpen(false) | ||
| } | ||
| }, [props.isLoading, props.setOpen]) | ||
|
|
||
| const handleConfirm = useCallback(() => { | ||
| if (!ticketUrl.trim()) { | ||
| setError('Delete ticket URL is required') | ||
| return | ||
| } | ||
|
|
||
| setError('') | ||
| props.onDelete(ticketUrl.trim()) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [❗❗ |
||
| }, [props, ticketUrl]) | ||
|
|
||
| const handleTicketUrlChange = useCallback( | ||
| (event: ChangeEvent<HTMLInputElement>) => { | ||
| if (error) { | ||
| setError('') | ||
| } | ||
|
|
||
| setTicketUrl(event.target.value) | ||
| }, | ||
| [error], | ||
| ) | ||
|
|
||
| const description | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [💡 |
||
| = `Are you sure you want to DELETE user ${props.userInfo.handle} with email address ${props.userInfo.email}. ` | ||
| + 'If you are sure, please enter the associated delete request ticket URL below' | ||
|
|
||
| return ( | ||
| <BaseModal | ||
| allowBodyScroll | ||
| blockScroll | ||
| title={`Delete ${props.userInfo.handle}`} | ||
| onClose={handleClose} | ||
| open={props.open} | ||
| focusTrapped={false} | ||
| > | ||
| <div className={classNames(styles.container, props.className)}> | ||
| <p className={styles.description}>{description}</p> | ||
| <InputText | ||
| name='ticketUrl' | ||
| label='Delete request ticket URL' | ||
| placeholder='https://' | ||
| type='text' | ||
| value={ticketUrl} | ||
| error={error} | ||
| onChange={handleTicketUrlChange} | ||
| disabled={props.isLoading} | ||
| /> | ||
|
|
||
| <div className={styles.actions}> | ||
| <Button | ||
| secondary | ||
| size='lg' | ||
| onClick={handleClose} | ||
| disabled={props.isLoading} | ||
| > | ||
| Cancel | ||
| </Button> | ||
| <Button | ||
| primary | ||
| variant='danger' | ||
| size='lg' | ||
| onClick={handleConfirm} | ||
| disabled={props.isLoading} | ||
| > | ||
| DELETE | ||
| </Button> | ||
| </div> | ||
| </div> | ||
| </BaseModal> | ||
| ) | ||
| } | ||
|
|
||
| export default DialogDeleteUser | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export { DialogDeleteUser } from './DialogDeleteUser' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,7 +57,7 @@ | |
| } | ||
|
|
||
| .blockColumnAction { | ||
| width: 240px; | ||
| width: 320px; | ||
|
|
||
| @include ltelg { | ||
| width: 60px; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ import { DialogEditUserSSOLogin } from '../DialogEditUserSSOLogin' | |
| import { DialogEditUserTerms } from '../DialogEditUserTerms' | ||
| import { DialogEditUserStatus } from '../DialogEditUserStatus' | ||
| import { DialogUserStatusHistory } from '../DialogUserStatusHistory' | ||
| import { DialogDeleteUser } from '../DialogDeleteUser' | ||
| import { DropdownMenuButton } from '../common/DropdownMenuButton' | ||
| import { useTableFilterLocal, useTableFilterLocalProps } from '../../hooks' | ||
| import { TABLE_DATE_FORMAT } from '../../../config/index.config' | ||
|
|
@@ -43,12 +44,18 @@ interface Props { | |
| totalPages: number | ||
| onPageChange: (page: number) => void | ||
| updatingStatus: { [key: string]: boolean } | ||
| deletingUsers: { [key: string]: boolean } | ||
| doUpdateStatus: ( | ||
| userInfo: UserInfo, | ||
| newStatus: string, | ||
| comment: string, | ||
| onSuccess?: () => void, | ||
| ) => void | ||
| doDeleteUser: ( | ||
| userInfo: UserInfo, | ||
| ticketUrl: string, | ||
| onSuccess?: () => void, | ||
| ) => void | ||
| } | ||
|
|
||
| export const UsersTable: FC<Props> = props => { | ||
|
|
@@ -100,6 +107,9 @@ export const UsersTable: FC<Props> = props => { | |
| const [showDialogStatusHistory, setShowDialogStatusHistory] = useState< | ||
| UserInfo | undefined | ||
| >() | ||
| const [showDialogDeleteUser, setShowDialogDeleteUser] = useState< | ||
| UserInfo | undefined | ||
| >() | ||
| const { width: screenWidth }: WindowSize = useWindowSize() | ||
|
|
||
| const updatingStatusBool = useMemo( | ||
|
|
@@ -294,6 +304,8 @@ export const UsersTable: FC<Props> = props => { | |
| columnId: 'Action', | ||
| label: 'Action', | ||
| renderer: (data: UserInfo) => { | ||
| const isDeleting = props.deletingUsers?.[data.id] === true | ||
|
|
||
| function onSelectOption(item: string): void { | ||
| if (item === 'Primary Email') { | ||
| setShowDialogEditUserEmail(data) | ||
|
|
@@ -321,6 +333,8 @@ export const UsersTable: FC<Props> = props => { | |
| data, | ||
| message: confirmation, | ||
| }) | ||
| } else if (item === 'Delete') { | ||
| setShowDialogDeleteUser(data) | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -335,8 +349,8 @@ export const UsersTable: FC<Props> = props => { | |
| 'Terms', | ||
| 'SSO Logins', | ||
| ...(data.active | ||
| ? ['Deactivate'] | ||
| : ['Activate']), | ||
| ? ['Deactivate', 'Delete'] | ||
| : ['Activate', 'Delete']), | ||
| ]} | ||
| onSelectOption={onSelectOption} | ||
| > | ||
|
|
@@ -374,6 +388,7 @@ export const UsersTable: FC<Props> = props => { | |
| onClick={function onClick() { | ||
| onSelectOption('Deactivate') | ||
| }} | ||
| disabled={isDeleting} | ||
| /> | ||
| ) : ( | ||
| <Button | ||
|
|
@@ -385,6 +400,15 @@ export const UsersTable: FC<Props> = props => { | |
| }} | ||
| /> | ||
| )} | ||
| <Button | ||
| primary | ||
| variant='danger' | ||
| label='Delete' | ||
| onClick={function onClick() { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [💡 |
||
| onSelectOption('Delete') | ||
| }} | ||
| disabled={isDeleting} | ||
| /> | ||
| </> | ||
| )} | ||
| </div> | ||
|
|
@@ -393,7 +417,7 @@ export const UsersTable: FC<Props> = props => { | |
| type: 'action', | ||
| }, | ||
| ], | ||
| [isTablet, isMobile], | ||
| [isTablet, isMobile, props.deletingUsers, props.updatingStatus], | ||
| ) | ||
|
|
||
| return ( | ||
|
|
@@ -473,6 +497,23 @@ export const UsersTable: FC<Props> = props => { | |
| isLoading={updatingStatusBool} | ||
| /> | ||
| )} | ||
| {showDialogDeleteUser && ( | ||
| <DialogDeleteUser | ||
| open | ||
| setOpen={function setOpen() { | ||
| setShowDialogDeleteUser(undefined) | ||
| }} | ||
| userInfo={showDialogDeleteUser} | ||
| isLoading={props.deletingUsers?.[showDialogDeleteUser.id]} | ||
| onDelete={function onDelete(ticketUrl: string) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [❗❗ |
||
| props.doDeleteUser( | ||
| showDialogDeleteUser, | ||
| ticketUrl, | ||
| () => setShowDialogDeleteUser(undefined), | ||
| ) | ||
| }} | ||
| /> | ||
| )} | ||
| {showDialogStatusHistory && ( | ||
| <DialogUserStatusHistory | ||
| open | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[💡
readability]Consider using a more specific error message to guide the user, such as 'Please enter a valid delete ticket URL.' This can improve user experience by providing clearer instructions.