import type { LicenseInfo } from '@rocket.chat/core-typings'; import { Callout, Skeleton, Tabs, TabsItem } from '@rocket.chat/fuselage'; import { useDebouncedValue, useStableCallback } from '@rocket.chat/fuselage-hooks'; import type { OptionProp } from '@rocket.chat/ui-client'; import { ExternalLink, ContextualbarHeader, ContextualbarIcon, ContextualbarTitle, ContextualbarClose, ContextualbarDialog, usePagination, useSort, Page, PageHeader, PageContent, } from '@rocket.chat/ui-client'; import { useRouteParameter, useTranslation, useRouter, useEndpoint } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import { useEffect, useMemo, useRef, useState } from 'react'; import { Trans } from 'react-i18next'; import AdminInviteUsers from './AdminInviteUsers'; import AdminUserCreated from './AdminUserCreated'; import AdminUserForm from './AdminUserForm'; import AdminUserFormWithData from './AdminUserFormWithData'; import AdminUserInfoWithData from './AdminUserInfoWithData'; import AdminUserUpgrade from './AdminUserUpgrade'; import UsersPageHeaderContent from './UsersPageHeaderContent'; import UsersTable from './UsersTable'; import useFilteredUsers from './hooks/useFilteredUsers'; import usePendingUsersCount from './hooks/usePendingUsersCount'; import { useSeatsCap } from './useSeatsCap'; import { useLicenseLimitsByBehavior } from '../../../hooks/useLicenseLimitsByBehavior'; import { useShouldPreventAction } from '../../../hooks/useShouldPreventAction'; import { useCheckoutUrl } from '../subscription/hooks/useCheckoutUrl'; export type UsersFilters = { text: string; roles: OptionProp[]; }; export type AdminUsersTab = 'all' | 'active' | 'deactivated' | 'pending'; export type UsersTableSortingOption = 'name' | 'username' | 'emails.address' | 'status' | 'active' | 'freeSwitchExtension'; const AdminUsersPage = () => { const t = useTranslation(); const seatsCap = useSeatsCap(); const isSeatsCapExceeded = useShouldPreventAction('activeUsers'); const { prevent_action: preventAction } = useLicenseLimitsByBehavior() ?? {}; const manageSubscriptionUrl = useCheckoutUrl(); const router = useRouter(); const context = useRouteParameter('context'); const id = useRouteParameter('id'); const isCreateUserDisabled = useShouldPreventAction('activeUsers'); const getRoles = useEndpoint('GET', '/v1/roles.list'); const { data, error } = useQuery({ queryKey: ['roles'], queryFn: async () => getRoles(), }); const paginationData = usePagination(); const sortData = useSort('name'); const [tab, setTab] = useState('all'); const [userFilters, setUserFilters] = useState({ text: '', roles: [] }); const searchTerm = useDebouncedValue(userFilters.text, 500); const prevSearchTerm = useRef(''); const filteredUsersQueryResult = useFilteredUsers({ searchTerm, prevSearchTerm, sortData, paginationData, tab, selectedRoles: useMemo(() => userFilters.roles.map((role) => role.id), [userFilters.roles]), }); const pendingUsersCount = usePendingUsersCount(filteredUsersQueryResult.data?.users); const handleReload = (): void => { seatsCap?.reload(); filteredUsersQueryResult?.refetch(); }; const handleTabChange = (tab: AdminUsersTab) => { setTab(tab); paginationData.setCurrent(0); sortData.setSort(tab === 'pending' ? 'active' : 'name', 'asc'); }; const handleCloseContextualbar = useStableCallback(() => router.navigate('/admin/users')); useEffect(() => { prevSearchTerm.current = searchTerm; }, [searchTerm]); const isRoutePrevented = useMemo( () => context && ['new', 'invite'].includes(context) && isCreateUserDisabled, [context, isCreateUserDisabled], ); const toTranslationKey = (key: keyof LicenseInfo['limits']) => t(`subscription.callout.${key}`); return ( {preventAction?.includes('activeUsers') && ( Your workspace exceeded the <>{preventAction.map(toTranslationKey)} license limit. Manage your subscription to increase limits. )} handleTabChange('all')}> {t('All')} handleTabChange('pending')} display='flex' flexDirection='row'> {`${t('Pending')} `} {pendingUsersCount.isLoading && } {pendingUsersCount.isSuccess && `(${pendingUsersCount.data})`} handleTabChange('active')}> {t('Active')} handleTabChange('deactivated')}> {t('Deactivated')} {context && ( {['new', 'created', 'upgrade'].includes(context) && } {context === 'info' && t('User_Info')} {context === 'edit' && t('Edit_User')} {(context === 'new' || context === 'created') && t('New_user')} {context === 'invite' && t('Invite_Users')} {context === 'info' && id && } {context === 'edit' && id && ( )} {!isRoutePrevented && context === 'new' && ( )} {!isRoutePrevented && context === 'created' && id && } {!isRoutePrevented && context === 'invite' && } {isRoutePrevented && } )} ); }; export default AdminUsersPage;