import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { isNonEmptyArray } from '@sniptt/guards'; import { useState } from 'react'; import { useRecoilValue, useSetRecoilState } from 'recoil'; import { AppTooltip, Avatar, H2Title, IconButton, IconMail, IconReload, IconTrash, Section, Status, TooltipDelay, } from 'twenty-ui'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath'; import { SettingsPath } from '@/types/SettingsPath'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer'; import { Table } from '@/ui/layout/table/components/Table'; import { TableHeader } from '@/ui/layout/table/components/TableHeader'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; import { WorkspaceInviteLink } from '@/workspace/components/WorkspaceInviteLink'; import { WorkspaceInviteTeam } from '@/workspace/components/WorkspaceInviteTeam'; import { formatDistanceToNow } from 'date-fns'; import { useGetWorkspaceInvitationsQuery } from '~/generated/graphql'; import { isDefined } from '~/utils/isDefined'; import { TableCell } from '../../modules/ui/layout/table/components/TableCell'; import { TableRow } from '../../modules/ui/layout/table/components/TableRow'; import { useDeleteWorkspaceInvitation } from '../../modules/workspace-invitation/hooks/useDeleteWorkspaceInvitation'; import { useResendWorkspaceInvitation } from '../../modules/workspace-invitation/hooks/useResendWorkspaceInvitation'; import { workspaceInvitationsState } from '../../modules/workspace-invitation/states/workspaceInvitationsStates'; const StyledButtonContainer = styled.div` align-items: center; display: flex; flex-direction: row; margin-left: ${({ theme }) => theme.spacing(3)}; `; const StyledTable = styled(Table)` margin-top: ${({ theme }) => theme.spacing(0.5)}; `; const StyledTableHeaderRow = styled(Table)` margin-bottom: ${({ theme }) => theme.spacing(1.5)}; `; const StyledIconWrapper = styled.div` display: flex; align-items: center; margin-right: ${({ theme }) => theme.spacing(2)}; `; const StyledTextContainerWithEllipsis = styled.div` overflow: hidden; text-overflow: ellipsis; white-space: nowrap; `; export const SettingsWorkspaceMembers = () => { const { enqueueSnackBar } = useSnackBar(); const theme = useTheme(); const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false); const [workspaceMemberToDelete, setWorkspaceMemberToDelete] = useState< string | undefined >(); const { records: workspaceMembers } = useFindManyRecords({ objectNameSingular: CoreObjectNameSingular.WorkspaceMember, }); const { deleteOneRecord: deleteOneWorkspaceMember } = useDeleteOneRecord({ objectNameSingular: CoreObjectNameSingular.WorkspaceMember, }); const { resendInvitation } = useResendWorkspaceInvitation(); const { deleteWorkspaceInvitation } = useDeleteWorkspaceInvitation(); const currentWorkspace = useRecoilValue(currentWorkspaceState); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const handleRemoveWorkspaceMember = async (workspaceMemberId: string) => { await deleteOneWorkspaceMember?.(workspaceMemberId); setIsConfirmationModalOpen(false); }; const workspaceInvitations = useRecoilValue(workspaceInvitationsState); const setWorkspaceInvitations = useSetRecoilState(workspaceInvitationsState); useGetWorkspaceInvitationsQuery({ onError: (error: Error) => { enqueueSnackBar(error.message, { variant: SnackBarVariant.Error, }); }, onCompleted: (data) => { setWorkspaceInvitations(data?.findWorkspaceInvitations ?? []); }, }); const handleRemoveWorkspaceInvitation = async (appTokenId: string) => { const result = await deleteWorkspaceInvitation({ appTokenId }); if (isDefined(result.errors)) { enqueueSnackBar('Error deleting invitation', { variant: SnackBarVariant.Error, duration: 2000, }); } }; const handleResendWorkspaceInvitation = async (appTokenId: string) => { const result = await resendInvitation({ appTokenId }); if (isDefined(result.errors)) { enqueueSnackBar('Error resending invitation', { variant: SnackBarVariant.Error, duration: 2000, }); } }; const getExpiresAtText = (expiresAt: string) => { const expiresAtDate = new Date(expiresAt); return expiresAtDate < new Date() ? 'Expired' : formatDistanceToNow(new Date(expiresAt)); }; return ( {currentWorkspace?.inviteHash && currentWorkspace?.isPublicInviteLinkEnabled && (
)}
Name Email {workspaceMembers?.map((workspaceMember) => ( {workspaceMember.name.firstName + ' ' + workspaceMember.name.lastName} {workspaceMember.userEmail} {currentWorkspaceMember?.id !== workspaceMember.id && ( { setIsConfirmationModalOpen(true); setWorkspaceMemberToDelete(workspaceMember.id); }} variant="tertiary" size="medium" Icon={IconTrash} /> )} ))}
{isNonEmptyArray(workspaceInvitations) && ( Email Expires in {workspaceInvitations?.map((workspaceInvitation) => ( {workspaceInvitation.email} { handleResendWorkspaceInvitation( workspaceInvitation.id, ); }} variant="tertiary" size="medium" Icon={IconReload} /> { handleRemoveWorkspaceInvitation( workspaceInvitation.id, ); }} variant="tertiary" size="medium" Icon={IconTrash} /> ))}
)}
This action cannot be undone. This will permanently delete this user and remove them from all their assignements. } onConfirmClick={() => workspaceMemberToDelete && handleRemoveWorkspaceMember(workspaceMemberToDelete) } deleteButtonText="Delete account" />
); };