Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1ec39f4

Browse files
authored
feat: add pagination to the organizaton members table (#16870)
Closes[coder/internal#344](coder/internal#344)
1 parent7ba4df1 commit1ec39f4

File tree

11 files changed

+172
-100
lines changed

11 files changed

+172
-100
lines changed

‎coderd/database/dbmem/dbmem.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9596,7 +9596,7 @@ func (q *FakeQuerier) PaginatedOrganizationMembers(_ context.Context, arg databa
95969596
// All of the members in the organization
95979597
orgMembers:=make([]database.OrganizationMember,0)
95989598
for_,mem:=rangeq.organizationMembers {
9599-
ifarg.OrganizationID!=uuid.Nil&&mem.OrganizationID!=arg.OrganizationID {
9599+
ifmem.OrganizationID!=arg.OrganizationID {
96009600
continue
96019601
}
96029602

@@ -9606,7 +9606,7 @@ func (q *FakeQuerier) PaginatedOrganizationMembers(_ context.Context, arg databa
96069606
selectedMembers:=make([]database.PaginatedOrganizationMembersRow,0)
96079607

96089608
skippedMembers:=0
9609-
for_,organizationMember:=rangeq.organizationMembers {
9609+
for_,organizationMember:=rangeorgMembers {
96109610
ifskippedMembers<int(arg.OffsetOpt) {
96119611
skippedMembers++
96129612
continue

‎codersdk/organizations.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,13 @@ type OrganizationMemberWithUserData struct {
8282
}
8383

8484
typePaginatedMembersRequeststruct {
85-
OrganizationID uuid.UUID`table:"organization id" json:"organization_id" format:"uuid"`
86-
Limitint`json:"limit,omitempty"`
87-
Offsetint`json:"offset,omitempty"`
85+
Limitint`json:"limit,omitempty"`
86+
Offsetint`json:"offset,omitempty"`
8887
}
8988

9089
typePaginatedMembersResponsestruct {
91-
Members []OrganizationMemberWithUserData
92-
Countint`json:"count"`
90+
Members []OrganizationMemberWithUserData`json:"members"`
91+
Countint`json:"count"`
9392
}
9493

9594
typeCreateOrganizationRequeststruct {

‎site/src/api/api.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,24 @@ class ApiMethods {
583583
returnresponse.data;
584584
};
585585

586+
/**
587+
*@param organization Can be the organization's ID or name
588+
*@param options Pagination options
589+
*/
590+
getOrganizationPaginatedMembers=async(
591+
organization:string,
592+
options?:TypesGen.Pagination,
593+
)=>{
594+
consturl=getURLWithSearchParams(
595+
`/api/v2/organizations/${organization}/paginated-members`,
596+
options,
597+
);
598+
constresponse=
599+
awaitthis.axios.get<TypesGen.PaginatedMembersResponse>(url);
600+
601+
returnresponse.data;
602+
};
603+
586604
/**
587605
*@param organization Can be the organization's ID or name
588606
*/

‎site/src/api/queries/organizations.ts

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ import { API } from "api/api";
22
importtype{
33
CreateOrganizationRequest,
44
GroupSyncSettings,
5+
PaginatedMembersRequest,
6+
PaginatedMembersResponse,
57
RoleSyncSettings,
68
UpdateOrganizationRequest,
79
}from"api/typesGenerated";
10+
importtype{UsePaginatedQueryOptions}from"hooks/usePaginatedQuery";
811
import{
912
typeOrganizationPermissionName,
1013
typeOrganizationPermissions,
@@ -59,13 +62,45 @@ export const organizationMembersKey = (id: string) => [
5962
"members",
6063
];
6164

65+
/**
66+
* Creates a query configuration to fetch all members of an organization.
67+
*
68+
* Unlike the paginated version, this function sets the `limit` parameter to 0,
69+
* which instructs the API to return all organization members in a single request
70+
* without pagination.
71+
*
72+
*@param id - The unique identifier of the organization
73+
*@returns A query configuration object for use with React Query
74+
*
75+
*@see paginatedOrganizationMembers - For fetching members with pagination support
76+
*/
6277
exportconstorganizationMembers=(id:string)=>{
6378
return{
64-
queryFn:()=>API.getOrganizationMembers(id),
79+
queryFn:()=>API.getOrganizationPaginatedMembers(id,{limit:0}),
6580
queryKey:organizationMembersKey(id),
6681
};
6782
};
6883

84+
exportconstpaginatedOrganizationMembers=(
85+
id:string,
86+
searchParams:URLSearchParams,
87+
):UsePaginatedQueryOptions<
88+
PaginatedMembersResponse,
89+
PaginatedMembersRequest
90+
>=>{
91+
return{
92+
searchParams,
93+
queryPayload:({ limit, offset})=>{
94+
return{
95+
limit:limit,
96+
offset:offset,
97+
};
98+
},
99+
queryKey:({ payload})=>[...organizationMembersKey(id),payload],
100+
queryFn:({ payload})=>API.getOrganizationPaginatedMembers(id,payload),
101+
};
102+
};
103+
69104
exportconstaddOrganizationMember=(queryClient:QueryClient,id:string)=>{
70105
return{
71106
mutationFn:(userId:string)=>{

‎site/src/api/typesGenerated.ts

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎site/src/components/UserAutocomplete/UserAutocomplete.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ export const MemberAutocomplete: FC<MemberAutocompleteProps> = ({
6969
})=>{
7070
const[filter,setFilter]=useState<string>();
7171

72-
// Currently this queries all members, as there is no pagination.
7372
constmembersQuery=useQuery({
7473
...organizationMembers(organizationId),
7574
enabled:filter!==undefined,
@@ -80,7 +79,7 @@ export const MemberAutocomplete: FC<MemberAutocompleteProps> = ({
8079
error={membersQuery.error}
8180
isFetching={membersQuery.isFetching}
8281
setFilter={setFilter}
83-
users={membersQuery.data}
82+
users={membersQuery.data?.members}
8483
{...props}
8584
/>
8685
);

‎site/src/pages/OrganizationSettingsPage/OrganizationMembersPage.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ beforeEach(() => {
3838

3939
constrenderPage=async()=>{
4040
renderWithOrganizationSettingsLayout(<OrganizationMembersPage/>,{
41-
route:`/organizations/${MockOrganization.name}/members`,
42-
path:"/organizations/:organization/members",
41+
route:`/organizations/${MockOrganization.name}/paginated-members`,
42+
path:"/organizations/:organization/paginated-members",
4343
});
4444
awaitwaitForLoaderToBeRemoved();
4545
};

‎site/src/pages/OrganizationSettingsPage/OrganizationMembersPage.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { getErrorMessage } from "api/errors";
33
import{groupsByUserIdInOrganization}from"api/queries/groups";
44
import{
55
addOrganizationMember,
6-
organizationMembers,
6+
paginatedOrganizationMembers,
77
removeOrganizationMember,
88
updateOrganizationMemberRoles,
99
}from"api/queries/organizations";
@@ -14,12 +14,13 @@ import { EmptyState } from "components/EmptyState/EmptyState";
1414
import{displayError,displaySuccess}from"components/GlobalSnackbar/utils";
1515
import{Stack}from"components/Stack/Stack";
1616
import{useAuthenticated}from"contexts/auth/RequireAuth";
17+
import{usePaginatedQuery}from"hooks/usePaginatedQuery";
1718
import{useOrganizationSettings}from"modules/management/OrganizationSettingsLayout";
1819
import{RequirePermission}from"modules/permissions/RequirePermission";
1920
import{typeFC,useState}from"react";
2021
import{Helmet}from"react-helmet-async";
2122
import{useMutation,useQuery,useQueryClient}from"react-query";
22-
import{useParams}from"react-router-dom";
23+
import{useParams,useSearchParams}from"react-router-dom";
2324
import{pageTitle}from"utils/page";
2425
import{OrganizationMembersPageView}from"./OrganizationMembersPageView";
2526

@@ -30,17 +31,23 @@ const OrganizationMembersPage: FC = () => {
3031
organization:string;
3132
};
3233
const{ organization, organizationPermissions}=useOrganizationSettings();
34+
constsearchParamsResult=useSearchParams();
3335

34-
constmembersQuery=useQuery(organizationMembers(organizationName));
3536
constorganizationRolesQuery=useQuery(organizationRoles(organizationName));
3637
constgroupsByUserIdQuery=useQuery(
3738
groupsByUserIdInOrganization(organizationName),
3839
);
3940

40-
constmembers=membersQuery.data?.map((member)=>{
41-
constgroups=groupsByUserIdQuery.data?.get(member.user_id)??[];
42-
return{ ...member, groups};
43-
});
41+
constmembersQuery=usePaginatedQuery(
42+
paginatedOrganizationMembers(organizationName,searchParamsResult[0]),
43+
);
44+
45+
constmembers=membersQuery.data?.members.map(
46+
(member:OrganizationMemberWithUserData)=>{
47+
constgroups=groupsByUserIdQuery.data?.get(member.user_id)??[];
48+
return{ ...member, groups};
49+
},
50+
);
4451

4552
constaddMemberMutation=useMutation(
4653
addOrganizationMember(queryClient,organizationName),
@@ -95,6 +102,7 @@ const OrganizationMembersPage: FC = () => {
95102
isUpdatingMemberRoles={updateMemberRolesMutation.isLoading}
96103
me={me}
97104
members={members}
105+
membersQuery={membersQuery}
98106
addMember={async(user:User)=>{
99107
awaitaddMemberMutation.mutateAsync(user.id);
100108
voidmembersQuery.refetch();

‎site/src/pages/OrganizationSettingsPage/OrganizationMembersPageView.stories.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
importtype{Meta,StoryObj}from"@storybook/react";
2+
import{mockSuccessResult}from"components/PaginationWidget/PaginationContainer.mocks";
3+
importtype{UsePaginatedQueryResult}from"hooks/usePaginatedQuery";
24
import{
35
MockOrganizationMember,
46
MockOrganizationMember2,
@@ -14,11 +16,16 @@ const meta: Meta<typeof OrganizationMembersPageView> = {
1416
error:undefined,
1517
isAddingMember:false,
1618
isUpdatingMemberRoles:false,
19+
canViewMembers:true,
1720
me:MockUser,
1821
members:[
1922
{ ...MockOrganizationMember,groups:[]},
2023
{ ...MockOrganizationMember2,groups:[]},
2124
],
25+
membersQuery:{
26+
...mockSuccessResult,
27+
totalRecords:2,
28+
}asUsePaginatedQueryResult,
2229
addMember:()=>Promise.resolve(),
2330
removeMember:()=>Promise.resolve(),
2431
updateMemberRoles:()=>Promise.resolve(),

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp