| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- import {
- useState,
- type ComponentProps,
- useCallback,
- type Dispatch,
- type SetStateAction,
- } from 'react'
- import { useTranslation } from 'react-i18next'
- import { Dropdown, MenuItem } from 'react-bootstrap'
- import { User } from '../../../../../../types/group-management/user'
- import useAsync from '@/shared/hooks/use-async'
- import { type FetchError, postJSON } from '@/infrastructure/fetch-json'
- import Icon from '@/shared/components/icon'
- import { GroupUserAlert } from '../../utils/types'
- import { useGroupMembersContext } from '../../context/group-members-context'
- import getMeta from '@/utils/meta'
- type resendInviteResponse = {
- success: boolean
- }
- type ManagedUserDropdownButtonProps = {
- user: User
- openOffboardingModalForUser: (user: User) => void
- groupId: string
- setGroupUserAlert: Dispatch<SetStateAction<GroupUserAlert>>
- }
- export default function DropdownButton({
- user,
- openOffboardingModalForUser,
- groupId,
- setGroupUserAlert,
- }: ManagedUserDropdownButtonProps) {
- const { t } = useTranslation()
- const { removeMember } = useGroupMembersContext()
- const [isOpened, setIsOpened] = useState(false)
- const {
- runAsync: runResendManagedUserInviteAsync,
- isLoading: isResendingManagedUserInvite,
- } = useAsync<resendInviteResponse>()
- const {
- runAsync: runResendLinkSSOInviteAsync,
- isLoading: isResendingSSOLinkInvite,
- } = useAsync<resendInviteResponse>()
- const {
- runAsync: runResendGroupInviteAsync,
- isLoading: isResendingGroupInvite,
- } = useAsync<resendInviteResponse>()
- const managedUsersActive = getMeta('ol-managedUsersActive')
- const groupSSOActive = getMeta('ol-groupSSOActive')
- const userPending = user.invite
- const isGroupSSOLinked =
- !userPending && user.enrollment?.sso?.some(sso => sso.groupId === groupId)
- const isUserManaged = !userPending && user.enrollment?.managedBy === groupId
- const handleResendManagedUserInvite = useCallback(
- async user => {
- try {
- const result = await runResendManagedUserInviteAsync(
- postJSON(
- `/manage/groups/${groupId}/resendManagedUserInvite/${user._id}`
- )
- )
- if (result.success) {
- setGroupUserAlert({
- variant: 'resendManagedUserInviteSuccess',
- email: user.email,
- })
- setIsOpened(false)
- }
- } catch (err) {
- if ((err as FetchError)?.response?.status === 429) {
- setGroupUserAlert({
- variant: 'resendInviteTooManyRequests',
- email: user.email,
- })
- } else {
- setGroupUserAlert({
- variant: 'resendManagedUserInviteFailed',
- email: user.email,
- })
- }
- setIsOpened(false)
- }
- },
- [setGroupUserAlert, groupId, runResendManagedUserInviteAsync]
- )
- const handleResendLinkSSOInviteAsync = useCallback(
- async user => {
- try {
- const result = await runResendLinkSSOInviteAsync(
- postJSON(`/manage/groups/${groupId}/resendSSOLinkInvite/${user._id}`)
- )
- if (result.success) {
- setGroupUserAlert({
- variant: 'resendSSOLinkInviteSuccess',
- email: user.email,
- })
- setIsOpened(false)
- }
- } catch (err) {
- if ((err as FetchError)?.response?.status === 429) {
- setGroupUserAlert({
- variant: 'resendInviteTooManyRequests',
- email: user.email,
- })
- } else {
- setGroupUserAlert({
- variant: 'resendSSOLinkInviteFailed',
- email: user.email,
- })
- }
- setIsOpened(false)
- }
- },
- [setGroupUserAlert, groupId, runResendLinkSSOInviteAsync]
- )
- const handleResendGroupInvite = useCallback(
- async user => {
- try {
- await runResendGroupInviteAsync(
- postJSON(`/manage/groups/${groupId}/resendInvite/`, {
- body: {
- email: user.email,
- },
- })
- )
- setGroupUserAlert({
- variant: 'resendGroupInviteSuccess',
- email: user.email,
- })
- setIsOpened(false)
- } catch (err) {
- if ((err as FetchError)?.response?.status === 429) {
- setGroupUserAlert({
- variant: 'resendInviteTooManyRequests',
- email: user.email,
- })
- } else {
- setGroupUserAlert({
- variant: 'resendGroupInviteFailed',
- email: user.email,
- })
- }
- setIsOpened(false)
- }
- },
- [setGroupUserAlert, groupId, runResendGroupInviteAsync]
- )
- const onResendManagedUserInviteClick = () => {
- handleResendManagedUserInvite(user)
- }
- const onResendSSOLinkInviteClick = () => {
- handleResendLinkSSOInviteAsync(user)
- }
- const onResendGroupInviteClick = () => {
- handleResendGroupInvite(user)
- }
- const onDeleteUserClick = () => {
- openOffboardingModalForUser(user)
- }
- const onRemoveFromGroup = () => {
- removeMember(user)
- }
- const buttons = []
- if (userPending) {
- buttons.push(
- <MenuItemButton
- onClick={onResendGroupInviteClick}
- key="resend-group-invite-action"
- data-testid="resend-group-invite-action"
- >
- {t('resend_group_invite')}
- {isResendingGroupInvite ? (
- <Icon type="spinner" spin style={{ marginLeft: '5px' }} />
- ) : null}
- </MenuItemButton>
- )
- }
- if (managedUsersActive && !isUserManaged && !userPending) {
- buttons.push(
- <MenuItemButton
- onClick={onResendManagedUserInviteClick}
- key="resend-managed-user-invite-action"
- data-testid="resend-managed-user-invite-action"
- >
- {t('resend_managed_user_invite')}
- {isResendingManagedUserInvite ? (
- <Icon type="spinner" spin style={{ marginLeft: '5px' }} />
- ) : null}
- </MenuItemButton>
- )
- }
- if (groupSSOActive && !isGroupSSOLinked && !userPending) {
- buttons.push(
- <MenuItemButton
- onClick={onResendSSOLinkInviteClick}
- key="resend-sso-link-invite-action"
- data-testid="resend-sso-link-invite-action"
- >
- {t('resend_link_sso')}
- {isResendingSSOLinkInvite ? (
- <Icon type="spinner" spin style={{ marginLeft: '5px' }} />
- ) : null}
- </MenuItemButton>
- )
- }
- if (isUserManaged && !user.isEntityAdmin) {
- buttons.push(
- <MenuItemButton
- className="delete-user-action"
- key="delete-user-action"
- data-testid="delete-user-action"
- onClick={onDeleteUserClick}
- >
- {t('delete_user')}
- </MenuItemButton>
- )
- } else if (!isUserManaged) {
- buttons.push(
- <MenuItemButton
- key="remove-user-action"
- data-testid="remove-user-action"
- onClick={onRemoveFromGroup}
- className="delete-user-action"
- >
- {t('remove_from_group')}
- </MenuItemButton>
- )
- }
- if (buttons.length === 0) {
- buttons.push(
- <MenuItem key="no-actions-available" data-testid="no-actions-available">
- <span className="text-muted">{t('no_actions')}</span>
- </MenuItem>
- )
- }
- return (
- <span className="managed-user-actions">
- <Dropdown
- id={`managed-user-dropdown-${user.email}`}
- open={isOpened}
- onToggle={open => setIsOpened(open)}
- >
- <Dropdown.Toggle
- bsStyle={null}
- className="btn btn-link action-btn"
- noCaret
- >
- <i
- className="fa fa-ellipsis-v"
- aria-hidden="true"
- aria-label={t('actions')}
- />
- </Dropdown.Toggle>
- <Dropdown.Menu className="dropdown-menu-right managed-user-dropdown-menu">
- {buttons}
- </Dropdown.Menu>
- </Dropdown>
- </span>
- )
- }
- function MenuItemButton({
- children,
- onClick,
- className,
- ...buttonProps
- }: ComponentProps<'button'>) {
- return (
- <li role="presentation" className={className}>
- <button
- className="managed-user-menu-item-button"
- role="menuitem"
- onClick={onClick}
- {...buttonProps}
- >
- {children}
- </button>
- </li>
- )
- }
|