Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: UI enhancement for knowledge #298

Merged
merged 1 commit into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 1 addition & 14 deletions ui/admin/app/components/knowledge/AgentKnowledgePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,14 @@ export function AgentKnowledgePanel({ agentId }: { agentId: string }) {
let notionSource = remoteKnowledgeSources.find(
(source) => source.sourceType === "notion"
);
let onedriveSource = remoteKnowledgeSources.find(
const onedriveSource = remoteKnowledgeSources.find(
(source) => source.sourceType === "onedrive"
);
const websiteSource = remoteKnowledgeSources.find(
(source) => source.sourceType === "website"
);

const onClickNotion = async () => {
// For notion, we need to ensure the remote knowledge source is created so that client can fetch a list of pages
if (!notionSource) {
await KnowledgeService.createRemoteKnowledgeSource(agentId, {
sourceType: "notion",
Expand All @@ -159,18 +158,6 @@ export function AgentKnowledgePanel({ agentId }: { agentId: string }) {
await KnowledgeService.createRemoteKnowledgeSource(agentId, {
sourceType: "onedrive",
});
const intervalId = setInterval(() => {
getRemoteKnowledgeSources.mutate();
onedriveSource = remoteKnowledgeSources.find(
(source) => source.sourceType === "onedrive"
);
if (onedriveSource?.runID) {
clearInterval(intervalId);
}
}, 1000);
setTimeout(() => {
clearInterval(intervalId);
}, 10000);
}
setIsOnedriveModalOpen(true);
};
Expand Down
4 changes: 2 additions & 2 deletions ui/admin/app/components/knowledge/FileItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FileIcon, PlusIcon, XIcon } from "lucide-react";
import { FileIcon, PlusIcon, TrashIcon } from "lucide-react";
import { useState } from "react";

import { KnowledgeFile } from "~/lib/model/knowledge";
Expand Down Expand Up @@ -101,7 +101,7 @@ function FileItem({
{actionIcon ? (
actionIcon
) : (
<XIcon className="w-4 h-4" />
<TrashIcon className="w-4 h-4" />
)}
</Button>
)
Expand Down
32 changes: 24 additions & 8 deletions ui/admin/app/components/knowledge/file/FileModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ import {
} from "~/components/ui/dialog";
import { Input } from "~/components/ui/input";
import { ScrollArea } from "~/components/ui/scroll-area";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";
import { useAsync } from "~/hooks/useAsync";
import { useMultiAsync } from "~/hooks/useMultiAsync";

Expand Down Expand Up @@ -115,14 +121,24 @@ function FileModal({
>
<DialogHeader className="flex flex-row justify-between items-center">
<DialogTitle>Manage Files</DialogTitle>
<Button
variant="secondary"
size="sm"
className="mr-2"
onClick={() => fileInputRef.current?.click()}
>
<UploadIcon className="upload-icon" />
</Button>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="secondary"
size="sm"
className="mr-2"
onClick={() =>
fileInputRef.current?.click()
}
tabIndex={-1}
>
<UploadIcon className="upload-icon" />
</Button>
</TooltipTrigger>
<TooltipContent>Upload</TooltipContent>
</Tooltip>
</TooltipProvider>
</DialogHeader>
<ScrollArea className="max-h-[45vh] mt-4">
<div className={cn("p-2 flex flex-wrap gap-2")}>
Expand Down
67 changes: 47 additions & 20 deletions ui/admin/app/components/knowledge/notion/NotionModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ import {
DialogTitle,
} from "~/components/ui/dialog";
import { ScrollArea } from "~/components/ui/scroll-area";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";

import IngestionStatusComponent from "../IngestionStatus";

Expand Down Expand Up @@ -60,6 +66,8 @@ export const NotionModal: FC<NotionModalProps> = ({
startPolling();
};

const hasKnowledgeFiles = knowledgeFiles.length > 0;

return (
<Dialog open={isOpen} onOpenChange={onOpenChange}>
<DialogContent
Expand All @@ -78,25 +86,44 @@ export const NotionModal: FC<NotionModalProps> = ({
Notion
</div>

<div>
<Button
size="sm"
variant="secondary"
onClick={() =>
handleRemoteKnowledgeSourceSync("notion")
}
className="mr-2"
>
<RefreshCcwIcon className="w-4 h-4" />
</Button>
<Button
size="sm"
variant="secondary"
onClick={() => setIsSettingModalOpen(true)}
className="mr-2"
>
<SettingsIcon className="w-4 h-4" />
</Button>
<div className="flex flex-row items-center">
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="secondary"
onClick={() =>
handleRemoteKnowledgeSourceSync(
"notion"
)
}
className="mr-2"
tabIndex={-1}
disabled={!hasKnowledgeFiles}
>
<RefreshCcwIcon className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Refresh</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="secondary"
onClick={() =>
setIsSettingModalOpen(true)
}
className="mr-2"
tabIndex={-1}
>
<SettingsIcon className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Settings</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</DialogTitle>
</DialogHeader>
Expand All @@ -109,7 +136,7 @@ export const NotionModal: FC<NotionModalProps> = ({
subTitle={
notionSource?.state?.notionState?.pages?.[
item.uploadID!
]?.title
]?.folderPath
}
remoteKnowledgeSourceType={
item.remoteKnowledgeSourceType!
Expand Down
133 changes: 85 additions & 48 deletions ui/admin/app/components/knowledge/onedrive/OneDriveModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ import { Avatar } from "~/components/ui/avatar";
import { Button } from "~/components/ui/button";
import { Dialog, DialogContent, DialogTitle } from "~/components/ui/dialog";
import { ScrollArea } from "~/components/ui/scroll-area";
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "~/components/ui/tooltip";

import IngestionStatusComponent from "../IngestionStatus";
import RemoteFileItemChip from "../RemoteFileItemChip";
Expand Down Expand Up @@ -95,6 +101,7 @@ export const OnedriveModal: FC<OnedriveModalProps> = ({
startPolling();
};

const hasKnowledgeFiles = knowledgeFiles.length > 0;
return (
<Dialog open={isOpen} onOpenChange={onOpenChange}>
<DialogContent
Expand All @@ -112,42 +119,69 @@ export const OnedriveModal: FC<OnedriveModalProps> = ({
OneDrive
</div>
<div>
<Button
size="sm"
variant="secondary"
onClick={() => setIsAddLinkModalOpen(true)}
className="mr-2"
>
<UploadIcon className="w-4 h-4" />
</Button>
<Button
size="sm"
variant="secondary"
onClick={() =>
handleRemoteKnowledgeSourceSync("onedrive")
}
className="mr-2"
>
<RefreshCcwIcon className="w-4 h-4" />
</Button>
<Button
size="sm"
variant="secondary"
onClick={() => setIsSettingModalOpen(true)}
className="mr-2"
>
<SettingsIcon className="w-4 h-4" />
</Button>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="secondary"
onClick={() =>
setIsAddLinkModalOpen(true)
}
className="mr-2"
tabIndex={-1}
>
<UploadIcon className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Add</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="secondary"
onClick={() =>
handleRemoteKnowledgeSourceSync(
"onedrive"
)
}
className="mr-2"
tabIndex={-1}
disabled={!hasKnowledgeFiles}
>
<RefreshCcwIcon className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Refresh</TooltipContent>
</Tooltip>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="secondary"
onClick={() =>
setIsSettingModalOpen(true)
}
className="mr-2"
tabIndex={-1}
>
<SettingsIcon className="w-4 h-4" />
</Button>
</TooltipTrigger>
<TooltipContent>Settings</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</DialogTitle>
<ScrollArea className="max-h-[45vh] overflow-x-auto">
<div className="max-h-[400px] overflow-x-auto">
{links.map((link, index) => (
<div key={index}>
{/* eslint-disable-next-line */}
<div
<Button
key={index}
className="flex flex-row items-center justify-between overflow-x-auto pr-4 h-12 cursor-pointer"
variant="ghost"
className="flex flex-row w-full items-center justify-between overflow-x-auto pr-4 h-12 cursor-pointer"
onClick={() => {
if (
showTable[index] === undefined ||
Expand Down Expand Up @@ -222,12 +256,11 @@ export const OnedriveModal: FC<OnedriveModalProps> = ({
) : (
<ChevronDown className="h-4 w-4" />
))}
</div>
</Button>
{showTable[index] && (
<ScrollArea className="max-h-[200px] overflow-x-auto mb-2">
<div className="flex flex-col gap-2">
{knowledgeFiles

.filter((item) =>
onedriveSource?.state?.onedriveState?.files?.[
item.uploadID!
Expand Down Expand Up @@ -274,19 +307,22 @@ export const OnedriveModal: FC<OnedriveModalProps> = ({
))}
<div className="flex flex-col gap-2 mt-2">
{knowledgeFiles
.filter(
(item) =>
!links.some(
(link) =>
onedriveSource?.state?.onedriveState?.files?.[
item.uploadID!
]?.folderPath?.startsWith(
onedriveSource?.state
?.onedriveState
?.links?.[link]?.name ??
""
) ?? false
)
.filter((item) =>
links.every((link) => {
// If we have file state and find out that file doesn't belong to any link, then we should it as separate files as this link is pointing to a file
const fileState =
onedriveSource?.state?.onedriveState
?.files?.[item.uploadID!];
return (
fileState &&
!fileState?.folderPath?.startsWith(
onedriveSource?.state
?.onedriveState?.links?.[
link
]?.name ?? ""
)
);
})
)
.map((item) => (
<RemoteFileItemChip
Expand Down Expand Up @@ -317,9 +353,10 @@ export const OnedriveModal: FC<OnedriveModalProps> = ({
{knowledgeFiles?.some((item) => item.approved) && (
<IngestionStatusComponent knowledge={knowledgeFiles} />
)}
{onedriveSource?.runID && (
<RemoteKnowledgeSourceStatus source={onedriveSource!} />
)}
{onedriveSource?.state?.onedriveState?.links &&
onedriveSource?.runID && (
<RemoteKnowledgeSourceStatus source={onedriveSource!} />
)}

<div className="mt-4 flex justify-between">
<Button
Expand All @@ -333,7 +370,7 @@ export const OnedriveModal: FC<OnedriveModalProps> = ({
handleApproveAll();
setLoading(false);
}}
disabled={loading}
disabled={loading || !hasKnowledgeFiles}
>
{loading ? (
<LoadingSpinner className="w-4 h-4" />
Expand Down
Loading