mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
chore: apply design changes to the admin settings menu dropdown (#15947)
resolves coder/internal#177 Design changes for the admin settings menu dropdown <img width="327" alt="Screenshot 2024-12-20 at 17 44 48" src="https://github.com/user-attachments/assets/04af04b3-bfa2-4659-b31c-58252bf43c05" />
This commit is contained in:
@@ -84,7 +84,7 @@ test("change quota settings", async ({ page }) => {
|
||||
|
||||
// Go to settings
|
||||
await page.goto(`/organizations/${org.name}/groups/${group.name}`);
|
||||
await page.getByRole("button", { name: "Settings" }).click();
|
||||
await page.getByRole("button", { name: "Settings", exact: true }).click();
|
||||
expectUrl(page).toHavePathName(
|
||||
`/organizations/${org.name}/groups/${group.name}/settings`,
|
||||
);
|
||||
@@ -99,6 +99,6 @@ test("change quota settings", async ({ page }) => {
|
||||
);
|
||||
|
||||
// ...and that setting should persist if we go back
|
||||
await page.getByRole("button", { name: "Settings" }).click();
|
||||
await page.getByRole("button", { name: "Settings", exact: true }).click();
|
||||
await expect(page.getByLabel("Quota Allowance")).toHaveValue("100");
|
||||
});
|
||||
|
||||
@@ -19,12 +19,14 @@ type FeatureStageBadgeProps = Readonly<
|
||||
Omit<HTMLAttributes<HTMLSpanElement>, "children"> & {
|
||||
contentType: keyof typeof featureStageBadgeTypes;
|
||||
size?: "sm" | "md" | "lg";
|
||||
showTooltip?: boolean;
|
||||
}
|
||||
>;
|
||||
|
||||
export const FeatureStageBadge: FC<FeatureStageBadgeProps> = ({
|
||||
contentType,
|
||||
size = "md",
|
||||
showTooltip = true, // This is a temporary until the deprecated popover is removed
|
||||
...delegatedProps
|
||||
}) => {
|
||||
return (
|
||||
@@ -49,24 +51,26 @@ export const FeatureStageBadge: FC<FeatureStageBadgeProps> = ({
|
||||
)}
|
||||
</PopoverTrigger>
|
||||
|
||||
<HelpTooltipContent
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "center" }}
|
||||
>
|
||||
<p css={styles.tooltipDescription}>
|
||||
This feature has not yet reached general availability (GA).
|
||||
</p>
|
||||
|
||||
<Link
|
||||
href={docs("/contributing/feature-stages")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
css={styles.tooltipLink}
|
||||
{showTooltip && (
|
||||
<HelpTooltipContent
|
||||
anchorOrigin={{ vertical: "bottom", horizontal: "center" }}
|
||||
transformOrigin={{ vertical: "top", horizontal: "center" }}
|
||||
>
|
||||
Learn about feature stages
|
||||
<span style={visuallyHidden}> (link opens in new tab)</span>
|
||||
</Link>
|
||||
</HelpTooltipContent>
|
||||
<p css={styles.tooltipDescription}>
|
||||
This feature has not yet reached general availability (GA).
|
||||
</p>
|
||||
|
||||
<Link
|
||||
href={docs("/contributing/feature-stages")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
css={styles.tooltipLink}
|
||||
>
|
||||
Learn about feature stages
|
||||
<span style={visuallyHidden}> (link opens in new tab)</span>
|
||||
</Link>
|
||||
</HelpTooltipContent>
|
||||
)}
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,13 +2,14 @@ import { type Interpolation, type Theme, css, useTheme } from "@emotion/react";
|
||||
import Button from "@mui/material/Button";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import { DropdownArrow } from "components/DropdownArrow/DropdownArrow";
|
||||
import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge";
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
usePopover,
|
||||
} from "components/deprecated/Popover/Popover";
|
||||
import { linkToAuditing, linkToUsers } from "modules/navigation";
|
||||
import { linkToAuditing } from "modules/navigation";
|
||||
import type { FC } from "react";
|
||||
import { NavLink } from "react-router-dom";
|
||||
|
||||
@@ -52,7 +53,7 @@ export const DeploymentDropdown: FC<DeploymentDropdownProps> = ({
|
||||
/>
|
||||
}
|
||||
>
|
||||
Administration
|
||||
Admin settings
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
|
||||
@@ -81,7 +82,6 @@ export const DeploymentDropdown: FC<DeploymentDropdownProps> = ({
|
||||
const DeploymentDropdownContent: FC<DeploymentDropdownProps> = ({
|
||||
canViewDeployment,
|
||||
canViewOrganizations,
|
||||
canViewAllUsers,
|
||||
canViewAuditLog,
|
||||
canViewHealth,
|
||||
}) => {
|
||||
@@ -98,7 +98,7 @@ const DeploymentDropdownContent: FC<DeploymentDropdownProps> = ({
|
||||
css={styles.menuItem}
|
||||
onClick={onPopoverClose}
|
||||
>
|
||||
Settings
|
||||
Deployment
|
||||
</MenuItem>
|
||||
)}
|
||||
{canViewOrganizations && (
|
||||
@@ -109,16 +109,7 @@ const DeploymentDropdownContent: FC<DeploymentDropdownProps> = ({
|
||||
onClick={onPopoverClose}
|
||||
>
|
||||
Organizations
|
||||
</MenuItem>
|
||||
)}
|
||||
{canViewAllUsers && (
|
||||
<MenuItem
|
||||
component={NavLink}
|
||||
to={linkToUsers}
|
||||
css={styles.menuItem}
|
||||
onClick={onPopoverClose}
|
||||
>
|
||||
Users
|
||||
<FeatureStageBadge contentType="beta" size="sm" showTooltip={false} />
|
||||
</MenuItem>
|
||||
)}
|
||||
{canViewAuditLog && (
|
||||
|
||||
@@ -22,7 +22,7 @@ describe("Navbar", () => {
|
||||
}),
|
||||
);
|
||||
render(<App />);
|
||||
const deploymentMenu = await screen.findByText("Administration");
|
||||
const deploymentMenu = await screen.findByText("Admin settings");
|
||||
await userEvent.click(deploymentMenu);
|
||||
await waitFor(
|
||||
() => {
|
||||
@@ -37,7 +37,7 @@ describe("Navbar", () => {
|
||||
// by default, user is an Admin with permission to see the audit log,
|
||||
// but is unlicensed so not entitled to see the audit log
|
||||
render(<App />);
|
||||
const deploymentMenu = await screen.findByText("Administration");
|
||||
const deploymentMenu = await screen.findByText("Admin settings");
|
||||
await userEvent.click(deploymentMenu);
|
||||
await waitFor(
|
||||
() => {
|
||||
|
||||
@@ -27,7 +27,7 @@ export const ForAdmin: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await userEvent.click(
|
||||
canvas.getByRole("button", { name: "Administration" }),
|
||||
canvas.getByRole("button", { name: "Admin settings" }),
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -44,7 +44,7 @@ export const ForAuditor: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await userEvent.click(
|
||||
canvas.getByRole("button", { name: "Administration" }),
|
||||
canvas.getByRole("button", { name: "Admin settings" }),
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -61,7 +61,7 @@ export const ForOrgAdmin: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await userEvent.click(
|
||||
canvas.getByRole("button", { name: "Administration" }),
|
||||
canvas.getByRole("button", { name: "Admin settings" }),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -56,25 +56,6 @@ describe("NavbarView", () => {
|
||||
expect((templatesLink as HTMLAnchorElement).href).toContain("/templates");
|
||||
});
|
||||
|
||||
it("users nav link has the correct href", async () => {
|
||||
renderWithAuth(
|
||||
<NavbarView
|
||||
proxyContextValue={proxyContextValue}
|
||||
user={MockUser}
|
||||
onSignOut={noop}
|
||||
canViewDeployment
|
||||
canViewOrganizations
|
||||
canViewAllUsers
|
||||
canViewHealth
|
||||
canViewAuditLog
|
||||
/>,
|
||||
);
|
||||
const deploymentMenu = await screen.findByText("Administration");
|
||||
await userEvent.click(deploymentMenu);
|
||||
const userLink = await screen.findByText(navLanguage.users);
|
||||
expect((userLink as HTMLAnchorElement).href).toContain("/users");
|
||||
});
|
||||
|
||||
it("audit nav link has the correct href", async () => {
|
||||
renderWithAuth(
|
||||
<NavbarView
|
||||
@@ -88,7 +69,7 @@ describe("NavbarView", () => {
|
||||
canViewAuditLog
|
||||
/>,
|
||||
);
|
||||
const deploymentMenu = await screen.findByText("Administration");
|
||||
const deploymentMenu = await screen.findByText("Admin settings");
|
||||
await userEvent.click(deploymentMenu);
|
||||
const auditLink = await screen.findByText(navLanguage.audit);
|
||||
expect((auditLink as HTMLAnchorElement).href).toContain("/audit");
|
||||
@@ -107,7 +88,7 @@ describe("NavbarView", () => {
|
||||
canViewAuditLog
|
||||
/>,
|
||||
);
|
||||
const deploymentMenu = await screen.findByText("Administration");
|
||||
const deploymentMenu = await screen.findByText("Admin settings");
|
||||
await userEvent.click(deploymentMenu);
|
||||
const deploymentSettingsLink = await screen.findByText(
|
||||
navLanguage.deployment,
|
||||
|
||||
@@ -32,7 +32,7 @@ export const Language = {
|
||||
templates: "Templates",
|
||||
users: "Users",
|
||||
audit: "Audit Logs",
|
||||
deployment: "Settings",
|
||||
deployment: "Deployment",
|
||||
};
|
||||
|
||||
interface NavItemsProps {
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "components/Breadcrumb/Breadcrumb";
|
||||
import { FeatureStageBadge } from "components/FeatureStageBadge/FeatureStageBadge";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { RequirePermission } from "contexts/auth/RequirePermission";
|
||||
@@ -81,8 +82,12 @@ const OrganizationSettingsLayout: FC = () => {
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink href="/organizations">
|
||||
<BreadcrumbLink
|
||||
href="/organizations"
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
Organizations
|
||||
<FeatureStageBadge contentType="beta" size="sm" />
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
{organization && (
|
||||
|
||||
Reference in New Issue
Block a user