This commit is contained in:
pablodanswer 2024-10-17 12:54:33 -07:00
parent 080f5cd2e2
commit a5a06d2bbe
8 changed files with 184 additions and 159 deletions

View File

@ -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(

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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}

View File

@ -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"

View File

@ -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>
);
};