Add empty states to settings tables (#10978)
## Context Fixes https://github.com/twentyhq/twenty/issues/10964 ## Test <img width="617" alt="Screenshot 2025-03-18 at 12 18 30" src="https://github.com/user-attachments/assets/dab8738d-d221-4a6b-a72e-061ab5fffb70" /> <img width="647" alt="Screenshot 2025-03-18 at 12 18 25" src="https://github.com/user-attachments/assets/45466a80-7a80-4cde-a0c5-420cd6c05cb2" /> <img width="637" alt="Screenshot 2025-03-18 at 12 18 19" src="https://github.com/user-attachments/assets/46a9f27a-bd3a-4e91-9885-668cf780d562" /> <img width="630" alt="Screenshot 2025-03-18 at 12 18 07" src="https://github.com/user-attachments/assets/e1f805a0-ed7f-4cf2-8f75-78b865bd1ca2" /> <img width="649" alt="Screenshot 2025-03-18 at 12 18 01" src="https://github.com/user-attachments/assets/e9f3086f-fe97-4f3b-99e0-25249e9dd43b" />
This commit is contained in:
@ -7,6 +7,7 @@ import { SettingsPath } from '@/types/SettingsPath';
|
|||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||||
|
import { TableCell } from '@/ui/layout/table/components/TableCell';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
@ -41,19 +42,14 @@ const StyledSearchContainer = styled.div`
|
|||||||
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTable = styled.div<{ hasRows: boolean }>`
|
const StyledTable = styled.div`
|
||||||
border-bottom: ${({ hasRows, theme }) =>
|
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||||
hasRows ? `1px solid ${theme.border.color.light}` : 'none'};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledSearchInput = styled(TextInput)`
|
const StyledSearchInput = styled(TextInput)`
|
||||||
input {
|
input {
|
||||||
background: ${({ theme }) => theme.background.transparent.lighter};
|
background: ${({ theme }) => theme.background.transparent.lighter};
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -63,6 +59,10 @@ const StyledTableRows = styled.div`
|
|||||||
padding-top: ${({ theme }) => theme.spacing(2)};
|
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledNoMembers = styled(TableCell)`
|
||||||
|
color: ${({ theme }) => theme.font.color.tertiary};
|
||||||
|
`;
|
||||||
|
|
||||||
type RoleAssignmentProps = {
|
type RoleAssignmentProps = {
|
||||||
role: Pick<Role, 'id' | 'label' | 'canUpdateAllSettings'> & {
|
role: Pick<Role, 'id' | 'label' | 'canUpdateAllSettings'> & {
|
||||||
workspaceMembers: Array<WorkspaceMember>;
|
workspaceMembers: Array<WorkspaceMember>;
|
||||||
@ -175,21 +175,29 @@ export const RoleAssignment = ({ role }: RoleAssignmentProps) => {
|
|||||||
<StyledSearchInput
|
<StyledSearchInput
|
||||||
value={searchFilter}
|
value={searchFilter}
|
||||||
onChange={handleSearchChange}
|
onChange={handleSearchChange}
|
||||||
placeholder={t`Search a member`}
|
placeholder={t`Search an assigned team member...`}
|
||||||
fullWidth
|
fullWidth
|
||||||
LeftIcon={IconSearch}
|
LeftIcon={IconSearch}
|
||||||
sizeVariant="lg"
|
sizeVariant="lg"
|
||||||
/>
|
/>
|
||||||
</StyledSearchContainer>
|
</StyledSearchContainer>
|
||||||
<StyledTable hasRows={filteredWorkspaceMembers.length > 0}>
|
<StyledTable>
|
||||||
<RoleAssignmentTableHeader />
|
<RoleAssignmentTableHeader />
|
||||||
<StyledTableRows>
|
<StyledTableRows>
|
||||||
{filteredWorkspaceMembers.map((workspaceMember) => (
|
{filteredWorkspaceMembers.length > 0 ? (
|
||||||
<RoleAssignmentTableRow
|
filteredWorkspaceMembers.map((workspaceMember) => (
|
||||||
key={workspaceMember.id}
|
<RoleAssignmentTableRow
|
||||||
workspaceMember={workspaceMember}
|
key={workspaceMember.id}
|
||||||
/>
|
workspaceMember={workspaceMember}
|
||||||
))}
|
/>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<StyledNoMembers>
|
||||||
|
{!searchFilter
|
||||||
|
? t`No members assigned`
|
||||||
|
: t`No members match your search`}
|
||||||
|
</StyledNoMembers>
|
||||||
|
)}
|
||||||
</StyledTableRows>
|
</StyledTableRows>
|
||||||
</StyledTable>
|
</StyledTable>
|
||||||
|
|
||||||
|
|||||||
@ -1,13 +1,10 @@
|
|||||||
import { Table } from '@/ui/layout/table/components/Table';
|
|
||||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||||
import { t } from '@lingui/core/macro';
|
import { t } from '@lingui/core/macro';
|
||||||
|
|
||||||
export const RoleAssignmentTableHeader = () => (
|
export const RoleAssignmentTableHeader = () => (
|
||||||
<Table>
|
<TableRow gridAutoColumns="2fr 4fr">
|
||||||
<TableRow gridAutoColumns="2fr 4fr">
|
<TableHeader>{t`Name`}</TableHeader>
|
||||||
<TableHeader>{t`Name`}</TableHeader>
|
<TableHeader>{t`Email`}</TableHeader>
|
||||||
<TableHeader>{t`Email`}</TableHeader>
|
</TableRow>
|
||||||
</TableRow>
|
|
||||||
</Table>
|
|
||||||
);
|
);
|
||||||
|
|||||||
@ -32,7 +32,11 @@ const StyledRolePermissionsContainer = styled.div`
|
|||||||
|
|
||||||
const StyledTable = styled.div`
|
const StyledTable = styled.div`
|
||||||
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTableRows = styled.div`
|
||||||
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type RolePermissionsProps = {
|
type RolePermissionsProps = {
|
||||||
@ -136,12 +140,14 @@ export const RolePermissions = ({ role }: RolePermissionsProps) => {
|
|||||||
/>
|
/>
|
||||||
<StyledTable>
|
<StyledTable>
|
||||||
<RolePermissionsObjectsTableHeader allPermissions={true} />
|
<RolePermissionsObjectsTableHeader allPermissions={true} />
|
||||||
{objectPermissionsConfig.map((permission) => (
|
<StyledTableRows>
|
||||||
<RolePermissionsObjectsTableRow
|
{objectPermissionsConfig.map((permission) => (
|
||||||
key={permission.key}
|
<RolePermissionsObjectsTableRow
|
||||||
permission={permission}
|
key={permission.key}
|
||||||
/>
|
permission={permission}
|
||||||
))}
|
/>
|
||||||
|
))}
|
||||||
|
</StyledTableRows>
|
||||||
</StyledTable>
|
</StyledTable>
|
||||||
</Section>
|
</Section>
|
||||||
<Section>
|
<Section>
|
||||||
@ -150,12 +156,14 @@ export const RolePermissions = ({ role }: RolePermissionsProps) => {
|
|||||||
<RolePermissionsSettingsTableHeader
|
<RolePermissionsSettingsTableHeader
|
||||||
allPermissions={role.canUpdateAllSettings}
|
allPermissions={role.canUpdateAllSettings}
|
||||||
/>
|
/>
|
||||||
{settingsPermissionsConfig.map((permission) => (
|
<StyledTableRows>
|
||||||
<RolePermissionsSettingsTableRow
|
{settingsPermissionsConfig.map((permission) => (
|
||||||
key={permission.key}
|
<RolePermissionsSettingsTableRow
|
||||||
permission={permission}
|
key={permission.key}
|
||||||
/>
|
permission={permission}
|
||||||
))}
|
/>
|
||||||
|
))}
|
||||||
|
</StyledTableRows>
|
||||||
</StyledTable>
|
</StyledTable>
|
||||||
</Section>
|
</Section>
|
||||||
</StyledRolePermissionsContainer>
|
</StyledRolePermissionsContainer>
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { Table } from '@/ui/layout/table/components/Table';
|
|
||||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
@ -20,25 +19,17 @@ const StyledActionsHeader = styled(TableHeader)`
|
|||||||
padding-right: ${({ theme }) => theme.spacing(4)};
|
padding-right: ${({ theme }) => theme.spacing(4)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTable = styled(Table)`
|
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
type RolePermissionsObjectsTableHeaderProps = {
|
type RolePermissionsObjectsTableHeaderProps = {
|
||||||
className?: string;
|
|
||||||
allPermissions: boolean;
|
allPermissions: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RolePermissionsObjectsTableHeader = ({
|
export const RolePermissionsObjectsTableHeader = ({
|
||||||
className,
|
|
||||||
allPermissions,
|
allPermissions,
|
||||||
}: RolePermissionsObjectsTableHeaderProps) => (
|
}: RolePermissionsObjectsTableHeaderProps) => (
|
||||||
<StyledTable className={className}>
|
<StyledTableHeaderRow>
|
||||||
<StyledTableHeaderRow>
|
<StyledNameHeader>{t`Name`}</StyledNameHeader>
|
||||||
<StyledNameHeader>{t`Name`}</StyledNameHeader>
|
<StyledActionsHeader aria-label={t`Actions`}>
|
||||||
<StyledActionsHeader aria-label={t`Actions`}>
|
<Checkbox checked={allPermissions} disabled />
|
||||||
<Checkbox checked={allPermissions} disabled />
|
</StyledActionsHeader>
|
||||||
</StyledActionsHeader>
|
</StyledTableHeaderRow>
|
||||||
</StyledTableHeaderRow>
|
|
||||||
</StyledTable>
|
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { Table } from '@/ui/layout/table/components/Table';
|
|
||||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
@ -23,30 +22,22 @@ const StyledActionsHeader = styled(TableHeader)`
|
|||||||
padding-right: ${({ theme }) => theme.spacing(4)};
|
padding-right: ${({ theme }) => theme.spacing(4)};
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTable = styled(Table)`
|
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledTypeHeader = styled(TableHeader)`
|
const StyledTypeHeader = styled(TableHeader)`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
type RolePermissionsSettingsTableHeaderProps = {
|
type RolePermissionsSettingsTableHeaderProps = {
|
||||||
className?: string;
|
|
||||||
allPermissions: boolean;
|
allPermissions: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RolePermissionsSettingsTableHeader = ({
|
export const RolePermissionsSettingsTableHeader = ({
|
||||||
className,
|
|
||||||
allPermissions,
|
allPermissions,
|
||||||
}: RolePermissionsSettingsTableHeaderProps) => (
|
}: RolePermissionsSettingsTableHeaderProps) => (
|
||||||
<StyledTable className={className}>
|
<StyledTableHeaderRow>
|
||||||
<StyledTableHeaderRow>
|
<StyledNameHeader>{t`Name`}</StyledNameHeader>
|
||||||
<StyledNameHeader>{t`Name`}</StyledNameHeader>
|
<StyledTypeHeader>{t`Type`}</StyledTypeHeader>
|
||||||
<StyledTypeHeader>{t`Type`}</StyledTypeHeader>
|
<StyledActionsHeader aria-label={t`Actions`}>
|
||||||
<StyledActionsHeader aria-label={t`Actions`}>
|
<Checkbox checked={allPermissions} disabled />
|
||||||
<Checkbox checked={allPermissions} disabled />
|
</StyledActionsHeader>
|
||||||
</StyledActionsHeader>
|
</StyledTableHeaderRow>
|
||||||
</StyledTableHeaderRow>
|
|
||||||
</StyledTable>
|
|
||||||
);
|
);
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import {
|
|||||||
IconButton,
|
IconButton,
|
||||||
IconMail,
|
IconMail,
|
||||||
IconReload,
|
IconReload,
|
||||||
|
IconSearch,
|
||||||
IconTrash,
|
IconTrash,
|
||||||
Section,
|
Section,
|
||||||
Status,
|
Status,
|
||||||
@ -26,6 +27,7 @@ import { SettingsPageContainer } from '@/settings/components/SettingsPageContain
|
|||||||
import { SettingsPath } from '@/types/SettingsPath';
|
import { SettingsPath } from '@/types/SettingsPath';
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
|
||||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||||
import { Table } from '@/ui/layout/table/components/Table';
|
import { Table } from '@/ui/layout/table/components/Table';
|
||||||
@ -51,11 +53,7 @@ const StyledButtonContainer = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledTable = styled(Table)`
|
const StyledTable = styled(Table)`
|
||||||
margin-top: ${({ theme }) => theme.spacing(0.5)};
|
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledTableHeaderRow = styled(Table)`
|
|
||||||
margin-bottom: ${({ theme }) => theme.spacing(1.5)};
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledIconWrapper = styled.div`
|
const StyledIconWrapper = styled.div`
|
||||||
@ -70,6 +68,26 @@ const StyledTextContainerWithEllipsis = styled.div`
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledSearchContainer = styled.div`
|
||||||
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledSearchInput = styled(TextInput)`
|
||||||
|
input {
|
||||||
|
background: ${({ theme }) => theme.background.transparent.lighter};
|
||||||
|
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTableRows = styled.div`
|
||||||
|
padding-bottom: ${({ theme }) => theme.spacing(2)};
|
||||||
|
padding-top: ${({ theme }) => theme.spacing(2)};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledNoMembers = styled(TableCell)`
|
||||||
|
color: ${({ theme }) => theme.font.color.tertiary};
|
||||||
|
`;
|
||||||
|
|
||||||
export const SettingsWorkspaceMembers = () => {
|
export const SettingsWorkspaceMembers = () => {
|
||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
const { enqueueSnackBar } = useSnackBar();
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
@ -100,6 +118,12 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
const workspaceInvitations = useRecoilValue(workspaceInvitationsState);
|
const workspaceInvitations = useRecoilValue(workspaceInvitationsState);
|
||||||
const setWorkspaceInvitations = useSetRecoilState(workspaceInvitationsState);
|
const setWorkspaceInvitations = useSetRecoilState(workspaceInvitationsState);
|
||||||
|
|
||||||
|
const [searchFilter, setSearchFilter] = useState('');
|
||||||
|
|
||||||
|
const handleSearchChange = (text: string) => {
|
||||||
|
setSearchFilter(text);
|
||||||
|
};
|
||||||
|
|
||||||
useGetWorkspaceInvitationsQuery({
|
useGetWorkspaceInvitationsQuery({
|
||||||
onError: (error: Error) => {
|
onError: (error: Error) => {
|
||||||
enqueueSnackBar(error.message, {
|
enqueueSnackBar(error.message, {
|
||||||
@ -138,6 +162,21 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
: formatDistanceToNow(new Date(expiresAt));
|
: formatDistanceToNow(new Date(expiresAt));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const filteredWorkspaceMembers = !searchFilter
|
||||||
|
? workspaceMembers
|
||||||
|
: workspaceMembers.filter((member) => {
|
||||||
|
const searchTerm = searchFilter.toLowerCase();
|
||||||
|
const firstName = member.name.firstName?.toLowerCase() || '';
|
||||||
|
const lastName = member.name.lastName?.toLowerCase() || '';
|
||||||
|
const email = member.userEmail?.toLowerCase() || '';
|
||||||
|
|
||||||
|
return (
|
||||||
|
firstName.includes(searchTerm) ||
|
||||||
|
lastName.includes(searchTerm) ||
|
||||||
|
email.includes(searchTerm)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SubMenuTopBarContainer
|
<SubMenuTopBarContainer
|
||||||
title={t`Members`}
|
title={t`Members`}
|
||||||
@ -167,77 +206,94 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
title={t`Manage Members`}
|
title={t`Manage Members`}
|
||||||
description={t`Manage the members of your space here`}
|
description={t`Manage the members of your space here`}
|
||||||
/>
|
/>
|
||||||
<Table>
|
<StyledSearchContainer>
|
||||||
<StyledTableHeaderRow>
|
<StyledSearchInput
|
||||||
<TableRow
|
value={searchFilter}
|
||||||
gridAutoColumns="150px 1fr 1fr"
|
onChange={handleSearchChange}
|
||||||
mobileGridAutoColumns="100px 1fr 1fr"
|
placeholder={t`Search a team member...`}
|
||||||
>
|
fullWidth
|
||||||
<TableHeader>
|
LeftIcon={IconSearch}
|
||||||
<Trans>Name</Trans>
|
sizeVariant="lg"
|
||||||
</TableHeader>
|
/>
|
||||||
<TableHeader>
|
</StyledSearchContainer>
|
||||||
<Trans>Email</Trans>
|
<StyledTable>
|
||||||
</TableHeader>
|
<TableRow
|
||||||
<TableHeader align={'right'}></TableHeader>
|
gridAutoColumns="150px 1fr 1fr"
|
||||||
</TableRow>
|
mobileGridAutoColumns="100px 1fr 1fr"
|
||||||
</StyledTableHeaderRow>
|
>
|
||||||
{workspaceMembers?.map((workspaceMember) => (
|
<TableHeader>
|
||||||
<StyledTable key={workspaceMember.id}>
|
<Trans>Name</Trans>
|
||||||
<TableRow
|
</TableHeader>
|
||||||
gridAutoColumns="150px 1fr 1fr"
|
<TableHeader>
|
||||||
mobileGridAutoColumns="100px 1fr 1fr"
|
<Trans>Email</Trans>
|
||||||
>
|
</TableHeader>
|
||||||
<TableCell>
|
<TableHeader align={'right'}></TableHeader>
|
||||||
<StyledIconWrapper>
|
</TableRow>
|
||||||
<Avatar
|
<StyledTableRows>
|
||||||
avatarUrl={workspaceMember.avatarUrl}
|
{filteredWorkspaceMembers.length > 0 ? (
|
||||||
placeholderColorSeed={workspaceMember.id}
|
filteredWorkspaceMembers.map((workspaceMember) => (
|
||||||
placeholder={workspaceMember.name.firstName ?? ''}
|
<TableRow
|
||||||
type="rounded"
|
gridAutoColumns="150px 1fr 1fr"
|
||||||
size="sm"
|
mobileGridAutoColumns="100px 1fr 1fr"
|
||||||
/>
|
key={workspaceMember.id}
|
||||||
</StyledIconWrapper>
|
>
|
||||||
<StyledTextContainerWithEllipsis
|
<TableCell>
|
||||||
id={`hover-text-${workspaceMember.id}`}
|
<StyledIconWrapper>
|
||||||
>
|
<Avatar
|
||||||
{workspaceMember.name.firstName +
|
avatarUrl={workspaceMember.avatarUrl}
|
||||||
' ' +
|
placeholderColorSeed={workspaceMember.id}
|
||||||
workspaceMember.name.lastName}
|
placeholder={workspaceMember.name.firstName ?? ''}
|
||||||
</StyledTextContainerWithEllipsis>
|
type="rounded"
|
||||||
<AppTooltip
|
size="sm"
|
||||||
anchorSelect={`#hover-text-${workspaceMember.id}`}
|
|
||||||
content={`${workspaceMember.name.firstName} ${workspaceMember.name.lastName}`}
|
|
||||||
noArrow
|
|
||||||
place="top"
|
|
||||||
positionStrategy="fixed"
|
|
||||||
delay={TooltipDelay.shortDelay}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell>
|
|
||||||
<StyledTextContainerWithEllipsis>
|
|
||||||
{workspaceMember.userEmail}
|
|
||||||
</StyledTextContainerWithEllipsis>
|
|
||||||
</TableCell>
|
|
||||||
<TableCell align={'right'}>
|
|
||||||
{currentWorkspaceMember?.id !== workspaceMember.id && (
|
|
||||||
<StyledButtonContainer>
|
|
||||||
<IconButton
|
|
||||||
onClick={() => {
|
|
||||||
setIsConfirmationModalOpen(true);
|
|
||||||
setWorkspaceMemberToDelete(workspaceMember.id);
|
|
||||||
}}
|
|
||||||
variant="tertiary"
|
|
||||||
size="medium"
|
|
||||||
Icon={IconTrash}
|
|
||||||
/>
|
/>
|
||||||
</StyledButtonContainer>
|
</StyledIconWrapper>
|
||||||
)}
|
<StyledTextContainerWithEllipsis
|
||||||
</TableCell>
|
id={`hover-text-${workspaceMember.id}`}
|
||||||
</TableRow>
|
>
|
||||||
</StyledTable>
|
{workspaceMember.name.firstName +
|
||||||
))}
|
' ' +
|
||||||
</Table>
|
workspaceMember.name.lastName}
|
||||||
|
</StyledTextContainerWithEllipsis>
|
||||||
|
<AppTooltip
|
||||||
|
anchorSelect={`#hover-text-${workspaceMember.id}`}
|
||||||
|
content={`${workspaceMember.name.firstName} ${workspaceMember.name.lastName}`}
|
||||||
|
noArrow
|
||||||
|
place="top"
|
||||||
|
positionStrategy="fixed"
|
||||||
|
delay={TooltipDelay.shortDelay}
|
||||||
|
/>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<StyledTextContainerWithEllipsis>
|
||||||
|
{workspaceMember.userEmail}
|
||||||
|
</StyledTextContainerWithEllipsis>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell align={'right'}>
|
||||||
|
{currentWorkspaceMember?.id !== workspaceMember.id && (
|
||||||
|
<StyledButtonContainer>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
setIsConfirmationModalOpen(true);
|
||||||
|
setWorkspaceMemberToDelete(workspaceMember.id);
|
||||||
|
}}
|
||||||
|
variant="tertiary"
|
||||||
|
size="medium"
|
||||||
|
Icon={IconTrash}
|
||||||
|
/>
|
||||||
|
</StyledButtonContainer>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<StyledNoMembers>
|
||||||
|
{!searchFilter
|
||||||
|
? t`No members`
|
||||||
|
: t`No members match your search`}
|
||||||
|
</StyledNoMembers>
|
||||||
|
)}
|
||||||
|
</StyledTableRows>
|
||||||
|
</StyledTable>
|
||||||
</Section>
|
</Section>
|
||||||
<Section>
|
<Section>
|
||||||
<H2Title
|
<H2Title
|
||||||
@ -246,26 +302,25 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
/>
|
/>
|
||||||
<WorkspaceInviteTeam />
|
<WorkspaceInviteTeam />
|
||||||
{isNonEmptyArray(workspaceInvitations) && (
|
{isNonEmptyArray(workspaceInvitations) && (
|
||||||
<Table>
|
<StyledTable>
|
||||||
<StyledTableHeaderRow>
|
<TableRow
|
||||||
<TableRow
|
gridAutoColumns="150px 1fr 1fr"
|
||||||
gridAutoColumns="150px 1fr 1fr"
|
mobileGridAutoColumns="100px 1fr 1fr"
|
||||||
mobileGridAutoColumns="100px 1fr 1fr"
|
>
|
||||||
>
|
<TableHeader>
|
||||||
<TableHeader>
|
<Trans>Email</Trans>
|
||||||
<Trans>Email</Trans>
|
</TableHeader>
|
||||||
</TableHeader>
|
<TableHeader align={'right'}>
|
||||||
<TableHeader align={'right'}>
|
<Trans>Expires in</Trans>
|
||||||
<Trans>Expires in</Trans>
|
</TableHeader>
|
||||||
</TableHeader>
|
<TableHeader></TableHeader>
|
||||||
<TableHeader></TableHeader>
|
</TableRow>
|
||||||
</TableRow>
|
<StyledTableRows>
|
||||||
</StyledTableHeaderRow>
|
{workspaceInvitations?.map((workspaceInvitation) => (
|
||||||
{workspaceInvitations?.map((workspaceInvitation) => (
|
|
||||||
<StyledTable key={workspaceInvitation.id}>
|
|
||||||
<TableRow
|
<TableRow
|
||||||
gridAutoColumns="150px 1fr 1fr"
|
gridAutoColumns="150px 1fr 1fr"
|
||||||
mobileGridAutoColumns="100px 1fr 1fr"
|
mobileGridAutoColumns="100px 1fr 1fr"
|
||||||
|
key={workspaceInvitation.id}
|
||||||
>
|
>
|
||||||
<TableCell>
|
<TableCell>
|
||||||
<StyledIconWrapper>
|
<StyledIconWrapper>
|
||||||
@ -309,9 +364,9 @@ export const SettingsWorkspaceMembers = () => {
|
|||||||
</StyledButtonContainer>
|
</StyledButtonContainer>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</StyledTable>
|
))}
|
||||||
))}
|
</StyledTableRows>
|
||||||
</Table>
|
</StyledTable>
|
||||||
)}
|
)}
|
||||||
</Section>
|
</Section>
|
||||||
</SettingsPageContainer>
|
</SettingsPageContainer>
|
||||||
|
|||||||
Reference in New Issue
Block a user