feat(site): embed users page in management settings (#14006)

This commit is contained in:
Kayla Washburn-Love
2024-07-25 10:50:07 -06:00
committed by GitHub
parent 6161d173d3
commit 615bb94ec4
7 changed files with 70 additions and 12 deletions
@@ -32,10 +32,10 @@ export const CreateUserPage: FC = () => {
onSubmit={async (user) => {
await createUserMutation.mutateAsync(user);
displaySuccess("Successfully created user.");
navigate("/users");
navigate("..", { relative: "path" });
}}
onCancel={() => {
navigate("/users");
navigate("..", { relative: "path" });
}}
isLoading={createUserMutation.isLoading}
organizationId={organizationId}
@@ -9,6 +9,7 @@ import { Sidebar as BaseSidebar } from "components/Sidebar/Sidebar";
import { Stack } from "components/Stack/Stack";
import { UserAvatar } from "components/UserAvatar/UserAvatar";
import { type ClassName, useClassName } from "hooks/useClassName";
import { USERS_LINK } from "modules/navigation";
import { useOrganizationSettings } from "./ManagementSettingsLayout";
export const Sidebar: FC = () => {
@@ -77,7 +78,9 @@ const DeploymentSettingsNavigation: FC = () => {
<SidebarNavSubItem href="observability">
Observability
</SidebarNavSubItem>
<SidebarNavSubItem href="/users">Users</SidebarNavSubItem>
<SidebarNavSubItem href={USERS_LINK.slice(1)}>
Users
</SidebarNavSubItem>
</Stack>
)}
</div>
+3 -1
View File
@@ -27,6 +27,8 @@ export const UsersLayout: FC = () => {
const location = useLocation();
const activeTab = location.pathname.endsWith("groups") ? "groups" : "users";
const isMultiOrg = experiments.includes("multi-organization");
return (
<>
<Margins>
@@ -59,7 +61,7 @@ export const UsersLayout: FC = () => {
</PageHeader>
</Margins>
{!experiments.includes("multi-organization") && (
{!isMultiOrg && (
<Tabs
css={{ marginBottom: 40, marginTop: -TAB_PADDING_Y }}
active={activeTab}
+23 -4
View File
@@ -1,7 +1,12 @@
import { type FC, useState } from "react";
import { Helmet } from "react-helmet-async";
import { useMutation, useQuery, useQueryClient } from "react-query";
import { useSearchParams, useNavigate } from "react-router-dom";
import {
useSearchParams,
useNavigate,
Navigate,
useLocation,
} from "react-router-dom";
import { getErrorMessage } from "api/errors";
import { deploymentConfig } from "api/queries/deployment";
import { groupsByUserId } from "api/queries/groups";
@@ -33,16 +38,21 @@ import { UsersPageView } from "./UsersPageView";
const UsersPage: FC = () => {
const queryClient = useQueryClient();
const navigate = useNavigate();
const location = useLocation();
const searchParamsResult = useSearchParams();
const { entitlements, organizationId } = useDashboard();
const { entitlements, experiments, organizationId } = useDashboard();
const [searchParams] = searchParamsResult;
const isMultiOrg = experiments.includes("multi-organization");
const groupsByUserIdQuery = useQuery(groupsByUserId(organizationId));
const authMethodsQuery = useQuery(authMethods());
const { permissions, user: me } = useAuthenticated();
const { updateUsers: canEditUsers, viewDeploymentValues } = permissions;
const {
createUser: canCreateUser,
updateUsers: canEditUsers,
viewDeploymentValues,
} = permissions;
const rolesQuery = useQuery(roles());
const { data: deploymentValues } = useQuery({
...deploymentConfig(),
@@ -93,6 +103,13 @@ const UsersPage: FC = () => {
authMethodsQuery.isLoading ||
groupsByUserIdQuery.isLoading;
if (
experiments.includes("multi-organization") &&
location.pathname !== "/deployment/users"
) {
return <Navigate to={`/deployment/users${location.search}`} replace />;
}
return (
<>
<Helmet>
@@ -147,6 +164,8 @@ const UsersPage: FC = () => {
menus: { status: statusMenu },
}}
usersQuery={usersQuery}
isMultiOrg={isMultiOrg}
canCreateUser={canCreateUser}
/>
<DeleteDialog
@@ -1,6 +1,10 @@
import PersonAdd from "@mui/icons-material/PersonAdd";
import Button from "@mui/material/Button";
import type { ComponentProps, FC } from "react";
import { useNavigate } from "react-router-dom";
import type { GroupsByUserId } from "api/queries/groups";
import type * as TypesGen from "api/typesGenerated";
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
import {
PaginationContainer,
type PaginationResult,
@@ -32,6 +36,10 @@ export interface UsersPageViewProps {
actorID: string;
groupsByUserId: GroupsByUserId | undefined;
usersQuery: PaginationResult;
// TODO: Refactor these out once we remove the multi-organization experiment.
isMultiOrg?: boolean;
canCreateUser?: boolean;
}
export const UsersPageView: FC<UsersPageViewProps> = ({
@@ -55,9 +63,33 @@ export const UsersPageView: FC<UsersPageViewProps> = ({
authMethods,
groupsByUserId,
usersQuery,
isMultiOrg,
canCreateUser,
}) => {
const navigate = useNavigate();
return (
<>
{isMultiOrg && (
<PageHeader
css={{ paddingTop: 0 }}
actions={
<>
{canCreateUser && (
<Button
onClick={() => navigate("create")}
startIcon={<PersonAdd />}
>
Create user
</Button>
)}
</>
}
>
<PageHeaderTitle>Users</PageHeaderTitle>
</PageHeader>
)}
<UsersFilter {...filterProps} />
<PaginationContainer query={usersQuery} paginationUnitLabel="users">
@@ -69,7 +69,7 @@ export const UsersTable: FC<UsersTableProps> = ({
<Table data-testid="users-table">
<TableHead>
<TableRow>
<TableCell width="29%">{Language.usernameLabel}</TableCell>
<TableCell width="32%">{Language.usernameLabel}</TableCell>
<TableCell width="29%">
<Stack direction="row" spacing={1} alignItems="center">
@@ -78,15 +78,15 @@ export const UsersTable: FC<UsersTableProps> = ({
</Stack>
</TableCell>
<TableCell width="14%">
<TableCell width="13%">
<Stack direction="row" spacing={1} alignItems="center">
<span>{Language.groupsLabel}</span>
<TableColumnHelpTooltip variant="groups" />
</Stack>
</TableCell>
<TableCell width="14%">{Language.loginTypeLabel}</TableCell>
<TableCell width="14%">{Language.statusLabel}</TableCell>
<TableCell width="13%">{Language.loginTypeLabel}</TableCell>
<TableCell width="13%">{Language.statusLabel}</TableCell>
{/* 1% is a trick to make the table cell width fit the content */}
{canEditUsers && <TableCell width="1%" />}
+2
View File
@@ -407,6 +407,8 @@ export const router = createBrowserRouter(
</Route>
<Route path="workspace-proxies" element={<WorkspaceProxyPage />} />
<Route path="users" element={<UsersPage />} />
<Route path="users/create" element={<CreateUserPage />} />
</Route>
<Route path="/settings" element={<UserSettingsLayout />}>