mirror of
https://github.com/QuivrHQ/quivr.git
synced 2024-09-11 14:36:35 +03:00
feat(frontend): Add Brain On Search Page (#2067)
# Description - Implement Icon Component - Implement TextButton Component - Change Add Brain Button And Set it in the Search Page - Fix Errors When sending empty message - Change EsLint rules ## 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
921ab11067
commit
b5e2d5ad9c
@ -41,7 +41,9 @@ module.exports = {
|
||||
["external", "builtin"],
|
||||
"unknown",
|
||||
"internal",
|
||||
["parent", "sibling", "index"],
|
||||
"sibling",
|
||||
"parent",
|
||||
"index",
|
||||
],
|
||||
alphabetize: {
|
||||
order: "asc",
|
||||
|
@ -9,6 +9,7 @@ import { useAuthModes } from "@/lib/hooks/useAuthModes";
|
||||
import { EmailInput } from "./components/EmailInput";
|
||||
import { MagicLinkLogin } from "./components/MagicLinkLogin/MaginLinkLogin";
|
||||
import { PasswordLogin } from "./components/PasswordLogin/PasswordLogin";
|
||||
|
||||
import { EmailAuthContextType } from "../../types";
|
||||
|
||||
export const EmailLogin = (): JSX.Element => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Link from "next/link";
|
||||
|
||||
import { Avatar } from "@/lib/components/ui/Avatar";
|
||||
import { Testimonial } from "@/lib/types/testimonial";
|
||||
import { Testimonial } from "@/lib/types/Testimonial";
|
||||
|
||||
import { socialMediaToIcon } from "../utils/socialMediaToIcon";
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { AiFillLinkedin } from "react-icons/ai";
|
||||
import { RiTwitterXFill } from "react-icons/ri";
|
||||
|
||||
import { Testimonial } from "@/lib/types/testimonial";
|
||||
import { Testimonial } from "@/lib/types/Testimonial";
|
||||
|
||||
export const socialMediaToIcon: Record<
|
||||
Testimonial["socialMedia"],
|
||||
|
@ -5,6 +5,7 @@ import { LuChevronRight } from "react-icons/lu";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
|
||||
import { UseCasesListing } from "./components/UseCasesListing/UseCasesListing";
|
||||
|
||||
import { useHomepageTracking } from "../../hooks/useHomepageTracking";
|
||||
|
||||
export const UseCases = (): JSX.Element => {
|
||||
|
@ -3,6 +3,7 @@ import { useEffect } from "react";
|
||||
import { useUrlBrain } from "@/lib/hooks/useBrainIdFromUrl";
|
||||
|
||||
import { useFeedBrain } from "./useFeedBrain";
|
||||
|
||||
import { useKnowledge } from "../../../hooks/useKnowledge";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
|
@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
|
||||
import Spinner from "@/lib/components/ui/Spinner";
|
||||
|
||||
import { useAddedKnowledge } from "./hooks/useAddedKnowledge";
|
||||
|
||||
import { KnowledgeTable } from "../KnowledgeTable/KnowledgeTable";
|
||||
|
||||
type AddedKnowledgeProps = {
|
||||
|
@ -8,6 +8,7 @@ import { KnowledgeToFeedProvider } from "@/lib/context";
|
||||
|
||||
import { AddKnowledge } from "./components/AddKnowledge/AddKnowledge";
|
||||
import { AddedKnowledge } from "./components/AddedKnowledge/AddedKnowledge";
|
||||
|
||||
import { useBrainFetcher } from "../../hooks/useBrainFetcher";
|
||||
import { NoAccess } from "../NoAccess";
|
||||
|
||||
|
@ -12,6 +12,7 @@ import { TextArea } from "@/lib/components/ui/TextArea";
|
||||
|
||||
import { BrainAccess } from "./components/BrainAccess/BrainAccess";
|
||||
import { useGeneralInformation } from "./hooks/useGeneralInformation";
|
||||
|
||||
import { useBrainFormState } from "../../hooks/useBrainFormState";
|
||||
|
||||
type GeneralInformationProps = {
|
||||
|
@ -2,7 +2,7 @@ import { UseFormSetValue } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { LuLock, LuUnlock } from "react-icons/lu";
|
||||
|
||||
import { BrainConfig, BrainStatus } from "@/lib/types/brainConfig";
|
||||
import { BrainConfig, BrainStatus } from "@/lib/types/BrainConfig";
|
||||
|
||||
import { BrainAccessRadio } from "./components/BrainAccessRadio";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { BrainType } from "@/lib/types/brainConfig";
|
||||
import { BrainType } from "@/lib/types/BrainConfig";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export const useGeneralInformation = () => {
|
||||
|
@ -6,7 +6,7 @@ import { useFormContext } from "react-hook-form";
|
||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||
import { Brain } from "@/lib/context/BrainProvider/types";
|
||||
import { useUrlBrain } from "@/lib/hooks/useBrainIdFromUrl";
|
||||
import { BrainConfig } from "@/lib/types/brainConfig";
|
||||
import { BrainConfig } from "@/lib/types/BrainConfig";
|
||||
|
||||
import { useBrainFetcher } from "../../../hooks/useBrainFetcher";
|
||||
|
||||
|
@ -12,6 +12,7 @@ import { useToast } from "@/lib/hooks";
|
||||
import { useUserData } from "@/lib/hooks/useUserData";
|
||||
|
||||
import { useBrainFormState } from "./useBrainFormState";
|
||||
|
||||
import { isBrainDescriptionValid } from "../utils/isBrainDescriptionValid";
|
||||
import { isBrainNameValid } from "../utils/isBrainNameValid";
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { Tabs, TabsContent, TabsList } from "@/lib/components/ui/Tabs";
|
||||
import { BrainSearchBar } from "./components/BrainSearchBar";
|
||||
import { BrainsList } from "./components/BrainsList";
|
||||
import { useBrainsTabs } from "./hooks/useBrainsTabs";
|
||||
|
||||
import { StyledTabsTrigger } from "../StyledTabsTrigger";
|
||||
|
||||
export const BrainsTabs = (): JSX.Element => {
|
||||
|
@ -11,8 +11,8 @@ const BrainsManagement = (): JSX.Element => {
|
||||
const { t } = useTranslation("chat");
|
||||
|
||||
return (
|
||||
<div className="flex flex-col flex-1">
|
||||
<div className="w-full h-full p-6 bg-highlight flex flex-col flex-1 overflow-auto">
|
||||
<div className="flex flex-col flex-1 bg-highlight">
|
||||
<div className="w-full h-full p-6 flex flex-col flex-1 overflow-auto">
|
||||
<div className="w-full mb-10">
|
||||
<div className="flex flex-row justify-center items-center gap-2">
|
||||
<LuBrain size={20} className="text-primary" />
|
||||
@ -24,7 +24,7 @@ const BrainsManagement = (): JSX.Element => {
|
||||
<BrainsTabs />
|
||||
</div>
|
||||
<div className="w-full flex justify-center py-4">
|
||||
<AddBrainModal triggerClassName="bg-primary text-white font-normal" />
|
||||
<AddBrainModal />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -40,7 +40,7 @@ export const MentionList = forwardRef<MentionListRef, MentionListProps>(
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="relative">
|
||||
<div className="relative flex justify-center items-center py-1">
|
||||
{shouldShowScrollToBottomIcon && (
|
||||
<FaAngleDoubleDown
|
||||
size={20}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { useMentionItemIcon } from "./hooks/useMentionItemIcon";
|
||||
|
||||
import { SuggestionDataType, SuggestionItem } from "../../../../types";
|
||||
|
||||
type MentionItemProps = {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||
|
||||
import { useMentionConfig } from "./useMentionConfig";
|
||||
|
||||
import { SuggestionItem } from "../types";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
|
@ -28,9 +28,7 @@ export const useChatStateUpdater = ({
|
||||
const { text, brainId, promptId } =
|
||||
getChatInputAttributesFromEditorState(editorNewState);
|
||||
|
||||
if (text !== "") {
|
||||
setMessage(text);
|
||||
}
|
||||
setMessage(text);
|
||||
|
||||
if (brainId !== currentBrainId) {
|
||||
if (brainId === "") {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||
|
||||
import { useMentionConfig } from "./useMentionConfig";
|
||||
|
||||
import { SuggestionItem } from "../types";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
|
@ -3,6 +3,7 @@ import { Fragment } from "react";
|
||||
import { useOnboarding } from "@/lib/hooks/useOnboarding";
|
||||
|
||||
import { useOnboardingQuestion } from "./hooks/useOnboardingQuestion";
|
||||
|
||||
import { QuestionId } from "../../types";
|
||||
|
||||
type OnboardingQuestionsProps = {
|
||||
|
@ -7,6 +7,7 @@ import { useOnboardingTracker } from "@/lib/hooks/useOnboardingTracker";
|
||||
import { useStreamText } from "@/lib/hooks/useStreamText";
|
||||
|
||||
import { stepsContainerStyle } from "./styles";
|
||||
|
||||
import { MessageRow } from "../QADisplay";
|
||||
|
||||
export const Onboarding = (): JSX.Element => {
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
chatItemContainerClassName,
|
||||
} from "./styles";
|
||||
import { getKeyFromChatItem } from "./utils/getKeyFromChatItem";
|
||||
|
||||
import { ChatItemWithGroupedNotifications } from "../../types";
|
||||
|
||||
type MessagesDialogueProps = {
|
||||
|
@ -17,6 +17,7 @@ import { useEventTracking } from "@/services/analytics/june/useEventTracking";
|
||||
|
||||
import { useLocalStorageChatConfig } from "./useLocalStorageChatConfig";
|
||||
import { useQuestion } from "./useQuestion";
|
||||
|
||||
import { ChatQuestion } from "../types";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
|
@ -5,6 +5,7 @@ import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainConte
|
||||
import { useFetch, useToast } from "@/lib/hooks";
|
||||
|
||||
import { useHandleStream } from "./useHandleStream";
|
||||
|
||||
import { ChatQuestion } from "../types";
|
||||
import { generatePlaceHolderMessage } from "../utils/generatePlaceHolderMessage";
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
|
||||
import { ContactForm } from "./components";
|
||||
|
||||
import {
|
||||
FooterSection,
|
||||
HomeHeader,
|
||||
|
@ -1,43 +1,52 @@
|
||||
@use '@/styles/Colors.module.scss';
|
||||
@use '@/styles/IconSizes.module.scss';
|
||||
@use '@/styles/ScreenSizes.module.scss';
|
||||
@use '@/styles/Spacings.module.scss';
|
||||
@use '@/styles/Typography.module.scss';
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
@use "@/styles/ScreenSizes.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
@use "@/styles/Typography.module.scss";
|
||||
@use "@/styles/Variables.module.scss";
|
||||
|
||||
.search_page_container {
|
||||
background-color: Colors.$ivory;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: Colors.$ivory;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.main_container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
row-gap: Spacings.$spacing05;
|
||||
position: relative;
|
||||
width: 50%;
|
||||
margin-inline: auto;
|
||||
transform: translateY(-#{Variables.$searchBarHeight});
|
||||
|
||||
.main_container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: Spacings.$spacing05;
|
||||
position: relative;
|
||||
width: 50vw;
|
||||
margin-inline: auto;
|
||||
|
||||
@media (max-width: ScreenSizes.$small) {
|
||||
width: 100%;
|
||||
margin-inline: Spacings.$spacing07;
|
||||
}
|
||||
|
||||
.quivr_logo_wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.quivr_text {
|
||||
@include Typography.H1;
|
||||
|
||||
.quivr_text_primary {
|
||||
color: Colors.$primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media (max-width: ScreenSizes.$small) {
|
||||
width: 100%;
|
||||
margin-inline: Spacings.$spacing07;
|
||||
}
|
||||
}
|
||||
|
||||
.quivr_logo_wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.quivr_text {
|
||||
@include Typography.H1;
|
||||
|
||||
.quivr_text_primary {
|
||||
color: Colors.$primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add_brain_wrapper {
|
||||
position: absolute;
|
||||
bottom: Spacings.$spacing05;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
@ -3,44 +3,50 @@ import { usePathname } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { QuivrLogo } from "@/lib/assets/QuivrLogo";
|
||||
import { AddBrainModal } from "@/lib/components/AddBrainModal";
|
||||
import { SearchBar } from "@/lib/components/ui/SearchBar/SearchBar";
|
||||
import { useMenuContext } from "@/lib/context/MenuProvider/hooks/useMenuContext";
|
||||
import { useSupabase } from "@/lib/context/SupabaseProvider";
|
||||
import { redirectToLogin } from "@/lib/router/redirectToLogin";
|
||||
|
||||
import { useChatsList } from "../chat/[chatId]/hooks/useChatsList";
|
||||
// eslint-disable-next-line import/order
|
||||
import styles from "./page.module.scss";
|
||||
|
||||
import { useChatsList } from "../chat/[chatId]/hooks/useChatsList";
|
||||
|
||||
|
||||
const Search = (): JSX.Element => {
|
||||
const {setIsOpened} = useMenuContext();
|
||||
const pathname = usePathname()
|
||||
const { session } = useSupabase();
|
||||
const { setIsOpened } = useMenuContext();
|
||||
const pathname = usePathname();
|
||||
const { session } = useSupabase();
|
||||
|
||||
useEffect(() => {
|
||||
if (session === null) {
|
||||
redirectToLogin();
|
||||
}
|
||||
setIsOpened(false)
|
||||
}, [pathname, session, setIsOpened]);
|
||||
useEffect(() => {
|
||||
if (session === null) {
|
||||
redirectToLogin();
|
||||
}
|
||||
setIsOpened(false);
|
||||
}, [pathname, session, setIsOpened]);
|
||||
|
||||
useChatsList();
|
||||
useChatsList();
|
||||
|
||||
return (
|
||||
<div className={styles.search_page_container}>
|
||||
<div className={styles.main_container}>
|
||||
<div className={styles.quivr_logo_wrapper}>
|
||||
<QuivrLogo size={80} color="black" />
|
||||
<div className={styles.quivr_text}>
|
||||
<span>Talk to </span>
|
||||
<span className={styles.quivr_text_primary}>Quivr</span>
|
||||
</div>
|
||||
</div>
|
||||
<SearchBar />
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
return (
|
||||
<div className={styles.search_page_container}>
|
||||
<div className={styles.main_container}>
|
||||
<div className={styles.quivr_logo_wrapper}>
|
||||
<QuivrLogo size={80} color="black" />
|
||||
<div className={styles.quivr_text}>
|
||||
<span>Talk to </span>
|
||||
<span className={styles.quivr_text_primary}>Quivr</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.search_bar_wrapper}>
|
||||
<SearchBar />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.add_brain_wrapper}>
|
||||
<AddBrainModal />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Search;
|
||||
|
@ -4,6 +4,7 @@ import { testChat } from "./utils/testChat";
|
||||
import { testDeleteChats } from "./utils/testDeleteChats";
|
||||
import { testSelectBrain } from "./utils/testSelectBrain";
|
||||
import { testUnplugChat } from "./utils/testUnplugChat";
|
||||
|
||||
import { login } from "../../utils/login";
|
||||
|
||||
export const chatTests = (): void => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Page } from "@playwright/test";
|
||||
|
||||
import { getEditor } from "./getEditor";
|
||||
|
||||
export const testSelectBrain = async (page: Page): Promise<void> => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Page } from "@playwright/test";
|
||||
|
||||
import { getEditor } from "./getEditor";
|
||||
|
||||
export const testUnplugChat = async (page: Page): Promise<void> => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { UUID } from "crypto";
|
||||
|
||||
import { BrainRoleType } from "@/lib/components/BrainUsers/types";
|
||||
import { BrainStatus, BrainType, Model } from "@/lib/types/brainConfig";
|
||||
import { BrainStatus, BrainType, Model } from "@/lib/types/BrainConfig";
|
||||
|
||||
export type ApiBrainDefinitionSchemaPropertyType = "string" | "number";
|
||||
|
||||
@ -25,12 +25,12 @@ export type SubscriptionUpdatableProperties = {
|
||||
|
||||
export type ListFilesProps = {
|
||||
files: {
|
||||
file_name: string;
|
||||
file_sha1: string;
|
||||
file_size: number;
|
||||
file_url: string;
|
||||
file_id: string;
|
||||
file_similarity: number;
|
||||
file_name: string;
|
||||
file_sha1: string;
|
||||
file_size: number;
|
||||
file_url: string;
|
||||
file_id: string;
|
||||
file_similarity: number;
|
||||
}[];
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { AxiosInstance } from "axios";
|
||||
|
||||
import { Testimonial } from "@/lib/types/testimonial";
|
||||
import { Testimonial } from "@/lib/types/Testimonial";
|
||||
|
||||
type CmsTestimonials = {
|
||||
data: {
|
||||
|
@ -6,13 +6,7 @@ import { KnowledgeToFeedProvider } from "@/lib/context";
|
||||
import { AddBrainSteps } from "./components/AddBrainSteps/AddBrainSteps";
|
||||
import { CreateBrainProps } from "./types";
|
||||
|
||||
type AddBrainModalProps = {
|
||||
triggerClassName?: string;
|
||||
};
|
||||
|
||||
export const AddBrainModal = ({
|
||||
triggerClassName,
|
||||
}: AddBrainModalProps): JSX.Element => {
|
||||
export const AddBrainModal = (): JSX.Element => {
|
||||
const defaultValues: CreateBrainProps = {
|
||||
...addBrainDefaultValues,
|
||||
setDefault: true,
|
||||
@ -26,7 +20,7 @@ export const AddBrainModal = ({
|
||||
return (
|
||||
<FormProvider {...methods}>
|
||||
<KnowledgeToFeedProvider>
|
||||
<AddBrainSteps triggerClassName={triggerClassName} />
|
||||
<AddBrainSteps />
|
||||
</KnowledgeToFeedProvider>
|
||||
</FormProvider>
|
||||
);
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { LuPlusCircle } from "react-icons/lu";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { Modal } from "@/lib/components/ui/Modal";
|
||||
import { cn } from "@/lib/utils";
|
||||
import TextButton from "@/lib/components/ui/TextButton/TextButton";
|
||||
|
||||
import { BrainKnowledgeStep } from "./components/BrainKnowledgeStep/BrainKnowledgeStep";
|
||||
import { BrainParamsStep } from "./components/BrainParamsStep/BrainParamsStep";
|
||||
@ -11,13 +9,7 @@ import { BrainTypeSelectionStep } from "./components/BrainTypeSelectionStep/Brai
|
||||
import { Stepper } from "./components/Stepper/Stepper";
|
||||
import { useAddBrainConfig } from "./hooks/useAddBrainConfig";
|
||||
|
||||
type AddBrainConfigProps = {
|
||||
triggerClassName?: string;
|
||||
};
|
||||
|
||||
export const AddBrainSteps = ({
|
||||
triggerClassName,
|
||||
}: AddBrainConfigProps): JSX.Element => {
|
||||
export const AddBrainSteps = (): JSX.Element => {
|
||||
const { t } = useTranslation(["translation", "brain", "config"]);
|
||||
|
||||
const { isBrainCreationModalOpened, setIsBrainCreationModalOpened } =
|
||||
@ -26,15 +18,13 @@ export const AddBrainSteps = ({
|
||||
return (
|
||||
<Modal
|
||||
Trigger={
|
||||
<Button
|
||||
onClick={() => void 0}
|
||||
variant={"tertiary"}
|
||||
className={cn("border-0", triggerClassName)}
|
||||
data-testid="add-brain-button"
|
||||
>
|
||||
<LuPlusCircle className="text-xl" />
|
||||
{t("newBrain", { ns: "brain" })}
|
||||
</Button>
|
||||
<div onClick={() => void 0}>
|
||||
<TextButton
|
||||
iconName="add"
|
||||
label={t("newBrain", { ns: "brain" })}
|
||||
color="black"
|
||||
></TextButton>
|
||||
</div>
|
||||
}
|
||||
title={t("newBrainTitle", { ns: "brain" })}
|
||||
desc={t("newBrainSubtitle", { ns: "brain" })}
|
||||
|
@ -4,12 +4,13 @@ import { FaArrowLeft } from "react-icons/fa";
|
||||
|
||||
import { ApiRequestDefinition } from "@/lib/components/ApiRequestDefinition";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { BrainType } from "@/lib/types/brainConfig";
|
||||
import { BrainType } from "@/lib/types/BrainConfig";
|
||||
|
||||
import { CompositeBrainConnections } from "./components/CompositeBrainConnections/CompositeBrainConnections";
|
||||
import { KnowledgeToFeedInput } from "./components/KnowledgeToFeedInput";
|
||||
import { useBrainCreationHandler } from "./hooks/useBrainCreationHandler";
|
||||
import { useBrainKnowledgeStep } from "./hooks/useBrainKnowledgeStep";
|
||||
|
||||
import { useBrainCreationSteps } from "../../hooks/useBrainCreationSteps";
|
||||
|
||||
type BrainKnowledgeStepProps = {
|
||||
|
@ -11,6 +11,7 @@ import { PublicAccessConfirmationModal } from "./components/PublicAccessConfirma
|
||||
import { useBrainParamsStep } from "./hooks/useBrainParamsStep";
|
||||
import { useBrainStatusOptions } from "./hooks/useBrainStatusOptions";
|
||||
import { usePublicAccessConfirmationModal } from "./hooks/usePublicAccessConfirmationModal";
|
||||
|
||||
import { useBrainCreationSteps } from "../../hooks/useBrainCreationSteps";
|
||||
import { useBrainTypeSelectionStep } from "../BrainTypeSelectionStep/hooks/useBrainTypeSelectionStep";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { BrainStatus } from "@/lib/types/brainConfig";
|
||||
import { BrainStatus } from "@/lib/types/BrainConfig";
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export const useBrainStatusOptions = () => {
|
||||
const { t } = useTranslation(["translation", "brain", "config"]);
|
||||
|
@ -7,6 +7,7 @@ import { Radio } from "@/lib/components/ui/Radio";
|
||||
|
||||
import { useBrainTypeSelectionStep } from "./hooks/useBrainTypeSelectionStep";
|
||||
import { useKnowledgeSourceLabel } from "./hooks/useKnowledgeSourceLabel";
|
||||
|
||||
import { useBrainCreationSteps } from "../../hooks/useBrainCreationSteps";
|
||||
|
||||
type BrainTypeSelectionStepProps = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useFeatureIsOn } from "@growthbook/growthbook-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { BrainType } from "@/lib/types/brainConfig";
|
||||
import { BrainType } from "@/lib/types/BrainConfig";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
||||
export const useKnowledgeSourceLabel = () => {
|
||||
|
@ -3,6 +3,7 @@ import { Fragment } from "react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { Step } from "./components/Step";
|
||||
|
||||
import { useBrainCreationSteps } from "../../hooks/useBrainCreationSteps";
|
||||
|
||||
export const Stepper = (): JSX.Element => {
|
||||
|
@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { useBrainFetcher } from "@/app/brains-management/[brainId]/components/BrainManagementTabs/hooks/useBrainFetcher";
|
||||
|
||||
import { useApiBrainSecretsInputs } from "./hooks/useApiBrainSecretsInputs";
|
||||
|
||||
import Button from "../ui/Button";
|
||||
|
||||
type ApiBrainSecretsInputsProps = {
|
||||
|
@ -8,6 +8,7 @@ import Button from "@/lib/components/ui/Button";
|
||||
import { ParamDefinitionRow } from "./components/ParamDefinitionRow";
|
||||
import { defaultParamDefinitionRow } from "./config";
|
||||
import { useParamsDefinition } from "./hooks/useParamsDefinition";
|
||||
|
||||
import { tabDescriptionStyle } from "../../styles";
|
||||
|
||||
type ParamsDefinitionProps = {
|
||||
|
@ -2,6 +2,7 @@ import { useEffect } from "react";
|
||||
import { useForm, useFormContext, useWatch } from "react-hook-form";
|
||||
|
||||
import { useParamsDefinitionDefaultValues } from "./useParamsDefinitionDefaultValues";
|
||||
|
||||
import { ApiDefinitionContextType } from "../../../types";
|
||||
import { ParameterDefinition } from "../types";
|
||||
import { mapParameterDefinitionToApiBrainDefinitionSchema } from "../utils/mapParameterDefinitionToApiBrainDefinitionSchema";
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
defaultSecretDefinitionRow,
|
||||
} from "./config";
|
||||
import { useSecretsDefinition } from "./hooks/useSecretsDefinition";
|
||||
|
||||
import { tabDescriptionStyle } from "../../styles";
|
||||
|
||||
const paramsNameStyle = "flex flex-1 justify-center";
|
||||
|
@ -2,6 +2,7 @@ import { useEffect } from "react";
|
||||
import { useForm, useFormContext, useWatch } from "react-hook-form";
|
||||
|
||||
import { useSecretsDefinitionDefaultValues } from "./useSecretsDefinitionDefaultValues";
|
||||
|
||||
import { ApiDefinitionContextType } from "../../../types";
|
||||
import {
|
||||
brainSecretsSchemaDefinitionKeyInForm,
|
||||
|
@ -7,7 +7,9 @@ import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainConte
|
||||
|
||||
import { RemoveAccessIcon } from "./components/RemoveAccessIcon";
|
||||
import { useBrainUser } from "./hooks/useBrainUser";
|
||||
|
||||
import { BrainRoleType } from "../../types";
|
||||
|
||||
type BrainUserProps = {
|
||||
email: string;
|
||||
role: BrainRoleType;
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
isWithinLast7Days,
|
||||
isYesterday,
|
||||
} from "./utils";
|
||||
|
||||
import Spinner from "../ui/Spinner";
|
||||
|
||||
export const ChatHistory = (): JSX.Element => {
|
||||
|
@ -2,6 +2,7 @@ import { IoMdCloseCircle } from "react-icons/io";
|
||||
import { MdLink } from "react-icons/md";
|
||||
|
||||
import { FeedTitleDisplayer } from "./FeedTitleDisplayer";
|
||||
|
||||
import { StyledFeedItemDiv } from "../styles/StyledFeedItemDiv";
|
||||
|
||||
type CrawlFeedItemProps = {
|
||||
|
@ -3,6 +3,7 @@ import { IoMdCloseCircle } from "react-icons/io";
|
||||
import { getFileIcon } from "@/lib/helpers/getFileIcon";
|
||||
|
||||
import { FeedTitleDisplayer } from "./FeedTitleDisplayer";
|
||||
|
||||
import { StyledFeedItemDiv } from "../styles/StyledFeedItemDiv";
|
||||
|
||||
type FileFeedItemProps = {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { StripePricingTable } from "./components/PricingTable/PricingTable";
|
||||
|
||||
import { Modal } from "../../ui/ModalPayment";
|
||||
|
||||
type StripePricingModalProps = {
|
||||
|
46
frontend/lib/components/ui/Icon/Icon.module.scss
Normal file
46
frontend/lib/components/ui/Icon/Icon.module.scss
Normal file
@ -0,0 +1,46 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/IconSizes.module.scss";
|
||||
|
||||
.small {
|
||||
width: IconSizes.$small;
|
||||
height: IconSizes.$small;
|
||||
}
|
||||
|
||||
.normal {
|
||||
width: IconSizes.$normal;
|
||||
height: IconSizes.$normal;
|
||||
}
|
||||
|
||||
.large {
|
||||
width: IconSizes.$large;
|
||||
height: IconSizes.$large;
|
||||
}
|
||||
|
||||
.big {
|
||||
width: IconSizes.$big;
|
||||
height: IconSizes.$big;
|
||||
}
|
||||
|
||||
.black {
|
||||
color: Colors.$black;
|
||||
|
||||
&.hovered {
|
||||
color: Colors.$accent;
|
||||
}
|
||||
}
|
||||
|
||||
.primary {
|
||||
color: Colors.$primary;
|
||||
}
|
||||
|
||||
.accent {
|
||||
color: Colors.$accent;
|
||||
}
|
||||
|
||||
.white {
|
||||
color: Colors.$white;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.2;
|
||||
}
|
41
frontend/lib/components/ui/Icon/Icon.tsx
Normal file
41
frontend/lib/components/ui/Icon/Icon.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import { IconType } from "react-icons/lib";
|
||||
|
||||
import { iconList } from "@/lib/helpers/iconList";
|
||||
import { Color } from "@/lib/types/Colors";
|
||||
import { IconSize } from "@/lib/types/Icons";
|
||||
|
||||
import styles from "./Icon.module.scss";
|
||||
|
||||
interface IconProps {
|
||||
name: keyof typeof iconList;
|
||||
size: IconSize;
|
||||
color: Color;
|
||||
disabled?: boolean;
|
||||
classname?: string;
|
||||
hovered?: boolean;
|
||||
}
|
||||
|
||||
export const Icon = ({
|
||||
name,
|
||||
size,
|
||||
color,
|
||||
disabled,
|
||||
classname,
|
||||
hovered,
|
||||
}: IconProps): JSX.Element => {
|
||||
const IconComponent: IconType = iconList[name];
|
||||
|
||||
return (
|
||||
<IconComponent
|
||||
className={`
|
||||
${classname ?? ""}
|
||||
${styles[size] ?? ""}
|
||||
${styles[color] ?? ""}
|
||||
${disabled ? styles.disabled ?? "" : ""}
|
||||
${hovered ? styles.hovered ?? "" : ""}
|
||||
`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Icon;
|
@ -3,9 +3,6 @@
|
||||
|
||||
.loader_icon {
|
||||
animation: spin 1s linear infinite;
|
||||
width: IconSizes.$big;
|
||||
height: IconSizes.$big;
|
||||
color: Colors.$accent;
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
@ -15,24 +12,4 @@
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
width: IconSizes.$small;
|
||||
height: IconSizes.$small;
|
||||
}
|
||||
|
||||
&.normal {
|
||||
width: IconSizes.$normal;
|
||||
height: IconSizes.$normal;
|
||||
}
|
||||
|
||||
&.large {
|
||||
width: IconSizes.$large;
|
||||
height: IconSizes.$large;
|
||||
}
|
||||
|
||||
&.big {
|
||||
width: IconSizes.$big;
|
||||
height: IconSizes.$big;
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,22 @@
|
||||
import { AiOutlineLoading3Quarters } from "react-icons/ai";
|
||||
|
||||
import { Color } from "@/lib/types/Colors";
|
||||
import { IconSize } from "@/lib/types/Icons";
|
||||
|
||||
import styles from "./LoaderIcon.module.scss";
|
||||
|
||||
import { Icon } from "../Icon/Icon";
|
||||
|
||||
interface LoaderIconProps {
|
||||
size: IconSize;
|
||||
color: Color;
|
||||
}
|
||||
|
||||
export const LoaderIcon = (props: LoaderIconProps): JSX.Element => {
|
||||
return (
|
||||
<AiOutlineLoading3Quarters
|
||||
className={`${styles.loader_icon ?? ""} ${styles[props.size] ?? ""}`}
|
||||
<Icon
|
||||
name="loader"
|
||||
size={props.size}
|
||||
color={props.color}
|
||||
classname={styles.loader_icon ?? ""}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
@ -7,12 +7,13 @@ import { useChat } from "@/app/chat/[chatId]/hooks/useChat";
|
||||
import { useChatContext } from "@/lib/context";
|
||||
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
|
||||
|
||||
import { LoaderIcon } from "../LoaderIcon/LoaderIcon";
|
||||
// eslint-disable-next-line import/order
|
||||
import styles from "./SearchBar.module.scss";
|
||||
|
||||
import { LoaderIcon } from "../LoaderIcon/LoaderIcon";
|
||||
|
||||
export const SearchBar = (): JSX.Element => {
|
||||
const [searching, setSearching] = useState(false);
|
||||
const [isDisabled, setIsDisabled] = useState(true);
|
||||
const { message, setMessage } = useChatInput();
|
||||
const { setMessages } = useChatContext();
|
||||
const { addQuestion } = useChat();
|
||||
@ -20,7 +21,8 @@ export const SearchBar = (): JSX.Element => {
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentBrainId(null);
|
||||
}, [setCurrentBrainId]);
|
||||
setIsDisabled(message === "");
|
||||
}, [setCurrentBrainId, message]);
|
||||
|
||||
const submit = async (): Promise<void> => {
|
||||
setSearching(true);
|
||||
@ -35,7 +37,6 @@ export const SearchBar = (): JSX.Element => {
|
||||
};
|
||||
|
||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
||||
|
||||
return (
|
||||
<div className={styles.search_bar_wrapper}>
|
||||
<Editor
|
||||
@ -45,10 +46,13 @@ export const SearchBar = (): JSX.Element => {
|
||||
placeholder="Search"
|
||||
></Editor>
|
||||
{searching ? (
|
||||
<LoaderIcon size="big" />
|
||||
<LoaderIcon size="big" color="accent" />
|
||||
) : (
|
||||
<LuSearch
|
||||
className={`${styles.search_icon} ${!message ? styles.disabled : ""}`}
|
||||
className={`
|
||||
${styles.search_icon}
|
||||
${isDisabled ? styles.disabled : ""}
|
||||
`}
|
||||
onClick={() => void submit()}
|
||||
/>
|
||||
)}
|
||||
|
18
frontend/lib/components/ui/TextButton/TextButton.module.scss
Normal file
18
frontend/lib/components/ui/TextButton/TextButton.module.scss
Normal file
@ -0,0 +1,18 @@
|
||||
@use "@/styles/Colors.module.scss";
|
||||
@use "@/styles/Spacings.module.scss";
|
||||
|
||||
.text_button_wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: Spacings.$spacing03;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.black {
|
||||
color: Colors.$black;
|
||||
|
||||
&.hovered {
|
||||
color: Colors.$accent;
|
||||
}
|
||||
}
|
43
frontend/lib/components/ui/TextButton/TextButton.tsx
Normal file
43
frontend/lib/components/ui/TextButton/TextButton.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { iconList } from "@/lib/helpers/iconList";
|
||||
import { Color } from "@/lib/types/Colors";
|
||||
|
||||
import styles from "./TextButton.module.scss";
|
||||
|
||||
import { Icon } from "../Icon/Icon";
|
||||
|
||||
interface TextButtonProps {
|
||||
iconName: keyof typeof iconList;
|
||||
label: string;
|
||||
color: Color;
|
||||
}
|
||||
|
||||
export const TextButton = (props: TextButtonProps): JSX.Element => {
|
||||
const [hovered, setHovered] = useState(false);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.text_button_wrapper}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
>
|
||||
<Icon
|
||||
name={props.iconName}
|
||||
size="normal"
|
||||
color={props.color}
|
||||
hovered={hovered}
|
||||
/>
|
||||
<span
|
||||
className={`
|
||||
${styles[props.color] ?? ""}
|
||||
${hovered ? styles.hovered ?? "" : ""}
|
||||
`}
|
||||
>
|
||||
{props.label}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextButton;
|
@ -1,5 +1,5 @@
|
||||
import { CreateBrainInput } from "../api/brain/types";
|
||||
import { Model } from "../types/brainConfig";
|
||||
import { Model } from "../types/BrainConfig";
|
||||
|
||||
export const addBrainDefaultValues: CreateBrainInput = {
|
||||
model: "gpt-3.5-turbo",
|
||||
|
@ -5,7 +5,8 @@ import { BrainRoleType } from "@/lib/components/BrainUsers/types";
|
||||
import { Document } from "@/lib/types/Document";
|
||||
|
||||
import { useBrainProvider } from "./hooks/useBrainProvider";
|
||||
import { BrainType, Model } from "../../types/brainConfig";
|
||||
|
||||
import { BrainType, Model } from "../../types/BrainConfig";
|
||||
|
||||
export type BrainAccessStatus = "private" | "public";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ChatMessage, Notification } from "@/app/chat/[chatId]/types";
|
||||
|
||||
import { Model } from "../../types/brainConfig";
|
||||
import { Model } from "../../types/BrainConfig";
|
||||
|
||||
export type ChatConfig = {
|
||||
model: Model;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Model, PaidModels } from "../types/brainConfig";
|
||||
import { Model, PaidModels } from "../types/BrainConfig";
|
||||
|
||||
export const defineMaxTokens = (
|
||||
model: Model | PaidModels | undefined
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { freeModels, paidModels } from "@/lib/types/BrainConfig";
|
||||
import { UserStats } from "@/lib/types/User";
|
||||
import { freeModels, paidModels } from "@/lib/types/brainConfig";
|
||||
|
||||
type GetAccessibleModelsInput = {
|
||||
openAiKey?: string | null;
|
||||
|
@ -3,7 +3,7 @@ import { LuBot, LuBrain } from "react-icons/lu";
|
||||
import { PiPaperclipFill } from "react-icons/pi";
|
||||
import { TbWorld } from "react-icons/tb";
|
||||
|
||||
import { BrainType } from "@/lib/types/brainConfig";
|
||||
import { BrainType } from "@/lib/types/BrainConfig";
|
||||
type GetBrainIconFromBrainTypeOptions = {
|
||||
iconSize?: number;
|
||||
ApiBrainIcon?: IconType;
|
||||
|
@ -17,6 +17,7 @@ import { LiaFileVideo } from "react-icons/lia";
|
||||
import { IconType } from "react-icons/lib";
|
||||
|
||||
import { getFileType } from "./getFileType";
|
||||
|
||||
import { SupportedFileExtensions } from "../types/SupportedFileExtensions";
|
||||
|
||||
const fileTypeIcons: Record<SupportedFileExtensions, IconType> = {
|
||||
|
9
frontend/lib/helpers/iconList.ts
Normal file
9
frontend/lib/helpers/iconList.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { AiOutlineLoading3Quarters } from "react-icons/ai";
|
||||
import { IconType } from "react-icons/lib";
|
||||
import { LuPlusCircle, LuSearch } from "react-icons/lu";
|
||||
|
||||
export const iconList: { [name: string]: IconType } = {
|
||||
add: LuPlusCircle,
|
||||
loader: AiOutlineLoading3Quarters,
|
||||
search: LuSearch,
|
||||
};
|
@ -7,6 +7,7 @@ import { useEventTracking } from "@/services/analytics/june/useEventTracking";
|
||||
import { useOnboarding } from "./useOnboarding";
|
||||
import { useOnboardingTracker } from "./useOnboardingTracker";
|
||||
import { useToast } from "./useToast";
|
||||
|
||||
import { useKnowledgeToFeedContext } from "../context/KnowledgeToFeedProvider/hooks/useKnowledgeToFeedContext";
|
||||
import { acceptedFormats } from "../helpers/acceptedFormats";
|
||||
import { cloneFileWithSanitizedName } from "../helpers/cloneFileWithSanitizedName";
|
||||
|
1
frontend/lib/types/Colors.ts
Normal file
1
frontend/lib/types/Colors.ts
Normal file
@ -0,0 +1 @@
|
||||
export type Color = "black" | "primary" | "accent" | "white";
|
1
frontend/styles/_Variables.module.scss
Normal file
1
frontend/styles/_Variables.module.scss
Normal file
@ -0,0 +1 @@
|
||||
$searchBarHeight: 62px;
|
Loading…
Reference in New Issue
Block a user