mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-03 06:24:15 +03:00
feat(frontend): manage current brain (#2165)
# Description Please include a summary of the changes and the related issue. Please also include relevant motivation and context. ## Checklist before requesting a review Please delete options that are not relevant. - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented hard-to-understand areas - [ ] I have ideally added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged ## Screenshots (if appropriate):
This commit is contained in:
parent
9d948b33d5
commit
9517b01d9a
@ -33,7 +33,7 @@ export const ChatInput = (): JSX.Element => {
|
||||
}}
|
||||
>
|
||||
<div className={styles.chat_container}>
|
||||
<CurrentBrain />
|
||||
<CurrentBrain allowingRemoveBrain={false} />
|
||||
<div
|
||||
className={`
|
||||
${styles.chat_wrapper}
|
||||
|
@ -1,9 +1,14 @@
|
||||
"use client";
|
||||
|
||||
import { UUID } from "crypto";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { AddBrainModal } from "@/lib/components/AddBrainModal";
|
||||
import { useBrainCreationContext } from "@/lib/components/AddBrainModal/components/AddBrainSteps/brainCreation-provider";
|
||||
import PageHeader from "@/lib/components/PageHeader/PageHeader";
|
||||
import { UploadDocumentModal } from "@/lib/components/UploadDocumentModal/UploadDocumentModal";
|
||||
import { useChatContext } from "@/lib/context";
|
||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||
import { useKnowledgeToFeedContext } from "@/lib/context/KnowledgeToFeedProvider/hooks/useKnowledgeToFeedContext";
|
||||
import { useDevice } from "@/lib/hooks/useDevice";
|
||||
import { useCustomDropzone } from "@/lib/hooks/useDropzone";
|
||||
@ -23,6 +28,9 @@ const SelectedChatPage = (): JSX.Element => {
|
||||
const { setShouldDisplayFeedCard } = useKnowledgeToFeedContext();
|
||||
const { setIsBrainCreationModalOpened } = useBrainCreationContext();
|
||||
|
||||
const { currentBrain, setCurrentBrainId } = useBrainContext();
|
||||
const { messages } = useChatContext();
|
||||
|
||||
useChatNotificationsSync();
|
||||
|
||||
const buttons: ButtonType[] = [
|
||||
@ -32,6 +40,7 @@ const SelectedChatPage = (): JSX.Element => {
|
||||
onClick: () => {
|
||||
setIsBrainCreationModalOpened(true);
|
||||
},
|
||||
iconName: "brain",
|
||||
},
|
||||
{
|
||||
label: "Add knowledge",
|
||||
@ -39,9 +48,24 @@ const SelectedChatPage = (): JSX.Element => {
|
||||
onClick: () => {
|
||||
setShouldDisplayFeedCard(true);
|
||||
},
|
||||
iconName: "upload",
|
||||
},
|
||||
{
|
||||
label: "Manage current brain",
|
||||
color: "primary",
|
||||
onClick: () => {
|
||||
window.location.href = `/studio/${currentBrain?.id}`;
|
||||
},
|
||||
iconName: "edit",
|
||||
},
|
||||
];
|
||||
|
||||
useEffect(() => {
|
||||
if (!currentBrain && messages.length > 0) {
|
||||
setCurrentBrainId(messages[messages.length - 1].brain_id as UUID);
|
||||
}
|
||||
}, [messages]);
|
||||
|
||||
return (
|
||||
<div className={styles.main_container}>
|
||||
<div className={styles.page_header}>
|
||||
|
@ -34,6 +34,7 @@ const Search = (): JSX.Element => {
|
||||
onClick: () => {
|
||||
setIsBrainCreationModalOpened(true);
|
||||
},
|
||||
iconName: "brain",
|
||||
},
|
||||
{
|
||||
label: "Add knowledge",
|
||||
@ -41,6 +42,7 @@ const Search = (): JSX.Element => {
|
||||
onClick: () => {
|
||||
setShouldDisplayFeedCard(true);
|
||||
},
|
||||
iconName: "upload",
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -42,6 +42,7 @@ const Studio = (): JSX.Element => {
|
||||
onClick: () => {
|
||||
setIsBrainCreationModalOpened(true);
|
||||
},
|
||||
iconName: "brain",
|
||||
},
|
||||
{
|
||||
label: "Add knowledge",
|
||||
@ -49,6 +50,7 @@ const Studio = (): JSX.Element => {
|
||||
onClick: () => {
|
||||
setShouldDisplayFeedCard(true);
|
||||
},
|
||||
iconName: "upload",
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -38,6 +38,7 @@ const UserPage = (): JSX.Element => {
|
||||
onClick: () => {
|
||||
setIsLogoutModalOpened(true);
|
||||
},
|
||||
iconName: "logout",
|
||||
};
|
||||
const userTabs: Tab[] = [
|
||||
{
|
||||
@ -91,12 +92,14 @@ const UserPage = (): JSX.Element => {
|
||||
onClick={() => setIsLogoutModalOpened(false)}
|
||||
color="primary"
|
||||
label={t("cancel", { ns: "logout" })}
|
||||
iconName="close"
|
||||
></QuivrButton>
|
||||
<QuivrButton
|
||||
isLoading={isLoggingOut}
|
||||
color="dangerous"
|
||||
onClick={() => void handleLogout()}
|
||||
label={t("logoutButton")}
|
||||
iconName="logout"
|
||||
></QuivrButton>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,7 +4,13 @@ import styles from "./CurrentBrain.module.scss";
|
||||
|
||||
import { Icon } from "../ui/Icon/Icon";
|
||||
|
||||
export const CurrentBrain = (): JSX.Element => {
|
||||
interface CurrentBrainProps {
|
||||
allowingRemoveBrain: boolean;
|
||||
}
|
||||
|
||||
export const CurrentBrain = ({
|
||||
allowingRemoveBrain,
|
||||
}: CurrentBrainProps): JSX.Element => {
|
||||
const { currentBrain, setCurrentBrainId } = useBrainContext();
|
||||
|
||||
const removeCurrentBrain = (): void => {
|
||||
@ -25,14 +31,16 @@ export const CurrentBrain = (): JSX.Element => {
|
||||
<span className={styles.brain_name}>{currentBrain.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
onClick={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation();
|
||||
removeCurrentBrain();
|
||||
}}
|
||||
>
|
||||
<Icon size="normal" name="close" color="black" handleHover={true} />
|
||||
</div>
|
||||
{allowingRemoveBrain && (
|
||||
<div
|
||||
onClick={(event) => {
|
||||
event.nativeEvent.stopImmediatePropagation();
|
||||
removeCurrentBrain();
|
||||
}}
|
||||
>
|
||||
<Icon size="normal" name="close" color="black" handleHover={true} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -32,6 +32,7 @@ export const PageHeader = ({
|
||||
label={button.label}
|
||||
onClick={button.onClick}
|
||||
color={button.color}
|
||||
iconName={button.iconName}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
@ -51,10 +51,6 @@
|
||||
|
||||
.white {
|
||||
color: Colors.$white;
|
||||
|
||||
&:hover {
|
||||
color: Colors.$accent;
|
||||
}
|
||||
}
|
||||
|
||||
.dangerous {
|
||||
|
@ -1,5 +1,6 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Radius.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
|
||||
@ -11,6 +12,7 @@
|
||||
border-radius: Radius.$normal;
|
||||
border: 1.5px solid transparent;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
|
||||
&.primary {
|
||||
border-color: Colors.$primary;
|
||||
@ -32,3 +34,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon_label {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: Spacings.$spacing02;
|
||||
align-items: center;
|
||||
|
||||
@media (max-width: ScreenSizes.$small) {
|
||||
.label {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { ButtonType } from "@/lib/types/QuivrButton";
|
||||
|
||||
import styles from "./QuivrButton.module.scss";
|
||||
|
||||
import { Icon } from "../Icon/Icon";
|
||||
import { LoaderIcon } from "../LoaderIcon/LoaderIcon";
|
||||
|
||||
export const QuivrButton = ({
|
||||
@ -9,14 +12,27 @@ export const QuivrButton = ({
|
||||
label,
|
||||
color,
|
||||
isLoading,
|
||||
iconName,
|
||||
}: ButtonType): JSX.Element => {
|
||||
const [hovered, setHovered] = useState<boolean>(false);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.button_wrapper} ${styles[color]}`}
|
||||
onClick={onClick}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
>
|
||||
{!isLoading ? (
|
||||
<span>{label}</span>
|
||||
<div className={styles.icon_label}>
|
||||
<Icon
|
||||
name={iconName}
|
||||
size="normal"
|
||||
color={hovered ? "white" : color}
|
||||
handleHover={false}
|
||||
/>
|
||||
<span className={styles.label}>{label}</span>
|
||||
</div>
|
||||
) : (
|
||||
<LoaderIcon color="black" size="small" />
|
||||
)}
|
||||
|
@ -56,7 +56,7 @@ export const SearchBar = ({
|
||||
${currentBrain ? styles.with_brain : ""}
|
||||
`}
|
||||
>
|
||||
<CurrentBrain />
|
||||
<CurrentBrain allowingRemoveBrain={true} />
|
||||
<div
|
||||
className={`
|
||||
${styles.editor_wrapper}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { AiOutlineLoading3Quarters } from "react-icons/ai";
|
||||
import { BsArrowRightShort } from "react-icons/bs";
|
||||
import { CiChat1, CiFlag1 } from "react-icons/ci";
|
||||
import { BsArrowRightShort, BsChatLeftText } from "react-icons/bs";
|
||||
import { CiFlag1 } from "react-icons/ci";
|
||||
import {
|
||||
FaCheck,
|
||||
FaCheckCircle,
|
||||
@ -9,9 +9,12 @@ import {
|
||||
FaRegUserCircle,
|
||||
FaUnlock,
|
||||
} from "react-icons/fa";
|
||||
import { FaArrowUpFromBracket } from "react-icons/fa6";
|
||||
import { IoIosAdd, IoMdClose, IoMdLogOut } from "react-icons/io";
|
||||
import { IoHomeOutline, IoSettingsSharp } from "react-icons/io5";
|
||||
import {
|
||||
IoArrowUpCircleOutline,
|
||||
IoHomeOutline,
|
||||
IoSettingsSharp,
|
||||
} from "react-icons/io5";
|
||||
import { IconType } from "react-icons/lib";
|
||||
import {
|
||||
LuBrain,
|
||||
@ -38,7 +41,7 @@ export const iconList: { [name: string]: IconType } = {
|
||||
addWithoutCircle: IoIosAdd,
|
||||
brain: LuBrain,
|
||||
brainCircuit: LuBrainCircuit,
|
||||
chat: CiChat1,
|
||||
chat: BsChatLeftText,
|
||||
check: FaCheck,
|
||||
checkCircle: FaCheckCircle,
|
||||
chevronDown: LuChevronDown,
|
||||
@ -50,7 +53,7 @@ export const iconList: { [name: string]: IconType } = {
|
||||
email: MdAlternateEmail,
|
||||
file: LuFile,
|
||||
flag: CiFlag1,
|
||||
followUp: FaArrowUpFromBracket,
|
||||
followUp: IoArrowUpCircleOutline,
|
||||
graph: VscGraph,
|
||||
hastag: RiHashtag,
|
||||
history: MdHistory,
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { Color } from "./Colors";
|
||||
|
||||
import { iconList } from "../helpers/iconList";
|
||||
|
||||
export interface ButtonType {
|
||||
label: string;
|
||||
color: Color;
|
||||
isLoading?: boolean;
|
||||
iconName: keyof typeof iconList;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user