2024-10-12 16:53:42 +05:30
|
|
|
import { Form, Input, Modal, Table, message, Tooltip, Select } from "antd"
|
2024-09-28 16:08:02 +05:30
|
|
|
import { useState } from "react"
|
|
|
|
|
import { useTranslation } from "react-i18next"
|
|
|
|
|
import {
|
|
|
|
|
addOpenAICofig,
|
|
|
|
|
getAllOpenAIConfig,
|
|
|
|
|
deleteOpenAIConfig,
|
|
|
|
|
updateOpenAIConfig
|
|
|
|
|
} from "@/db/openai"
|
|
|
|
|
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
2024-10-12 18:28:29 +05:30
|
|
|
import { Pencil, Trash2, RotateCwIcon, DownloadIcon } from "lucide-react"
|
2024-09-29 19:12:19 +05:30
|
|
|
import { OpenAIFetchModel } from "./openai-fetch-model"
|
2024-10-12 16:53:42 +05:30
|
|
|
import { OAI_API_PROVIDERS } from "@/utils/oai-api-providers"
|
2024-09-28 16:08:02 +05:30
|
|
|
|
|
|
|
|
export const OpenAIApp = () => {
|
|
|
|
|
const { t } = useTranslation("openai")
|
|
|
|
|
const [open, setOpen] = useState(false)
|
|
|
|
|
const [editingConfig, setEditingConfig] = useState(null)
|
|
|
|
|
const queryClient = useQueryClient()
|
|
|
|
|
const [form] = Form.useForm()
|
2024-09-29 19:12:19 +05:30
|
|
|
const [openaiId, setOpenaiId] = useState<string | null>(null)
|
|
|
|
|
const [openModelModal, setOpenModelModal] = useState(false)
|
2024-10-12 18:28:29 +05:30
|
|
|
const [provider, setProvider] = useState("custom")
|
2024-09-28 16:08:02 +05:30
|
|
|
|
|
|
|
|
const { data: configs, isLoading } = useQuery({
|
|
|
|
|
queryKey: ["openAIConfigs"],
|
|
|
|
|
queryFn: getAllOpenAIConfig
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const addMutation = useMutation({
|
|
|
|
|
mutationFn: addOpenAICofig,
|
2024-09-29 19:12:19 +05:30
|
|
|
onSuccess: (data) => {
|
2024-09-28 16:08:02 +05:30
|
|
|
queryClient.invalidateQueries({
|
|
|
|
|
queryKey: ["openAIConfigs"]
|
|
|
|
|
})
|
|
|
|
|
setOpen(false)
|
|
|
|
|
message.success(t("addSuccess"))
|
2024-09-29 19:12:19 +05:30
|
|
|
setOpenaiId(data)
|
|
|
|
|
setOpenModelModal(true)
|
2024-09-28 16:08:02 +05:30
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const updateMutation = useMutation({
|
|
|
|
|
mutationFn: updateOpenAIConfig,
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({
|
|
|
|
|
queryKey: ["openAIConfigs"]
|
|
|
|
|
})
|
|
|
|
|
setOpen(false)
|
|
|
|
|
message.success(t("updateSuccess"))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const deleteMutation = useMutation({
|
|
|
|
|
mutationFn: deleteOpenAIConfig,
|
|
|
|
|
onSuccess: () => {
|
|
|
|
|
queryClient.invalidateQueries({
|
|
|
|
|
queryKey: ["openAIConfigs"]
|
|
|
|
|
})
|
|
|
|
|
message.success(t("deleteSuccess"))
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const handleSubmit = (values: {
|
|
|
|
|
id?: string
|
|
|
|
|
name: string
|
|
|
|
|
baseUrl: string
|
|
|
|
|
apiKey: string
|
|
|
|
|
}) => {
|
|
|
|
|
if (editingConfig) {
|
|
|
|
|
updateMutation.mutate({ id: editingConfig.id, ...values })
|
|
|
|
|
} else {
|
2024-10-12 18:28:29 +05:30
|
|
|
addMutation.mutate({
|
|
|
|
|
...values,
|
|
|
|
|
provider
|
|
|
|
|
})
|
2024-09-28 16:08:02 +05:30
|
|
|
}
|
2024-10-12 18:28:29 +05:30
|
|
|
|
|
|
|
|
setProvider("custom")
|
2024-09-28 16:08:02 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleEdit = (record: any) => {
|
|
|
|
|
setEditingConfig(record)
|
|
|
|
|
setOpen(true)
|
|
|
|
|
form.setFieldsValue(record)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleDelete = (id: string) => {
|
|
|
|
|
deleteMutation.mutate(id)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<div>
|
|
|
|
|
<div>
|
|
|
|
|
<h2 className="text-base font-semibold leading-7 text-gray-900 dark:text-white">
|
|
|
|
|
{t("heading")}
|
|
|
|
|
</h2>
|
|
|
|
|
<p className="mt-1 text-sm leading-6 text-gray-600 dark:text-gray-400">
|
|
|
|
|
{t("subheading")}
|
|
|
|
|
</p>
|
|
|
|
|
<div className="border border-b border-gray-200 dark:border-gray-600 mt-3 mb-6"></div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="mb-6">
|
|
|
|
|
<div className="-ml-4 -mt-2 flex flex-wrap items-center justify-end sm:flex-nowrap">
|
|
|
|
|
<div className="ml-4 mt-2 flex-shrink-0">
|
|
|
|
|
<button
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setEditingConfig(null)
|
|
|
|
|
setOpen(true)
|
|
|
|
|
form.resetFields()
|
|
|
|
|
}}
|
|
|
|
|
className="inline-flex items-center rounded-md border border-transparent bg-black px-2 py-2 text-md font-medium leading-4 text-white shadow-sm hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-white dark:text-gray-800 dark:hover:bg-gray-100 dark:focus:ring-gray-500 dark:focus:ring-offset-gray-100 disabled:opacity-50">
|
|
|
|
|
{t("addBtn")}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<Table
|
|
|
|
|
columns={[
|
|
|
|
|
{
|
|
|
|
|
title: t("table.name"),
|
|
|
|
|
dataIndex: "name",
|
|
|
|
|
key: "name"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: t("table.baseUrl"),
|
|
|
|
|
dataIndex: "baseUrl",
|
|
|
|
|
key: "baseUrl"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: t("table.actions"),
|
|
|
|
|
key: "actions",
|
|
|
|
|
render: (_, record) => (
|
|
|
|
|
<div className="flex gap-4">
|
|
|
|
|
<Tooltip title={t("edit")}>
|
|
|
|
|
<button
|
|
|
|
|
className="text-gray-700 dark:text-gray-400"
|
|
|
|
|
onClick={() => handleEdit(record)}>
|
|
|
|
|
<Pencil className="size-4" />
|
|
|
|
|
</button>
|
|
|
|
|
</Tooltip>
|
2024-09-29 19:12:19 +05:30
|
|
|
|
|
|
|
|
<Tooltip title={t("refetch")}>
|
|
|
|
|
<button
|
|
|
|
|
className="text-gray-700 dark:text-gray-400"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setOpenModelModal(true)
|
|
|
|
|
setOpenaiId(record.id)
|
|
|
|
|
}}
|
|
|
|
|
disabled={!record.id}>
|
2024-10-12 18:28:29 +05:30
|
|
|
<DownloadIcon className="size-4" />
|
2024-09-29 19:12:19 +05:30
|
|
|
</button>
|
|
|
|
|
</Tooltip>
|
2024-09-28 16:08:02 +05:30
|
|
|
<Tooltip title={t("delete")}>
|
|
|
|
|
<button
|
|
|
|
|
className="text-red-500 dark:text-red-400"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
// add confirmation here
|
|
|
|
|
if (
|
|
|
|
|
confirm(
|
|
|
|
|
t("modal.deleteConfirm", {
|
|
|
|
|
name: record.name
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
handleDelete(record.id)
|
|
|
|
|
}
|
|
|
|
|
}}>
|
|
|
|
|
<Trash2 className="size-4" />
|
|
|
|
|
</button>
|
|
|
|
|
</Tooltip>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
]}
|
|
|
|
|
dataSource={configs}
|
|
|
|
|
loading={isLoading}
|
|
|
|
|
rowKey="id"
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
<Modal
|
|
|
|
|
open={open}
|
|
|
|
|
title={editingConfig ? t("modal.titleEdit") : t("modal.titleAdd")}
|
|
|
|
|
onCancel={() => {
|
|
|
|
|
setOpen(false)
|
|
|
|
|
setEditingConfig(null)
|
2024-10-12 18:28:29 +05:30
|
|
|
setProvider("custom")
|
2024-09-28 16:08:02 +05:30
|
|
|
form.resetFields()
|
|
|
|
|
}}
|
|
|
|
|
footer={null}>
|
2024-10-12 16:53:42 +05:30
|
|
|
{!editingConfig && (
|
|
|
|
|
<Select
|
2024-10-12 18:28:29 +05:30
|
|
|
value={provider}
|
2024-10-12 16:53:42 +05:30
|
|
|
onSelect={(e) => {
|
|
|
|
|
const value = OAI_API_PROVIDERS.find((item) => item.value === e)
|
|
|
|
|
form.setFieldsValue({
|
|
|
|
|
baseUrl: value?.baseUrl,
|
|
|
|
|
name: value?.label
|
|
|
|
|
})
|
2024-10-12 18:28:29 +05:30
|
|
|
setProvider(e)
|
2024-10-12 16:53:42 +05:30
|
|
|
}}
|
|
|
|
|
className="w-full !mb-4"
|
|
|
|
|
options={OAI_API_PROVIDERS}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2024-09-28 16:08:02 +05:30
|
|
|
<Form
|
|
|
|
|
form={form}
|
|
|
|
|
layout="vertical"
|
|
|
|
|
onFinish={handleSubmit}
|
2024-10-12 16:53:42 +05:30
|
|
|
initialValues={{ ...editingConfig }}>
|
2024-09-28 16:08:02 +05:30
|
|
|
<Form.Item
|
|
|
|
|
name="name"
|
|
|
|
|
label={t("modal.name.label")}
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: t("modal.name.required")
|
|
|
|
|
}
|
|
|
|
|
]}>
|
|
|
|
|
<Input size="large" placeholder={t("modal.name.placeholder")} />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item
|
|
|
|
|
name="baseUrl"
|
|
|
|
|
label={t("modal.baseUrl.label")}
|
|
|
|
|
help={t("modal.baseUrl.help")}
|
|
|
|
|
rules={[
|
|
|
|
|
{
|
|
|
|
|
required: true,
|
|
|
|
|
message: t("modal.baseUrl.required")
|
|
|
|
|
}
|
|
|
|
|
]}>
|
|
|
|
|
<Input
|
|
|
|
|
size="large"
|
|
|
|
|
placeholder={t("modal.baseUrl.placeholder")}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<Form.Item name="apiKey" label={t("modal.apiKey.label")}>
|
|
|
|
|
<Input.Password
|
|
|
|
|
size="large"
|
|
|
|
|
placeholder={t("modal.apiKey.placeholder")}
|
|
|
|
|
/>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
type="submit"
|
|
|
|
|
className="inline-flex justify-center w-full text-center mt-4 items-center rounded-md border border-transparent bg-black px-2 py-2 text-sm font-medium leading-4 text-white shadow-sm hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:bg-white dark:text-gray-800 dark:hover:bg-gray-100 dark:focus:ring-gray-500 dark:focus:ring-offset-gray-100 disabled:opacity-50">
|
|
|
|
|
{editingConfig ? t("modal.update") : t("modal.submit")}
|
|
|
|
|
</button>
|
|
|
|
|
</Form>
|
|
|
|
|
</Modal>
|
2024-09-29 19:12:19 +05:30
|
|
|
|
|
|
|
|
<Modal
|
|
|
|
|
open={openModelModal}
|
|
|
|
|
title={t("modal.model.title")}
|
|
|
|
|
footer={null}
|
|
|
|
|
onCancel={() => setOpenModelModal(false)}>
|
|
|
|
|
{openaiId ? (
|
|
|
|
|
<OpenAIFetchModel
|
|
|
|
|
openaiId={openaiId}
|
|
|
|
|
setOpenModelModal={setOpenModelModal}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
</Modal>
|
2024-09-28 16:08:02 +05:30
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|