mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-05-06 18:00:29 +02:00
Clean chat banner (#2056)
* fully functional * formatting * ensure consistency with large logos * ensure mobile support
This commit is contained in:
parent
ab564a9ec8
commit
dc2a50034d
@ -4,7 +4,7 @@ import { ValidSources } from "@/lib/types";
|
||||
import AddConnector from "./AddConnectorPage";
|
||||
import { FormProvider } from "@/components/context/FormContext";
|
||||
import Sidebar from "./Sidebar";
|
||||
import { HeaderTitle } from "@/components/header/Header";
|
||||
import { HeaderTitle } from "@/components/header/HeaderTitle";
|
||||
import { Button } from "@tremor/react";
|
||||
import { isValidSource } from "@/lib/sources";
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { useFormContext } from "@/components/context/FormContext";
|
||||
import { HeaderTitle } from "@/components/header/Header";
|
||||
import { HeaderTitle } from "@/components/header/HeaderTitle";
|
||||
|
||||
import { BackIcon, SettingsIcon } from "@/components/icons/icons";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
|
@ -124,6 +124,7 @@ export default function SidebarWrapper<T extends object>({
|
||||
|
||||
<div className="absolute h-svh left-0 w-full top-0">
|
||||
<FunctionalHeader
|
||||
sidebarToggled={toggledSidebar}
|
||||
toggleSidebar={toggleSidebar}
|
||||
page="assistants"
|
||||
user={headerProps.user}
|
||||
|
@ -2,57 +2,116 @@
|
||||
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
import { useContext } from "react";
|
||||
import { useContext, useState, useRef, useLayoutEffect } from "react";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { Popover } from "@/components/popover/Popover";
|
||||
import { ChevronDownIcon } from "@/components/icons/icons";
|
||||
import { Divider } from "@tremor/react";
|
||||
|
||||
export function ChatBanner() {
|
||||
const settings = useContext(SettingsContext);
|
||||
const [isOverflowing, setIsOverflowing] = useState(false);
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
const contentRef = useRef<HTMLDivElement>(null);
|
||||
const fullContentRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const checkOverflow = () => {
|
||||
if (contentRef.current && fullContentRef.current) {
|
||||
setIsOverflowing(
|
||||
fullContentRef.current.scrollHeight > contentRef.current.clientHeight
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
checkOverflow();
|
||||
window.addEventListener("resize", checkOverflow);
|
||||
return () => window.removeEventListener("resize", checkOverflow);
|
||||
}, []);
|
||||
|
||||
if (!settings?.enterpriseSettings?.custom_header_content) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const renderMarkdown = (className: string) => (
|
||||
<ReactMarkdown
|
||||
className={`w-full text-wrap break-word ${className}`}
|
||||
components={{
|
||||
a: ({ node, ...props }) => (
|
||||
<a
|
||||
{...props}
|
||||
className="text-sm text-link hover:text-link-hover"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
/>
|
||||
),
|
||||
p: ({ node, ...props }) => (
|
||||
<p {...props} className="text-wrap break-word text-sm m-0 w-full" />
|
||||
),
|
||||
}}
|
||||
remarkPlugins={[remarkGfm]}
|
||||
>
|
||||
{settings.enterpriseSettings?.custom_header_content}
|
||||
</ReactMarkdown>
|
||||
);
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
mt-8
|
||||
mb-2
|
||||
p-1
|
||||
mx-2
|
||||
px-2
|
||||
z-[39]
|
||||
py-1.5
|
||||
text-wrap
|
||||
w-[500px]
|
||||
w-full
|
||||
mx-auto
|
||||
relative
|
||||
bg-background-100
|
||||
shadow-sm
|
||||
rounded
|
||||
border-l-8 border-l-400
|
||||
border-r-4 border-r-200
|
||||
border-border
|
||||
border
|
||||
flex`}
|
||||
>
|
||||
<div className="mx-auto text-emphasis text-sm flex flex-col">
|
||||
<div className="my-auto">
|
||||
<ReactMarkdown
|
||||
className="prose flex text-wrap break-all text-wrap max-w-full"
|
||||
components={{
|
||||
a: ({ node, ...props }) => (
|
||||
<a
|
||||
{...props}
|
||||
className="text-sm text-link hover:text-link-hover"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
/>
|
||||
),
|
||||
p: ({ node, ...props }) => (
|
||||
<p
|
||||
{...props}
|
||||
className="text-wrap break-all line-clamp-3 text-sm"
|
||||
/>
|
||||
),
|
||||
}}
|
||||
remarkPlugins={[remarkGfm]}
|
||||
<div className="text-emphasis text-sm w-full">
|
||||
<div className="relative">
|
||||
<div
|
||||
ref={contentRef}
|
||||
className="line-clamp-2 text-center w-full overflow-hidden pr-8"
|
||||
>
|
||||
{settings.enterpriseSettings.custom_header_content}
|
||||
</ReactMarkdown>
|
||||
{renderMarkdown("")}
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref={fullContentRef}
|
||||
className="absolute top-0 left-0 invisible w-full"
|
||||
>
|
||||
{renderMarkdown("")}
|
||||
</div>
|
||||
<div className="absolute bottom-0 right-0 ">
|
||||
{isOverflowing && (
|
||||
<Popover
|
||||
open={isPopoverOpen}
|
||||
onOpenChange={setIsPopoverOpen}
|
||||
content={
|
||||
<button
|
||||
onClick={() => setIsPopoverOpen(true)}
|
||||
className="cursor-poiner bg-background-100 p-1 rounded-full"
|
||||
>
|
||||
<ChevronDownIcon className="h-4 w-4 text-emphasis" />
|
||||
</button>
|
||||
}
|
||||
popover={
|
||||
<div className="bg-background-100 p-4 rounded shadow-lg mobile:max-w-xs desktop:max-w-md">
|
||||
<p className="text-lg font-bold">Banner Content</p>
|
||||
{renderMarkdown("max-h-96 overflow-y-auto")}
|
||||
</div>
|
||||
}
|
||||
side="bottom"
|
||||
align="end"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -66,7 +66,6 @@ import { useChatContext } from "@/components/context/ChatContext";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { orderAssistantsForUser } from "@/lib/assistants/orderAssistants";
|
||||
import { ChatPopup } from "./ChatPopup";
|
||||
import { ChatBanner } from "./ChatBanner";
|
||||
|
||||
import FunctionalHeader from "@/components/chat_search/Header";
|
||||
import { useSidebarVisibility } from "@/components/chat_search/hooks";
|
||||
@ -1192,6 +1191,7 @@ export function ChatPage({
|
||||
<div className="flex h-full flex-col w-full">
|
||||
{liveAssistant && (
|
||||
<FunctionalHeader
|
||||
sidebarToggled={toggledSidebar}
|
||||
reset={() => setMessage("")}
|
||||
page="chat"
|
||||
setSharingModalVisible={
|
||||
@ -1204,23 +1204,7 @@ export function ChatPage({
|
||||
currentChatSession={selectedChatSession}
|
||||
/>
|
||||
)}
|
||||
<div className="w-full flex">
|
||||
<div
|
||||
style={{ transition: "width 0.30s ease-out" }}
|
||||
className={`
|
||||
flex-none
|
||||
overflow-y-hidden
|
||||
bg-background-100
|
||||
transition-all
|
||||
bg-opacity-80
|
||||
duration-300
|
||||
ease-in-out
|
||||
h-full
|
||||
${toggledSidebar ? "w-[250px]" : "w-[0px]"}
|
||||
`}
|
||||
/>
|
||||
<ChatBanner />
|
||||
</div>
|
||||
|
||||
{documentSidebarInitialWidth !== undefined ? (
|
||||
<Dropzone onDrop={handleImageUpload} noClick>
|
||||
{({ getRootProps }) => (
|
||||
|
@ -11,13 +11,9 @@ import {
|
||||
} from "react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { BasicClickable } from "@/components/BasicClickable";
|
||||
import { ChatSession } from "../interfaces";
|
||||
|
||||
import {
|
||||
NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED,
|
||||
NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA,
|
||||
} from "@/lib/constants";
|
||||
import { NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA } from "@/lib/constants";
|
||||
|
||||
import { Folder } from "../folders/interfaces";
|
||||
import { createFolder } from "../folders/FolderManagement";
|
||||
@ -25,24 +21,16 @@ import { usePopup } from "@/components/admin/connectors/Popup";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
|
||||
import React from "react";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { HeaderTitle } from "@/components/header/Header";
|
||||
import { TbLayoutSidebarRightExpand } from "react-icons/tb";
|
||||
import {
|
||||
AssistantsIcon,
|
||||
AssistantsIconSkeleton,
|
||||
BackIcon,
|
||||
BookIcon,
|
||||
BookmarkIconSkeleton,
|
||||
ClosedBookIcon,
|
||||
LefToLineIcon,
|
||||
RightToLineIcon,
|
||||
} from "@/components/icons/icons";
|
||||
import { PagesTab } from "./PagesTab";
|
||||
import { Tooltip } from "@/components/tooltip/Tooltip";
|
||||
import KeyboardSymbol from "@/lib/browserUtilities";
|
||||
import { pageType } from "./types";
|
||||
import { usePaidEnterpriseFeaturesEnabled } from "@/components/settings/usePaidEnterpriseFeaturesEnabled";
|
||||
import LogoType from "@/components/header/LogoType";
|
||||
|
||||
interface HistorySidebarProps {
|
||||
page: pageType;
|
||||
@ -115,43 +103,15 @@ export const HistorySidebar = forwardRef<HTMLDivElement, HistorySidebarProps>(
|
||||
flex
|
||||
flex-col relative
|
||||
h-screen
|
||||
transition-transform`}
|
||||
transition-transform
|
||||
mt-2`}
|
||||
>
|
||||
<div className="max-w-full ml-3 mr-3 mt-2 flex flex gap-x-1 items-center my-auto text-text-700 text-xl">
|
||||
<div className="mr-1 desktop:invisible mb-auto h-6 w-6">
|
||||
<Logo height={24} width={24} />
|
||||
</div>
|
||||
|
||||
<div className="desktop:invisible">
|
||||
{enterpriseSettings && enterpriseSettings.application_name ? (
|
||||
<div>
|
||||
<HeaderTitle>
|
||||
{enterpriseSettings.application_name}
|
||||
</HeaderTitle>
|
||||
{!NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED && (
|
||||
<p className="text-xs text-subtle">Powered by Danswer</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<HeaderTitle>Danswer</HeaderTitle>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{toggleSidebar && (
|
||||
<Tooltip
|
||||
delayDuration={0}
|
||||
content={toggled ? `Unpin sidebar` : "Pin sidebar"}
|
||||
>
|
||||
<button className="my-auto ml-auto" onClick={toggleSidebar}>
|
||||
{!toggled && !combinedSettings.isMobile ? (
|
||||
<RightToLineIcon />
|
||||
) : (
|
||||
<LefToLineIcon />
|
||||
)}
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<LogoType
|
||||
showArrow={true}
|
||||
toggled={toggled}
|
||||
page={page}
|
||||
toggleSidebar={toggleSidebar}
|
||||
/>
|
||||
|
||||
{page == "chat" && (
|
||||
<div className="mx-3 mt-4 gap-y-1 flex-col flex gap-x-1.5 items-center items-center">
|
||||
|
@ -7,10 +7,10 @@ import {
|
||||
import { fetchSS } from "@/lib/utilsSS";
|
||||
import { redirect } from "next/navigation";
|
||||
import { BackendChatSession } from "../../interfaces";
|
||||
import { Header } from "@/components/header/Header";
|
||||
import { SharedChatDisplay } from "./SharedChatDisplay";
|
||||
import { Persona } from "@/app/admin/assistants/interfaces";
|
||||
import { fetchAssistantsSS } from "@/lib/assistants/fetchAssistantsSS";
|
||||
import FunctionalHeader from "@/components/chat_search/Header";
|
||||
|
||||
async function getSharedChat(chatId: string) {
|
||||
const response = await fetchSS(
|
||||
@ -57,7 +57,7 @@ export default async function Page({ params }: { params: { chatId: string } }) {
|
||||
return (
|
||||
<div>
|
||||
<div className="absolute top-0 z-40 w-full">
|
||||
<Header user={user} />
|
||||
<FunctionalHeader page="chat" toggleSidebar={() => null} user={user} />
|
||||
</div>
|
||||
|
||||
<div className="flex relative bg-background text-default overflow-hidden pt-16 h-screen">
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { HeaderTitle } from "@/components/header/Header";
|
||||
import { HeaderTitle } from "@/components/header/HeaderTitle";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
import { NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED } from "@/lib/constants";
|
||||
|
@ -115,7 +115,10 @@ export default function FunctionalWrapper({
|
||||
window.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [router]);
|
||||
const settings = useContext(SettingsContext)?.settings;
|
||||
const combinedSettings = useContext(SettingsContext);
|
||||
const settings = combinedSettings?.settings;
|
||||
const chatBannerPresent =
|
||||
combinedSettings?.enterpriseSettings?.custom_header_content;
|
||||
|
||||
const [toggledSidebar, setToggledSidebar] = useState(initiallyToggled);
|
||||
|
||||
@ -131,7 +134,9 @@ export default function FunctionalWrapper({
|
||||
<>
|
||||
{(!settings ||
|
||||
(settings.search_page_enabled && settings.chat_page_enabled)) && (
|
||||
<div className="mobile:hidden z-30 flex fixed top-4 left-1/2 transform -translate-x-1/2">
|
||||
<div
|
||||
className={`mobile:hidden z-30 flex fixed ${chatBannerPresent ? "top-20" : "top-4"} left-1/2 transform -translate-x-1/2`}
|
||||
>
|
||||
<div
|
||||
style={{ transition: "width 0.30s ease-out" }}
|
||||
className={`flex-none overflow-y-hidden bg-background-100 transition-all bg-opacity-80 duration-300 ease-in-out h-full
|
||||
|
@ -1,5 +1,3 @@
|
||||
import { SearchSection } from "@/components/search/SearchSection";
|
||||
import { Header } from "@/components/header/Header";
|
||||
import {
|
||||
AuthTypeMetadata,
|
||||
getAuthTypeMetadataSS,
|
||||
|
@ -1,19 +1,3 @@
|
||||
import { Header } from "@/components/header/Header";
|
||||
import { AdminSidebar } from "@/components/admin/connectors/AdminSidebar";
|
||||
import {
|
||||
NotebookIcon,
|
||||
UsersIcon,
|
||||
ThumbsUpIcon,
|
||||
BookmarkIcon,
|
||||
ZoomInIcon,
|
||||
RobotIcon,
|
||||
ConnectorIcon,
|
||||
GroupsIcon,
|
||||
DatabaseIcon,
|
||||
KeyIcon,
|
||||
ClipboardIcon,
|
||||
BookstackIcon,
|
||||
} from "@/components/icons/icons";
|
||||
import { User } from "@/lib/types";
|
||||
import {
|
||||
AuthTypeMetadata,
|
||||
|
@ -4,7 +4,7 @@ import React, { useContext } from "react";
|
||||
import Link from "next/link";
|
||||
import { Logo } from "@/components/Logo";
|
||||
import { NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED } from "@/lib/constants";
|
||||
import { HeaderTitle } from "@/components/header/Header";
|
||||
import { HeaderTitle } from "@/components/header/HeaderTitle";
|
||||
import { SettingsContext } from "@/components/settings/SettingsProvider";
|
||||
import { BackIcon } from "@/components/icons/icons";
|
||||
|
||||
|
@ -1,22 +1,17 @@
|
||||
"use client";
|
||||
import { User } from "@/lib/types";
|
||||
import { TbLayoutSidebarLeftExpand } from "react-icons/tb";
|
||||
import { UserDropdown } from "../UserDropdown";
|
||||
import { FiShare2, FiSidebar } from "react-icons/fi";
|
||||
import { FiShare2 } from "react-icons/fi";
|
||||
import { SetStateAction, useContext, useEffect } from "react";
|
||||
import { Logo } from "../Logo";
|
||||
import { ChatIcon, NewChatIcon, PlusCircleIcon } from "../icons/icons";
|
||||
import {
|
||||
NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED,
|
||||
NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA,
|
||||
} from "@/lib/constants";
|
||||
import { NewChatIcon } from "../icons/icons";
|
||||
import { NEXT_PUBLIC_NEW_CHAT_DIRECTS_TO_SAME_PERSONA } from "@/lib/constants";
|
||||
import { ChatSession } from "@/app/chat/interfaces";
|
||||
import { HeaderTitle } from "../header/Header";
|
||||
import { Tooltip } from "../tooltip/Tooltip";
|
||||
import KeyboardSymbol from "@/lib/browserUtilities";
|
||||
import Link from "next/link";
|
||||
import { SettingsContext } from "../settings/SettingsProvider";
|
||||
import { pageType } from "@/app/chat/sessionSidebar/types";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { ChatBanner } from "@/app/chat/ChatBanner";
|
||||
import LogoType from "../header/LogoType";
|
||||
|
||||
export default function FunctionalHeader({
|
||||
user,
|
||||
@ -25,10 +20,12 @@ export default function FunctionalHeader({
|
||||
setSharingModalVisible,
|
||||
toggleSidebar,
|
||||
reset = () => null,
|
||||
sidebarToggled,
|
||||
}: {
|
||||
reset?: () => void;
|
||||
page: pageType;
|
||||
user: User | null;
|
||||
sidebarToggled?: boolean;
|
||||
currentChatSession?: ChatSession | null | undefined;
|
||||
setSharingModalVisible?: (value: SetStateAction<boolean>) => void;
|
||||
toggleSidebar: () => void;
|
||||
@ -36,8 +33,6 @@ export default function FunctionalHeader({
|
||||
const combinedSettings = useContext(SettingsContext);
|
||||
const enterpriseSettings = combinedSettings?.enterpriseSettings;
|
||||
|
||||
const commandSymbol = KeyboardSymbol();
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.metaKey || event.ctrlKey) {
|
||||
@ -74,43 +69,40 @@ export default function FunctionalHeader({
|
||||
};
|
||||
return (
|
||||
<div className="pb-6 left-0 sticky top-0 z-20 w-full relative flex">
|
||||
<div className="mt-2 mx-4 text-text-700 flex w-full">
|
||||
<div className="absolute z-[100] my-auto flex items-center text-xl font-bold">
|
||||
<button
|
||||
onClick={() => toggleSidebar()}
|
||||
className="pt-[2px] desktop:invisible mb-auto"
|
||||
>
|
||||
<FiSidebar size={20} />
|
||||
</button>
|
||||
<div className="invisible break-words inline-block w-fit ml-2 text-text-700 text-xl">
|
||||
<div className="max-w-[200px]">
|
||||
{enterpriseSettings && enterpriseSettings.application_name ? (
|
||||
<div>
|
||||
<HeaderTitle>
|
||||
{enterpriseSettings.application_name}
|
||||
</HeaderTitle>
|
||||
{!NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED && (
|
||||
<p className="text-xs text-subtle">Powered by Danswer</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<HeaderTitle>Danswer</HeaderTitle>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-2 mx-2.5 text-text-700 relative flex w-full">
|
||||
<LogoType
|
||||
page={page}
|
||||
toggleSidebar={toggleSidebar}
|
||||
handleNewChat={handleNewChat}
|
||||
/>
|
||||
|
||||
{page == "chat" && (
|
||||
<Tooltip delayDuration={1000} content="New Chat">
|
||||
<button className="mobile:hidden my-auto" onClick={handleNewChat}>
|
||||
<div className="cursor-pointer ml-2 flex-none text-text-700 hover:text-text-600 transition-colors duration-300">
|
||||
<NewChatIcon size={20} />
|
||||
</div>
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
<div
|
||||
style={{ transition: "width 0.30s ease-out" }}
|
||||
className={`
|
||||
mobile:hidden
|
||||
flex-none
|
||||
mx-auto
|
||||
overflow-y-hidden
|
||||
transition-all
|
||||
duration-300
|
||||
ease-in-out
|
||||
h-full
|
||||
${sidebarToggled ? "w-[250px]" : "w-[0px]"}
|
||||
`}
|
||||
/>
|
||||
<div className="w-full mobile:-mx-20 desktop:px-4">
|
||||
<ChatBanner />
|
||||
</div>
|
||||
|
||||
<div className="ml-auto my-auto flex gap-x-2">
|
||||
<div className="invisible">
|
||||
<LogoType
|
||||
page={page}
|
||||
toggleSidebar={toggleSidebar}
|
||||
handleNewChat={handleNewChat}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="absolute right-0 top-0 flex gap-x-2">
|
||||
{setSharingModalVisible && (
|
||||
<div
|
||||
onClick={() => setSharingModalVisible(true)}
|
||||
@ -133,7 +125,7 @@ export default function FunctionalHeader({
|
||||
: "")
|
||||
}
|
||||
>
|
||||
<div className="cursor-pointer ml-2 flex-none text-text-700 hover:text-text-600 transition-colors duration-300">
|
||||
<div className="cursor-pointer mr-4 flex-none text-text-700 hover:text-text-600 transition-colors duration-300">
|
||||
<NewChatIcon size={20} />
|
||||
</div>
|
||||
</Link>
|
||||
|
@ -1,78 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { User } from "@/lib/types";
|
||||
import Link from "next/link";
|
||||
import React, { useContext } from "react";
|
||||
import { HeaderWrapper } from "./HeaderWrapper";
|
||||
import { SettingsContext } from "../settings/SettingsProvider";
|
||||
import { UserDropdown } from "../UserDropdown";
|
||||
import { Logo } from "../Logo";
|
||||
import { NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED } from "@/lib/constants";
|
||||
import { pageType } from "@/app/chat/sessionSidebar/types";
|
||||
|
||||
export function HeaderTitle({ children }: { children: JSX.Element | string }) {
|
||||
const isString = typeof children === "string";
|
||||
const textSize = isString && children.length > 10 ? "text-xl" : "text-2xl";
|
||||
|
||||
return (
|
||||
<h1 className={`flex ${textSize} text-strong leading-none font-bold`}>
|
||||
{children}
|
||||
</h1>
|
||||
);
|
||||
}
|
||||
interface HeaderProps {
|
||||
user: User | null;
|
||||
page?: pageType;
|
||||
}
|
||||
|
||||
export function Header({ user, page }: HeaderProps) {
|
||||
const combinedSettings = useContext(SettingsContext);
|
||||
if (!combinedSettings) {
|
||||
return null;
|
||||
}
|
||||
const settings = combinedSettings.settings;
|
||||
const enterpriseSettings = combinedSettings.enterpriseSettings;
|
||||
|
||||
return (
|
||||
<HeaderWrapper>
|
||||
<div className="flex h-full">
|
||||
<Link
|
||||
className="py-3 flex flex-col"
|
||||
href={
|
||||
settings && settings.default_page === "chat" ? "/chat" : "/search"
|
||||
}
|
||||
>
|
||||
<div className="max-w-[200px] flex my-auto">
|
||||
<div className="mr-1 mb-auto">
|
||||
<Logo />
|
||||
</div>
|
||||
<div className="my-auto">
|
||||
{enterpriseSettings && enterpriseSettings.application_name ? (
|
||||
<div>
|
||||
<HeaderTitle>
|
||||
{enterpriseSettings.application_name}
|
||||
</HeaderTitle>
|
||||
{!NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED && (
|
||||
<p className="text-xs text-subtle">Powered by Danswer</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<HeaderTitle>Danswer</HeaderTitle>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<div className="ml-auto h-full flex flex-col">
|
||||
<div className="my-auto">
|
||||
<UserDropdown user={user} page={page} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</HeaderWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
*/
|
14
web/src/components/header/HeaderTitle.tsx
Normal file
14
web/src/components/header/HeaderTitle.tsx
Normal file
@ -0,0 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
export function HeaderTitle({ children }: { children: JSX.Element | string }) {
|
||||
const isString = typeof children === "string";
|
||||
const textSize = isString && children.length > 10 ? "text-xl" : "text-2xl";
|
||||
|
||||
return (
|
||||
<h1 className={`flex ${textSize} text-strong leading-none font-bold`}>
|
||||
{children}
|
||||
</h1>
|
||||
);
|
||||
}
|
88
web/src/components/header/LogoType.tsx
Normal file
88
web/src/components/header/LogoType.tsx
Normal file
@ -0,0 +1,88 @@
|
||||
"use effect";
|
||||
import { useContext } from "react";
|
||||
import { FiSidebar } from "react-icons/fi";
|
||||
import { SettingsContext } from "../settings/SettingsProvider";
|
||||
import { NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED } from "@/lib/constants";
|
||||
import { LefToLineIcon, NewChatIcon, RightToLineIcon } from "../icons/icons";
|
||||
import { Tooltip } from "../tooltip/Tooltip";
|
||||
import { pageType } from "@/app/chat/sessionSidebar/types";
|
||||
import { Logo } from "../Logo";
|
||||
import { HeaderTitle } from "./HeaderTitle";
|
||||
|
||||
export default function LogoType({
|
||||
toggleSidebar,
|
||||
hideOnMobile,
|
||||
handleNewChat,
|
||||
page,
|
||||
toggled,
|
||||
showArrow,
|
||||
}: {
|
||||
hideOnMobile?: boolean;
|
||||
toggleSidebar?: () => void;
|
||||
handleNewChat?: () => void;
|
||||
page: pageType;
|
||||
toggled?: boolean;
|
||||
showArrow?: boolean;
|
||||
}) {
|
||||
const combinedSettings = useContext(SettingsContext);
|
||||
const enterpriseSettings = combinedSettings?.enterpriseSettings;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${hideOnMobile && "mobile:hidden"} z-[100] mb-auto shrink-0 flex items-center text-xl font-bold`}
|
||||
>
|
||||
{toggleSidebar && page == "chat" ? (
|
||||
<button
|
||||
onClick={() => toggleSidebar()}
|
||||
className="pt-[2px] ml-4 desktop:invisible mb-auto"
|
||||
>
|
||||
<FiSidebar size={20} />
|
||||
</button>
|
||||
) : (
|
||||
<div className="mr-1 invisible mb-auto h-6 w-6">
|
||||
<Logo height={24} width={24} />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={` ${showArrow ? "desktop:invisible" : "invisible"} break-words inline-block w-fit ml-2 text-text-700 text-xl`}
|
||||
>
|
||||
<div className="max-w-[175px]">
|
||||
{enterpriseSettings && enterpriseSettings.application_name ? (
|
||||
<div>
|
||||
<HeaderTitle>{enterpriseSettings.application_name}</HeaderTitle>
|
||||
{!NEXT_PUBLIC_DO_NOT_USE_TOGGLE_OFF_DANSWER_POWERED && (
|
||||
<p className="text-xs text-subtle">Powered by Danswer</p>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<HeaderTitle>Danswer</HeaderTitle>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{page == "chat" && !showArrow && (
|
||||
<Tooltip delayDuration={1000} content="New Chat">
|
||||
<button className="my-auto mobile:hidden" onClick={handleNewChat}>
|
||||
<div className="cursor-pointer ml-2 flex-none text-text-700 hover:text-text-600 transition-colors duration-300">
|
||||
<NewChatIcon size={20} />
|
||||
</div>
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showArrow && (
|
||||
<Tooltip
|
||||
delayDuration={0}
|
||||
content={toggled ? `Unpin sidebar` : "Pin sidebar"}
|
||||
>
|
||||
<button className="mr-3 my-auto ml-auto" onClick={toggleSidebar}>
|
||||
{!toggled && !combinedSettings?.isMobile ? (
|
||||
<RightToLineIcon />
|
||||
) : (
|
||||
<LefToLineIcon />
|
||||
)}
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -514,6 +514,8 @@ export const SearchSection = ({
|
||||
});
|
||||
}
|
||||
|
||||
const chatBannerPresent = settings?.enterpriseSettings?.custom_header_content;
|
||||
|
||||
const { popup, setPopup } = usePopup();
|
||||
|
||||
return (
|
||||
@ -553,6 +555,7 @@ export const SearchSection = ({
|
||||
|
||||
<div className="absolute left-0 w-full top-0">
|
||||
<FunctionalHeader
|
||||
sidebarToggled={toggledSidebar}
|
||||
reset={() => setQuery("")}
|
||||
toggleSidebar={toggleSidebar}
|
||||
page="search"
|
||||
@ -575,7 +578,9 @@ export const SearchSection = ({
|
||||
/>
|
||||
|
||||
{
|
||||
<div className="desktop:px-24 w-full pt-10 relative max-w-[2000px] xl:max-w-[1430px] mx-auto">
|
||||
<div
|
||||
className={`desktop:px-24 w-full ${chatBannerPresent && "mt-10"} pt-10 relative max-w-[2000px] xl:max-w-[1430px] mx-auto`}
|
||||
>
|
||||
<div className="absolute z-10 mobile:px-4 mobile:max-w-searchbar-max mobile:w-[90%] top-12 desktop:left-0 hidden 2xl:block mobile:left-1/2 mobile:transform mobile:-translate-x-1/2 desktop:w-52 3xl:w-64">
|
||||
{!settings?.isMobile &&
|
||||
(ccPairs.length > 0 || documentSets.length > 0) && (
|
||||
|
Loading…
x
Reference in New Issue
Block a user