From 3e45f785a0bde86226b6eb758666ba59bcf48d74 Mon Sep 17 00:00:00 2001 From: James Ritchie Date: Wed, 7 May 2025 18:38:00 +0100 Subject: [PATCH] Dashboard: Org menu improvements for admins (#1969) * Adds path for admin route * Updates impersonation banner and show new org button if only 1 org * Simpler UI for displaying admin access --- .../app/components/ImpersonationBanner.tsx | 32 ++++++++------ .../app/components/navigation/SideMenu.tsx | 42 ++++++++++++++----- apps/webapp/app/utils/pathBuilder.ts | 4 ++ 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/apps/webapp/app/components/ImpersonationBanner.tsx b/apps/webapp/app/components/ImpersonationBanner.tsx index 367f31dfd..1ef5bff64 100644 --- a/apps/webapp/app/components/ImpersonationBanner.tsx +++ b/apps/webapp/app/components/ImpersonationBanner.tsx @@ -1,21 +1,29 @@ import { UserMinusIcon } from "@heroicons/react/20/solid"; import { Form } from "@remix-run/react"; import { Button } from "./primitives/Buttons"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./primitives/Tooltip"; export function ImpersonationBanner() { return ( -
-
- +
+ + + + +
); diff --git a/apps/webapp/app/components/navigation/SideMenu.tsx b/apps/webapp/app/components/navigation/SideMenu.tsx index 3efea3273..fe6d57e7c 100644 --- a/apps/webapp/app/components/navigation/SideMenu.tsx +++ b/apps/webapp/app/components/navigation/SideMenu.tsx @@ -16,6 +16,7 @@ import { RectangleStackIcon, ServerStackIcon, Squares2X2Icon, + UsersIcon, } from "@heroicons/react/20/solid"; import { useLocation, useNavigation } from "@remix-run/react"; import { useEffect, useRef, useState, type ReactNode } from "react"; @@ -28,12 +29,14 @@ import { Avatar } from "~/components/primitives/Avatar"; import { type MatchedEnvironment } from "~/hooks/useEnvironment"; import { type MatchedOrganization } from "~/hooks/useOrganizations"; import { type MatchedProject } from "~/hooks/useProject"; +import { useHasAdminAccess } from "~/hooks/useUser"; import { type User } from "~/models/user.server"; import { useCurrentPlan } from "~/routes/_app.orgs.$organizationSlug/route"; import { type FeedbackType } from "~/routes/resources.feedback"; import { cn } from "~/utils/cn"; import { accountPath, + adminPath, logoutPath, newOrganizationPath, newProjectPath, @@ -110,6 +113,7 @@ export function SideMenu({ const currentPlan = useCurrentPlan(); const { isConnected } = useDevPresence(); const isFreeUser = currentPlan?.v3Subscription?.isPaying === false; + const isAdmin = useHasAdminAccess(); useEffect(() => { const handleScroll = () => { @@ -143,6 +147,20 @@ export function SideMenu({ project={project} user={user} /> + {isAdmin && !user.isImpersonating ? ( + + + + + + + Admin dashboard + + + + ) : isAdmin && user.isImpersonating ? ( + + ) : null}
@@ -412,19 +427,24 @@ function ProjectSelector({
- + {organizations.length > 1 ? ( + + ) : ( + + )}
- {user.isImpersonating && }
diff --git a/apps/webapp/app/utils/pathBuilder.ts b/apps/webapp/app/utils/pathBuilder.ts index 6996eff9d..c4d48c343 100644 --- a/apps/webapp/app/utils/pathBuilder.ts +++ b/apps/webapp/app/utils/pathBuilder.ts @@ -430,3 +430,7 @@ export function docsPath(path: string) { export function docsTroubleshootingPath(path: string) { return `${docsRoot()}/v3/troubleshooting`; } + +export function adminPath() { + return `/@`; +}