import { useDebouncedCallback } from "use-debounce"; import OpenAPIClientAxios from "openapi-client-axios"; import yaml from "js-yaml"; import { IconButton } from "./button"; import { ErrorBoundary } from "./error"; import styles from "./mask.module.scss"; import pluginStyles from "./plugin.module.scss"; import DownloadIcon from "../icons/download.svg"; import EditIcon from "../icons/edit.svg"; import AddIcon from "../icons/add.svg"; import CloseIcon from "../icons/close.svg"; import DeleteIcon from "../icons/delete.svg"; import EyeIcon from "../icons/eye.svg"; import CopyIcon from "../icons/copy.svg"; import { Plugin, usePluginStore, FunctionToolService } from "../store/plugin"; import { Input, List, ListItem, Modal, Popover, Select, showConfirm, showToast, } from "./ui-lib"; import { downloadAs } from "../utils"; import Locale from "../locales"; import { useNavigate } from "react-router-dom"; import { useEffect, useState } from "react"; import { Path } from "../constant"; import { nanoid } from "nanoid"; export function PluginPage() { const navigate = useNavigate(); const pluginStore = usePluginStore(); const allPlugins = pluginStore.getAll(); const [searchPlugins, setSearchPlugins] = useState([]); const [searchText, setSearchText] = useState(""); const plugins = searchText.length > 0 ? searchPlugins : allPlugins; // refactored already, now it accurate const onSearch = (text: string) => { setSearchText(text); if (text.length > 0) { const result = allPlugins.filter( (m) => m?.title.toLowerCase().includes(text.toLowerCase()), ); setSearchPlugins(result); } else { setSearchPlugins(allPlugins); } }; const [editingPluginId, setEditingPluginId] = useState(); const editingPlugin = pluginStore.get(editingPluginId); const editingPluginTool = FunctionToolService.get(editingPlugin?.id); const closePluginModal = () => setEditingPluginId(undefined); const onChangePlugin = useDebouncedCallback((editingPlugin, e) => { const content = e.target.innerText; try { const api = new OpenAPIClientAxios({ definition: yaml.load(content) as any, }); api .init() .then(() => { if (content != editingPlugin.content) { pluginStore.updatePlugin(editingPlugin.id, (plugin) => { plugin.content = content; const tool = FunctionToolService.add(plugin, true); plugin.title = tool.api.definition.info.title; plugin.version = tool.api.definition.info.version; }); } }) .catch((e) => { console.error(e); showToast(Locale.Plugin.EditModal.Error); }); } catch (e) { console.error(e); showToast(Locale.Plugin.EditModal.Error); } }, 100).bind(null, editingPlugin); return (
{Locale.Plugin.Page.Title}
{Locale.Plugin.Page.SubTitle(plugins.length)}
} bordered onClick={() => navigate(-1)} />
onSearch(e.currentTarget.value)} /> } text={Locale.Plugin.Page.Create} bordered onClick={() => { const createdPlugin = pluginStore.create(); setEditingPluginId(createdPlugin.id); }} />
{plugins.map((m) => (
{m.title}@{m.version}
{Locale.Plugin.Item.Info( FunctionToolService.add(m).length, )}
{m.builtin ? ( } text={Locale.Plugin.Item.View} onClick={() => setEditingPluginId(m.id)} /> ) : ( } text={Locale.Plugin.Item.Edit} onClick={() => setEditingPluginId(m.id)} /> )} {!m.builtin && ( } text={Locale.Plugin.Item.Delete} onClick={async () => { if ( await showConfirm(Locale.Plugin.Item.DeleteConfirm) ) { pluginStore.delete(m.id); } }} /> )}
))}
{editingPlugin && (
} text={Locale.Plugin.EditModal.Download} key="export" bordered onClick={() => downloadAs( JSON.stringify(editingPlugin), `${editingPlugin.title}@${editingPlugin.version}.json`, ) } />, ]} >
{Locale.Plugin.EditModal.Content}
                  
                
{Locale.Plugin.EditModal.Method}
{editingPluginTool?.tools.map((tool, index) => (
{tool?.function?.name}
{tool?.function?.description}
))}
)}
); }