diff --git a/site/src/api/queries/groups.ts b/site/src/api/queries/groups.ts index ddc3d7e3b921c..4ddce87a249a2 100644 --- a/site/src/api/queries/groups.ts +++ b/site/src/api/queries/groups.ts @@ -53,6 +53,13 @@ export function groupsByUserId() { } satisfies UseQueryOptions; } +export function groupsByUserIdInOrganization(organization: string) { + return { + ...groupsByOrganization(organization), + select: selectGroupsByUserId, + } satisfies UseQueryOptions; +} + export function selectGroupsByUserId(groups: Group[]): GroupsByUserId { // Sorting here means that nothing has to be sorted for the individual // user arrays later diff --git a/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx b/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx index 209d3c14e11e9..9edd091ec6dac 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationMembersPage.tsx @@ -1,3 +1,7 @@ +import { + groupsByUserId, + groupsByUserIdInOrganization, +} from "api/queries/groups"; import { addOrganizationMember, organizationMembers, @@ -22,9 +26,18 @@ const OrganizationMembersPage: FC = () => { }; const { user: me } = useAuthenticated(); + const groupsByUserIdQuery = useQuery( + groupsByUserIdInOrganization(organizationName), + ); + const membersQuery = useQuery(organizationMembers(organizationName)); const organizationRolesQuery = useQuery(organizationRoles(organizationName)); + const members = membersQuery.data?.map((member) => { + const groups = groupsByUserIdQuery.data?.get(member.user_id) ?? []; + return { ...member, groups }; + }); + const addMemberMutation = useMutation( addOrganizationMember(queryClient, organizationName), ); @@ -57,7 +70,8 @@ const OrganizationMembersPage: FC = () => { isAddingMember={addMemberMutation.isLoading} isUpdatingMemberRoles={updateMemberRolesMutation.isLoading} me={me} - members={membersQuery.data} + members={members} + groupsByUserId={groupsByUserIdQuery.data} addMember={async (user: User) => { await addMemberMutation.mutateAsync(user.id); void membersQuery.refetch(); diff --git a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.stories.tsx b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.stories.tsx index 6e7cb9317600a..f3427bd58775d 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.stories.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.stories.tsx @@ -15,7 +15,10 @@ const meta: Meta = { isAddingMember: false, isUpdatingMemberRoles: false, me: MockUser, - members: [MockOrganizationMember, MockOrganizationMember2], + members: [ + { ...MockOrganizationMember, groups: [] }, + { ...MockOrganizationMember2, groups: [] }, + ], addMember: () => Promise.resolve(), removeMember: () => Promise.resolve(), updateMemberRoles: () => Promise.resolve(), diff --git a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx index 58c260a360e89..18200b1e5e3d4 100644 --- a/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx +++ b/site/src/pages/ManagementSettingsPage/OrganizationMembersPageView.tsx @@ -8,7 +8,9 @@ import TableContainer from "@mui/material/TableContainer"; import TableHead from "@mui/material/TableHead"; import TableRow from "@mui/material/TableRow"; import { getErrorMessage } from "api/errors"; +import type { GroupsByUserId } from "api/queries/groups"; import type { + Group, OrganizationMemberWithUserData, SlimRole, User, @@ -27,6 +29,7 @@ import { SettingsHeader } from "components/SettingsHeader/SettingsHeader"; import { Stack } from "components/Stack/Stack"; import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete"; import { UserAvatar } from "components/UserAvatar/UserAvatar"; +import { UserGroupsCell } from "pages/UsersPage/UsersTable/UserGroupsCell"; import { type FC, useState } from "react"; import { TableColumnHelpTooltip } from "./UserTable/TableColumnHelpTooltip"; import { UserRoleCell } from "./UserTable/UserRoleCell"; @@ -38,7 +41,8 @@ interface OrganizationMembersPageViewProps { isAddingMember: boolean; isUpdatingMemberRoles: boolean; me: User; - members: OrganizationMemberWithUserData[] | undefined; + members: Array | undefined; + groupsByUserId: GroupsByUserId | undefined; addMember: (user: User) => Promise; removeMember: (member: OrganizationMemberWithUserData) => Promise; updateMemberRoles: ( @@ -47,6 +51,10 @@ interface OrganizationMembersPageViewProps { ) => Promise; } +interface OrganizationMemberTableEntry extends OrganizationMemberWithUserData { + groups: readonly Group[] | undefined; +} + export const OrganizationMembersPageView: FC< OrganizationMembersPageViewProps > = (props) => { @@ -68,13 +76,19 @@ export const OrganizationMembersPageView: FC< - User - + User + Roles + + + Groups + + + @@ -111,6 +125,7 @@ export const OrganizationMembersPageView: FC< } }} /> + {member.user_id !== props.me.id && props.canEditMembers && (