mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-04-08 03:48:14 +02:00
k
This commit is contained in:
parent
080f5cd2e2
commit
a5a06d2bbe
@ -134,7 +134,7 @@ POSTGRES_PASSWORD = urllib.parse.quote_plus(
|
||||
os.environ.get("POSTGRES_PASSWORD") or "password"
|
||||
)
|
||||
POSTGRES_HOST = os.environ.get("POSTGRES_HOST") or "localhost"
|
||||
POSTGRES_PORT = os.environ.get("POSTGRES_PORT") or "5432"
|
||||
POSTGRES_PORT = os.environ.get("POSTGRES_PORT") or "5433"
|
||||
POSTGRES_DB = os.environ.get("POSTGRES_DB") or "postgres"
|
||||
|
||||
POSTGRES_API_SERVER_POOL_SIZE = int(
|
||||
|
@ -312,7 +312,7 @@ services:
|
||||
- POSTGRES_USER=${POSTGRES_USER:-postgres}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
- "5433:5432"
|
||||
volumes:
|
||||
- db_volume:/var/lib/postgresql/data
|
||||
|
||||
|
@ -312,7 +312,7 @@ services:
|
||||
- POSTGRES_USER=${POSTGRES_USER:-postgres}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}
|
||||
ports:
|
||||
- "5432:5432"
|
||||
- "5433:5432"
|
||||
volumes:
|
||||
- db_volume:/var/lib/postgresql/data
|
||||
|
||||
|
@ -157,7 +157,7 @@ services:
|
||||
- POSTGRES_USER=${POSTGRES_USER:-postgres}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-password}
|
||||
ports:
|
||||
- "5432"
|
||||
- "5433"
|
||||
volumes:
|
||||
- db_volume:/var/lib/postgresql/data
|
||||
|
||||
|
@ -9,14 +9,24 @@ import { checkUserIsNoAuthUser, logout } from "@/lib/user";
|
||||
import { Popover } from "./popover/Popover";
|
||||
import { LOGOUT_DISABLED } from "@/lib/constants";
|
||||
import { SettingsContext } from "./settings/SettingsProvider";
|
||||
import { LightSettingsIcon } from "./icons/icons";
|
||||
import {
|
||||
AssistantsIconSkeleton,
|
||||
LightSettingsIcon,
|
||||
UsersIcon,
|
||||
} from "./icons/icons";
|
||||
import { pageType } from "@/app/chat/sessionSidebar/types";
|
||||
import { NavigationItem } from "@/app/admin/settings/interfaces";
|
||||
import { NavigationItem, Notification } from "@/app/admin/settings/interfaces";
|
||||
import DynamicFaIcon, { preloadIcons } from "./icons/DynamicFaIcon";
|
||||
import { useUser } from "./user/UserProvider";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "./settings/usePaidEnterpriseFeaturesEnabled";
|
||||
import { Notifications } from "./chat_search/Notifications";
|
||||
import useSWR from "swr";
|
||||
import { errorHandlingFetcher } from "@/lib/fetcher";
|
||||
import { Bell } from "@phosphor-icons/react";
|
||||
|
||||
interface DropdownOptionProps {
|
||||
href?: string;
|
||||
onClick?: () => void;
|
||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
|
||||
icon: React.ReactNode;
|
||||
label: string;
|
||||
openInNewTab?: boolean;
|
||||
@ -51,24 +61,26 @@ const DropdownOption: React.FC<DropdownOptionProps> = ({
|
||||
}
|
||||
};
|
||||
|
||||
export function UserDropdown({
|
||||
user,
|
||||
page,
|
||||
}: {
|
||||
user: User | null;
|
||||
page?: pageType;
|
||||
}) {
|
||||
export function UserDropdown({ page }: { page?: pageType }) {
|
||||
const { user } = useUser();
|
||||
const [userInfoVisible, setUserInfoVisible] = useState(false);
|
||||
const userInfoRef = useRef<HTMLDivElement>(null);
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const isPaidEnterpriseFeaturesEnabled = usePaidEnterpriseFeaturesEnabled();
|
||||
const [showNotifications, setShowNotifications] = useState(false);
|
||||
|
||||
const combinedSettings = useContext(SettingsContext);
|
||||
const customNavItems: NavigationItem[] = useMemo(
|
||||
() => combinedSettings?.enterpriseSettings?.custom_nav_items || [],
|
||||
[combinedSettings]
|
||||
);
|
||||
const {
|
||||
data: notifications,
|
||||
error,
|
||||
mutate: refreshNotifications,
|
||||
} = useSWR<Notification[]>("/api/notifications", errorHandlingFetcher);
|
||||
|
||||
useEffect(() => {
|
||||
const iconNames = customNavItems
|
||||
@ -137,8 +149,15 @@ export function UserDropdown({
|
||||
</div>
|
||||
}
|
||||
popover={
|
||||
<div
|
||||
className={`
|
||||
<>
|
||||
{showNotifications ? (
|
||||
<Notifications
|
||||
notifications={notifications || []}
|
||||
refreshNotifications={refreshNotifications}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
className={`
|
||||
p-2
|
||||
min-w-[200px]
|
||||
text-strong
|
||||
@ -156,15 +175,15 @@ export function UserDropdown({
|
||||
p-1
|
||||
overscroll-contain
|
||||
`}
|
||||
>
|
||||
{customNavItems.map((item, i) => (
|
||||
<DropdownOption
|
||||
key={i}
|
||||
href={item.link}
|
||||
icon={
|
||||
item.svg_logo ? (
|
||||
<div
|
||||
className="
|
||||
>
|
||||
{customNavItems.map((item, i) => (
|
||||
<DropdownOption
|
||||
key={i}
|
||||
href={item.link}
|
||||
icon={
|
||||
item.svg_logo ? (
|
||||
<div
|
||||
className="
|
||||
h-4
|
||||
w-4
|
||||
my-auto
|
||||
@ -174,59 +193,78 @@ export function UserDropdown({
|
||||
items-center
|
||||
justify-center
|
||||
"
|
||||
aria-label={item.title}
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width="100%"
|
||||
height="100%"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
dangerouslySetInnerHTML={{ __html: item.svg_logo }}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<DynamicFaIcon
|
||||
name={item.icon!}
|
||||
className="h-4 w-4 my-auto mr-2"
|
||||
aria-label={item.title}
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 24 24"
|
||||
width="100%"
|
||||
height="100%"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
dangerouslySetInnerHTML={{ __html: item.svg_logo }}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<DynamicFaIcon
|
||||
name={item.icon!}
|
||||
className="h-4 w-4 my-auto mr-2"
|
||||
/>
|
||||
)
|
||||
}
|
||||
label={item.title}
|
||||
openInNewTab
|
||||
/>
|
||||
))}
|
||||
|
||||
{showAdminPanel ? (
|
||||
<DropdownOption
|
||||
href="/admin/indexing/status"
|
||||
icon={
|
||||
<LightSettingsIcon className="h-5 w-5 my-auto mr-2" />
|
||||
}
|
||||
label="Admin Panel"
|
||||
/>
|
||||
) : (
|
||||
showCuratorPanel && (
|
||||
<DropdownOption
|
||||
href="/admin/indexing/status"
|
||||
icon={
|
||||
<LightSettingsIcon className="h-5 w-5 my-auto mr-2" />
|
||||
}
|
||||
label="Curator Panel"
|
||||
/>
|
||||
)
|
||||
}
|
||||
label={item.title}
|
||||
openInNewTab
|
||||
/>
|
||||
))}
|
||||
)}
|
||||
|
||||
{showAdminPanel ? (
|
||||
<DropdownOption
|
||||
href="/admin/indexing/status"
|
||||
icon={<LightSettingsIcon className="h-5 w-5 my-auto mr-2" />}
|
||||
label="Admin Panel"
|
||||
/>
|
||||
) : (
|
||||
showCuratorPanel && (
|
||||
<DropdownOption
|
||||
href="/admin/indexing/status"
|
||||
icon={<LightSettingsIcon className="h-5 w-5 my-auto mr-2" />}
|
||||
label="Curator Panel"
|
||||
/>
|
||||
)
|
||||
{isPaidEnterpriseFeaturesEnabled && (
|
||||
<DropdownOption
|
||||
onClick={(e) => {
|
||||
console.log("CLICKKK");
|
||||
e.stopPropagation();
|
||||
setUserInfoVisible(true);
|
||||
setShowNotifications(true);
|
||||
}}
|
||||
icon={<Bell className="h-5 w-5 my-auto mr-2" />}
|
||||
label={`Notifications ${notifications && notifications.length > 0 ? `(${notifications.length})` : ""}`}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showLogout &&
|
||||
(showCuratorPanel ||
|
||||
showAdminPanel ||
|
||||
customNavItems.length > 0) && (
|
||||
<div className="border-t border-border my-1" />
|
||||
)}
|
||||
|
||||
{showLogout && (
|
||||
<DropdownOption
|
||||
onClick={handleLogout}
|
||||
icon={<FiLogOut className="my-auto mr-2 text-lg" />}
|
||||
label="Log out"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showLogout &&
|
||||
(showCuratorPanel ||
|
||||
showAdminPanel ||
|
||||
customNavItems.length > 0) && (
|
||||
<div className="border-t border-border my-1" />
|
||||
)}
|
||||
|
||||
{showLogout && (
|
||||
<DropdownOption
|
||||
onClick={handleLogout}
|
||||
icon={<FiLogOut className="my-auto mr-2 text-lg" />}
|
||||
label="Log out"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
side="bottom"
|
||||
align="end"
|
||||
|
@ -418,7 +418,7 @@ export function ClientLayout({
|
||||
</div>
|
||||
<div className="pb-8 relative h-full overflow-y-auto w-full">
|
||||
<div className="fixed bg-background left-0 gap-x-4 mb-8 px-4 py-2 w-full items-center flex justify-end">
|
||||
<UserDropdown user={user} />
|
||||
<UserDropdown />
|
||||
</div>
|
||||
<div className="pt-20 flex overflow-y-auto h-full px-4 md:px-12">
|
||||
{children}
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { User } from "@/lib/types";
|
||||
import { UserDropdown } from "../UserDropdown";
|
||||
import { FiShare2 } from "react-icons/fi";
|
||||
import { SetStateAction, useEffect } from "react";
|
||||
import { SetStateAction, useContext, useEffect } from "react";
|
||||
import { NewChatIcon } from "../icons/icons";
|
||||
import { NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA } from "@/lib/constants";
|
||||
import { ChatSession } from "@/app/chat/interfaces";
|
||||
@ -11,10 +11,9 @@ import { pageType } from "@/app/chat/sessionSidebar/types";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ChatBanner } from "@/app/chat/ChatBanner";
|
||||
import LogoType from "../header/LogoType";
|
||||
import { Notifications } from "./Notifications";
|
||||
import { useUser } from "../user/UserProvider";
|
||||
|
||||
export default function FunctionalHeader({
|
||||
user,
|
||||
page,
|
||||
currentChatSession,
|
||||
setSharingModalVisible,
|
||||
@ -24,12 +23,12 @@ export default function FunctionalHeader({
|
||||
}: {
|
||||
reset?: () => void;
|
||||
page: pageType;
|
||||
user: User | null;
|
||||
sidebarToggled?: boolean;
|
||||
currentChatSession?: ChatSession | null | undefined;
|
||||
setSharingModalVisible?: (value: SetStateAction<boolean>) => void;
|
||||
toggleSidebar?: () => void;
|
||||
}) {
|
||||
const { user } = useUser();
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.metaKey || event.ctrlKey) {
|
||||
@ -64,7 +63,6 @@ export default function FunctionalHeader({
|
||||
: "");
|
||||
router.push(newChatUrl);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="left-0 bg-transparent sticky top-0 z-20 w-full relative flex">
|
||||
<div className="mt-2 mx-2.5 cursor-pointer text-text-700 relative flex w-full">
|
||||
@ -110,9 +108,8 @@ export default function FunctionalHeader({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Notifications />
|
||||
<div className="mobile:hidden flex my-auto">
|
||||
<UserDropdown user={user} />
|
||||
<UserDropdown />
|
||||
</div>
|
||||
<Link
|
||||
className="desktop:hidden my-auto"
|
||||
|
@ -10,15 +10,16 @@ import { AssistantIcon } from "@/components/assistants/AssistantIcon";
|
||||
import { addAssistantToList } from "@/lib/assistants/updateAssistantPreferences";
|
||||
import { useAssistants } from "../context/AssisantsContext";
|
||||
import { useUser } from "../user/UserProvider";
|
||||
import { Bell } from "@phosphor-icons/react";
|
||||
|
||||
export const Notifications = () => {
|
||||
export const Notifications = ({
|
||||
notifications,
|
||||
refreshNotifications,
|
||||
}: {
|
||||
notifications: Notification[];
|
||||
refreshNotifications: () => void;
|
||||
}) => {
|
||||
const [showDropdown, setShowDropdown] = useState(false);
|
||||
const {
|
||||
data: notifications,
|
||||
error,
|
||||
mutate: refreshNotifications,
|
||||
} = useSWR<Notification[]>("/api/notifications", errorHandlingFetcher);
|
||||
|
||||
const { refreshAssistants } = useAssistants();
|
||||
|
||||
const { refreshUser } = useUser();
|
||||
@ -120,80 +121,69 @@ export const Notifications = () => {
|
||||
|
||||
return (
|
||||
<div className="my-auto relative">
|
||||
<div
|
||||
onClick={() => setShowDropdown(!showDropdown)}
|
||||
className="cursor-pointer relative notification-dropdown"
|
||||
>
|
||||
<Bell size={20} />
|
||||
{sortedNotifications.length > 0 && (
|
||||
<span className="absolute top-0 right-0 h-2 w-2 bg-red-500 rounded-full"></span>
|
||||
)}
|
||||
</div>
|
||||
{showDropdown && (
|
||||
<div className="absolute right-0 mt-2 w-80 bg-white rounded-lg shadow-xl z-20 max-h-[80vh] overflow-y-auto notification-dropdown">
|
||||
{sortedNotifications.length > 0 ? (
|
||||
sortedNotifications
|
||||
.filter(
|
||||
(notification) =>
|
||||
notification.notif_type === NotificationType.PERSONA_SHARED
|
||||
)
|
||||
.map((notification) => {
|
||||
const persona = notification.additional_data?.persona_id
|
||||
? personas[notification.additional_data.persona_id]
|
||||
: null;
|
||||
<div className="absolute right-0 mt-2 w-80 bg-white rounded-lg shadow-xl z-20 max-h-[80vh] overflow-y-auto notification-dropdown">
|
||||
{sortedNotifications.length > 0 ? (
|
||||
sortedNotifications
|
||||
.filter(
|
||||
(notification) =>
|
||||
notification.notif_type === NotificationType.PERSONA_SHARED
|
||||
)
|
||||
.map((notification) => {
|
||||
const persona = notification.additional_data?.persona_id
|
||||
? personas[notification.additional_data.persona_id]
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={notification.id}
|
||||
className="px-4 py-3 border-b last:border-b-0 hover:bg-gray-50 transition duration-150 ease-in-out"
|
||||
>
|
||||
<div className="flex items-start">
|
||||
{persona && (
|
||||
<div className="mt-2 flex-shrink-0 mr-3">
|
||||
<AssistantIcon assistant={persona} size="small" />
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-grow">
|
||||
<p className="font-semibold text-sm text-gray-800">
|
||||
New Assistant Shared With You
|
||||
</p>
|
||||
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
Do you want to accept this assistant?
|
||||
</p>
|
||||
{persona && (
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
Assistant: {persona.name}
|
||||
</p>
|
||||
)}
|
||||
return (
|
||||
<div
|
||||
key={notification.id}
|
||||
className="px-4 py-3 border-b last:border-b-0 hover:bg-gray-50 transition duration-150 ease-in-out"
|
||||
>
|
||||
<div className="flex items-start">
|
||||
{persona && (
|
||||
<div className="mt-2 flex-shrink-0 mr-3">
|
||||
<AssistantIcon assistant={persona} size="small" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-end mt-2 space-x-2">
|
||||
<button
|
||||
onClick={() =>
|
||||
handleAssistantShareAcceptance(notification, persona!)
|
||||
}
|
||||
className="px-3 py-1 text-sm font-medium text-blue-600 hover:text-blue-800 transition duration-150 ease-in-out"
|
||||
>
|
||||
Accept
|
||||
</button>
|
||||
<button
|
||||
onClick={() => dismissNotification(notification.id)}
|
||||
className="px-3 py-1 text-sm font-medium text-gray-600 hover:text-gray-800 transition duration-150 ease-in-out"
|
||||
>
|
||||
Dismiss
|
||||
</button>
|
||||
)}
|
||||
<div className="flex-grow">
|
||||
<p className="font-semibold text-sm text-gray-800">
|
||||
New Assistant Shared With You
|
||||
</p>
|
||||
|
||||
<p className="text-sm text-gray-600 mt-1">
|
||||
Do you want to accept this assistant?
|
||||
</p>
|
||||
{persona && (
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
Assistant: {persona.name}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div className="px-4 py-3 text-center text-gray-600">
|
||||
No new notifications
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex justify-end mt-2 space-x-2">
|
||||
<button
|
||||
onClick={() =>
|
||||
handleAssistantShareAcceptance(notification, persona!)
|
||||
}
|
||||
className="px-3 py-1 text-sm font-medium text-blue-600 hover:text-blue-800 transition duration-150 ease-in-out"
|
||||
>
|
||||
Accept
|
||||
</button>
|
||||
<button
|
||||
onClick={() => dismissNotification(notification.id)}
|
||||
className="px-3 py-1 text-sm font-medium text-gray-600 hover:text-gray-800 transition duration-150 ease-in-out"
|
||||
>
|
||||
Dismiss
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : (
|
||||
<div className="px-4 py-3 text-center text-gray-600">
|
||||
No new notifications
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user