From e3925bcbc0362bc05d4f8d222340c0ee2dec64f3 Mon Sep 17 00:00:00 2001 From: Mamadou DICKO <63923024+mamadoudicko@users.noreply.github.com> Date: Tue, 31 Oct 2023 19:02:26 +0100 Subject: [PATCH] feat(brainSettings): rework knowledge tab (#1534) Issue: https://github.com/StanGirard/quivr/issues/1435 - feat(knowledgeTab): update structure - refactor: change AddKnowledge structure - feat: change AddKnowledge component structure - feat: rework sources logic - feat: change knowledge tab upload process - fix: change knowledge tab fetch, create, update logic - feat: improve added knowledge ui - style: improve responsivity Fix: - https://github.com/StanGirard/quivr/issues/1516 - https://github.com/StanGirard/quivr/issues/1336 - https://github.com/StanGirard/quivr/issues/1204 https://github.com/StanGirard/quivr/assets/63923024/f2917bf3-4ff8-42c6-8149-0b36287441b4 --- .../components/KnowledgeTab/AddKnowledge.tsx | 52 ------------------- .../KnowledgeItem/CrawledKnowledgeItem.tsx | 31 ----------- .../KnowledgeItem/UploadedKnowledgeItem.tsx | 28 ---------- .../KnowledgeTab/KnowledgeItem/index.tsx | 21 -------- .../KnowledgeTab/KnowledgeTable.tsx | 23 -------- .../components/AddKnowledge/AddKnowledge.tsx | 24 +++++++++ .../AddKnowledge/hooks/useAddKnowledge.ts | 31 +++++++++++ .../AddKnowledge}/hooks/useFeedBrain.ts | 8 +-- .../hooks/useFeedBrainHandler.ts | 0 .../AddKnowledge}/hooks/useKnowledgeToFeed.ts | 0 .../AddedKnowledge/AddedKnowledge.tsx | 46 ++++++++++++++++ .../AddedKnowledge/hooks/useAddedKnowledge.ts | 44 ++++++++++++++++ .../KnowledgeTable/KnowledgeTable.tsx | 19 +++++++ .../components/CrawledKnowledgeItem.tsx | 11 ++++ .../components}/DeleteKnowledge.tsx | 15 +++--- .../components}/DownloadUploadedKnowledge.tsx | 19 ++++--- .../KnowledgeItem/hooks}/useKnowledgeItem.ts | 15 +++--- .../components/KnowledgeItem/index.tsx | 51 ++++++++++++++++++ .../components/KnowledgeTab/index.tsx | 38 ++++---------- .../GeneralInformation/GeneralInformation.tsx | 39 +++++++------- .../hooks/useBrainManagementTabs.ts | 1 + frontend/lib/hooks/useBrainIdFromUrl.ts | 19 +++++++ 22 files changed, 303 insertions(+), 232 deletions(-) delete mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/AddKnowledge.tsx delete mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/CrawledKnowledgeItem.tsx delete mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/UploadedKnowledgeItem.tsx delete mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/index.tsx delete mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeTable.tsx create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/AddKnowledge.tsx create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useAddKnowledge.ts rename frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/{ => components/AddKnowledge}/hooks/useFeedBrain.ts (90%) rename frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/{ => components/AddKnowledge}/hooks/useFeedBrainHandler.ts (100%) rename frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/{ => components/AddKnowledge}/hooks/useKnowledgeToFeed.ts (100%) create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/AddedKnowledge.tsx create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/hooks/useAddedKnowledge.ts create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/KnowledgeTable.tsx create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/CrawledKnowledgeItem.tsx rename frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/{KnowledgeItem => components/KnowledgeTable/components/KnowledgeItem/components}/DeleteKnowledge.tsx (57%) rename frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/{KnowledgeItem => components/KnowledgeTable/components/KnowledgeItem/components}/DownloadUploadedKnowledge.tsx (67%) rename frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/{KnowledgeItem => components/KnowledgeTable/components/KnowledgeItem/hooks}/useKnowledgeItem.ts (83%) create mode 100644 frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/index.tsx create mode 100644 frontend/lib/hooks/useBrainIdFromUrl.ts diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/AddKnowledge.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/AddKnowledge.tsx deleted file mode 100644 index 22548e83b..000000000 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/AddKnowledge.tsx +++ /dev/null @@ -1,52 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import { AiOutlineLoading3Quarters } from "react-icons/ai"; - -import { KnowledgeToFeedInput } from "@/lib/components/KnowledgeToFeedInput"; -import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext"; - -import { useFeedBrain } from "./hooks/useFeedBrain"; -import { useKnowledge } from "./hooks/useKnowledge"; - -export const AddKnowledge = (): JSX.Element => { - const [shouldDisplayModal, setShouldDisplayModal] = useState(false); - const { currentBrain } = useBrainContext(); - const { invalidateKnowledgeDataKey } = useKnowledge({ - brainId: currentBrain?.id, - }); - - const { feedBrain, hasPendingRequests, setHasPendingRequests } = useFeedBrain( - { - dispatchHasPendingRequests: () => setHasPendingRequests(true), - closeFeedInput: () => setShouldDisplayModal(false), - } - ); - - useEffect(() => { - if (!hasPendingRequests) { - invalidateKnowledgeDataKey(); - } - }, [hasPendingRequests, invalidateKnowledgeDataKey]); - - return ( - <> - - {hasPendingRequests && ( -
- -
- )} - {shouldDisplayModal && ( - void feedBrain()} /> - )} - - ); -}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/CrawledKnowledgeItem.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/CrawledKnowledgeItem.tsx deleted file mode 100644 index bf3c8c7a8..000000000 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/CrawledKnowledgeItem.tsx +++ /dev/null @@ -1,31 +0,0 @@ -"use client"; - -import { MdLink } from "react-icons/md"; - -import { CrawledKnowledge } from "@/lib/types/Knowledge"; - -import { DeleteKnowledge } from "./DeleteKnowledge"; - -export const CrawledKnowledgeItem = ({ - knowledge, -}: { - knowledge: CrawledKnowledge; -}): JSX.Element => { - return ( - - - - - - - -
-

{knowledge.url}

-
- - - - - - ); -}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/UploadedKnowledgeItem.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/UploadedKnowledgeItem.tsx deleted file mode 100644 index 772d69ed1..000000000 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/UploadedKnowledgeItem.tsx +++ /dev/null @@ -1,28 +0,0 @@ -"use client"; - -import { UploadedKnowledge } from "@/lib/types/Knowledge"; - -import { DeleteKnowledge } from "./DeleteKnowledge"; -import { DownloadUploadedKnowledge } from "./DownloadUploadedKnowledge"; - -export const UploadedKnowledgeItem = ({ - knowledge, -}: { - knowledge: UploadedKnowledge; -}): JSX.Element => { - return ( - - - - - -
-

{knowledge.fileName}

-
- - - - - - ); -}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/index.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/index.tsx deleted file mode 100644 index 8715fae76..000000000 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/index.tsx +++ /dev/null @@ -1,21 +0,0 @@ -"use client"; - -import { isUploadedKnowledge, Knowledge } from "@/lib/types/Knowledge"; - -import { CrawledKnowledgeItem } from "./CrawledKnowledgeItem"; -import { UploadedKnowledgeItem } from "./UploadedKnowledgeItem"; - -const KnowledgeItem = ({ - knowledge, -}: { - knowledge: Knowledge; -}): JSX.Element => { - return isUploadedKnowledge(knowledge) ? ( - - ) : ( - - ); -}; - -KnowledgeItem.displayName = "KnowledgeItem"; -export default KnowledgeItem; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeTable.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeTable.tsx deleted file mode 100644 index 5c347fe04..000000000 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeTable.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Knowledge } from "@/lib/types/Knowledge"; - -import KnowledgeItem from "./KnowledgeItem"; - -interface KnowledgeTableProps { - knowledgeList: Knowledge[]; -} - -export const KnowledgeTable = ({ - knowledgeList, -}: KnowledgeTableProps): JSX.Element => { - return ( -
- - - {knowledgeList.map((knowledge) => ( - - ))} - -
-
- ); -}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/AddKnowledge.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/AddKnowledge.tsx new file mode 100644 index 000000000..995a038cc --- /dev/null +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/AddKnowledge.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { AiOutlineLoading3Quarters } from "react-icons/ai"; + +import { KnowledgeToFeedInput } from "@/lib/components/KnowledgeToFeedInput"; + +import { useAddKnowledge } from "./hooks/useAddKnowledge"; + +export const AddKnowledge = (): JSX.Element => { + const { hasPendingRequests, feedBrain } = useAddKnowledge(); + + return ( + <> + {hasPendingRequests && ( +
+ +
+ )} +
+ void feedBrain()} /> +
+ + ); +}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useAddKnowledge.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useAddKnowledge.ts new file mode 100644 index 000000000..230499f80 --- /dev/null +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useAddKnowledge.ts @@ -0,0 +1,31 @@ +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 +export const useAddKnowledge = () => { + const { brainId } = useUrlBrain(); + const { invalidateKnowledgeDataKey } = useKnowledge({ + brainId, + }); + + const { feedBrain, hasPendingRequests, setHasPendingRequests } = useFeedBrain( + { + dispatchHasPendingRequests: () => setHasPendingRequests(true), + } + ); + + useEffect(() => { + if (!hasPendingRequests) { + invalidateKnowledgeDataKey(); + } + }, [hasPendingRequests, invalidateKnowledgeDataKey]); + + return { + feedBrain, + hasPendingRequests, + }; +}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/hooks/useFeedBrain.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useFeedBrain.ts similarity index 90% rename from frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/hooks/useFeedBrain.ts rename to frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useFeedBrain.ts index e3b34afd3..99eb8cc12 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/hooks/useFeedBrain.ts +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useFeedBrain.ts @@ -2,9 +2,9 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; import { useChatApi } from "@/lib/api/chat/useChatApi"; -import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext"; import { useKnowledgeToFeedContext } from "@/lib/context/KnowledgeToFeedProvider/hooks/useKnowledgeToFeedContext"; import { useToast } from "@/lib/hooks"; +import { useUrlBrain } from "@/lib/hooks/useBrainIdFromUrl"; import { useFeedBrainHandler } from "./useFeedBrainHandler"; @@ -18,14 +18,14 @@ export const useFeedBrain = ({ }) => { const { publish } = useToast(); const { t } = useTranslation(["upload"]); - const { currentBrainId } = useBrainContext(); + const { brainId } = useUrlBrain(); const { setKnowledgeToFeed, knowledgeToFeed } = useKnowledgeToFeedContext(); const [hasPendingRequests, setHasPendingRequests] = useState(false); const { handleFeedBrain } = useFeedBrainHandler(); const { createChat, deleteChat } = useChatApi(); const feedBrain = async (): Promise => { - if (currentBrainId === null) { + if (brainId === undefined) { publish({ variant: "danger", text: t("selectBrainFirst"), @@ -51,7 +51,7 @@ export const useFeedBrain = ({ closeFeedInput?.(); setHasPendingRequests(true); await handleFeedBrain({ - brainId: currentBrainId, + brainId, chatId: currentChatId, }); diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/hooks/useFeedBrainHandler.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useFeedBrainHandler.ts similarity index 100% rename from frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/hooks/useFeedBrainHandler.ts rename to frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useFeedBrainHandler.ts diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/hooks/useKnowledgeToFeed.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useKnowledgeToFeed.ts similarity index 100% rename from frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/hooks/useKnowledgeToFeed.ts rename to frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddKnowledge/hooks/useKnowledgeToFeed.ts diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/AddedKnowledge.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/AddedKnowledge.tsx new file mode 100644 index 000000000..b7b15c9a6 --- /dev/null +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/AddedKnowledge.tsx @@ -0,0 +1,46 @@ +import { UUID } from "crypto"; +import { AnimatePresence, motion } from "framer-motion"; +import { useTranslation } from "react-i18next"; + +import Spinner from "@/lib/components/ui/Spinner"; + +import { useAddedKnowledge } from "./hooks/useAddedKnowledge"; +import { KnowledgeTable } from "../KnowledgeTable/KnowledgeTable"; + +type AddedKnowledgeProps = { + brainId: UUID; +}; +export const AddedKnowledge = ({ + brainId, +}: AddedKnowledgeProps): JSX.Element => { + const { isPending, allKnowledge } = useAddedKnowledge({ + brainId, + }); + + const { t } = useTranslation("explore"); + + if (isPending) { + return ; + } + + if (allKnowledge.length === 0) { + return ( + +
+

{t("empty", { ns: "explore" })}

+

+ {t("feed_brain_instructions", { ns: "explore" })} +

+
+
+ ); + } + + return ( + + + + + + ); +}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/hooks/useAddedKnowledge.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/hooks/useAddedKnowledge.ts new file mode 100644 index 000000000..984a997b5 --- /dev/null +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/AddedKnowledge/hooks/useAddedKnowledge.ts @@ -0,0 +1,44 @@ +import { useQuery, useQueryClient } from "@tanstack/react-query"; +import { UUID } from "crypto"; + +import { getKnowledgeDataKey } from "@/lib/api/knowledge/config"; +import { useKnowledgeApi } from "@/lib/api/knowledge/useKnowledgeApi"; + +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export const useAddedKnowledge = ({ brainId }: { brainId?: UUID }) => { + const queryClient = useQueryClient(); + + const { getAllKnowledge } = useKnowledgeApi(); + + const fetchKnowledge = () => { + if (brainId !== undefined) { + return getAllKnowledge({ brainId }); + } + }; + + const { data: allKnowledge, isLoading: isPending } = useQuery({ + queryKey: brainId !== undefined ? [getKnowledgeDataKey(brainId)] : [], + queryFn: fetchKnowledge, + enabled: brainId !== undefined, + }); + + if (brainId === undefined) { + return { + invalidateKnowledgeDataKey: () => void {}, + isPending: false, + allKnowledge: [], + }; + } + + const knowledge_data_key = getKnowledgeDataKey(brainId); + + const invalidateKnowledgeDataKey = () => { + void queryClient.invalidateQueries({ queryKey: [knowledge_data_key] }); + }; + + return { + invalidateKnowledgeDataKey, + isPending, + allKnowledge: allKnowledge ?? [], + }; +}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/KnowledgeTable.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/KnowledgeTable.tsx new file mode 100644 index 000000000..39a0b26d4 --- /dev/null +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/KnowledgeTable.tsx @@ -0,0 +1,19 @@ +import { Knowledge } from "@/lib/types/Knowledge"; + +import KnowledgeItem from "./components/KnowledgeItem"; + +interface KnowledgeTableProps { + knowledgeList: Knowledge[]; +} + +export const KnowledgeTable = ({ + knowledgeList, +}: KnowledgeTableProps): JSX.Element => { + return ( +
+ {knowledgeList.map((knowledge) => ( + + ))} +
+ ); +}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/CrawledKnowledgeItem.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/CrawledKnowledgeItem.tsx new file mode 100644 index 000000000..15568cccb --- /dev/null +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/CrawledKnowledgeItem.tsx @@ -0,0 +1,11 @@ +"use client"; + +export const CrawledKnowledgeItem = ({ url }: { url: string }): JSX.Element => { + return ( + +
+

{url}

+
+
+ ); +}; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/DeleteKnowledge.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/DeleteKnowledge.tsx similarity index 57% rename from frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/DeleteKnowledge.tsx rename to frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/DeleteKnowledge.tsx index f532db704..dc6f8c20f 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/DeleteKnowledge.tsx +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/DeleteKnowledge.tsx @@ -3,20 +3,20 @@ import { AiOutlineLoading3Quarters } from "react-icons/ai"; import { MdDelete } from "react-icons/md"; -import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext"; +import { useUrlBrain } from "@/lib/hooks/useBrainIdFromUrl"; import { Knowledge } from "@/lib/types/Knowledge"; -import { useKnowledgeItem } from "./useKnowledgeItem"; +import { useKnowledgeItem } from "../hooks/useKnowledgeItem"; + export const DeleteKnowledge = ({ knowledge, }: { knowledge: Knowledge; }): JSX.Element => { const { isDeleting, onDeleteKnowledge } = useKnowledgeItem(); + const { brain } = useUrlBrain(); - const { currentBrain } = useBrainContext(); - - const canDeleteFile = currentBrain?.role === "Owner"; + const canDeleteFile = brain?.role === "Owner"; if (!canDeleteFile) { return <>; @@ -25,10 +25,7 @@ export const DeleteKnowledge = ({ return isDeleting ? ( ) : ( - ); diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/DownloadUploadedKnowledge.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/DownloadUploadedKnowledge.tsx similarity index 67% rename from frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/DownloadUploadedKnowledge.tsx rename to frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/DownloadUploadedKnowledge.tsx index 5c06d1830..b7a45bd05 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/DownloadUploadedKnowledge.tsx +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/components/DownloadUploadedKnowledge.tsx @@ -1,17 +1,20 @@ import axios from "axios"; -import { BsFillCloudArrowDownFill } from "react-icons/bs"; +import { HiOutlineDownload } from "react-icons/hi"; import { useKnowledgeApi } from "@/lib/api/knowledge/useKnowledgeApi"; -import { getFileIcon } from "@/lib/helpers/getFileIcon"; -import { UploadedKnowledge } from "@/lib/types/Knowledge"; +import { isUploadedKnowledge, Knowledge } from "@/lib/types/Knowledge"; export const DownloadUploadedKnowledge = ({ knowledge, }: { - knowledge: UploadedKnowledge; + knowledge: Knowledge; }): JSX.Element => { const { generateSignedUrlKnowledge } = useKnowledgeApi(); + if (!isUploadedKnowledge(knowledge)) { + return
; + } + const downloadFile = async () => { const download_url = await generateSignedUrlKnowledge({ knowledgeId: knowledge.id, @@ -37,12 +40,8 @@ export const DownloadUploadedKnowledge = ({ }; return ( - void downloadFile()} - style={{ display: "flex", flexDirection: "column", alignItems: "center" }} - > - {getFileIcon(knowledge.fileName)} - + void downloadFile()} className="cursor-pointer"> + ); }; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/useKnowledgeItem.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/hooks/useKnowledgeItem.ts similarity index 83% rename from frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/useKnowledgeItem.ts rename to frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/hooks/useKnowledgeItem.ts index 409db1541..16236a022 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/KnowledgeItem/useKnowledgeItem.ts +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/hooks/useKnowledgeItem.ts @@ -3,12 +3,12 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; import { useKnowledgeApi } from "@/lib/api/knowledge/useKnowledgeApi"; -import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext"; import { useToast } from "@/lib/hooks"; +import { useUrlBrain } from "@/lib/hooks/useBrainIdFromUrl"; import { Knowledge } from "@/lib/types/Knowledge"; import { useEventTracking } from "@/services/analytics/june/useEventTracking"; -import { useKnowledge } from "../hooks/useKnowledge"; +import { useKnowledge } from "../../../../../hooks/useKnowledge"; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export const useKnowledgeItem = () => { @@ -16,10 +16,9 @@ export const useKnowledgeItem = () => { const [isDeleting, setIsDeleting] = useState(false); const { publish } = useToast(); const { track } = useEventTracking(); - const { currentBrain } = useBrainContext(); - + const { brainId, brain } = useUrlBrain(); const { invalidateKnowledgeDataKey } = useKnowledge({ - brainId: currentBrain?.id, + brainId, }); const { t } = useTranslation(["translation", "explore"]); @@ -30,11 +29,11 @@ export const useKnowledgeItem = () => { const knowledge_name = "fileName" in knowledge ? knowledge.fileName : knowledge.url; try { - if (currentBrain?.id === undefined) { + if (brainId === undefined) { throw new Error(t("noBrain", { ns: "explore" })); } await deleteKnowledge({ - brainId: currentBrain.id, + brainId, knowledgeId: knowledge.id, }); @@ -44,7 +43,7 @@ export const useKnowledgeItem = () => { variant: "success", text: t("deleted", { fileName: knowledge_name, - brain: currentBrain.name, + brain: brain?.name, ns: "explore", }), }); diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/index.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/index.tsx new file mode 100644 index 000000000..ea30f4e6e --- /dev/null +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/components/KnowledgeTable/components/KnowledgeItem/index.tsx @@ -0,0 +1,51 @@ +"use client"; + +import { useState } from "react"; +import { MdLink } from "react-icons/md"; + +import { getFileIcon } from "@/lib/helpers/getFileIcon"; +import { isUploadedKnowledge, Knowledge } from "@/lib/types/Knowledge"; + +import { CrawledKnowledgeItem } from "./components/CrawledKnowledgeItem"; +import { DeleteKnowledge } from "./components/DeleteKnowledge"; +import { DownloadUploadedKnowledge } from "./components/DownloadUploadedKnowledge"; + +const KnowledgeItem = ({ + knowledge, +}: { + knowledge: Knowledge; +}): JSX.Element => { + const [isHovered, setIsHovered] = useState(false); + + return ( +
setIsHovered(true)} + onMouseLeave={() => setIsHovered(false)} + className="hover:bg-gray-50 rounded-lg flex justify-between w-full py-2 px-1" + > +
+ {isUploadedKnowledge(knowledge) ? ( + getFileIcon(knowledge.fileName) + ) : ( + + )} + {isUploadedKnowledge(knowledge) ? ( +

{knowledge.fileName}

+ ) : ( + + )} +
+
+ {isHovered && ( +
+ + +
+ )} +
+
+ ); +}; + +KnowledgeItem.displayName = "KnowledgeItem"; +export default KnowledgeItem; diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/index.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/index.tsx index 11f4940fc..ebbd90c97 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/index.tsx +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/KnowledgeTab/index.tsx @@ -1,23 +1,18 @@ "use client"; import { UUID } from "crypto"; -import { AnimatePresence, motion } from "framer-motion"; import { useTranslation } from "react-i18next"; -import Spinner from "@/lib/components/ui/Spinner"; +import { Divider } from "@/lib/components/ui/Divider"; import { KnowledgeToFeedProvider } from "@/lib/context"; -import { AddKnowledge } from "./AddKnowledge"; -import { KnowledgeTable } from "./KnowledgeTable"; -import { useKnowledge } from "./hooks/useKnowledge"; +import { AddKnowledge } from "./components/AddKnowledge/AddKnowledge"; +import { AddedKnowledge } from "./components/AddedKnowledge/AddedKnowledge"; type KnowledgeTabProps = { brainId: UUID; }; export const KnowledgeTab = ({ brainId }: KnowledgeTabProps): JSX.Element => { - const { t } = useTranslation(["translation", "explore"]); - const { isPending, allKnowledge } = useKnowledge({ - brainId, - }); + const { t } = useTranslation(["translation", "explore", "config"]); return ( @@ -29,25 +24,14 @@ export const KnowledgeTab = ({ brainId }: KnowledgeTabProps): JSX.Element => {

{t("subtitle", { ns: "explore" })}

+ - {isPending ? ( - - ) : ( - - {allKnowledge.length !== 0 ? ( - - - - ) : ( -
-

{t("empty", { ns: "explore" })}

-

- {t("feed_brain_instructions", { ns: "explore" })} -

-
- )} -
- )} + + diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/components/GeneralInformation/GeneralInformation.tsx b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/components/GeneralInformation/GeneralInformation.tsx index 763b0560d..d148392bf 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/components/GeneralInformation/GeneralInformation.tsx +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/components/SettingsTab/components/GeneralInformation/GeneralInformation.tsx @@ -40,7 +40,7 @@ export const GeneralInformation = ( return ( <> -
+
-
+
{isPublicBrain && !isOwnedByCurrentUser && ( {t("brain:public_brain_label")} )} - - {isDefaultBrain ? ( -
- {t("defaultBrain", { ns: "brain" })} -
- ) : ( - hasEditRights && ( - - ) - )} +
+ {isDefaultBrain ? ( +
+ {t("defaultBrain", { ns: "brain" })} +
+ ) : ( + hasEditRights && ( + + ) + )} +
diff --git a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/hooks/useBrainManagementTabs.ts b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/hooks/useBrainManagementTabs.ts index 3a9ce61b5..1c85bf837 100644 --- a/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/hooks/useBrainManagementTabs.ts +++ b/frontend/app/brains-management/[brainId]/components/BrainManagementTabs/hooks/useBrainManagementTabs.ts @@ -43,6 +43,7 @@ export const useBrainManagementTabs = () => { const params = useParams(); const { t } = useTranslation(["delete_or_unsubscribe_from_brain"]); const brainId = params?.brainId as UUID | undefined; + const { hasEditRights, isOwnedByCurrentUser } = getBrainPermissions({ brainId, userAccessibleBrains: allBrains, diff --git a/frontend/lib/hooks/useBrainIdFromUrl.ts b/frontend/lib/hooks/useBrainIdFromUrl.ts new file mode 100644 index 000000000..c16da9087 --- /dev/null +++ b/frontend/lib/hooks/useBrainIdFromUrl.ts @@ -0,0 +1,19 @@ +import { UUID } from "crypto"; +import { useParams } from "next/navigation"; + +import { useBrainContext } from "../context/BrainProvider/hooks/useBrainContext"; + +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export const useUrlBrain = () => { + const { allBrains } = useBrainContext(); + + const params = useParams(); + + const brainId = params?.brainId as UUID | undefined; + const correspondingBrain = allBrains.find((brain) => brain.id === brainId); + + return { + brain: correspondingBrain, + brainId, + }; +};