mirror of
https://github.com/docmost/docmost.git
synced 2026-08-29 01:37:05 +08:00
feat: search group members (#2445)
This commit is contained in:
@@ -12,13 +12,19 @@ import useUserRole from "@/hooks/use-user-role.tsx";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { IUser } from "@/features/user/types/user.types.ts";
|
import { IUser } from "@/features/user/types/user.types.ts";
|
||||||
import Paginate from "@/components/common/paginate.tsx";
|
import Paginate from "@/components/common/paginate.tsx";
|
||||||
import { useCursorPaginate } from "@/hooks/use-cursor-paginate";
|
import { SearchInput } from "@/components/common/search-input.tsx";
|
||||||
|
import NoTableResults from "@/components/common/no-table-results.tsx";
|
||||||
|
import { usePaginateAndSearch } from "@/hooks/use-paginate-and-search.tsx";
|
||||||
|
|
||||||
export default function GroupMembersList() {
|
export default function GroupMembersList() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { groupId } = useParams();
|
const { groupId } = useParams();
|
||||||
const { cursor, goNext, goPrev } = useCursorPaginate();
|
const { search, cursor, goNext, goPrev, handleSearch } =
|
||||||
const { data, isLoading } = useGroupMembersQuery(groupId, { cursor });
|
usePaginateAndSearch();
|
||||||
|
const { data, isLoading } = useGroupMembersQuery(groupId, {
|
||||||
|
cursor,
|
||||||
|
query: search,
|
||||||
|
});
|
||||||
const removeGroupMember = useRemoveGroupMemberMutation();
|
const removeGroupMember = useRemoveGroupMemberMutation();
|
||||||
const { isAdmin } = useUserRole();
|
const { isAdmin } = useUserRole();
|
||||||
|
|
||||||
@@ -48,6 +54,7 @@ export default function GroupMembersList() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<SearchInput onSearch={handleSearch} />
|
||||||
<Table.ScrollContainer minWidth={500}>
|
<Table.ScrollContainer minWidth={500}>
|
||||||
<Table highlightOnHover verticalSpacing="sm">
|
<Table highlightOnHover verticalSpacing="sm">
|
||||||
<Table.Thead>
|
<Table.Thead>
|
||||||
@@ -59,55 +66,62 @@ export default function GroupMembersList() {
|
|||||||
</Table.Thead>
|
</Table.Thead>
|
||||||
|
|
||||||
<Table.Tbody>
|
<Table.Tbody>
|
||||||
{data?.items.map((user: IUser, index: number) => (
|
{data?.items.length > 0 ? (
|
||||||
<Table.Tr key={index}>
|
data?.items.map((user: IUser, index: number) => (
|
||||||
<Table.Td>
|
<Table.Tr key={index}>
|
||||||
<Group gap="sm" wrap="nowrap">
|
<Table.Td>
|
||||||
<CustomAvatar avatarUrl={user.avatarUrl} name={user.name} />
|
<Group gap="sm" wrap="nowrap">
|
||||||
<div>
|
<CustomAvatar
|
||||||
<Text fz="sm" fw={500} lineClamp={1}>
|
avatarUrl={user.avatarUrl}
|
||||||
{user.name}
|
name={user.name}
|
||||||
</Text>
|
/>
|
||||||
<Text fz="xs" c="dimmed">
|
<div>
|
||||||
{user.email}
|
<Text fz="sm" fw={500} lineClamp={1}>
|
||||||
</Text>
|
{user.name}
|
||||||
</div>
|
</Text>
|
||||||
</Group>
|
<Text fz="xs" c="dimmed">
|
||||||
</Table.Td>
|
{user.email}
|
||||||
<Table.Td>
|
</Text>
|
||||||
<Badge variant="light">{t("Active")}</Badge>
|
</div>
|
||||||
</Table.Td>
|
</Group>
|
||||||
<Table.Td>
|
</Table.Td>
|
||||||
{isAdmin && (
|
<Table.Td>
|
||||||
<Menu
|
<Badge variant="light">{t("Active")}</Badge>
|
||||||
shadow="xl"
|
</Table.Td>
|
||||||
position="bottom-end"
|
<Table.Td>
|
||||||
offset={20}
|
{isAdmin && (
|
||||||
width={200}
|
<Menu
|
||||||
withArrow
|
shadow="xl"
|
||||||
arrowPosition="center"
|
position="bottom-end"
|
||||||
>
|
offset={20}
|
||||||
<Menu.Target>
|
width={200}
|
||||||
<ActionIcon
|
withArrow
|
||||||
variant="subtle"
|
arrowPosition="center"
|
||||||
c="gray"
|
>
|
||||||
aria-label={t("Member actions for {{name}}", {
|
<Menu.Target>
|
||||||
name: user.name,
|
<ActionIcon
|
||||||
})}
|
variant="subtle"
|
||||||
>
|
c="gray"
|
||||||
<IconDots size={20} stroke={2} />
|
aria-label={t("Member actions for {{name}}", {
|
||||||
</ActionIcon>
|
name: user.name,
|
||||||
</Menu.Target>
|
})}
|
||||||
<Menu.Dropdown>
|
>
|
||||||
<Menu.Item onClick={() => openRemoveModal(user.id)}>
|
<IconDots size={20} stroke={2} />
|
||||||
{t("Remove group member")}
|
</ActionIcon>
|
||||||
</Menu.Item>
|
</Menu.Target>
|
||||||
</Menu.Dropdown>
|
<Menu.Dropdown>
|
||||||
</Menu>
|
<Menu.Item onClick={() => openRemoveModal(user.id)}>
|
||||||
)}
|
{t("Remove group member")}
|
||||||
</Table.Td>
|
</Menu.Item>
|
||||||
</Table.Tr>
|
</Menu.Dropdown>
|
||||||
))}
|
</Menu>
|
||||||
|
)}
|
||||||
|
</Table.Td>
|
||||||
|
</Table.Tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<NoTableResults colSpan={3} />
|
||||||
|
)}
|
||||||
</Table.Tbody>
|
</Table.Tbody>
|
||||||
</Table>
|
</Table>
|
||||||
</Table.ScrollContainer>
|
</Table.ScrollContainer>
|
||||||
|
|||||||
@@ -60,6 +60,10 @@ export class GroupUserRepo {
|
|||||||
sql`f_unaccent(users.name)`,
|
sql`f_unaccent(users.name)`,
|
||||||
'ilike',
|
'ilike',
|
||||||
sql`f_unaccent(${'%' + pagination.query + '%'})`,
|
sql`f_unaccent(${'%' + pagination.query + '%'})`,
|
||||||
|
).or(
|
||||||
|
sql`users.email`,
|
||||||
|
'ilike',
|
||||||
|
sql`f_unaccent(${'%' + pagination.query + '%'})`,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user