From 606fc7be0c0e5e3b9e828d2f04735e9060c1ab93 Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 24 Oct 2024 17:14:17 +0800 Subject: [PATCH] feat: support upload pkg --- .../plugins/install-plugin/base/installed.tsx | 26 ++++++++++++------- .../install-from-local-package/index.tsx | 24 +++++++++++------ .../steps/install.tsx | 2 ++ .../steps/uploading.tsx | 23 ++++++++++------ web/app/components/plugins/types.ts | 1 + web/i18n/en-US/plugin.ts | 1 + web/i18n/zh-Hans/plugin.ts | 1 + web/service/plugins.ts | 11 +++++++- 8 files changed, 62 insertions(+), 27 deletions(-) diff --git a/web/app/components/plugins/install-plugin/base/installed.tsx b/web/app/components/plugins/install-plugin/base/installed.tsx index 03f392447c..af39b47995 100644 --- a/web/app/components/plugins/install-plugin/base/installed.tsx +++ b/web/app/components/plugins/install-plugin/base/installed.tsx @@ -6,31 +6,37 @@ import Card from '../../card' import Button from '@/app/components/base/button' import { pluginManifestToCardPluginProps } from '../utils' import { useTranslation } from 'react-i18next' +import Badge, { BadgeState } from '@/app/components/base/badge/index' type Props = { - payload: PluginDeclaration + payload?: PluginDeclaration | null isFailed: boolean + errMsg?: string | null onCancel: () => void } const Installed: FC = ({ payload, isFailed, + errMsg, onCancel, }) => { const { t } = useTranslation() return ( <>
-

{t(`plugin.installModal.${isFailed ? 'installFailedDesc' : 'installedSuccessfullyDesc'}`)}

-
- -
+

{(isFailed && errMsg) ? errMsg : t(`plugin.installModal.${isFailed ? 'installFailedDesc' : 'installedSuccessfullyDesc'}`)}

+ {payload && ( +
+ {payload.version}} + /> +
+ )}
{/* Action Buttons */}
diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/index.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/index.tsx index 0f75d7cf5b..e71f5f7e2f 100644 --- a/web/app/components/plugins/install-plugin/install-from-local-package/index.tsx +++ b/web/app/components/plugins/install-plugin/install-from-local-package/index.tsx @@ -8,7 +8,6 @@ import Uploading from './steps/uploading' import Install from './steps/install' import Installed from '../base/installed' import { useTranslation } from 'react-i18next' -import { toolNotionManifest } from '../../card/card-mock' const i18nPrefix = 'plugin.installModal' @@ -23,19 +22,21 @@ const InstallFromLocalPackage: React.FC = ({ onClose, }) => { const { t } = useTranslation() - // uploading -> readyToInstall -> installed/failed + // uploading -> !uploadFailed -> readyToInstall -> installed/failed const [step, setStep] = useState(InstallStep.uploading) - const [uniqueIdentifier, setUniqueIdentifier] = useState(null) - + const [manifest, setManifest] = useState(null) + const [errorMsg, setErrorMsg] = useState(null) const getTitle = useCallback(() => { + if (step === InstallStep.uploadFailed) + return t(`${i18nPrefix}.uploadFailed`) if (step === InstallStep.installed) return t(`${i18nPrefix}.installedSuccessfully`) if (step === InstallStep.installFailed) return t(`${i18nPrefix}.installFailed`) + return t(`${i18nPrefix}.installPlugin`) }, [step]) - const [manifest, setManifest] = useState(toolNotionManifest) const handleUploaded = useCallback((result: { uniqueIdentifier: string @@ -46,6 +47,11 @@ const InstallFromLocalPackage: React.FC = ({ setStep(InstallStep.readyToInstall) }, []) + const handleUploadFail = useCallback((errorMsg: string) => { + setErrorMsg(errorMsg) + setStep(InstallStep.uploadFailed) + }, []) + const handleInstalled = useCallback(async () => { setStep(InstallStep.installed) }, []) @@ -71,6 +77,7 @@ const InstallFromLocalPackage: React.FC = ({ file={file} onCancel={onClose} onUploaded={handleUploaded} + onFailed={handleUploadFail} /> )} { @@ -84,10 +91,11 @@ const InstallFromLocalPackage: React.FC = ({ ) } { - ([InstallStep.installed, InstallStep.installFailed].includes(step)) && ( + ([InstallStep.uploadFailed, InstallStep.installed, InstallStep.installFailed].includes(step)) && ( ) diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx index 8572d96a3a..42e3ef74b8 100644 --- a/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-from-local-package/steps/install.tsx @@ -8,6 +8,7 @@ import Button from '@/app/components/base/button' import { sleep } from '@/utils' import { Trans, useTranslation } from 'react-i18next' import { RiLoader2Line } from '@remixicon/react' +import Badge, { BadgeState } from '@/app/components/base/badge/index' const i18nPrefix = 'plugin.installModal' @@ -51,6 +52,7 @@ const Installed: FC = ({ {payload.version}} />
diff --git a/web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx b/web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx index 6a8068515d..50b23ca9f0 100644 --- a/web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx +++ b/web/app/components/plugins/install-plugin/install-from-local-package/steps/uploading.tsx @@ -5,10 +5,8 @@ import { RiLoader2Line } from '@remixicon/react' import Card from '../../../card' import type { PluginDeclaration } from '../../../types' import Button from '@/app/components/base/button' -import { sleep } from '@/utils' import { useTranslation } from 'react-i18next' -import { toolNotionManifest } from '../../../card/card-mock' - +import { uploadPackageFile } from '@/service/plugins' const i18nPrefix = 'plugin.installModal' type Props = { @@ -18,21 +16,30 @@ type Props = { uniqueIdentifier: string manifest: PluginDeclaration }) => void + onFailed: (errorMsg: string) => void } const Uploading: FC = ({ file, onCancel, onUploaded, + onFailed, }) => { const { t } = useTranslation() const fileName = file.name const handleUpload = async () => { - await sleep(3000) - onUploaded({ - uniqueIdentifier: 'yeuoly/neko:0.0.1@5395654da2c0b919b3d9b946a1a0545b737004380765e5f3b8c49976d3276c87', - manifest: toolNotionManifest, - }) + try { + const res = await uploadPackageFile(file) + onUploaded(res) + } + catch (e: any) { + if (e.response?.message) { + onFailed(e.response?.message) + } + else { // Why it would into this branch? + onUploaded(e.response) + } + } } React.useEffect(() => { diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 8fdea20406..ba430a87c3 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -168,6 +168,7 @@ export type UpdateEndpointRequest = { export enum InstallStep { uploading = 'uploading', + uploadFailed = 'uploadFailed', readyToInstall = 'readyToInstall', installing = 'installing', installed = 'installed', diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index 1be0398331..62b3facdc3 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -63,6 +63,7 @@ const translation = { installPlugin: 'Install Plugin', installedSuccessfully: 'Installation successful', installedSuccessfullyDesc: 'The plugin has been installed successfully.', + uploadFailed: 'Upload failed', installFailed: 'Installation failed', installFailedDesc: 'The plugin has been installed failed.', install: 'Install', diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index 91f7a998eb..573ced6f94 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -63,6 +63,7 @@ const translation = { installPlugin: '安装插件', installedSuccessfully: '安装成功', installedSuccessfullyDesc: '插件已成功安装。', + uploadFailed: '上传失败', installFailed: '安装失败', installFailedDesc: '插件安装失败。', install: '安装', diff --git a/web/service/plugins.ts b/web/service/plugins.ts index 55309ae944..dfee63009b 100644 --- a/web/service/plugins.ts +++ b/web/service/plugins.ts @@ -1,5 +1,5 @@ import type { Fetcher } from 'swr' -import { del, get, post } from './base' +import { del, get, post, upload } from './base' import type { CreateEndpointRequest, EndpointOperationResponse, @@ -49,3 +49,12 @@ export const installPackageFromGitHub: Fetcher { return get('/workspaces/current/plugin/debugging-key') } + +export const uploadPackageFile = async (file: File) => { + const formData = new FormData() + formData.append('pkg', file) + return upload({ + xhr: new XMLHttpRequest(), + data: formData, + }, false, '/workspaces/current/plugin/upload/pkg') +}