mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-08-04 14:12:48 +02:00
Move user fetching to SS + parallelize some server-side calls (#2932)
* Move user fetching to SS * Cleanup * Add more logging * Small cleanup
This commit is contained in:
@@ -8,12 +8,47 @@ import { credentialTemplates } from "@/lib/connectors/credentials";
|
||||
import Link from "next/link";
|
||||
import { useUser } from "@/components/user/UserProvider";
|
||||
import { useContext } from "react";
|
||||
import { User } from "@/lib/types";
|
||||
|
||||
function BackButton({
|
||||
isAdmin,
|
||||
isCurator,
|
||||
user,
|
||||
}: {
|
||||
isAdmin: boolean;
|
||||
isCurator: boolean;
|
||||
user: User | null;
|
||||
}) {
|
||||
const buttonText = isAdmin ? "Admin Page" : "Curator Page";
|
||||
|
||||
if (!isAdmin && !isCurator) {
|
||||
console.error(
|
||||
`User is neither admin nor curator, defaulting to curator view. Found user:\n ${JSON.stringify(
|
||||
user,
|
||||
null,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx-3 mt-6 flex-col flex items-center">
|
||||
<Link
|
||||
href={"/admin/add-connector"}
|
||||
className="w-full p-2 bg-white border-border border rounded items-center hover:bg-background-200 cursor-pointer transition-all duration-150 flex gap-x-2"
|
||||
>
|
||||
<SettingsIcon className="flex-none " />
|
||||
<p className="my-auto flex items-center text-sm">{buttonText}</p>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Sidebar() {
|
||||
const { formStep, setFormStep, connector, allowAdvanced, allowCreate } =
|
||||
useFormContext();
|
||||
const combinedSettings = useContext(SettingsContext);
|
||||
const { isLoadingUser, isAdmin } = useUser();
|
||||
const { isCurator, isAdmin, user } = useUser();
|
||||
if (!combinedSettings) {
|
||||
return null;
|
||||
}
|
||||
@@ -55,17 +90,7 @@ export default function Sidebar() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mx-3 mt-6 gap-y-1 flex-col flex gap-x-1.5 items-center items-center">
|
||||
<Link
|
||||
href={"/admin/add-connector"}
|
||||
className="w-full p-2 bg-white border-border border rounded items-center hover:bg-background-200 cursor-pointer transition-all duration-150 flex gap-x-2"
|
||||
>
|
||||
<SettingsIcon className="flex-none " />
|
||||
<p className="my-auto flex items-center text-sm">
|
||||
{isAdmin ? "Admin Page" : "Curator Page"}
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
<BackButton isAdmin={isAdmin} isCurator={isCurator} user={user} />
|
||||
|
||||
<div className="h-full flex">
|
||||
<div className="mx-auto w-full max-w-2xl px-4 py-8">
|
||||
|
@@ -5,7 +5,6 @@ import { WelcomeModal } from "@/components/initialSetup/welcome/WelcomeModalWrap
|
||||
import { ChatProvider } from "@/components/context/ChatContext";
|
||||
import { fetchChatData } from "@/lib/chat/fetchChatData";
|
||||
import WrappedChat from "./WrappedChat";
|
||||
import { AssistantsProvider } from "@/components/context/AssistantsContext";
|
||||
|
||||
export default async function Page({
|
||||
searchParams,
|
||||
|
@@ -19,6 +19,7 @@ import { fetchAssistantData } from "@/lib/chat/fetchAssistantdata";
|
||||
import { AppProvider } from "@/components/context/AppProvider";
|
||||
import { PHProvider } from "./providers";
|
||||
import { default as dynamicImport } from "next/dynamic";
|
||||
import { getCurrentUserSS } from "@/lib/userSS";
|
||||
|
||||
const PostHogPageView = dynamicImport(() => import("./PostHogPageView"), {
|
||||
ssr: false,
|
||||
@@ -57,7 +58,11 @@ export default async function RootLayout({
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const combinedSettings = await fetchSettingsSS();
|
||||
const [combinedSettings, assistantsData, user] = await Promise.all([
|
||||
fetchSettingsSS(),
|
||||
fetchAssistantData(),
|
||||
getCurrentUserSS(),
|
||||
]);
|
||||
|
||||
const productGating =
|
||||
combinedSettings?.settings.product_gating ?? GatingType.NONE;
|
||||
@@ -165,11 +170,12 @@ export default async function RootLayout({
|
||||
);
|
||||
}
|
||||
|
||||
const data = await fetchAssistantData();
|
||||
const { assistants, hasAnyConnectors, hasImageCompatibleModel } = data;
|
||||
const { assistants, hasAnyConnectors, hasImageCompatibleModel } =
|
||||
assistantsData;
|
||||
|
||||
return getPageContent(
|
||||
<AppProvider
|
||||
user={user}
|
||||
settings={combinedSettings}
|
||||
assistants={assistants}
|
||||
hasAnyConnectors={hasAnyConnectors}
|
||||
|
@@ -5,9 +5,11 @@ import { ProviderContextProvider } from "../chat_search/ProviderContext";
|
||||
import { SettingsProvider } from "../settings/SettingsProvider";
|
||||
import { AssistantsProvider } from "./AssistantsContext";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { User } from "@/lib/types";
|
||||
|
||||
interface AppProviderProps {
|
||||
children: React.ReactNode;
|
||||
user: User | null;
|
||||
settings: CombinedSettings;
|
||||
assistants: Persona[];
|
||||
hasAnyConnectors: boolean;
|
||||
@@ -16,13 +18,14 @@ interface AppProviderProps {
|
||||
|
||||
export const AppProvider = ({
|
||||
children,
|
||||
user,
|
||||
settings,
|
||||
assistants,
|
||||
hasAnyConnectors,
|
||||
hasImageCompatibleModel,
|
||||
}: AppProviderProps) => {
|
||||
return (
|
||||
<UserProvider>
|
||||
<UserProvider user={user}>
|
||||
<ProviderContextProvider>
|
||||
<SettingsProvider settings={settings}>
|
||||
<AssistantsProvider
|
||||
|
@@ -14,20 +14,21 @@ interface UserContextType {
|
||||
|
||||
const UserContext = createContext<UserContextType | undefined>(undefined);
|
||||
|
||||
export function UserProvider({ children }: { children: React.ReactNode }) {
|
||||
const [user, setUser] = useState<User | null>(null);
|
||||
const [isLoadingUser, setIsLoadingUser] = useState(true);
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [isCurator, setIsCurator] = useState(false);
|
||||
export function UserProvider({
|
||||
children,
|
||||
user,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
user: User | null;
|
||||
}) {
|
||||
const [upToDateUser, setUpToDateUser] = useState<User | null>(user);
|
||||
const [isLoadingUser, setIsLoadingUser] = useState(false);
|
||||
|
||||
const fetchUser = async () => {
|
||||
try {
|
||||
const user = await getCurrentUser();
|
||||
setUser(user);
|
||||
setIsAdmin(user?.role === UserRole.ADMIN);
|
||||
setIsCurator(
|
||||
user?.role === UserRole.CURATOR || user?.role == UserRole.GLOBAL_CURATOR
|
||||
);
|
||||
setIsLoadingUser(true);
|
||||
const currentUser = await getCurrentUser();
|
||||
setUpToDateUser(currentUser);
|
||||
} catch (error) {
|
||||
console.error("Error fetching current user:", error);
|
||||
} finally {
|
||||
@@ -35,17 +36,19 @@ export function UserProvider({ children }: { children: React.ReactNode }) {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchUser();
|
||||
}, []);
|
||||
|
||||
const refreshUser = async () => {
|
||||
await fetchUser();
|
||||
};
|
||||
|
||||
return (
|
||||
<UserContext.Provider
|
||||
value={{ user, isLoadingUser, isAdmin, refreshUser, isCurator }}
|
||||
value={{
|
||||
user: upToDateUser,
|
||||
isLoadingUser,
|
||||
refreshUser,
|
||||
isAdmin: upToDateUser?.role === UserRole.ADMIN,
|
||||
isCurator: upToDateUser?.role === UserRole.CURATOR,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</UserContext.Provider>
|
||||
|
Reference in New Issue
Block a user