feat(frontend): Add admin button to user profile dropdown (#10774)

<!-- Clearly explain the need for these changes: -->

### Need 💡

This PR addresses Linear issue
[OPEN-2232](https://linear.app/autogpt/issue/OPEN-2232/add-admin-pages-in-dropdown)
by adding an "Admin" button to the user account dropdown menu. This
button is only visible to users with an "admin" role and provides direct
navigation to the admin marketplace management page, making existing
admin functionalities accessible from the new UI.

### Changes 🏗️

<!-- Concisely describe all of the changes made in this pull request:
-->

- **Added Admin Icon**: Integrated `IconSliders` into the `IconType`
enum and `getAccountMenuOptionIcon` function.
- **Dynamic Menu Generation**: Introduced
`getAccountMenuItems(userRole?: string)` to dynamically construct the
account menu. This function conditionally adds an "Admin" menu item
(linking to `/admin/marketplace`) if the `userRole` is "admin".
- **Navbar Integration**: Updated `NavbarView.tsx` to utilize the
`useSupabase` hook to retrieve the current user's role and then render
the account menu using the new dynamic `getAccountMenuItems` function
for both desktop and mobile views.

### Checklist 📋

#### For code changes:
- [x] I have clearly listed my changes in the PR description
- [x] I have made a test plan
- [x] I have tested my changes according to the test plan:
  <!-- Put your test plan here: -->
- [x] Log in as an admin user and verify the "Admin" button appears in
the account dropdown.
- [x] Click the "Admin" button and confirm navigation to
`/admin/marketplace`.
- [x] Log in as a non-admin user and verify the "Admin" button does not
appear in the account dropdown.
- [x] Verify all other existing menu items (e.g., "Edit profile", "Log
out") function correctly for both admin and non-admin users.
  - [x] Test the above scenarios on both desktop and mobile views.

---
Linear Issue:
[OPEN-2232](https://linear.app/autogpt/issue/OPEN-2232/add-admin-pages-in-dropdown)

<a
href="https://cursor.com/background-agent?bcId=bc-2dceda38-31b4-4e8e-8277-fb87c8858abf">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-cursor-dark.svg">
<source media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-cursor-light.svg">
<img alt="Open in Cursor" src="https://cursor.com/open-in-cursor.svg">
  </picture>
</a>
<a
href="https://cursor.com/agents?id=bc-2dceda38-31b4-4e8e-8277-fb87c8858abf">
  <picture>
<source media="(prefers-color-scheme: dark)"
srcset="https://cursor.com/open-in-web-dark.svg">
<source media="(prefers-color-scheme: light)"
srcset="https://cursor.com/open-in-web-light.svg">
    <img alt="Open in Web" src="https://cursor.com/open-in-web.svg">
  </picture>
</a>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
Nicholas Tindle
2025-09-03 04:26:24 -05:00
committed by GitHub
parent 57ecc10535
commit 6d39dfe382
3 changed files with 74 additions and 3 deletions

View File

@@ -5,15 +5,17 @@ import { AccountMenu } from "./AccountMenu/AccountMenu";
import { LoginButton } from "./LoginButton";
import { MobileNavBar } from "./MobileNavbar/MobileNavBar";
import { NavbarLink } from "./NavbarLink";
import { accountMenuItems, loggedInLinks, loggedOutLinks } from "../helpers";
import { getAccountMenuItems, loggedInLinks, loggedOutLinks } from "../helpers";
import { useGetV2GetUserProfile } from "@/app/api/__generated__/endpoints/store/store";
import { AgentActivityDropdown } from "./AgentActivityDropdown/AgentActivityDropdown";
import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
interface NavbarViewProps {
isLoggedIn: boolean;
}
export const NavbarView = ({ isLoggedIn }: NavbarViewProps) => {
const { user } = useSupabase();
const { data: profile } = useGetV2GetUserProfile({
query: {
select: (res) => (res.status === 200 ? res.data : null),
@@ -21,6 +23,8 @@ export const NavbarView = ({ isLoggedIn }: NavbarViewProps) => {
},
});
const dynamicMenuItems = getAccountMenuItems(user?.role);
return (
<>
<nav className="sticky top-0 z-40 hidden h-16 items-center border border-white/50 bg-[#f3f4f6]/20 p-3 backdrop-blur-[26px] md:inline-flex">
@@ -50,7 +54,7 @@ export const NavbarView = ({ isLoggedIn }: NavbarViewProps) => {
userName={profile?.username}
userEmail={profile?.name}
avatarSrc={profile?.avatar_url ?? ""}
menuItemGroups={accountMenuItems}
menuItemGroups={dynamicMenuItems}
/>
</div>
) : (
@@ -83,7 +87,7 @@ export const NavbarView = ({ isLoggedIn }: NavbarViewProps) => {
href: link.href,
})),
},
...accountMenuItems,
...dynamicMenuItems,
]}
userEmail={profile?.name}
avatarSrc={profile?.avatar_url ?? ""}

View File

@@ -7,6 +7,7 @@ import {
IconMarketplace,
IconRefresh,
IconSettings,
IconSliders,
IconType,
IconUploadCloud,
} from "@/components/ui/icons";
@@ -90,6 +91,69 @@ export const accountMenuItems: MenuItemGroup[] = [
},
];
export function getAccountMenuItems(userRole?: string): MenuItemGroup[] {
const baseMenuItems: MenuItemGroup[] = [
{
items: [
{
icon: IconType.Edit,
text: "Edit profile",
href: "/profile",
},
],
},
{
items: [
{
icon: IconType.LayoutDashboard,
text: "Creator Dashboard",
href: "/profile/dashboard",
},
{
icon: IconType.UploadCloud,
text: "Publish an agent",
},
],
},
];
// Add admin menu item for admin users
if (userRole === "admin") {
baseMenuItems.push({
items: [
{
icon: IconType.Sliders,
text: "Admin",
href: "/admin/marketplace",
},
],
});
}
// Add settings and logout
baseMenuItems.push(
{
items: [
{
icon: IconType.Settings,
text: "Settings",
href: "/profile/settings",
},
],
},
{
items: [
{
icon: IconType.LogOut,
text: "Log out",
},
],
},
);
return baseMenuItems;
}
export function getAccountMenuOptionIcon(icon: IconType) {
const iconClass = "w-6 h-6";
switch (icon) {
@@ -109,6 +173,8 @@ export function getAccountMenuOptionIcon(icon: IconType) {
return <IconLibrary className={iconClass} />;
case IconType.Builder:
return <IconBuilder className={iconClass} />;
case IconType.Sliders:
return <IconSliders className={iconClass} />;
default:
return <IconRefresh className={iconClass} />;
}

View File

@@ -1836,6 +1836,7 @@ export enum IconType {
Settings,
LogOut,
AutoGPTLogo,
Sliders,
}
export function getIconForSocial(