mirror of
https://github.com/coder/coder.git
synced 2026-09-22 13:10:21 +08:00
chore: update table component and styles (#16541)
- migrate styles to tailwind - migrate to new Table component
This commit is contained in:
@@ -1,14 +1,6 @@
|
||||
import type { Interpolation, Theme } from "@emotion/react";
|
||||
import PersonAdd from "@mui/icons-material/PersonAdd";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import Table from "@mui/material/Table";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import TableCell from "@mui/material/TableCell";
|
||||
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,
|
||||
@@ -28,6 +20,13 @@ import {
|
||||
} from "components/MoreMenu/MoreMenu";
|
||||
import { SettingsHeader } from "components/SettingsHeader/SettingsHeader";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "components/Table/Table";
|
||||
import { UserAutocomplete } from "components/UserAutocomplete/UserAutocomplete";
|
||||
import { UserGroupsCell } from "pages/UsersPage/UsersTable/UserGroupsCell";
|
||||
import { type FC, useState } from "react";
|
||||
@@ -80,83 +79,80 @@ export const OrganizationMembersPageView: FC<
|
||||
onSubmit={addMember}
|
||||
/>
|
||||
)}
|
||||
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<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%" />
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{members?.map((member) => (
|
||||
<TableRow key={member.user_id}>
|
||||
<TableCell>
|
||||
<AvatarData
|
||||
avatar={
|
||||
<Avatar
|
||||
fallback={member.username}
|
||||
src={member.avatar_url}
|
||||
/>
|
||||
}
|
||||
title={member.name || member.username}
|
||||
subtitle={member.email}
|
||||
/>
|
||||
</TableCell>
|
||||
<UserRoleCell
|
||||
inheritedRoles={member.global_roles}
|
||||
roles={member.roles}
|
||||
allAvailableRoles={allAvailableRoles}
|
||||
oidcRoleSyncEnabled={false}
|
||||
isLoading={isUpdatingMemberRoles}
|
||||
canEditUsers={canEditMembers}
|
||||
onEditRoles={async (roles) => {
|
||||
try {
|
||||
await updateMemberRoles(member, roles);
|
||||
displaySuccess("Roles updated successfully.");
|
||||
} catch (error) {
|
||||
displayError(
|
||||
getErrorMessage(error, "Failed to update roles."),
|
||||
);
|
||||
}
|
||||
}}
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<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%" />
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{members?.map((member) => (
|
||||
<TableRow key={member.user_id} className="align-baseline">
|
||||
<TableCell>
|
||||
<AvatarData
|
||||
avatar={
|
||||
<Avatar
|
||||
fallback={member.username}
|
||||
src={member.avatar_url}
|
||||
/>
|
||||
}
|
||||
title={member.name || member.username}
|
||||
subtitle={member.email}
|
||||
/>
|
||||
<UserGroupsCell userGroups={member.groups} />
|
||||
<TableCell>
|
||||
{member.user_id !== me.id && canEditMembers && (
|
||||
<MoreMenu>
|
||||
<MoreMenuTrigger>
|
||||
<ThreeDotsButton />
|
||||
</MoreMenuTrigger>
|
||||
<MoreMenuContent>
|
||||
<MoreMenuItem
|
||||
danger
|
||||
onClick={() => removeMember(member)}
|
||||
>
|
||||
Remove
|
||||
</MoreMenuItem>
|
||||
</MoreMenuContent>
|
||||
</MoreMenu>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</TableCell>
|
||||
<UserRoleCell
|
||||
inheritedRoles={member.global_roles}
|
||||
roles={member.roles}
|
||||
allAvailableRoles={allAvailableRoles}
|
||||
oidcRoleSyncEnabled={false}
|
||||
isLoading={isUpdatingMemberRoles}
|
||||
canEditUsers={canEditMembers}
|
||||
onEditRoles={async (roles) => {
|
||||
try {
|
||||
await updateMemberRoles(member, roles);
|
||||
displaySuccess("Roles updated successfully.");
|
||||
} catch (error) {
|
||||
displayError(
|
||||
getErrorMessage(error, "Failed to update roles."),
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<UserGroupsCell userGroups={member.groups} />
|
||||
<TableCell>
|
||||
{member.user_id !== me.id && canEditMembers && (
|
||||
<MoreMenu>
|
||||
<MoreMenuTrigger>
|
||||
<ThreeDotsButton />
|
||||
</MoreMenuTrigger>
|
||||
<MoreMenuContent>
|
||||
<MoreMenuItem
|
||||
danger
|
||||
onClick={() => removeMember(member)}
|
||||
>
|
||||
Remove
|
||||
</MoreMenuItem>
|
||||
</MoreMenuContent>
|
||||
</MoreMenu>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
@@ -190,7 +186,7 @@ const AddOrganizationMember: FC<AddOrganizationMemberProps> = ({
|
||||
>
|
||||
<Stack direction="row" alignItems="center" spacing={1}>
|
||||
<UserAutocomplete
|
||||
css={styles.autoComplete}
|
||||
className="w-[300px]"
|
||||
value={selectedUser}
|
||||
onChange={(newValue) => {
|
||||
setSelectedUser(newValue);
|
||||
@@ -210,17 +206,3 @@ const AddOrganizationMember: FC<AddOrganizationMemberProps> = ({
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = {
|
||||
role: (theme) => ({
|
||||
backgroundColor: theme.roles.notice.background,
|
||||
borderColor: theme.roles.notice.outline,
|
||||
}),
|
||||
globalRole: (theme) => ({
|
||||
backgroundColor: theme.roles.inactive.background,
|
||||
borderColor: theme.roles.inactive.outline,
|
||||
}),
|
||||
autoComplete: {
|
||||
width: 300,
|
||||
},
|
||||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
* users like that, though, know that it will be painful
|
||||
*/
|
||||
import { type Interpolation, type Theme, useTheme } from "@emotion/react";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import TableCell from "@mui/material/TableCell";
|
||||
import Tooltip from "@mui/material/Tooltip";
|
||||
import type { LoginType, SlimRole } from "api/typesGenerated";
|
||||
import { Pill } from "components/Pill/Pill";
|
||||
import { TableCell } from "components/Table/Table";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
@@ -59,7 +58,7 @@ export const UserRoleCell: FC<UserRoleCellProps> = ({
|
||||
|
||||
return (
|
||||
<TableCell>
|
||||
<Stack direction="row" spacing={1}>
|
||||
<div className="flex flex-row gap-1 items-center">
|
||||
{canEditUsers && (
|
||||
<EditRolesButton
|
||||
roles={sortRolesByAccessLevel(allAvailableRoles ?? [])}
|
||||
@@ -97,7 +96,7 @@ export const UserRoleCell: FC<UserRoleCellProps> = ({
|
||||
</Pill>
|
||||
|
||||
{extraRoles.length > 0 && <OverflowRolePill roles={extraRoles} />}
|
||||
</Stack>
|
||||
</div>
|
||||
</TableCell>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,11 +2,10 @@ import { useTheme } from "@emotion/react";
|
||||
import GroupIcon from "@mui/icons-material/Group";
|
||||
import List from "@mui/material/List";
|
||||
import ListItem from "@mui/material/ListItem";
|
||||
import TableCell from "@mui/material/TableCell";
|
||||
import type { Group } from "api/typesGenerated";
|
||||
import { Avatar } from "components/Avatar/Avatar";
|
||||
import { OverflowY } from "components/OverflowY/OverflowY";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { TableCell } from "components/Table/Table";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
@@ -40,12 +39,9 @@ export const UserGroupsCell: FC<GroupsCellProps> = ({ userGroups }) => {
|
||||
color: "inherit",
|
||||
lineHeight: "1",
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Stack
|
||||
spacing={0}
|
||||
direction="row"
|
||||
css={{ columnGap: 8, alignItems: "center" }}
|
||||
>
|
||||
<div className="flex flex-row gap-2 items-center">
|
||||
<GroupIcon
|
||||
css={{
|
||||
width: "1rem",
|
||||
@@ -57,7 +53,7 @@ export const UserGroupsCell: FC<GroupsCellProps> = ({ userGroups }) => {
|
||||
<span>
|
||||
{userGroups.length} Group{userGroups.length !== 1 && "s"}
|
||||
</span>
|
||||
</Stack>
|
||||
</div>
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user