diff --git a/web/src/app/home/components/home-titlebar/HomeTittleBar.module.css b/web/src/app/home/components/home-titlebar/HomeTittleBar.module.css index 183d59dc..7fa83d68 100644 --- a/web/src/app/home/components/home-titlebar/HomeTittleBar.module.css +++ b/web/src/app/home/components/home-titlebar/HomeTittleBar.module.css @@ -1,6 +1,7 @@ .titleBarContainer { width: 100%; - height: 6rem; + padding-top: 0.8rem; + height: 4rem; opacity: 1; font-size: 20px; display: flex; diff --git a/web/src/app/home/plugins/page.tsx b/web/src/app/home/plugins/page.tsx index b79b696f..9cf94c1d 100644 --- a/web/src/app/home/plugins/page.tsx +++ b/web/src/app/home/plugins/page.tsx @@ -1,12 +1,66 @@ 'use client'; -import PluginInstalledComponent from '@/app/home/plugins/plugin-installed/PluginInstalledComponent'; +import PluginInstalledComponent, { PluginInstalledComponentRef } from '@/app/home/plugins/plugin-installed/PluginInstalledComponent'; import PluginMarketComponent from '@/app/home/plugins/plugin-market/PluginMarketComponent'; import styles from './plugins.module.css'; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; import { PlusIcon } from "lucide-react"; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { GithubIcon } from "lucide-react"; +import { useState, useRef, useEffect } from 'react'; +import { httpClient } from '@/app/infra/http/HttpClient'; + +enum PluginInstallStatus { + WAIT_INPUT = 'wait_input', + INSTALLING = 'installing', + ERROR = 'error', +} export default function PluginConfigPage() { + + const [modalOpen, setModalOpen] = useState(false); + const [pluginInstallStatus, setPluginInstallStatus] = useState(PluginInstallStatus.WAIT_INPUT); + const [installError, setInstallError] = useState(null); + const [githubURL, setGithubURL] = useState(''); + const pluginInstalledRef = useRef(null); + + function handleModalConfirm() { + installPlugin(githubURL); + } + function installPlugin(url: string) { + setPluginInstallStatus(PluginInstallStatus.INSTALLING); + httpClient + .installPluginFromGithub(url) + .then((resp) => { + const taskId = resp.task_id; + + // 每秒拉取一次任务状态 + const interval = setInterval(() => { + httpClient.getAsyncTask(taskId).then((resp) => { + console.log('task status:', resp); + if (resp.runtime.done) { + clearInterval(interval); + if (resp.runtime.exception) { + setInstallError(resp.runtime.exception); + setPluginInstallStatus(PluginInstallStatus.ERROR); + } else { // success + setGithubURL(''); + setModalOpen(false); + pluginInstalledRef.current?.refreshPluginList(); + } + } + }); + }, 1000); + + }) + .catch((err) => { + console.log('error when install plugin:', err); + setInstallError(err.message); + setPluginInstallStatus(PluginInstallStatus.ERROR); + }); + } + return (
@@ -18,19 +72,68 @@ export default function PluginConfigPage() {
-
- + + + + + + + + + 从GitHub安装插件 + + + {pluginInstallStatus === PluginInstallStatus.WAIT_INPUT && ( +
+

目前仅支持从 GitHub 安装

+ setGithubURL(e.target.value)} + className="mb-4" + /> +
+ )} + {pluginInstallStatus === PluginInstallStatus.INSTALLING && ( +
+

正在安装插件...

+
+ )} + {pluginInstallStatus === PluginInstallStatus.ERROR && ( +
+

插件安装失败:

+

{installError}

+
+ )} + + {pluginInstallStatus === PluginInstallStatus.WAIT_INPUT && ( + <> + + + + )} + {pluginInstallStatus === PluginInstallStatus.ERROR && ( + + )} + +
+
); } diff --git a/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx b/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx index c04037a7..d9b4487e 100644 --- a/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx +++ b/web/src/app/home/plugins/plugin-installed/PluginInstalledComponent.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; import CreateCardComponent from '@/app/infra/basic-component/create-card-component/CreateCardComponent'; import { PluginCardVO } from '@/app/home/plugins/plugin-installed/PluginCardVO'; import PluginCardComponent from '@/app/home/plugins/plugin-installed/plugin-card/PluginCardComponent'; @@ -17,10 +17,12 @@ import { import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; -export default function PluginInstalledComponent() { +export interface PluginInstalledComponentRef { + refreshPluginList: () => void; +} + +const PluginInstalledComponent = forwardRef((props, ref) => { const [pluginList, setPluginList] = useState([]); - const [modalOpen, setModalOpen] = useState(false); - const [githubURL, setGithubURL] = useState(''); useEffect(() => { initData(); @@ -48,48 +50,12 @@ export default function PluginInstalledComponent() { }); } - function handleModalConfirm() { - installPlugin(githubURL); - setModalOpen(false); - } - - function installPlugin(url: string) { - httpClient - .installPluginFromGithub(url) - .then(() => { - // 安装后重新拉取 - getPluginList(); - }) - .catch((err) => { - console.log('error when install plugin:', err); - }); - } + useImperativeHandle(ref, () => ({ + refreshPluginList: getPluginList + })); return (
- - - - - - 从GitHub安装插件 - - -
-

目前仅支持从 GitHub 安装

- setGithubURL(e.target.value)} - className="mb-4" - /> -
- - - - -
-
{pluginList.map((vo, index) => { return ( @@ -98,14 +64,8 @@ export default function PluginInstalledComponent() {
); })} - - { - setModalOpen(true); - }} - /> ); -} +}); + +export default PluginInstalledComponent; diff --git a/web/src/app/infra/entities/api/index.ts b/web/src/app/infra/entities/api/index.ts index f722c3f2..85f5607a 100644 --- a/web/src/app/infra/entities/api/index.ts +++ b/web/src/app/infra/entities/api/index.ts @@ -168,10 +168,6 @@ export interface ApiRespAsyncTasks { tasks: AsyncTask[]; } -export interface ApiRespAsyncTask { - task: AsyncTask; -} - export interface AsyncTaskRuntimeInfo { done: boolean; exception?: string; diff --git a/web/src/app/infra/http/HttpClient.ts b/web/src/app/infra/http/HttpClient.ts index 18944511..d0f908cb 100644 --- a/web/src/app/infra/http/HttpClient.ts +++ b/web/src/app/infra/http/HttpClient.ts @@ -24,11 +24,11 @@ import { AsyncTaskCreatedResp, ApiRespSystemInfo, ApiRespAsyncTasks, - ApiRespAsyncTask, ApiRespUserToken, MarketPluginResponse, GetPipelineResponseData, - GetPipelineMetadataResponseData + GetPipelineMetadataResponseData, + AsyncTask } from '@/app/infra/entities/api'; import { notification } from 'antd'; @@ -391,7 +391,7 @@ class HttpClient { return this.get('/api/v1/system/tasks'); } - public getAsyncTask(id: number): Promise { + public getAsyncTask(id: number): Promise { return this.get(`/api/v1/system/tasks/${id}`); }