mirror of
https://github.com/StanGirard/quivr.git
synced 2024-12-12 11:26:07 +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}>
|
<div className={styles.chat_container}>
|
||||||
<CurrentBrain />
|
<CurrentBrain allowingRemoveBrain={false} />
|
||||||
<div
|
<div
|
||||||
className={`
|
className={`
|
||||||
${styles.chat_wrapper}
|
${styles.chat_wrapper}
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
|
import { UUID } from "crypto";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
import { AddBrainModal } from "@/lib/components/AddBrainModal";
|
import { AddBrainModal } from "@/lib/components/AddBrainModal";
|
||||||
import { useBrainCreationContext } from "@/lib/components/AddBrainModal/components/AddBrainSteps/brainCreation-provider";
|
import { useBrainCreationContext } from "@/lib/components/AddBrainModal/components/AddBrainSteps/brainCreation-provider";
|
||||||
import PageHeader from "@/lib/components/PageHeader/PageHeader";
|
import PageHeader from "@/lib/components/PageHeader/PageHeader";
|
||||||
import { UploadDocumentModal } from "@/lib/components/UploadDocumentModal/UploadDocumentModal";
|
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 { useKnowledgeToFeedContext } from "@/lib/context/KnowledgeToFeedProvider/hooks/useKnowledgeToFeedContext";
|
||||||
import { useDevice } from "@/lib/hooks/useDevice";
|
import { useDevice } from "@/lib/hooks/useDevice";
|
||||||
import { useCustomDropzone } from "@/lib/hooks/useDropzone";
|
import { useCustomDropzone } from "@/lib/hooks/useDropzone";
|
||||||
@ -23,6 +28,9 @@ const SelectedChatPage = (): JSX.Element => {
|
|||||||
const { setShouldDisplayFeedCard } = useKnowledgeToFeedContext();
|
const { setShouldDisplayFeedCard } = useKnowledgeToFeedContext();
|
||||||
const { setIsBrainCreationModalOpened } = useBrainCreationContext();
|
const { setIsBrainCreationModalOpened } = useBrainCreationContext();
|
||||||
|
|
||||||
|
const { currentBrain, setCurrentBrainId } = useBrainContext();
|
||||||
|
const { messages } = useChatContext();
|
||||||
|
|
||||||
useChatNotificationsSync();
|
useChatNotificationsSync();
|
||||||
|
|
||||||
const buttons: ButtonType[] = [
|
const buttons: ButtonType[] = [
|
||||||
@ -32,6 +40,7 @@ const SelectedChatPage = (): JSX.Element => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
setIsBrainCreationModalOpened(true);
|
setIsBrainCreationModalOpened(true);
|
||||||
},
|
},
|
||||||
|
iconName: "brain",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Add knowledge",
|
label: "Add knowledge",
|
||||||
@ -39,9 +48,24 @@ const SelectedChatPage = (): JSX.Element => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
setShouldDisplayFeedCard(true);
|
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 (
|
return (
|
||||||
<div className={styles.main_container}>
|
<div className={styles.main_container}>
|
||||||
<div className={styles.page_header}>
|
<div className={styles.page_header}>
|
||||||
|
@ -34,6 +34,7 @@ const Search = (): JSX.Element => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
setIsBrainCreationModalOpened(true);
|
setIsBrainCreationModalOpened(true);
|
||||||
},
|
},
|
||||||
|
iconName: "brain",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Add knowledge",
|
label: "Add knowledge",
|
||||||
@ -41,6 +42,7 @@ const Search = (): JSX.Element => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
setShouldDisplayFeedCard(true);
|
setShouldDisplayFeedCard(true);
|
||||||
},
|
},
|
||||||
|
iconName: "upload",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ const Studio = (): JSX.Element => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
setIsBrainCreationModalOpened(true);
|
setIsBrainCreationModalOpened(true);
|
||||||
},
|
},
|
||||||
|
iconName: "brain",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Add knowledge",
|
label: "Add knowledge",
|
||||||
@ -49,6 +50,7 @@ const Studio = (): JSX.Element => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
setShouldDisplayFeedCard(true);
|
setShouldDisplayFeedCard(true);
|
||||||
},
|
},
|
||||||
|
iconName: "upload",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ const UserPage = (): JSX.Element => {
|
|||||||
onClick: () => {
|
onClick: () => {
|
||||||
setIsLogoutModalOpened(true);
|
setIsLogoutModalOpened(true);
|
||||||
},
|
},
|
||||||
|
iconName: "logout",
|
||||||
};
|
};
|
||||||
const userTabs: Tab[] = [
|
const userTabs: Tab[] = [
|
||||||
{
|
{
|
||||||
@ -91,12 +92,14 @@ const UserPage = (): JSX.Element => {
|
|||||||
onClick={() => setIsLogoutModalOpened(false)}
|
onClick={() => setIsLogoutModalOpened(false)}
|
||||||
color="primary"
|
color="primary"
|
||||||
label={t("cancel", { ns: "logout" })}
|
label={t("cancel", { ns: "logout" })}
|
||||||
|
iconName="close"
|
||||||
></QuivrButton>
|
></QuivrButton>
|
||||||
<QuivrButton
|
<QuivrButton
|
||||||
isLoading={isLoggingOut}
|
isLoading={isLoggingOut}
|
||||||
color="dangerous"
|
color="dangerous"
|
||||||
onClick={() => void handleLogout()}
|
onClick={() => void handleLogout()}
|
||||||
label={t("logoutButton")}
|
label={t("logoutButton")}
|
||||||
|
iconName="logout"
|
||||||
></QuivrButton>
|
></QuivrButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,13 @@ import styles from "./CurrentBrain.module.scss";
|
|||||||
|
|
||||||
import { Icon } from "../ui/Icon/Icon";
|
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 { currentBrain, setCurrentBrainId } = useBrainContext();
|
||||||
|
|
||||||
const removeCurrentBrain = (): void => {
|
const removeCurrentBrain = (): void => {
|
||||||
@ -25,6 +31,7 @@ export const CurrentBrain = (): JSX.Element => {
|
|||||||
<span className={styles.brain_name}>{currentBrain.name}</span>
|
<span className={styles.brain_name}>{currentBrain.name}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{allowingRemoveBrain && (
|
||||||
<div
|
<div
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
event.nativeEvent.stopImmediatePropagation();
|
event.nativeEvent.stopImmediatePropagation();
|
||||||
@ -33,6 +40,7 @@ export const CurrentBrain = (): JSX.Element => {
|
|||||||
>
|
>
|
||||||
<Icon size="normal" name="close" color="black" handleHover={true} />
|
<Icon size="normal" name="close" color="black" handleHover={true} />
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -32,6 +32,7 @@ export const PageHeader = ({
|
|||||||
label={button.label}
|
label={button.label}
|
||||||
onClick={button.onClick}
|
onClick={button.onClick}
|
||||||
color={button.color}
|
color={button.color}
|
||||||
|
iconName={button.iconName}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,10 +51,6 @@
|
|||||||
|
|
||||||
.white {
|
.white {
|
||||||
color: Colors.$white;
|
color: Colors.$white;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: Colors.$accent;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dangerous {
|
.dangerous {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
@use "@/styles/Colors.module.scss";
|
@use "@/styles/Colors.module.scss";
|
||||||
@use "@/styles/Radius.module.scss";
|
@use "@/styles/Radius.module.scss";
|
||||||
|
@use "@/styles/ScreenSizes.module.scss";
|
||||||
@use "@/styles/Spacings.module.scss";
|
@use "@/styles/Spacings.module.scss";
|
||||||
@use "@/styles/Typography.module.scss";
|
@use "@/styles/Typography.module.scss";
|
||||||
|
|
||||||
@ -11,6 +12,7 @@
|
|||||||
border-radius: Radius.$normal;
|
border-radius: Radius.$normal;
|
||||||
border: 1.5px solid transparent;
|
border: 1.5px solid transparent;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
&.primary {
|
&.primary {
|
||||||
border-color: Colors.$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 { ButtonType } from "@/lib/types/QuivrButton";
|
||||||
|
|
||||||
import styles from "./QuivrButton.module.scss";
|
import styles from "./QuivrButton.module.scss";
|
||||||
|
|
||||||
|
import { Icon } from "../Icon/Icon";
|
||||||
import { LoaderIcon } from "../LoaderIcon/LoaderIcon";
|
import { LoaderIcon } from "../LoaderIcon/LoaderIcon";
|
||||||
|
|
||||||
export const QuivrButton = ({
|
export const QuivrButton = ({
|
||||||
@ -9,14 +12,27 @@ export const QuivrButton = ({
|
|||||||
label,
|
label,
|
||||||
color,
|
color,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
iconName,
|
||||||
}: ButtonType): JSX.Element => {
|
}: ButtonType): JSX.Element => {
|
||||||
|
const [hovered, setHovered] = useState<boolean>(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`${styles.button_wrapper} ${styles[color]}`}
|
className={`${styles.button_wrapper} ${styles[color]}`}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
onMouseEnter={() => setHovered(true)}
|
||||||
|
onMouseLeave={() => setHovered(false)}
|
||||||
>
|
>
|
||||||
{!isLoading ? (
|
{!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" />
|
<LoaderIcon color="black" size="small" />
|
||||||
)}
|
)}
|
||||||
|
@ -56,7 +56,7 @@ export const SearchBar = ({
|
|||||||
${currentBrain ? styles.with_brain : ""}
|
${currentBrain ? styles.with_brain : ""}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<CurrentBrain />
|
<CurrentBrain allowingRemoveBrain={true} />
|
||||||
<div
|
<div
|
||||||
className={`
|
className={`
|
||||||
${styles.editor_wrapper}
|
${styles.editor_wrapper}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { AiOutlineLoading3Quarters } from "react-icons/ai";
|
import { AiOutlineLoading3Quarters } from "react-icons/ai";
|
||||||
import { BsArrowRightShort } from "react-icons/bs";
|
import { BsArrowRightShort, BsChatLeftText } from "react-icons/bs";
|
||||||
import { CiChat1, CiFlag1 } from "react-icons/ci";
|
import { CiFlag1 } from "react-icons/ci";
|
||||||
import {
|
import {
|
||||||
FaCheck,
|
FaCheck,
|
||||||
FaCheckCircle,
|
FaCheckCircle,
|
||||||
@ -9,9 +9,12 @@ import {
|
|||||||
FaRegUserCircle,
|
FaRegUserCircle,
|
||||||
FaUnlock,
|
FaUnlock,
|
||||||
} from "react-icons/fa";
|
} from "react-icons/fa";
|
||||||
import { FaArrowUpFromBracket } from "react-icons/fa6";
|
|
||||||
import { IoIosAdd, IoMdClose, IoMdLogOut } from "react-icons/io";
|
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 { IconType } from "react-icons/lib";
|
||||||
import {
|
import {
|
||||||
LuBrain,
|
LuBrain,
|
||||||
@ -38,7 +41,7 @@ export const iconList: { [name: string]: IconType } = {
|
|||||||
addWithoutCircle: IoIosAdd,
|
addWithoutCircle: IoIosAdd,
|
||||||
brain: LuBrain,
|
brain: LuBrain,
|
||||||
brainCircuit: LuBrainCircuit,
|
brainCircuit: LuBrainCircuit,
|
||||||
chat: CiChat1,
|
chat: BsChatLeftText,
|
||||||
check: FaCheck,
|
check: FaCheck,
|
||||||
checkCircle: FaCheckCircle,
|
checkCircle: FaCheckCircle,
|
||||||
chevronDown: LuChevronDown,
|
chevronDown: LuChevronDown,
|
||||||
@ -50,7 +53,7 @@ export const iconList: { [name: string]: IconType } = {
|
|||||||
email: MdAlternateEmail,
|
email: MdAlternateEmail,
|
||||||
file: LuFile,
|
file: LuFile,
|
||||||
flag: CiFlag1,
|
flag: CiFlag1,
|
||||||
followUp: FaArrowUpFromBracket,
|
followUp: IoArrowUpCircleOutline,
|
||||||
graph: VscGraph,
|
graph: VscGraph,
|
||||||
hastag: RiHashtag,
|
hastag: RiHashtag,
|
||||||
history: MdHistory,
|
history: MdHistory,
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { Color } from "./Colors";
|
import { Color } from "./Colors";
|
||||||
|
|
||||||
|
import { iconList } from "../helpers/iconList";
|
||||||
|
|
||||||
export interface ButtonType {
|
export interface ButtonType {
|
||||||
label: string;
|
label: string;
|
||||||
color: Color;
|
color: Color;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
|
iconName: keyof typeof iconList;
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user