mirror of
https://github.com/coder/coder.git
synced 2026-09-21 20:51:01 +08:00
feat: add groups column to members page in organizations (#14620)
* feat: add groups column to members page in organizations * fix: run 'make fmt' * fix: stop displaying groups member is in for other organisations * fix: run 'make fmt'
This commit is contained in:
@@ -53,6 +53,13 @@ export function groupsByUserId() {
|
||||
} satisfies UseQueryOptions<Group[], unknown, GroupsByUserId>;
|
||||
}
|
||||
|
||||
export function groupsByUserIdInOrganization(organization: string) {
|
||||
return {
|
||||
...groupsByOrganization(organization),
|
||||
select: selectGroupsByUserId,
|
||||
} satisfies UseQueryOptions<Group[], unknown, GroupsByUserId>;
|
||||
}
|
||||
|
||||
export function selectGroupsByUserId(groups: Group[]): GroupsByUserId {
|
||||
// Sorting here means that nothing has to be sorted for the individual
|
||||
// user arrays later
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -15,7 +15,10 @@ const meta: Meta<typeof OrganizationMembersPageView> = {
|
||||
isAddingMember: false,
|
||||
isUpdatingMemberRoles: false,
|
||||
me: MockUser,
|
||||
members: [MockOrganizationMember, MockOrganizationMember2],
|
||||
members: [
|
||||
{ ...MockOrganizationMember, groups: [] },
|
||||
{ ...MockOrganizationMember2, groups: [] },
|
||||
],
|
||||
addMember: () => Promise.resolve(),
|
||||
removeMember: () => Promise.resolve(),
|
||||
updateMemberRoles: () => Promise.resolve(),
|
||||
|
||||
@@ -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<OrganizationMemberTableEntry> | undefined;
|
||||
groupsByUserId: GroupsByUserId | undefined;
|
||||
addMember: (user: User) => Promise<void>;
|
||||
removeMember: (member: OrganizationMemberWithUserData) => Promise<void>;
|
||||
updateMemberRoles: (
|
||||
@@ -47,6 +51,10 @@ interface OrganizationMembersPageViewProps {
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
interface OrganizationMemberTableEntry extends OrganizationMemberWithUserData {
|
||||
groups: readonly Group[] | undefined;
|
||||
}
|
||||
|
||||
export const OrganizationMembersPageView: FC<
|
||||
OrganizationMembersPageViewProps
|
||||
> = (props) => {
|
||||
@@ -68,13 +76,19 @@ export const OrganizationMembersPageView: FC<
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell width="50%">User</TableCell>
|
||||
<TableCell width="49%">
|
||||
<TableCell width="33%">User</TableCell>
|
||||
<TableCell width="33%">
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<span>Roles</span>
|
||||
<TableColumnHelpTooltip variant="roles" />
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell width="33%">
|
||||
<Stack direction="row" spacing={1} alignItems="center">
|
||||
<span>Groups</span>
|
||||
<TableColumnHelpTooltip variant="groups" />
|
||||
</Stack>
|
||||
</TableCell>
|
||||
<TableCell width="1%"></TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
@@ -111,6 +125,7 @@ export const OrganizationMembersPageView: FC<
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<UserGroupsCell userGroups={member.groups} />
|
||||
<TableCell>
|
||||
{member.user_id !== props.me.id && props.canEditMembers && (
|
||||
<MoreMenu>
|
||||
|
||||
Reference in New Issue
Block a user