diff --git a/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx b/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx index dce2e735c8..c046957263 100644 --- a/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx +++ b/web/app/components/plugins/install-plugin/install-from-github/steps/loaded.tsx @@ -9,7 +9,7 @@ import { pluginManifestToCardPluginProps } from '../../utils' import { useTranslation } from 'react-i18next' import { installPackageFromGitHub, uninstallPlugin } from '@/service/plugins' import { RiLoader2Line } from '@remixicon/react' -import { usePluginTasksStore } from '@/app/components/plugins/plugin-page/store' +import { usePluginTasksStore } from '@/app/components/plugins/plugin-page/plugin-tasks/store' import checkTaskStatus from '../../base/check-task-status' import { parseGitHubUrl } from '../../utils' 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 b48922bdb9..4d776f4430 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 @@ -10,7 +10,7 @@ import { RiLoader2Line } from '@remixicon/react' import Badge, { BadgeState } from '@/app/components/base/badge/index' import { useInstallPackageFromLocal } from '@/service/use-plugins' import checkTaskStatus from '../../base/check-task-status' -import { usePluginTasksStore } from '@/app/components/plugins/plugin-page/store' +import { usePluginTasksStore } from '@/app/components/plugins/plugin-page/plugin-tasks/store' const i18nPrefix = 'plugin.installModal' diff --git a/web/app/components/plugins/plugin-page/index.tsx b/web/app/components/plugins/plugin-page/index.tsx index f889bbc363..013c9bc9e2 100644 --- a/web/app/components/plugins/plugin-page/index.tsx +++ b/web/app/components/plugins/plugin-page/index.tsx @@ -16,8 +16,8 @@ import InstallPluginDropdown from './install-plugin-dropdown' import { useUploader } from './use-uploader' import usePermission from './use-permission' import DebugInfo from './debug-info' -import { usePluginTasksStore } from './store' -import InstallInfo from './install-info' +import { usePluginTasksStore } from './plugin-tasks/store' +import PluginTasks from './plugin-tasks' import Button from '@/app/components/base/button' import TabSlider from '@/app/components/base/tab-slider' import Tooltip from '@/app/components/base/tooltip' @@ -102,8 +102,6 @@ const PluginPage = ({ const options = usePluginPageContext(v => v.options) const [activeTab, setActiveTab] = usePluginPageContext(v => [v.activeTab, v.setActiveTab]) const { enable_marketplace } = useAppContextSelector(s => s.systemFeatures) - const [installed, total] = [2, 3] // Replace this with the actual progress - const progressPercentage = (installed / total) * 100 const uploaderProps = useUploader({ onFileChange: setCurrentFile, @@ -142,7 +140,7 @@ const PluginPage = ({ />
- + {canManagement && ( setActiveTab('discover')} diff --git a/web/app/components/plugins/plugin-page/install-info.tsx b/web/app/components/plugins/plugin-page/install-info.tsx deleted file mode 100644 index bb0a31f4be..0000000000 --- a/web/app/components/plugins/plugin-page/install-info.tsx +++ /dev/null @@ -1,86 +0,0 @@ -import { - useState, -} from 'react' -import { - RiCheckboxCircleFill, - RiErrorWarningFill, - RiInstallLine, -} from '@remixicon/react' -import { - PortalToFollowElem, - PortalToFollowElemContent, - PortalToFollowElemTrigger, -} from '@/app/components/base/portal-to-follow-elem' -import Tooltip from '@/app/components/base/tooltip' -import Button from '@/app/components/base/button' -// import ProgressCircle from '@/app/components/base/progress-bar/progress-circle' -import { useMemo } from 'react' -import cn from '@/utils/classnames' - -const InstallInfo = () => { - const [open, setOpen] = useState(false) - const status = 'error' - const statusError = useMemo(() => status === 'error', [status]) - - return ( -
- - setOpen(v => !v)}> - -
- -
- {/* */} - -
-
-
-
- -
-
3 plugins failed to install
-
-
- -
-
- DuckDuckGo Search -
- -
-
-
-
-
- ) -} - -export default InstallInfo diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts b/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts new file mode 100644 index 0000000000..3a198f5068 --- /dev/null +++ b/web/app/components/plugins/plugin-page/plugin-tasks/hooks.ts @@ -0,0 +1,27 @@ +import { usePluginTasksStore } from './store' +import { TaskStatus } from '@/app/components/plugins/types' +import type { PluginStatus } from '@/app/components/plugins/types' + +export const usePluginTaskStatus = () => { + const pluginTasks = usePluginTasksStore(s => s.pluginTasks) + const allPlugins = pluginTasks.map(task => task.plugins).flat() + const errorPlugins: PluginStatus[] = [] + const successPlugins: PluginStatus[] = [] + const runningPlugins: PluginStatus[] = [] + + allPlugins.forEach((plugin) => { + if (plugin.status === TaskStatus.running) + runningPlugins.push(plugin) + if (plugin.status === TaskStatus.failed) + errorPlugins.push(plugin) + if (plugin.status === TaskStatus.success) + successPlugins.push(plugin) + }) + + return { + errorPlugins, + successPlugins, + runningPlugins, + totalPluginsLength: allPlugins.length, + } +} diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx new file mode 100644 index 0000000000..bde4371839 --- /dev/null +++ b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx @@ -0,0 +1,137 @@ +import { + useMemo, + useState, +} from 'react' +import { + RiCheckboxCircleFill, + RiErrorWarningFill, + RiInstallLine, +} from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import { usePluginTaskStatus } from './hooks' +import { + PortalToFollowElem, + PortalToFollowElemContent, + PortalToFollowElemTrigger, +} from '@/app/components/base/portal-to-follow-elem' +import Tooltip from '@/app/components/base/tooltip' +import Button from '@/app/components/base/button' +import ProgressCircle from '@/app/components/base/progress-bar/progress-circle' +import cn from '@/utils/classnames' + +const PluginTasks = () => { + const { t } = useTranslation() + const [open, setOpen] = useState(false) + const { + errorPlugins, + runningPlugins, + successPlugins, + totalPluginsLength, + } = usePluginTaskStatus() + + const isInstalling = runningPlugins.length > 0 && errorPlugins.length === 0 && successPlugins.length === 0 + const isInstallingWithError = errorPlugins.length > 0 && errorPlugins.length < totalPluginsLength + const isSuccess = successPlugins.length === totalPluginsLength && totalPluginsLength > 0 + const isFailed = errorPlugins.length === totalPluginsLength && totalPluginsLength > 0 + + const tip = useMemo(() => { + if (isInstalling) + return t('plugin.task.installing', { installingLength: runningPlugins.length, totalLength: totalPluginsLength }) + + if (isInstallingWithError) + return t('plugin.task.installingWithError', { installingLength: runningPlugins.length, totalLength: totalPluginsLength, errorLength: errorPlugins.length }) + + if (isFailed) + return t('plugin.task.installError', { errorLength: errorPlugins.length }) + }, [isInstalling, isInstallingWithError, isFailed, errorPlugins, runningPlugins, totalPluginsLength, t]) + + return ( +
+ + { + if (isFailed || isInstallingWithError) + setOpen(v => !v) + }} + > + +
+ +
+ { + isInstalling && ( + + ) + } + { + isInstallingWithError && ( + + ) + } + { + isSuccess && ( + + ) + } + { + isFailed && ( + + ) + } +
+
+
+
+ +
+
{t('plugin.task.installedError')}
+
+
+ +
+
+ DuckDuckGo Search +
+ +
+
+
+
+
+ ) +} + +export default PluginTasks diff --git a/web/app/components/plugins/plugin-page/store.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/store.ts similarity index 94% rename from web/app/components/plugins/plugin-page/store.tsx rename to web/app/components/plugins/plugin-page/plugin-tasks/store.ts index 25074b973f..403d529a39 100644 --- a/web/app/components/plugins/plugin-page/store.tsx +++ b/web/app/components/plugins/plugin-page/plugin-tasks/store.ts @@ -1,5 +1,5 @@ import { create } from 'zustand' -import type { PluginTask } from '../types' +import type { PluginTask } from '@/app/components/plugins/types' import { fetchPluginTasks } from '@/service/plugins' type PluginTasksStore = { diff --git a/web/app/components/plugins/update-plugin/from-market-place.tsx b/web/app/components/plugins/update-plugin/from-market-place.tsx index e0b54a1acf..0454617a2e 100644 --- a/web/app/components/plugins/update-plugin/from-market-place.tsx +++ b/web/app/components/plugins/update-plugin/from-market-place.tsx @@ -12,7 +12,7 @@ import { pluginManifestToCardPluginProps } from '@/app/components/plugins/instal import useGetIcon from '../install-plugin/base/use-get-icon' import { updateFromMarketPlace } from '@/service/plugins' import checkTaskStatus from '@/app/components/plugins/install-plugin/base/check-task-status' -import { usePluginTasksStore } from '@/app/components/plugins/plugin-page/store' +import { usePluginTasksStore } from '@/app/components/plugins/plugin-page/plugin-tasks/store' const i18nPrefix = 'plugin.upgrade' diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts index 5c3bdc6f29..abcf3480bb 100644 --- a/web/i18n/en-US/plugin.ts +++ b/web/i18n/en-US/plugin.ts @@ -124,6 +124,12 @@ const translation = { inDifyMarketplace: 'in Dify Marketplace', moreFrom: 'More from Marketplace', }, + task: { + installing: 'Installing {{installingLength}}/{{totalLength}} plugins...', + installingWithError: 'Installing {{installingLength}} of {{totalLength}} plugins, {{errorLength}} failed, click to view', + installError: '{{errorLength}} plugins failed to install, click to view', + installedError: '{{errorLength}} plugins failed to install', + }, } export default translation diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts index c1f7bb7600..3355cb742c 100644 --- a/web/i18n/zh-Hans/plugin.ts +++ b/web/i18n/zh-Hans/plugin.ts @@ -124,6 +124,12 @@ const translation = { inDifyMarketplace: '在 Dify 市场中', moreFrom: '更多来自市场', }, + task: { + installing: '{{installingLength}}/{{totalLength}} 插件安装中...', + installingWithError: '{{installingLength}}/{{totalLength}} 插件安装中,{{errorLength}} 安装失败。点击查看', + installError: '{{errorLength}} 个插件安装失败,点击查看', + installedError: '{{errorLength}} 个插件安装失败', + }, } export default translation