Skip to content

Commit 5e2a96e

Browse files
committed
Updates impersonation banner and show new org button if only 1 org
1 parent 3c5946d commit 5e2a96e

File tree

2 files changed

+55
-24
lines changed

2 files changed

+55
-24
lines changed

apps/webapp/app/components/ImpersonationBanner.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
import { UserMinusIcon } from "@heroicons/react/20/solid";
22
import { Form } from "@remix-run/react";
33
import { Button } from "./primitives/Buttons";
4+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./primitives/Tooltip";
45

56
export function ImpersonationBanner() {
67
return (
7-
<div className="w-full">
8-
<Form action="/resources/impersonation" method="delete" reloadDocument className="w-full">
9-
<Button
10-
type="submit"
11-
variant="small-menu-item"
12-
LeadingIcon={UserMinusIcon}
13-
fullWidth
14-
textAlignLeft
15-
className="text-amber-400"
16-
>
17-
Stop impersonating
18-
</Button>
8+
<div>
9+
<Form action="/resources/impersonation" method="delete" reloadDocument>
10+
<TooltipProvider disableHoverableContent={true}>
11+
<Tooltip>
12+
<TooltipTrigger>
13+
<Button
14+
type="submit"
15+
variant="small-menu-item"
16+
LeadingIcon={UserMinusIcon}
17+
fullWidth
18+
textAlignLeft
19+
className="bg-amber-400 text-background-bright group-hover/button:bg-amber-300"
20+
/>
21+
</TooltipTrigger>
22+
<TooltipContent side="bottom" className={"text-xs"}>
23+
Stop impersonating
24+
</TooltipContent>
25+
</Tooltip>
26+
</TooltipProvider>
1927
</Form>
2028
</div>
2129
);

apps/webapp/app/components/navigation/SideMenu.tsx

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { type FeedbackType } from "~/routes/resources.feedback";
3333
import { cn } from "~/utils/cn";
3434
import {
3535
accountPath,
36+
adminPath,
3637
logoutPath,
3738
newOrganizationPath,
3839
newProjectPath,
@@ -76,6 +77,7 @@ import { HelpAndFeedback } from "./HelpAndFeedbackPopover";
7677
import { SideMenuHeader } from "./SideMenuHeader";
7778
import { SideMenuItem } from "./SideMenuItem";
7879
import { SideMenuSection } from "./SideMenuSection";
80+
import { useHasAdminAccess } from "~/hooks/useUser";
7981

8082
type SideMenuUser = Pick<User, "email" | "admin"> & { isImpersonating: boolean };
8183
export type SideMenuProject = Pick<
@@ -106,6 +108,7 @@ export function SideMenu({
106108
const currentPlan = useCurrentPlan();
107109
const { isConnected } = useDevPresence();
108110
const isFreeUser = currentPlan?.v3Subscription?.isPaying === false;
111+
const isAdmin = useHasAdminAccess();
109112

110113
useEffect(() => {
111114
const handleScroll = () => {
@@ -130,7 +133,8 @@ export function SideMenu({
130133
<div
131134
className={cn(
132135
"flex items-center justify-between overflow-hidden border-b px-1 py-1 transition duration-300",
133-
showHeaderDivider ? "border-grid-bright" : "border-transparent"
136+
showHeaderDivider ? "border-grid-bright" : "border-transparent",
137+
user.isImpersonating && "rounded-md border border-dashed border-amber-400"
134138
)}
135139
>
136140
<ProjectSelector
@@ -139,6 +143,23 @@ export function SideMenu({
139143
project={project}
140144
user={user}
141145
/>
146+
{isAdmin && (
147+
<TooltipProvider disableHoverableContent={true}>
148+
<Tooltip>
149+
<TooltipTrigger>
150+
<LinkButton
151+
variant="minimal/medium"
152+
to={adminPath()}
153+
TrailingIcon={Cog8ToothIcon}
154+
/>
155+
</TooltipTrigger>
156+
<TooltipContent side="bottom" className={"text-xs"}>
157+
Admin dashboard
158+
</TooltipContent>
159+
</Tooltip>
160+
</TooltipProvider>
161+
)}
162+
{user.isImpersonating && <ImpersonationBanner />}
142163
</div>
143164
<div
144165
className="overflow-hidden overflow-y-auto pt-2 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-charcoal-600"
@@ -319,10 +340,7 @@ function ProjectSelector({
319340
<PopoverArrowTrigger
320341
isOpen={isOrgMenuOpen}
321342
overflowHidden
322-
className={cn(
323-
"h-8 w-full justify-between py-1 pl-1.5",
324-
user.isImpersonating && "border border-dashed border-amber-400"
325-
)}
343+
className="h-8 w-full justify-between py-1 pl-1.5"
326344
>
327345
<span className="flex items-center gap-1.5 overflow-hidden">
328346
<Avatar avatar={organization.avatar} size={1.25} orgName={organization.title} />
@@ -406,19 +424,24 @@ function ProjectSelector({
406424
<PopoverMenuItem to={newProjectPath(organization)} title="New project" icon={PlusIcon} />
407425
</div>
408426
<div className="border-t border-charcoal-700 p-1">
409-
<SwitchOrganizations organizations={organizations} organization={organization} />
427+
{organizations.length > 1 ? (
428+
<SwitchOrganizations organizations={organizations} organization={organization} />
429+
) : (
430+
<PopoverMenuItem
431+
to={newOrganizationPath()}
432+
title="New organization"
433+
icon={PlusIcon}
434+
leadingIconClassName="text-text-dimmed"
435+
/>
436+
)}
410437
</div>
411438
<div className="border-t border-charcoal-700 p-1">
412439
<PopoverMenuItem
413440
to={accountPath()}
414441
title="Account"
415442
icon={UserProfilePhoto}
416-
leadingIconClassName={cn(
417-
"text-text-dimmed rounded-full border border-transparent",
418-
user.isImpersonating && "rounded-full border-yellow-500"
419-
)}
443+
leadingIconClassName="text-text-dimmed rounded-full border border-transparent"
420444
/>
421-
{user.isImpersonating && <ImpersonationBanner />}
422445
</div>
423446
<div className="border-t border-charcoal-700 p-1">
424447
<PopoverMenuItem
@@ -513,7 +536,7 @@ function SwitchOrganizations({
513536
<div className="border-t border-charcoal-700 p-1">
514537
<PopoverMenuItem
515538
to={newOrganizationPath()}
516-
title="New Organization"
539+
title="New organization"
517540
icon={PlusIcon}
518541
leadingIconClassName="text-text-dimmed"
519542
/>

0 commit comments

Comments
 (0)