mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-07 22:33:57 -05:00
Merge branch 'dev' into cursor/OPEN-2835-fix-xmlparserblock-list-object-error-29c3
This commit is contained in:
2
autogpt_platform/frontend/pnpm-lock.yaml
generated
2
autogpt_platform/frontend/pnpm-lock.yaml
generated
@@ -13011,7 +13011,7 @@ snapshots:
|
||||
minimatch: 3.1.2
|
||||
node-abort-controller: 3.1.1
|
||||
schema-utils: 3.3.0
|
||||
semver: 7.7.2
|
||||
semver: 7.7.3
|
||||
tapable: 2.2.3
|
||||
typescript: 5.9.3
|
||||
webpack: 5.101.3(esbuild@0.25.9)
|
||||
|
||||
@@ -1,13 +1,157 @@
|
||||
"use client";
|
||||
|
||||
import { useGetV2GetUserProfile } from "@/app/api/__generated__/endpoints/store/store";
|
||||
import { okData } from "@/app/api/helpers";
|
||||
import { IconAutoGPTLogo, IconType } from "@/components/__legacy__/ui/icons";
|
||||
import { PreviewBanner } from "@/components/layout/Navbar/components/PreviewBanner/PreviewBanner";
|
||||
import { useBreakpoint } from "@/lib/hooks/useBreakpoint";
|
||||
import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
|
||||
import { environment } from "@/services/environment";
|
||||
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
|
||||
import { AccountMenu } from "./components/AccountMenu/AccountMenu";
|
||||
import { AgentActivityDropdown } from "./components/AgentActivityDropdown/AgentActivityDropdown";
|
||||
import { LoginButton } from "./components/LoginButton";
|
||||
import { MobileNavBar } from "./components/MobileNavbar/MobileNavBar";
|
||||
import { NavbarLink } from "./components/NavbarLink";
|
||||
import { NavbarLoading } from "./components/NavbarLoading";
|
||||
import { Wallet } from "./components/Wallet/Wallet";
|
||||
import { getAccountMenuItems, loggedInLinks, loggedOutLinks } from "./helpers";
|
||||
|
||||
import { NavbarView } from "./components/NavbarView";
|
||||
import { getNavbarAccountData } from "./data";
|
||||
|
||||
export async function Navbar() {
|
||||
const { isLoggedIn } = await getNavbarAccountData();
|
||||
export function Navbar() {
|
||||
const { user, isLoggedIn, isUserLoading } = useSupabase();
|
||||
const breakpoint = useBreakpoint();
|
||||
const isSmallScreen = breakpoint === "sm" || breakpoint === "base";
|
||||
const dynamicMenuItems = getAccountMenuItems(user?.role);
|
||||
const isChatEnabled = useGetFlag(Flag.CHAT);
|
||||
const previewBranchName = environment.getPreviewStealingDev();
|
||||
|
||||
const { data: profile, isLoading: isProfileLoading } = useGetV2GetUserProfile(
|
||||
{
|
||||
query: {
|
||||
select: okData,
|
||||
enabled: isLoggedIn && !!user,
|
||||
// Include user ID in query key to ensure cache invalidation when user changes
|
||||
queryKey: ["/api/store/profile", user?.id],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const isLoadingProfile = isProfileLoading || isUserLoading;
|
||||
|
||||
const shouldShowPreviewBanner = Boolean(isLoggedIn && previewBranchName);
|
||||
|
||||
const actualLoggedInLinks =
|
||||
isChatEnabled === true
|
||||
? loggedInLinks.concat([{ name: "Chat", href: "/chat" }])
|
||||
: loggedInLinks;
|
||||
|
||||
if (isUserLoading) {
|
||||
return <NavbarLoading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<NavbarView isLoggedIn={isLoggedIn} previewBranchName={previewBranchName} />
|
||||
<>
|
||||
<div className="sticky top-0 z-40 w-full">
|
||||
{shouldShowPreviewBanner && previewBranchName ? (
|
||||
<PreviewBanner branchName={previewBranchName} />
|
||||
) : null}
|
||||
<nav className="border-zinc-[#EFEFF0] inline-flex h-[60px] w-full items-center border border-[#EFEFF0] bg-[#F3F4F6]/20 p-3 backdrop-blur-[26px]">
|
||||
{/* Left section */}
|
||||
{!isSmallScreen ? (
|
||||
<div className="flex flex-1 items-center gap-5">
|
||||
{isLoggedIn
|
||||
? actualLoggedInLinks.map((link) => (
|
||||
<NavbarLink
|
||||
key={link.name}
|
||||
name={link.name}
|
||||
href={link.href}
|
||||
/>
|
||||
))
|
||||
: loggedOutLinks.map((link) => (
|
||||
<NavbarLink
|
||||
key={link.name}
|
||||
name={link.name}
|
||||
href={link.href}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Centered logo */}
|
||||
<div className="static h-auto w-[4.5rem] md:absolute md:left-1/2 md:top-1/2 md:w-[5.5rem] md:-translate-x-1/2 md:-translate-y-1/2">
|
||||
<IconAutoGPTLogo className="h-full w-full" />
|
||||
</div>
|
||||
|
||||
{/* Right section */}
|
||||
{isLoggedIn && !isSmallScreen ? (
|
||||
<div className="flex flex-1 items-center justify-end gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<AgentActivityDropdown />
|
||||
{profile && <Wallet key={profile.username} />}
|
||||
<AccountMenu
|
||||
userName={profile?.username}
|
||||
userEmail={profile?.name}
|
||||
avatarSrc={profile?.avatar_url ?? ""}
|
||||
menuItemGroups={dynamicMenuItems}
|
||||
isLoading={isLoadingProfile}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : !isLoggedIn ? (
|
||||
<div className="flex w-full items-center justify-end">
|
||||
<LoginButton />
|
||||
</div>
|
||||
) : null}
|
||||
{/* <ThemeToggle /> */}
|
||||
</nav>
|
||||
</div>
|
||||
{/* Mobile Navbar - Adjust positioning */}
|
||||
<>
|
||||
{isLoggedIn && isSmallScreen ? (
|
||||
<div className="fixed right-0 top-2 z-50 flex items-center gap-0">
|
||||
<Wallet />
|
||||
<MobileNavBar
|
||||
userName={profile?.username}
|
||||
menuItemGroups={[
|
||||
{
|
||||
groupName: "Navigation",
|
||||
items: actualLoggedInLinks
|
||||
.map((link) => {
|
||||
if (link.name === "Chat" && !isChatEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
icon:
|
||||
link.name === "Marketplace"
|
||||
? IconType.Marketplace
|
||||
: link.name === "Library"
|
||||
? IconType.Library
|
||||
: link.name === "Build"
|
||||
? IconType.Builder
|
||||
: link.name === "Chat"
|
||||
? IconType.Chat
|
||||
: link.name === "Monitor"
|
||||
? IconType.Library
|
||||
: IconType.LayoutDashboard,
|
||||
text: link.name,
|
||||
href: link.href,
|
||||
};
|
||||
})
|
||||
.filter((item) => item !== null) as Array<{
|
||||
icon: IconType;
|
||||
text: string;
|
||||
href: string;
|
||||
}>,
|
||||
},
|
||||
...dynamicMenuItems,
|
||||
]}
|
||||
userEmail={profile?.name}
|
||||
avatarSrc={profile?.avatar_url ?? ""}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,45 +6,42 @@ import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
|
||||
import { cn } from "@/lib/utils";
|
||||
import * as Sentry from "@sentry/nextjs";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import { useTransition } from "react";
|
||||
|
||||
export function AccountLogoutOption() {
|
||||
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const supabase = useSupabase();
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
|
||||
async function handleLogout() {
|
||||
setIsLoggingOut(true);
|
||||
try {
|
||||
await supabase.logOut();
|
||||
router.push("/login");
|
||||
} catch (e) {
|
||||
Sentry.captureException(e);
|
||||
toast({
|
||||
title: "Error logging out",
|
||||
description:
|
||||
"Something went wrong when logging out. Please try again. If the problem persists, please contact support.",
|
||||
variant: "destructive",
|
||||
});
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
setIsLoggingOut(false);
|
||||
}, 3000);
|
||||
}
|
||||
function handleLogout() {
|
||||
startTransition(async () => {
|
||||
try {
|
||||
await supabase.logOut();
|
||||
router.replace("/login");
|
||||
} catch (e) {
|
||||
Sentry.captureException(e);
|
||||
toast({
|
||||
title: "Error logging out",
|
||||
description:
|
||||
"Something went wrong when logging out. Please try again. If the problem persists, please contact support.",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"inline-flex w-full items-center justify-start gap-2.5",
|
||||
isLoggingOut && "justify-center opacity-50",
|
||||
isPending && "justify-center opacity-50",
|
||||
)}
|
||||
onClick={handleLogout}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
>
|
||||
{isLoggingOut ? (
|
||||
{isPending ? (
|
||||
<LoadingSpinner className="size-5" />
|
||||
) : (
|
||||
<>
|
||||
|
||||
@@ -5,16 +5,15 @@ export function NavbarLoading() {
|
||||
return (
|
||||
<nav className="sticky top-0 z-40 hidden h-16 items-center rounded-bl-2xl rounded-br-2xl border border-white/50 bg-white/5 p-3 backdrop-blur-[26px] md:inline-flex">
|
||||
<div className="flex flex-1 items-center gap-6">
|
||||
<Skeleton className="h-4 w-20 bg-white/20" />
|
||||
<Skeleton className="h-4 w-16 bg-white/20" />
|
||||
<Skeleton className="h-4 w-12 bg-white/20" />
|
||||
<Skeleton className="h-6 w-24 bg-zinc-200/60" />
|
||||
<Skeleton className="h-6 w-24 bg-zinc-200/60" />
|
||||
<Skeleton className="h-6 w-16 bg-zinc-200/60" />
|
||||
</div>
|
||||
<div className="absolute left-1/2 top-1/2 h-10 w-[88.87px] -translate-x-1/2 -translate-y-1/2">
|
||||
<IconAutoGPTLogo className="h-full w-full" />
|
||||
</div>
|
||||
<div className="flex flex-1 items-center justify-end gap-4">
|
||||
<Skeleton className="h-8 w-8 rounded-full bg-white/20" />
|
||||
<Skeleton className="h-8 w-8 rounded-full bg-white/20" />
|
||||
<Skeleton className="h-8 w-8 rounded-full bg-zinc-200/60" />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
|
||||
@@ -1,144 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { useGetV2GetUserProfile } from "@/app/api/__generated__/endpoints/store/store";
|
||||
import { IconAutoGPTLogo, IconType } from "@/components/__legacy__/ui/icons";
|
||||
import { PreviewBanner } from "@/components/layout/Navbar/components/PreviewBanner/PreviewBanner";
|
||||
import { useBreakpoint } from "@/lib/hooks/useBreakpoint";
|
||||
import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
|
||||
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
|
||||
import { useMemo } from "react";
|
||||
import { okData } from "@/app/api/helpers";
|
||||
import { getAccountMenuItems, loggedInLinks, loggedOutLinks } from "../helpers";
|
||||
import { AccountMenu } from "./AccountMenu/AccountMenu";
|
||||
import { AgentActivityDropdown } from "./AgentActivityDropdown/AgentActivityDropdown";
|
||||
import { LoginButton } from "./LoginButton";
|
||||
import { MobileNavBar } from "./MobileNavbar/MobileNavBar";
|
||||
import { NavbarLink } from "./NavbarLink";
|
||||
import { Wallet } from "./Wallet/Wallet";
|
||||
interface NavbarViewProps {
|
||||
isLoggedIn: boolean;
|
||||
previewBranchName?: string | null;
|
||||
}
|
||||
|
||||
export function NavbarView({ isLoggedIn, previewBranchName }: NavbarViewProps) {
|
||||
const { user } = useSupabase();
|
||||
const breakpoint = useBreakpoint();
|
||||
const isSmallScreen = breakpoint === "sm" || breakpoint === "base";
|
||||
const dynamicMenuItems = getAccountMenuItems(user?.role);
|
||||
const isChatEnabled = useGetFlag(Flag.CHAT);
|
||||
|
||||
const { data: profile, isLoading: isProfileLoading } = useGetV2GetUserProfile(
|
||||
{
|
||||
query: {
|
||||
select: okData,
|
||||
enabled: isLoggedIn && !!user,
|
||||
// Include user ID in query key to ensure cache invalidation when user changes
|
||||
queryKey: ["/api/store/profile", user?.id],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const { isUserLoading } = useSupabase();
|
||||
const isLoadingProfile = isProfileLoading || isUserLoading;
|
||||
|
||||
const linksWithChat = useMemo(() => {
|
||||
const chatLink = { name: "Chat", href: "/chat" };
|
||||
return isChatEnabled ? [...loggedInLinks, chatLink] : loggedInLinks;
|
||||
}, [isChatEnabled]);
|
||||
|
||||
const shouldShowPreviewBanner = Boolean(isLoggedIn && previewBranchName);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="sticky top-0 z-40 w-full">
|
||||
{shouldShowPreviewBanner && previewBranchName ? (
|
||||
<PreviewBanner branchName={previewBranchName} />
|
||||
) : null}
|
||||
<nav className="border-zinc-[#EFEFF0] inline-flex h-[60px] w-full items-center border border-[#EFEFF0] bg-[#F3F4F6]/20 p-3 backdrop-blur-[26px]">
|
||||
{/* Left section */}
|
||||
{!isSmallScreen ? (
|
||||
<div className="flex flex-1 items-center gap-5">
|
||||
{isLoggedIn
|
||||
? linksWithChat.map((link) => (
|
||||
<NavbarLink
|
||||
key={link.name}
|
||||
name={link.name}
|
||||
href={link.href}
|
||||
/>
|
||||
))
|
||||
: loggedOutLinks.map((link) => (
|
||||
<NavbarLink
|
||||
key={link.name}
|
||||
name={link.name}
|
||||
href={link.href}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* Centered logo */}
|
||||
<div className="static h-auto w-[4.5rem] md:absolute md:left-1/2 md:top-1/2 md:w-[5.5rem] md:-translate-x-1/2 md:-translate-y-1/2">
|
||||
<IconAutoGPTLogo className="h-full w-full" />
|
||||
</div>
|
||||
|
||||
{/* Right section */}
|
||||
{isLoggedIn && !isSmallScreen ? (
|
||||
<div className="flex flex-1 items-center justify-end gap-4">
|
||||
<div className="flex items-center gap-4">
|
||||
<AgentActivityDropdown />
|
||||
{profile && <Wallet key={profile.username} />}
|
||||
<AccountMenu
|
||||
userName={profile?.username}
|
||||
userEmail={profile?.name}
|
||||
avatarSrc={profile?.avatar_url ?? ""}
|
||||
menuItemGroups={dynamicMenuItems}
|
||||
isLoading={isLoadingProfile}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : !isLoggedIn ? (
|
||||
<div className="flex w-full items-center justify-end">
|
||||
<LoginButton />
|
||||
</div>
|
||||
) : null}
|
||||
{/* <ThemeToggle /> */}
|
||||
</nav>
|
||||
</div>
|
||||
{/* Mobile Navbar - Adjust positioning */}
|
||||
<>
|
||||
{isLoggedIn && isSmallScreen ? (
|
||||
<div className="fixed right-0 top-2 z-50 flex items-center gap-0">
|
||||
<Wallet />
|
||||
<MobileNavBar
|
||||
userName={profile?.username}
|
||||
menuItemGroups={[
|
||||
{
|
||||
groupName: "Navigation",
|
||||
items: linksWithChat.map((link) => ({
|
||||
icon:
|
||||
link.name === "Marketplace"
|
||||
? IconType.Marketplace
|
||||
: link.name === "Library"
|
||||
? IconType.Library
|
||||
: link.name === "Build"
|
||||
? IconType.Builder
|
||||
: link.name === "Chat"
|
||||
? IconType.Chat
|
||||
: link.name === "Monitor"
|
||||
? IconType.Library
|
||||
: IconType.LayoutDashboard,
|
||||
text: link.name,
|
||||
href: link.href,
|
||||
})),
|
||||
},
|
||||
...dynamicMenuItems,
|
||||
]}
|
||||
userEmail={profile?.name}
|
||||
avatarSrc={profile?.avatar_url ?? ""}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
import { prefetchGetV2GetUserProfileQuery } from "@/app/api/__generated__/endpoints/store/store";
|
||||
import { getQueryClient } from "@/lib/react-query/queryClient";
|
||||
import { getServerUser } from "@/lib/supabase/server/getServerUser";
|
||||
|
||||
export async function getNavbarAccountData() {
|
||||
const { user } = await getServerUser();
|
||||
const isLoggedIn = Boolean(user);
|
||||
const queryClient = getQueryClient();
|
||||
|
||||
if (!isLoggedIn) {
|
||||
return {
|
||||
profile: null,
|
||||
isLoggedIn,
|
||||
};
|
||||
}
|
||||
try {
|
||||
await prefetchGetV2GetUserProfileQuery(queryClient);
|
||||
} catch (error) {
|
||||
console.error("Error fetching profile:", error);
|
||||
}
|
||||
|
||||
return {
|
||||
isLoggedIn,
|
||||
};
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { DEFAULT_SEARCH_TERMS } from "@/app/(platform)/marketplace/components/HeroSection/helpers";
|
||||
import { useFlags } from "launchdarkly-react-client-sdk";
|
||||
import { environment } from "../environment";
|
||||
|
||||
export enum Flag {
|
||||
BETA_BLOCKS = "beta-blocks",
|
||||
@@ -40,7 +39,7 @@ const mockFlags = {
|
||||
[Flag.BETA_BLOCKS]: [],
|
||||
[Flag.NEW_BLOCK_MENU]: false,
|
||||
[Flag.NEW_AGENT_RUNS]: false,
|
||||
[Flag.GRAPH_SEARCH]: true,
|
||||
[Flag.GRAPH_SEARCH]: false,
|
||||
[Flag.ENABLE_ENHANCED_OUTPUT_HANDLING]: false,
|
||||
[Flag.NEW_FLOW_EDITOR]: false,
|
||||
[Flag.BUILDER_VIEW_SWITCH]: false,
|
||||
@@ -48,17 +47,20 @@ const mockFlags = {
|
||||
[Flag.AGENT_FAVORITING]: false,
|
||||
[Flag.MARKETPLACE_SEARCH_TERMS]: DEFAULT_SEARCH_TERMS,
|
||||
[Flag.ENABLE_PLATFORM_PAYMENT]: false,
|
||||
[Flag.CHAT]: true,
|
||||
[Flag.CHAT]: false,
|
||||
};
|
||||
|
||||
export function useGetFlag<T extends Flag>(flag: T): FlagValues[T] | null {
|
||||
const currentFlags = useFlags<FlagValues>();
|
||||
const flagValue = currentFlags[flag];
|
||||
const isCloud = environment.isCloud();
|
||||
|
||||
if ((isPwMockEnabled && !isCloud) || flagValue === undefined) {
|
||||
const envEnabled = process.env.NEXT_PUBLIC_LAUNCHDARKLY_ENABLED === "true";
|
||||
const clientId = process.env.NEXT_PUBLIC_LAUNCHDARKLY_CLIENT_ID;
|
||||
const isLaunchDarklyConfigured = envEnabled && clientId;
|
||||
|
||||
if (!isLaunchDarklyConfigured || isPwMockEnabled) {
|
||||
return mockFlags[flag];
|
||||
}
|
||||
|
||||
return flagValue;
|
||||
return flagValue ?? mockFlags[flag];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user