feat: UI pagination and members search (#724)
* feat: pagination (UI) * Fixes * feat: add search to member list page * responsiveness
This commit is contained in:
@@ -15,7 +15,7 @@ interface MultiMemberSelectProps {
|
||||
const renderMultiSelectOption: MultiSelectProps["renderOption"] = ({
|
||||
option,
|
||||
}) => (
|
||||
<Group gap="sm">
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
{option["type"] === "user" && (
|
||||
<CustomAvatar
|
||||
avatarUrl={option["avatarUrl"]}
|
||||
@@ -25,7 +25,7 @@ const renderMultiSelectOption: MultiSelectProps["renderOption"] = ({
|
||||
)}
|
||||
{option["type"] === "group" && <IconGroupCircle />}
|
||||
<div>
|
||||
<Text size="sm">{option.label}</Text>
|
||||
<Text size="sm" lineClamp={1}>{option.label}</Text>
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
|
||||
@@ -12,10 +12,10 @@ interface SpaceSelectProps {
|
||||
}
|
||||
|
||||
const renderSelectOption: SelectProps["renderOption"] = ({ option }) => (
|
||||
<Group gap="sm">
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<Avatar color="initials" variant="filled" name={option.label} size={20} />
|
||||
<div>
|
||||
<Text size="sm">{option.label}</Text>
|
||||
<Text size="sm" lineClamp={1}>{option.label}</Text>
|
||||
</div>
|
||||
</Group>
|
||||
);
|
||||
|
||||
@@ -5,10 +5,12 @@ import SpaceSettingsModal from "@/features/space/components/settings-modal.tsx";
|
||||
import { useDisclosure } from "@mantine/hooks";
|
||||
import { formatMemberCount } from "@/lib";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Paginate from "@/components/common/paginate.tsx";
|
||||
|
||||
export default function SpaceList() {
|
||||
const { t } = useTranslation();
|
||||
const { data, isLoading } = useGetSpacesQuery();
|
||||
const [page, setPage] = useState(1);
|
||||
const { data, isLoading } = useGetSpacesQuery({ page });
|
||||
const [opened, { open, close }] = useDisclosure(false);
|
||||
const [selectedSpaceId, setSelectedSpaceId] = useState<string>(null);
|
||||
|
||||
@@ -19,50 +21,57 @@ export default function SpaceList() {
|
||||
|
||||
return (
|
||||
<>
|
||||
{data && (
|
||||
<Table.ScrollContainer minWidth={400}>
|
||||
<Table highlightOnHover verticalSpacing="sm">
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>{t("Space")}</Table.Th>
|
||||
<Table.Th>{t("Members")}</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.ScrollContainer minWidth={500}>
|
||||
<Table highlightOnHover verticalSpacing="sm" layout="fixed">
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>{t("Space")}</Table.Th>
|
||||
<Table.Th>{t("Members")}</Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
|
||||
<Table.Tbody>
|
||||
{data?.items.map((space, index) => (
|
||||
<Table.Tr
|
||||
key={index}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => handleClick(space.id)}
|
||||
>
|
||||
<Table.Td>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<Avatar
|
||||
color="initials"
|
||||
variant="filled"
|
||||
name={space.name}
|
||||
/>
|
||||
<div>
|
||||
<Text fz="sm" fw={500} lineClamp={1}>
|
||||
{space.name}
|
||||
</Text>
|
||||
<Text fz="xs" c="dimmed" lineClamp={2}>
|
||||
{space.description}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
{formatMemberCount(space.memberCount, t)}
|
||||
</Text>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Table.ScrollContainer>
|
||||
<Table.Tbody>
|
||||
{data?.items.map((space, index) => (
|
||||
<Table.Tr
|
||||
key={index}
|
||||
style={{ cursor: "pointer" }}
|
||||
onClick={() => handleClick(space.id)}
|
||||
>
|
||||
<Table.Td>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
<Avatar
|
||||
color="initials"
|
||||
variant="filled"
|
||||
name={space.name}
|
||||
/>
|
||||
<div>
|
||||
<Text fz="sm" fw={500} lineClamp={1}>
|
||||
{space.name}
|
||||
</Text>
|
||||
<Text fz="xs" c="dimmed" lineClamp={2}>
|
||||
{space.description}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
<Table.Td>
|
||||
<Text size="sm" style={{ whiteSpace: "nowrap" }}>
|
||||
{formatMemberCount(space.memberCount, t)}
|
||||
</Text>
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Table.ScrollContainer>
|
||||
|
||||
{data?.items.length > 0 && (
|
||||
<Paginate
|
||||
currentPage={page}
|
||||
hasPrevPage={data?.meta.hasPrevPage}
|
||||
hasNextPage={data?.meta.hasNextPage}
|
||||
onPageChange={setPage}
|
||||
/>
|
||||
)}
|
||||
|
||||
{selectedSpaceId && (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Group, Table, Text, Menu, ActionIcon } from "@mantine/core";
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { IconDots } from "@tabler/icons-react";
|
||||
import { modals } from "@mantine/modals";
|
||||
import { CustomAvatar } from "@/components/ui/custom-avatar.tsx";
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
} from "@/features/space/types/space-role-data.ts";
|
||||
import { formatMemberCount } from "@/lib";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Paginate from "@/components/common/paginate.tsx";
|
||||
|
||||
type MemberType = "user" | "group";
|
||||
|
||||
@@ -30,8 +31,11 @@ export default function SpaceMembersList({
|
||||
readOnly,
|
||||
}: SpaceMembersProps) {
|
||||
const { t } = useTranslation();
|
||||
const { data, isLoading } = useSpaceMembersQuery(spaceId);
|
||||
|
||||
const [page, setPage] = useState(1);
|
||||
const { data, isLoading } = useSpaceMembersQuery(spaceId, {
|
||||
page,
|
||||
limit: 100,
|
||||
});
|
||||
const removeSpaceMember = useRemoveSpaceMemberMutation();
|
||||
const changeSpaceMemberRoleMutation = useChangeSpaceMemberRoleMutation();
|
||||
|
||||
@@ -98,94 +102,101 @@ export default function SpaceMembersList({
|
||||
|
||||
return (
|
||||
<>
|
||||
{data && (
|
||||
<Table.ScrollContainer minWidth={500}>
|
||||
<Table verticalSpacing={8}>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>{t("Member")}</Table.Th>
|
||||
<Table.Th>{t("Role")}</Table.Th>
|
||||
<Table.Th></Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
<Table.ScrollContainer minWidth={500}>
|
||||
<Table highlightOnHover verticalSpacing={8}>
|
||||
<Table.Thead>
|
||||
<Table.Tr>
|
||||
<Table.Th>{t("Member")}</Table.Th>
|
||||
<Table.Th>{t("Role")}</Table.Th>
|
||||
<Table.Th></Table.Th>
|
||||
</Table.Tr>
|
||||
</Table.Thead>
|
||||
|
||||
<Table.Tbody>
|
||||
{data?.items.map((member, index) => (
|
||||
<Table.Tr key={index}>
|
||||
<Table.Td>
|
||||
<Group gap="sm">
|
||||
{member.type === "user" && (
|
||||
<CustomAvatar
|
||||
avatarUrl={member?.avatarUrl}
|
||||
name={member.name}
|
||||
/>
|
||||
)}
|
||||
|
||||
{member.type === "group" && <IconGroupCircle />}
|
||||
|
||||
<div>
|
||||
<Text fz="sm" fw={500}>
|
||||
{member?.name}
|
||||
</Text>
|
||||
<Text fz="xs" c="dimmed">
|
||||
{member.type == "user" && member?.email}
|
||||
|
||||
{member.type == "group" &&
|
||||
`${t("Group")} - ${formatMemberCount(member?.memberCount, t)}`}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
|
||||
<Table.Td>
|
||||
<RoleSelectMenu
|
||||
roles={spaceRoleData}
|
||||
roleName={getSpaceRoleLabel(member.role)}
|
||||
onChange={(newRole) =>
|
||||
handleRoleChange(
|
||||
member.id,
|
||||
member.type,
|
||||
newRole,
|
||||
member.role,
|
||||
)
|
||||
}
|
||||
disabled={readOnly}
|
||||
/>
|
||||
</Table.Td>
|
||||
|
||||
<Table.Td>
|
||||
{!readOnly && (
|
||||
<Menu
|
||||
shadow="xl"
|
||||
position="bottom-end"
|
||||
offset={20}
|
||||
width={200}
|
||||
withArrow
|
||||
arrowPosition="center"
|
||||
>
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="subtle" c="gray">
|
||||
<IconDots size={20} stroke={2} />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item
|
||||
onClick={() =>
|
||||
openRemoveModal(member.id, member.type)
|
||||
}
|
||||
>
|
||||
{t("Remove space member")}
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
<Table.Tbody>
|
||||
{data?.items.map((member, index) => (
|
||||
<Table.Tr key={index}>
|
||||
<Table.Td>
|
||||
<Group gap="sm" wrap="nowrap">
|
||||
{member.type === "user" && (
|
||||
<CustomAvatar
|
||||
avatarUrl={member?.avatarUrl}
|
||||
name={member.name}
|
||||
/>
|
||||
)}
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Table.ScrollContainer>
|
||||
|
||||
{member.type === "group" && <IconGroupCircle />}
|
||||
|
||||
<div>
|
||||
<Text fz="sm" fw={500} lineClamp={1}>
|
||||
{member?.name}
|
||||
</Text>
|
||||
<Text fz="xs" c="dimmed">
|
||||
{member.type == "user" && member?.email}
|
||||
|
||||
{member.type == "group" &&
|
||||
`${t("Group")} - ${formatMemberCount(member?.memberCount, t)}`}
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
|
||||
<Table.Td>
|
||||
<RoleSelectMenu
|
||||
roles={spaceRoleData}
|
||||
roleName={getSpaceRoleLabel(member.role)}
|
||||
onChange={(newRole) =>
|
||||
handleRoleChange(
|
||||
member.id,
|
||||
member.type,
|
||||
newRole,
|
||||
member.role,
|
||||
)
|
||||
}
|
||||
disabled={readOnly}
|
||||
/>
|
||||
</Table.Td>
|
||||
|
||||
<Table.Td>
|
||||
{!readOnly && (
|
||||
<Menu
|
||||
shadow="xl"
|
||||
position="bottom-end"
|
||||
offset={20}
|
||||
width={200}
|
||||
withArrow
|
||||
arrowPosition="center"
|
||||
>
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="subtle" c="gray">
|
||||
<IconDots size={20} stroke={2} />
|
||||
</ActionIcon>
|
||||
</Menu.Target>
|
||||
|
||||
<Menu.Dropdown>
|
||||
<Menu.Item
|
||||
onClick={() =>
|
||||
openRemoveModal(member.id, member.type)
|
||||
}
|
||||
>
|
||||
{t("Remove space member")}
|
||||
</Menu.Item>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
)}
|
||||
</Table.Td>
|
||||
</Table.Tr>
|
||||
))}
|
||||
</Table.Tbody>
|
||||
</Table>
|
||||
</Table.ScrollContainer>
|
||||
|
||||
{data?.items.length > 0 && (
|
||||
<Paginate
|
||||
currentPage={page}
|
||||
hasPrevPage={data?.meta.hasPrevPage}
|
||||
hasNextPage={data?.meta.hasNextPage}
|
||||
onPageChange={setPage}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import {
|
||||
keepPreviousData,
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient,
|
||||
UseQueryResult,
|
||||
} from '@tanstack/react-query';
|
||||
} from "@tanstack/react-query";
|
||||
import {
|
||||
IAddSpaceMember,
|
||||
IChangeSpaceMemberRole,
|
||||
IRemoveSpaceMember,
|
||||
ISpace,
|
||||
ISpaceMember,
|
||||
} from '@/features/space/types/space.types';
|
||||
} from "@/features/space/types/space.types";
|
||||
import {
|
||||
addSpaceMember,
|
||||
changeMemberRole,
|
||||
@@ -21,22 +22,23 @@ import {
|
||||
createSpace,
|
||||
updateSpace,
|
||||
deleteSpace,
|
||||
} from '@/features/space/services/space-service.ts';
|
||||
import { notifications } from '@mantine/notifications';
|
||||
import { IPagination, QueryParams } from '@/lib/types.ts';
|
||||
} from "@/features/space/services/space-service.ts";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import { IPagination, QueryParams } from "@/lib/types.ts";
|
||||
|
||||
export function useGetSpacesQuery(
|
||||
params?: QueryParams
|
||||
params?: QueryParams,
|
||||
): UseQueryResult<IPagination<ISpace>, Error> {
|
||||
return useQuery({
|
||||
queryKey: ['spaces', params],
|
||||
queryKey: ["spaces", params],
|
||||
queryFn: () => getSpaces(params),
|
||||
placeholderData: keepPreviousData,
|
||||
});
|
||||
}
|
||||
|
||||
export function useSpaceQuery(spaceId: string): UseQueryResult<ISpace, Error> {
|
||||
return useQuery({
|
||||
queryKey: ['space', spaceId],
|
||||
queryKey: ["space", spaceId],
|
||||
queryFn: () => getSpaceById(spaceId),
|
||||
enabled: !!spaceId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
@@ -50,22 +52,22 @@ export function useCreateSpaceMutation() {
|
||||
mutationFn: (data) => createSpace(data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['spaces'],
|
||||
queryKey: ["spaces"],
|
||||
});
|
||||
notifications.show({ message: 'Space created successfully' });
|
||||
notifications.show({ message: "Space created successfully" });
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error['response']?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: 'red' });
|
||||
const errorMessage = error["response"]?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: "red" });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useGetSpaceBySlugQuery(
|
||||
spaceId: string
|
||||
spaceId: string,
|
||||
): UseQueryResult<ISpace, Error> {
|
||||
return useQuery({
|
||||
queryKey: ['space', spaceId],
|
||||
queryKey: ["space", spaceId],
|
||||
queryFn: () => getSpaceById(spaceId),
|
||||
enabled: !!spaceId,
|
||||
staleTime: 5 * 60 * 1000,
|
||||
@@ -78,25 +80,25 @@ export function useUpdateSpaceMutation() {
|
||||
return useMutation<ISpace, Error, Partial<ISpace>>({
|
||||
mutationFn: (data) => updateSpace(data),
|
||||
onSuccess: (data, variables) => {
|
||||
notifications.show({ message: 'Space updated successfully' });
|
||||
notifications.show({ message: "Space updated successfully" });
|
||||
|
||||
const space = queryClient.getQueryData([
|
||||
'space',
|
||||
"space",
|
||||
variables.spaceId,
|
||||
]) as ISpace;
|
||||
if (space) {
|
||||
const updatedSpace = { ...space, ...data };
|
||||
queryClient.setQueryData(['space', variables.spaceId], updatedSpace);
|
||||
queryClient.setQueryData(['space', data.slug], updatedSpace);
|
||||
queryClient.setQueryData(["space", variables.spaceId], updatedSpace);
|
||||
queryClient.setQueryData(["space", data.slug], updatedSpace);
|
||||
}
|
||||
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['spaces'],
|
||||
queryKey: ["spaces"],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error['response']?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: 'red' });
|
||||
const errorMessage = error["response"]?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: "red" });
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -107,37 +109,39 @@ export function useDeleteSpaceMutation() {
|
||||
return useMutation({
|
||||
mutationFn: (data: Partial<ISpace>) => deleteSpace(data.id),
|
||||
onSuccess: (data, variables) => {
|
||||
notifications.show({ message: 'Space deleted successfully' });
|
||||
notifications.show({ message: "Space deleted successfully" });
|
||||
|
||||
if (variables.slug) {
|
||||
queryClient.removeQueries({
|
||||
queryKey: ['space', variables.slug],
|
||||
queryKey: ["space", variables.slug],
|
||||
exact: true,
|
||||
});
|
||||
}
|
||||
|
||||
const spaces = queryClient.getQueryData(['spaces']) as any;
|
||||
const spaces = queryClient.getQueryData(["spaces"]) as any;
|
||||
if (spaces) {
|
||||
spaces.items = spaces.items?.filter(
|
||||
(space: ISpace) => space.id !== variables.id
|
||||
(space: ISpace) => space.id !== variables.id,
|
||||
);
|
||||
queryClient.setQueryData(['spaces'], spaces);
|
||||
queryClient.setQueryData(["spaces"], spaces);
|
||||
}
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error['response']?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: 'red' });
|
||||
const errorMessage = error["response"]?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: "red" });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useSpaceMembersQuery(
|
||||
spaceId: string
|
||||
spaceId: string,
|
||||
params?: QueryParams,
|
||||
): UseQueryResult<IPagination<ISpaceMember>, Error> {
|
||||
return useQuery({
|
||||
queryKey: ['spaceMembers', spaceId],
|
||||
queryFn: () => getSpaceMembers(spaceId),
|
||||
queryKey: ["spaceMembers", spaceId, params],
|
||||
queryFn: () => getSpaceMembers(spaceId, params),
|
||||
enabled: !!spaceId,
|
||||
placeholderData: keepPreviousData,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -147,14 +151,14 @@ export function useAddSpaceMemberMutation() {
|
||||
return useMutation<void, Error, IAddSpaceMember>({
|
||||
mutationFn: (data) => addSpaceMember(data),
|
||||
onSuccess: (data, variables) => {
|
||||
notifications.show({ message: 'Members added successfully' });
|
||||
notifications.show({ message: "Members added successfully" });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ['spaceMembers', variables.spaceId],
|
||||
queryKey: ["spaceMembers", variables.spaceId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error['response']?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: 'red' });
|
||||
const errorMessage = error["response"]?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: "red" });
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -165,14 +169,14 @@ export function useRemoveSpaceMemberMutation() {
|
||||
return useMutation<void, Error, IRemoveSpaceMember>({
|
||||
mutationFn: (data) => removeSpaceMember(data),
|
||||
onSuccess: (data, variables) => {
|
||||
notifications.show({ message: 'Removed successfully' });
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ['spaceMembers', variables.spaceId],
|
||||
notifications.show({ message: "Removed successfully" });
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: ["spaceMembers", variables.spaceId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error['response']?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: 'red' });
|
||||
const errorMessage = error["response"]?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: "red" });
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -183,15 +187,15 @@ export function useChangeSpaceMemberRoleMutation() {
|
||||
return useMutation<void, Error, IChangeSpaceMemberRole>({
|
||||
mutationFn: (data) => changeMemberRole(data),
|
||||
onSuccess: (data, variables) => {
|
||||
notifications.show({ message: 'Member role updated successfully' });
|
||||
notifications.show({ message: "Member role updated successfully" });
|
||||
// due to pagination levels, change in cache instead
|
||||
queryClient.refetchQueries({
|
||||
queryKey: ['spaceMembers', variables.spaceId],
|
||||
queryKey: ["spaceMembers", variables.spaceId],
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
const errorMessage = error['response']?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: 'red' });
|
||||
const errorMessage = error["response"]?.data?.message;
|
||||
notifications.show({ message: errorMessage, color: "red" });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@ import {
|
||||
IExportSpaceParams,
|
||||
IRemoveSpaceMember,
|
||||
ISpace,
|
||||
ISpaceMember,
|
||||
} from "@/features/space/types/space.types";
|
||||
import { IPagination, QueryParams } from "@/lib/types.ts";
|
||||
import { IUser } from "@/features/user/types/user.types.ts";
|
||||
import { saveAs } from "file-saver";
|
||||
|
||||
export async function getSpaces(
|
||||
params?: QueryParams
|
||||
params?: QueryParams,
|
||||
): Promise<IPagination<ISpace>> {
|
||||
const req = await api.post("/spaces", params);
|
||||
return req.data;
|
||||
@@ -37,9 +38,10 @@ export async function deleteSpace(spaceId: string): Promise<void> {
|
||||
}
|
||||
|
||||
export async function getSpaceMembers(
|
||||
spaceId: string
|
||||
): Promise<IPagination<IUser>> {
|
||||
const req = await api.post<any>("/spaces/members", { spaceId });
|
||||
spaceId: string,
|
||||
params?: QueryParams,
|
||||
): Promise<IPagination<ISpaceMember>> {
|
||||
const req = await api.post<any>("/spaces/members", { spaceId, params });
|
||||
return req.data;
|
||||
}
|
||||
|
||||
@@ -48,13 +50,13 @@ export async function addSpaceMember(data: IAddSpaceMember): Promise<void> {
|
||||
}
|
||||
|
||||
export async function removeSpaceMember(
|
||||
data: IRemoveSpaceMember
|
||||
data: IRemoveSpaceMember,
|
||||
): Promise<void> {
|
||||
await api.post("/spaces/members/remove", data);
|
||||
}
|
||||
|
||||
export async function changeMemberRole(
|
||||
data: IChangeSpaceMemberRole
|
||||
data: IChangeSpaceMemberRole,
|
||||
): Promise<void> {
|
||||
await api.post("/spaces/members/change-role", data);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user