-
Notifications
You must be signed in to change notification settings - Fork 899
feat(site): add deployment menu to navbar #13401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
7c5a750
aa11ae9
c29e76c
b081a12
9104fce
c3d8207
b28025a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react"; | ||
import Button from "@mui/material/Button"; | ||
import MenuItem from "@mui/material/MenuItem"; | ||
import { type FC } from "react"; | ||
Check failure on line 4 in site/src/modules/dashboard/Navbar/DeploymentDropdown.tsx
|
||
import { NavLink } from "react-router-dom"; | ||
import { DropdownArrow } from "components/DropdownArrow/DropdownArrow"; | ||
import { | ||
Check failure on line 7 in site/src/modules/dashboard/Navbar/DeploymentDropdown.tsx
|
||
Popover, | ||
PopoverContent, | ||
PopoverTrigger, | ||
usePopover, | ||
} from "components/Popover/Popover"; | ||
|
||
import { USERS_LINK } from "modules/navigation"; | ||
|
||
interface DeploymentDropdownProps { | ||
canViewAuditLog: boolean; | ||
canViewDeployment: boolean; | ||
canViewAllUsers: boolean; | ||
canViewHealth: boolean; | ||
} | ||
|
||
export const DeploymentDropdown: FC<DeploymentDropdownProps> = ({ | ||
canViewAuditLog, | ||
canViewDeployment, | ||
canViewAllUsers, | ||
canViewHealth, | ||
}) => { | ||
const theme = useTheme(); | ||
|
||
if ( | ||
!canViewAuditLog && | ||
!canViewDeployment && | ||
!canViewAllUsers && | ||
!canViewHealth | ||
) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Popover> | ||
<PopoverTrigger> | ||
<Button> | ||
Deployment | ||
<DropdownArrow | ||
color={theme.experimental.l2.fill.solid} | ||
close={false} | ||
/> | ||
</Button> | ||
</PopoverTrigger> | ||
|
||
<PopoverContent | ||
horizontal="right" | ||
css={{ | ||
".MuiPaper-root": { | ||
minWidth: "auto", | ||
width: 180, | ||
boxShadow: theme.shadows[6], | ||
}, | ||
}} | ||
> | ||
<DeploymentDropdownContent | ||
canViewAuditLog={canViewAuditLog} | ||
canViewDeployment={canViewDeployment} | ||
canViewAllUsers={canViewAllUsers} | ||
canViewHealth={canViewHealth} | ||
/> | ||
</PopoverContent> | ||
</Popover> | ||
); | ||
}; | ||
|
||
const DeploymentDropdownContent: FC<DeploymentDropdownProps> = ({ | ||
canViewAuditLog, | ||
canViewDeployment, | ||
canViewAllUsers, | ||
canViewHealth, | ||
}) => { | ||
const popover = usePopover(); | ||
|
||
const onPopoverClose = () => popover.setIsOpen(false); | ||
|
||
return ( | ||
<nav> | ||
{canViewDeployment && ( | ||
<NavLink css={styles.link} to="/deployment/general"> | ||
<MenuItem css={styles.menuItem} onClick={onPopoverClose}> | ||
Settings | ||
</MenuItem> | ||
</NavLink> | ||
)} | ||
{canViewAllUsers && ( | ||
<NavLink css={styles.link} to={USERS_LINK}> | ||
<MenuItem css={styles.menuItem} onClick={onPopoverClose}> | ||
Users | ||
</MenuItem> | ||
</NavLink> | ||
)} | ||
{canViewAuditLog && ( | ||
<NavLink css={styles.link} to="/audit"> | ||
<MenuItem css={styles.menuItem} onClick={onPopoverClose}> | ||
Auditing | ||
</MenuItem> | ||
</NavLink> | ||
)} | ||
{canViewHealth && ( | ||
<NavLink css={styles.link} to="/health"> | ||
<MenuItem css={styles.menuItem} onClick={onPopoverClose}> | ||
Healthcheck | ||
</MenuItem> | ||
</NavLink> | ||
)} | ||
</nav> | ||
); | ||
}; | ||
|
||
const styles = { | ||
link: { | ||
textDecoration: "none", | ||
color: "inherit", | ||
}, | ||
menuItem: (theme) => css` | ||
gap: 20px; | ||
padding: 8px 20px; | ||
font-size: 14px; | ||
|
||
&:hover { | ||
background-color: ${theme.palette.action.hover}; | ||
transition: background-color 0.3s ease; | ||
} | ||
`, | ||
menuItemIcon: (theme) => ({ | ||
color: theme.palette.text.secondary, | ||
width: 20, | ||
height: 20, | ||
}), | ||
} satisfies Record<string, Interpolation<Theme>>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,10 +9,11 @@ | |
import MenuItem from "@mui/material/MenuItem"; | ||
import Skeleton from "@mui/material/Skeleton"; | ||
import { visuallyHidden } from "@mui/utils"; | ||
import { type FC, type ReactNode, useRef, useState } from "react"; | ||
import { type FC, useRef, useState } from "react"; | ||
import { NavLink, useLocation, useNavigate } from "react-router-dom"; | ||
import type * as TypesGen from "api/typesGenerated"; | ||
import { Abbr } from "components/Abbr/Abbr"; | ||
import { DropdownArrow } from "components/DropdownArrow/DropdownArrow"; | ||
Check failure on line 16 in site/src/modules/dashboard/Navbar/NavbarView.tsx
|
||
import { ExternalImage } from "components/ExternalImage/ExternalImage"; | ||
import { displayError } from "components/GlobalSnackbar/utils"; | ||
import { CoderIcon } from "components/Icons/CoderIcon"; | ||
|
@@ -21,10 +22,7 @@ | |
import type { ProxyContextValue } from "contexts/ProxyContext"; | ||
import { BUTTON_SM_HEIGHT, navHeight } from "theme/constants"; | ||
import { UserDropdown } from "./UserDropdown/UserDropdown"; | ||
|
||
export const USERS_LINK = `/users?filter=${encodeURIComponent( | ||
"status:active", | ||
)}`; | ||
import { DeploymentDropdown } from "./DeploymentDropdown"; | ||
Check failure on line 25 in site/src/modules/dashboard/Navbar/NavbarView.tsx
|
||
|
||
export interface NavbarViewProps { | ||
logo_url?: string; | ||
|
@@ -44,25 +42,14 @@ | |
templates: "Templates", | ||
users: "Users", | ||
audit: "Audit", | ||
deployment: "Deployment", | ||
deployment: "Settings", | ||
}; | ||
|
||
interface NavItemsProps { | ||
children?: ReactNode; | ||
className?: string; | ||
canViewAuditLog: boolean; | ||
canViewDeployment: boolean; | ||
canViewAllUsers: boolean; | ||
canViewHealth: boolean; | ||
} | ||
|
||
const NavItems: FC<NavItemsProps> = ({ | ||
className, | ||
canViewAuditLog, | ||
canViewDeployment, | ||
canViewAllUsers, | ||
canViewHealth, | ||
}) => { | ||
const NavItems: FC<NavItemsProps> = ({ className }) => { | ||
const location = useLocation(); | ||
const theme = useTheme(); | ||
|
||
|
@@ -83,26 +70,6 @@ | |
<NavLink css={styles.link} to="/templates"> | ||
{Language.templates} | ||
</NavLink> | ||
{canViewAllUsers && ( | ||
<NavLink css={styles.link} to={USERS_LINK}> | ||
{Language.users} | ||
</NavLink> | ||
)} | ||
{canViewAuditLog && ( | ||
<NavLink css={styles.link} to="/audit"> | ||
{Language.audit} | ||
</NavLink> | ||
)} | ||
{canViewDeployment && ( | ||
<NavLink css={styles.link} to="/deployment/general"> | ||
{Language.deployment} | ||
</NavLink> | ||
)} | ||
{canViewHealth && ( | ||
<NavLink css={styles.link} to="/health"> | ||
Health | ||
</NavLink> | ||
)} | ||
</nav> | ||
); | ||
}; | ||
|
@@ -157,12 +124,7 @@ | |
)} | ||
</div> | ||
</div> | ||
<NavItems | ||
canViewAuditLog={canViewAuditLog} | ||
canViewDeployment={canViewDeployment} | ||
canViewAllUsers={canViewAllUsers} | ||
canViewHealth={canViewHealth} | ||
/> | ||
<NavItems /> | ||
</div> | ||
</Drawer> | ||
|
||
|
@@ -174,18 +136,20 @@ | |
)} | ||
</NavLink> | ||
|
||
<NavItems | ||
css={styles.desktopNavItems} | ||
canViewAuditLog={canViewAuditLog} | ||
canViewDeployment={canViewDeployment} | ||
canViewAllUsers={canViewAllUsers} | ||
canViewHealth={canViewHealth} | ||
/> | ||
<NavItems css={styles.desktopNavItems} /> | ||
|
||
<div css={styles.navMenus}> | ||
{proxyContextValue && ( | ||
<ProxyMenu proxyContextValue={proxyContextValue} /> | ||
)} | ||
|
||
<DeploymentDropdown | ||
canViewAuditLog={canViewAuditLog} | ||
canViewDeployment={canViewDeployment} | ||
canViewAllUsers={canViewAllUsers} | ||
canViewHealth={canViewHealth} | ||
/> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if we can pass the root permissions to the component instead of creating derived values for each option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. eh, I don't mind this. the root permissions names are a lot less clear imo, so having the |
||
|
||
{user && ( | ||
<UserDropdown | ||
user={user} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* @fileoverview TODO: centralize navigation code here! URL constants, URL formatting, all of it | ||
*/ | ||
|
||
export const USERS_LINK = `/users?filter=${encodeURIComponent( | ||
"status:active", | ||
)}`; |
Uh oh!
There was an error while loading. Please reload this page.