Update useMessageOption hook and Playground component
This commit is contained in:
18
src/components/Option/Knowledge/KnowledgeIcon.tsx
Normal file
18
src/components/Option/Knowledge/KnowledgeIcon.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { CSVIcon } from "@/components/Icons/CSVIcon"
|
||||
import { PDFIcon } from "@/components/Icons/PDFIcon"
|
||||
import { TXTIcon } from "@/components/Icons/TXTIcon"
|
||||
|
||||
type Props = {
|
||||
type: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const KnowledgeIcon = ({ type, className = "w-6 h-6" }: Props) => {
|
||||
if (type === "pdf" || type === "application/pdf") {
|
||||
return <PDFIcon className={className} />
|
||||
} else if (type === "csv" || type === "text/csv") {
|
||||
return <CSVIcon className={className} />
|
||||
} else if (type === "txt" || type === "text/plain") {
|
||||
return <TXTIcon className={className} />
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { getAllKnowledge } from "@/db/knowledge"
|
||||
import { useMessageOption } from "@/hooks/useMessageOption"
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
import { Dropdown, Tooltip } from "antd"
|
||||
import { Blocks } from "lucide-react"
|
||||
@@ -7,6 +8,7 @@ import { useTranslation } from "react-i18next"
|
||||
|
||||
export const KnowledgeSelect: React.FC = () => {
|
||||
const { t } = useTranslation("playground")
|
||||
const { setSelectedKnowledge, selectedKnowledge } = useMessageOption()
|
||||
const { data } = useQuery({
|
||||
queryKey: ["getAllKnowledge"],
|
||||
queryFn: async () => {
|
||||
@@ -30,14 +32,21 @@ export const KnowledgeSelect: React.FC = () => {
|
||||
{d.title}
|
||||
</div>
|
||||
),
|
||||
onClick: () => {}
|
||||
onClick: () => {
|
||||
const knowledge = data?.find((k) => k.id === d.id)
|
||||
if (selectedKnowledge?.id === d.id) {
|
||||
setSelectedKnowledge(null)
|
||||
} else {
|
||||
setSelectedKnowledge(knowledge)
|
||||
}
|
||||
}
|
||||
})) || [],
|
||||
style: {
|
||||
maxHeight: 500,
|
||||
overflowY: "scroll"
|
||||
},
|
||||
// hidescrollbars: true
|
||||
className: "no-scrollbar"
|
||||
className: "no-scrollbar",
|
||||
activeKey: selectedKnowledge?.id
|
||||
}}
|
||||
placement={"topLeft"}
|
||||
trigger={["click"]}>
|
||||
|
||||
39
src/components/Option/Knowledge/SelectedKnwledge.tsx
Normal file
39
src/components/Option/Knowledge/SelectedKnwledge.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Knowledge } from "@/db/knowledge"
|
||||
import { XIcon } from "lucide-react"
|
||||
import { KnowledgeIcon } from "./KnowledgeIcon"
|
||||
|
||||
type Props = {
|
||||
knowledge: Knowledge
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
export const SelectedKnowledge = ({ knowledge, onClose }: Props) => {
|
||||
return (
|
||||
<div className="mb-3 border flex justify-between items-center rounded-md p-2 dark:border-gray-600">
|
||||
<div className="flex flex-col gap-2">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold dark:text-gray-100">
|
||||
{knowledge.title}
|
||||
</h3>
|
||||
</div>
|
||||
<div className="flex flex-row overflow-x-auto gap-2 w-full">
|
||||
{knowledge.source.map((source, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="inline-flex gap-2 border rounded-md p-1 dark:border-gray-600 dark:text-gray-100">
|
||||
<KnowledgeIcon type={source.type} className="w-4 h-4" />
|
||||
{source.filename}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="flex items-center justify-center bg-white dark:bg-[#262626] p-1 rounded-full hover:bg-gray-100 dark:hover:bg-gray-600 text-black dark:text-gray-100">
|
||||
<XIcon className="h-5 w-5" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,19 +1,21 @@
|
||||
import { useState } from "react"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { AddKnowledge } from "./AddKnowledge"
|
||||
import {
|
||||
useMutation,
|
||||
useQuery,
|
||||
useQueryClient
|
||||
} from "@tanstack/react-query"
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||
import { deleteKnowledge, getAllKnowledge } from "@/db/knowledge"
|
||||
import { Skeleton, Table, Tag, Tooltip, message } from "antd"
|
||||
import { Trash2 } from "lucide-react"
|
||||
import { KnowledgeIcon } from "./KnowledgeIcon"
|
||||
import { useMessageOption } from "@/hooks/useMessageOption"
|
||||
|
||||
export const KnowledgeSettings = () => {
|
||||
const { t } = useTranslation(["knownledge", "common"])
|
||||
const [open, setOpen] = useState(false)
|
||||
const queryClient = useQueryClient()
|
||||
const {
|
||||
selectedKnowledge,
|
||||
setSelectedKnowledge
|
||||
} = useMessageOption()
|
||||
|
||||
const { data, status } = useQuery({
|
||||
queryKey: ["fetchAllKnowledge"],
|
||||
@@ -91,6 +93,9 @@ export const KnowledgeSettings = () => {
|
||||
onClick={() => {
|
||||
if (window.confirm(t("confirm.delete"))) {
|
||||
deleteKnowledgeMutation(record.id)
|
||||
if(selectedKnowledge.id === record.id) {
|
||||
setSelectedKnowledge(null)
|
||||
}
|
||||
}
|
||||
}}
|
||||
className="text-red-500 dark:text-red-400">
|
||||
@@ -110,11 +115,6 @@ export const KnowledgeSettings = () => {
|
||||
title: t("expandedColumns.name"),
|
||||
key: "filename",
|
||||
dataIndex: "filename"
|
||||
},
|
||||
{
|
||||
title: t("expandedColumns.type"),
|
||||
key: "type",
|
||||
dataIndex: "type"
|
||||
}
|
||||
]}
|
||||
dataSource={record.source}
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import React from "react"
|
||||
import { PlaygroundForm } from "./PlaygroundForm"
|
||||
import { PlaygroundChat } from "./PlaygroundChat"
|
||||
import { useMessageOption } from "@/hooks/useMessageOption"
|
||||
|
||||
export const Playground = () => {
|
||||
const drop = React.useRef<HTMLDivElement>(null)
|
||||
const [dropedFile, setDropedFile] = React.useState<File | undefined>()
|
||||
const { selectedKnowledge } = useMessageOption()
|
||||
|
||||
const [dropState, setDropState] = React.useState<
|
||||
"idle" | "dragging" | "error"
|
||||
>("idle")
|
||||
React.useEffect(() => {
|
||||
if (selectedKnowledge) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!drop.current) {
|
||||
return
|
||||
}
|
||||
@@ -64,7 +70,7 @@ export const Playground = () => {
|
||||
drop.current.removeEventListener("dragleave", handleDragLeave)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
}, [selectedKnowledge])
|
||||
return (
|
||||
<div
|
||||
ref={drop}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { ImageIcon, MicIcon, StopCircleIcon, X } from "lucide-react"
|
||||
import { getVariable } from "~/utils/select-varaible"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { KnowledgeSelect } from "../Knowledge/KnowledgeSelect"
|
||||
import { SelectedKnowledge } from "../Knowledge/SelectedKnwledge"
|
||||
|
||||
type Props = {
|
||||
dropedFile: File | undefined
|
||||
@@ -33,7 +34,9 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
||||
setWebSearch,
|
||||
selectedQuickPrompt,
|
||||
textareaRef,
|
||||
setSelectedQuickPrompt
|
||||
setSelectedQuickPrompt,
|
||||
selectedKnowledge,
|
||||
setSelectedKnowledge
|
||||
} = useMessageOption()
|
||||
|
||||
const textAreaFocus = () => {
|
||||
@@ -155,6 +158,14 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
||||
}
|
||||
return (
|
||||
<div className="px-3 pt-3 md:px-6 md:pt-6 bg-gray-50 dark:bg-[#262626] border rounded-t-xl dark:border-gray-600">
|
||||
{selectedKnowledge && (
|
||||
<SelectedKnowledge
|
||||
onClose={() => {
|
||||
setSelectedKnowledge(null)
|
||||
}}
|
||||
knowledge={selectedKnowledge}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={`h-full rounded-md shadow relative ${
|
||||
form.values.image.length === 0 ? "hidden" : "block"
|
||||
@@ -225,29 +236,31 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
||||
/>
|
||||
<div className="mt-4 flex justify-between items-center">
|
||||
<div className="flex">
|
||||
<Tooltip title={t("tooltip.searchInternet")}>
|
||||
<div className="inline-flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-5 h-5 dark:text-gray-300">
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418"
|
||||
{!selectedKnowledge && (
|
||||
<Tooltip title={t("tooltip.searchInternet")}>
|
||||
<div className="inline-flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
strokeWidth={1.5}
|
||||
stroke="currentColor"
|
||||
className="w-5 h-5 dark:text-gray-300">
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418"
|
||||
/>
|
||||
</svg>
|
||||
<Switch
|
||||
value={webSearch}
|
||||
onChange={(e) => setWebSearch(e)}
|
||||
checkedChildren={t("form.webSearch.on")}
|
||||
unCheckedChildren={t("form.webSearch.off")}
|
||||
/>
|
||||
</svg>
|
||||
<Switch
|
||||
value={webSearch}
|
||||
onChange={(e) => setWebSearch(e)}
|
||||
checkedChildren={t("form.webSearch.on")}
|
||||
unCheckedChildren={t("form.webSearch.off")}
|
||||
/>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex !justify-end gap-3">
|
||||
<KnowledgeSelect />
|
||||
@@ -276,18 +289,20 @@ export const PlaygroundForm = ({ dropedFile }: Props) => {
|
||||
</button>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip title={t("tooltip.uploadImage")}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
inputRef.current?.click()
|
||||
}}
|
||||
className={`flex items-center justify-center dark:text-gray-300 ${
|
||||
chatMode === "rag" ? "hidden" : "block"
|
||||
}`}>
|
||||
<ImageIcon className="h-5 w-5" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
{!selectedKnowledge && (
|
||||
<Tooltip title={t("tooltip.uploadImage")}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
inputRef.current?.click()
|
||||
}}
|
||||
className={`flex items-center justify-center dark:text-gray-300 ${
|
||||
chatMode === "rag" ? "hidden" : "block"
|
||||
}`}>
|
||||
<ImageIcon className="h-5 w-5" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!isSending ? (
|
||||
<Dropdown.Button
|
||||
htmlType="submit"
|
||||
|
||||
Reference in New Issue
Block a user